<commit_before>#include <cybozu/test.hpp>
#include <cybozu/wavelet_matrix.hpp>
#include <algorithm>
#include <cybozu/xorshift.hpp>
#include <cybozu/time.hpp>

template<class T>
size_t selectC(const T *a, size_t N, uint32_t val, size_t n)
{
	n++;
	for (size_t i = 0; i < N; i++) {
		if (a[i] == val) n--;
		if (n == 0) return i;
	}
	return cybozu::NotFound;
}

template<class T>
size_t rankC(const T *a, size_t N, uint32_t val)
{
	return std::count(a, a + N, val);
}

template<class T>
size_t rankLtC(const T *a, size_t N, uint32_t val)
{
	size_t ret = 0;
	for (size_t i = 0; i < N; i++) {
		if (a[i] < val) ret++;
	}
	return ret;
}

CYBOZU_TEST_AUTO(mini)
{
	std::vector<uint32_t> v;
	const uint32_t vTbl[] = { 4, 7, 6, 5, 3, 2, 1, 0, 1, 4, 1, 7 };
	const size_t vn = CYBOZU_NUM_OF_ARRAY(vTbl);
	for (size_t i = 0; i < vn; i++) {
		v.push_back(vTbl[i]);
	}
	cybozu::WaveletMatrix wm;
	wm.init(v, 3);
	for (size_t i = 0; i < vn; i++) {
		CYBOZU_TEST_EQUAL(wm.get(i), vTbl[i]);
	}

	for (uint32_t val = 0; val <= 7; val++) {
		for (size_t pos = 0; pos < vn; pos++) {
			size_t a = wm.rank(val, pos);
			size_t b = rankC(vTbl, pos, val);
			CYBOZU_TEST_EQUAL(a, b);
			a = wm.rankLt(val, pos);
			b = rankLtC(vTbl, pos, val);
			CYBOZU_TEST_EQUAL(a, b);
		}
	}
	for (int r = 0; r < 3; r++) {
		for (int val = 0; val < 8; val++) {
			size_t a = wm.select(val, r);
			size_t b = selectC(vTbl, vn, val, r);
			CYBOZU_TEST_EQUAL(a, b);
		}
	}
}

void testSub(const cybozu::WaveletMatrix& wm, const std::vector<uint32_t>& v, uint32_t maxVal, size_t valBitLen)
{
	const size_t vn = v.size();
	for (size_t i = 0; i < vn; i++) {
		CYBOZU_TEST_EQUAL(wm.get(i), v[i]);
	}
	for (uint32_t val = 0; val < maxVal; val++) {
		for (size_t pos = 0; pos < vn; pos++) {
			size_t a = wm.rank(val, pos);
			size_t b = std::count(v.begin(), v.begin() + pos, val);
			CYBOZU_TEST_EQUAL(a, b);
		}
		CYBOZU_TEST_EQUAL(wm.rank(val, vn), (uint64_t)std::count(v.begin(), v.end(), val));
	}
	for (size_t r = 0; r < valBitLen; r++) {
		for (uint32_t val = 0; val < maxVal; val++) {
			size_t a = wm.select(val, r);
			size_t b = selectC(&v[0], vn, val, r);
			CYBOZU_TEST_EQUAL(a, b);
		}
	}
}

CYBOZU_TEST_AUTO(large_load_save)
{
	cybozu::XorShift rg;
	std::vector<uint32_t> v;
	const size_t vn = 5000;
	const size_t valBitLen = 8;
	const uint32_t maxVal = 1 << valBitLen;
	v.resize(vn);
	for (size_t i = 0; i < vn; i++) {
		v[i] = rg() % maxVal;
	}
	cybozu::WaveletMatrix wm;
	wm.init(v, valBitLen);
	testSub(wm, v, maxVal, valBitLen);
	std::string data;
	{
		std::ostringstream os;
		wm.save(os);
		data = os.str();
	}
	{
		std::istringstream is(data);
		cybozu::WaveletMatrix wm2;
		wm2.load(is);
		testSub(wm2, v, maxVal, valBitLen);
	}
#ifndef NDEUBG
	size_t x = 0;
	double begin = cybozu::GetCurrentTimeSec();
	for (uint32_t val = 0; val < maxVal; val++) {
		for (size_t pos = 0; pos < vn; pos++) {
			x += wm.rank(val, pos);
		}
	}
	printf("wm.rank   %08x %5.2fusec\n", (int)x, (cybozu::GetCurrentTimeSec() - begin) / (maxVal * vn) * 1e6);
	x = 0;
	begin = cybozu::GetCurrentTimeSec();
	const int N = 10;
	for (int i = 0; i < N; i++) {
		for (size_t r = 0; r < valBitLen; r++) {
			for (uint32_t val = 0; val < maxVal; val++) {
				x += wm.select(val, r);
			}
		}
	}
	printf("wm.select %08x %5.2fusec\n", (int)x, (cybozu::GetCurrentTimeSec() - begin) / (valBitLen * maxVal * N) * 1e6);
#endif
}
<commit_msg>reduce iteration number<commit_after>#include <cybozu/test.hpp>
#include <cybozu/wavelet_matrix.hpp>
#include <algorithm>
#include <cybozu/xorshift.hpp>
#include <cybozu/time.hpp>

template<class T>
size_t selectC(const T *a, size_t N, uint32_t val, size_t n)
{
	n++;
	for (size_t i = 0; i < N; i++) {
		if (a[i] == val) n--;
		if (n == 0) return i;
	}
	return cybozu::NotFound;
}

template<class T>
size_t rankC(const T *a, size_t N, uint32_t val)
{
	return std::count(a, a + N, val);
}

template<class T>
size_t rankLtC(const T *a, size_t N, uint32_t val)
{
	size_t ret = 0;
	for (size_t i = 0; i < N; i++) {
		if (a[i] < val) ret++;
	}
	return ret;
}

CYBOZU_TEST_AUTO(mini)
{
	std::vector<uint32_t> v;
	const uint32_t vTbl[] = { 4, 7, 6, 5, 3, 2, 1, 0, 1, 4, 1, 7 };
	const size_t vn = CYBOZU_NUM_OF_ARRAY(vTbl);
	for (size_t i = 0; i < vn; i++) {
		v.push_back(vTbl[i]);
	}
	cybozu::WaveletMatrix wm;
	wm.init(v, 3);
	for (size_t i = 0; i < vn; i++) {
		CYBOZU_TEST_EQUAL(wm.get(i), vTbl[i]);
	}

	for (uint32_t val = 0; val <= 7; val++) {
		for (size_t pos = 0; pos < vn; pos++) {
			size_t a = wm.rank(val, pos);
			size_t b = rankC(vTbl, pos, val);
			CYBOZU_TEST_EQUAL(a, b);
			a = wm.rankLt(val, pos);
			b = rankLtC(vTbl, pos, val);
			CYBOZU_TEST_EQUAL(a, b);
		}
	}
	for (int r = 0; r < 3; r++) {
		for (int val = 0; val < 8; val++) {
			size_t a = wm.select(val, r);
			size_t b = selectC(vTbl, vn, val, r);
			CYBOZU_TEST_EQUAL(a, b);
		}
	}
}

void testSub(const cybozu::WaveletMatrix& wm, const std::vector<uint32_t>& v, uint32_t maxVal, size_t valBitLen)
{
	const size_t vn = v.size();
	for (size_t i = 0; i < vn; i++) {
		CYBOZU_TEST_EQUAL(wm.get(i), v[i]);
	}
	for (uint32_t val = 0; val < maxVal; val++) {
		for (size_t pos = 0; pos < vn; pos++) {
			size_t a = wm.rank(val, pos);
			size_t b = std::count(v.begin(), v.begin() + pos, val);
			CYBOZU_TEST_EQUAL(a, b);
		}
		CYBOZU_TEST_EQUAL(wm.rank(val, vn), (uint64_t)std::count(v.begin(), v.end(), val));
	}
	for (size_t r = 0; r < valBitLen; r++) {
		for (uint32_t val = 0; val < maxVal; val++) {
			size_t a = wm.select(val, r);
			size_t b = selectC(&v[0], vn, val, r);
			CYBOZU_TEST_EQUAL(a, b);
		}
	}
}

CYBOZU_TEST_AUTO(large_load_save)
{
	cybozu::XorShift rg;
	std::vector<uint32_t> v;
	const size_t vn = 500;
	const size_t valBitLen = 8;
	const uint32_t maxVal = 1 << valBitLen;
	v.resize(vn);
	for (size_t i = 0; i < vn; i++) {
		v[i] = rg() % maxVal;
	}
	cybozu::WaveletMatrix wm;
	wm.init(v, valBitLen);
	testSub(wm, v, maxVal, valBitLen);
	std::string data;
	{
		std::ostringstream os;
		wm.save(os);
		data = os.str();
	}
	{
		std::istringstream is(data);
		cybozu::WaveletMatrix wm2;
		wm2.load(is);
		testSub(wm2, v, maxVal, valBitLen);
	}
#ifndef NDEUBG
	size_t x = 0;
	double begin = cybozu::GetCurrentTimeSec();
	for (uint32_t val = 0; val < maxVal; val++) {
		for (size_t pos = 0; pos < vn; pos++) {
			x += wm.rank(val, pos);
		}
	}
	printf("wm.rank   %08x %5.2fusec\n", (int)x, (cybozu::GetCurrentTimeSec() - begin) / (maxVal * vn) * 1e6);
	x = 0;
	begin = cybozu::GetCurrentTimeSec();
	const int N = 10;
	for (int i = 0; i < N; i++) {
		for (size_t r = 0; r < valBitLen; r++) {
			for (uint32_t val = 0; val < maxVal; val++) {
				x += wm.select(val, r);
			}
		}
	}
	printf("wm.select %08x %5.2fusec\n", (int)x, (cybozu::GetCurrentTimeSec() - begin) / (valBitLen * maxVal * N) * 1e6);
#endif
}
<|endoftext|>


<commit_before><commit_msg>adapt to change in field name<commit_after><|endoftext|>


<commit_before><commit_msg>Added preprocessing step determine if there are non-neutral alleles in the set<commit_after><|endoftext|>


<commit_before><commit_msg>DeviceLister: Don't fail silently when cannot iterate through DM slaves<commit_after><|endoftext|>


<commit_before><commit_msg>minus motifs<commit_after><|endoftext|>


<commit_before><commit_msg>introduce /src qmake property variants<commit_after><|endoftext|>


<commit_before>#include "PaxosAcceptor.h"
#include "PaxosProposer.h"
#include "Framework/Replication/ReplicationConfig.h"

PaxosAcceptor::PaxosAcceptor()
{
    onStateWritten = MFUNC(PaxosAcceptor, OnStateWritten);
}

void PaxosAcceptor::Init(QuorumContext* context_)
{
    context = context_;
    sendReply = false;

    ReadState();
}

void PaxosAcceptor::SetAsyncCommit(bool asyncCommit_)
{
    asyncCommit = asyncCommit_;
}

bool PaxosAcceptor::GetAsyncCommit()
{
    return asyncCommit;
}

void PaxosAcceptor::OnMessage(PaxosMessage& imsg)
{
    if (imsg.type == PAXOS_PREPARE_REQUEST)
        OnPrepareRequest(imsg);
    else if (imsg.type == PAXOS_PROPOSE_REQUEST)
        OnProposeRequest(imsg);
    else
        ASSERT_FAIL();
}

void PaxosAcceptor::OnCatchupComplete()
{
    ResetState();
}

void PaxosAcceptor::OnPrepareRequest(PaxosMessage& imsg)
{
    Log_Trace();

    senderID = imsg.nodeID;

    Log_Trace("state.promisedProposalID: %U msg.proposalID: %U",
     state.promisedProposalID, imsg.proposalID);

    if (imsg.paxosID != context->GetPaxosID() ||
     imsg.proposalID < state.promisedProposalID ||
     context->GetDatabase()->IsCommiting() ||
     context->IsPaxosBlocked())
    {
        omsg.PrepareRejected(imsg.paxosID, MY_NODEID,
         imsg.proposalID, state.promisedProposalID);
        context->GetTransport()->SendMessage(senderID, omsg);
        return;
    }

    state.promisedProposalID = imsg.proposalID;

    if (!state.accepted)
    {
        omsg.PrepareCurrentlyOpen(imsg.paxosID, MY_NODEID, imsg.proposalID);
    }
    else
    {
        ASSERT(state.acceptedValue.GetLength() > 0);
        omsg.PreparePreviouslyAccepted(imsg.paxosID, MY_NODEID,
         imsg.proposalID, state.acceptedProposalID,
         state.acceptedRunID, state.acceptedValue);
    }

    WriteState();
    Commit(true);
}

void PaxosAcceptor::OnProposeRequest(PaxosMessage& imsg)
{
    Log_Trace();

    senderID = imsg.nodeID;

    Log_Trace("state.promisedProposalID: %U msg.proposalID: %U",
     state.promisedProposalID, imsg.proposalID);

    if (imsg.paxosID != context->GetPaxosID() ||
     imsg.proposalID < state.promisedProposalID ||
     context->GetDatabase()->IsCommiting() ||
     context->IsPaxosBlocked())
    {
        omsg.ProposeRejected(imsg.paxosID, MY_NODEID, imsg.proposalID);
        context->GetTransport()->SendMessage(senderID, omsg);
        return;
    }

    state.accepted = true;
    state.acceptedProposalID = imsg.proposalID;
    state.acceptedRunID = imsg.runID;
    ASSERT(imsg.value.GetLength() > 0);
    state.acceptedValue.Write(imsg.value);
    omsg.ProposeAccepted(imsg.paxosID, MY_NODEID, imsg.proposalID);

    WriteState();
    Commit(true);
}

void PaxosAcceptor::OnStateWritten()
{
    Log_Trace();

    if (!sendReply || writtenPaxosID != context->GetPaxosID())
        return;

    context->GetTransport()->SendMessage(senderID, omsg);
}

void PaxosAcceptor::ReadState()
{
    Log_Trace();

    QuorumDatabase* db;

    db = context->GetDatabase();

    context->SetPaxosID(db->GetPaxosID());
    state.accepted = db->GetAccepted();
    state.promisedProposalID = db->GetPromisedProposalID();
    if (state.accepted)
    {
        state.acceptedRunID = db->GetAcceptedRunID();
        state.acceptedProposalID = db->GetAcceptedProposalID();
        db->GetAcceptedValue(context->GetPaxosID(), state.acceptedValue);
        ASSERT(state.acceptedValue.GetLength() > 0);
    }
}

void PaxosAcceptor::WriteState()
{
    QuorumDatabase* db;

    db = context->GetDatabase();

    db->SetPaxosID(context->GetPaxosID());
    db->SetAccepted(state.accepted);
    db->SetPromisedProposalID(state.promisedProposalID);
    if (state.accepted)
    {
        db->SetAcceptedRunID(state.acceptedRunID);
        db->SetAcceptedProposalID(state.acceptedProposalID);
        ASSERT(state.acceptedValue.GetLength() > 0);
        db->SetAcceptedValue(context->GetPaxosID(), state.acceptedValue);
    }
}

void PaxosAcceptor::Commit(bool sendReply_)
{
    QuorumDatabase* db;

    db = context->GetDatabase();

    sendReply = sendReply_; // used in OnStateWritten()

    writtenPaxosID = context->GetPaxosID();

    if (asyncCommit)
    {
        db->Commit(onStateWritten);
    }
    else
    {
        db->Commit();
        OnStateWritten();
    }
}

void PaxosAcceptor::ResetState()
{
    bool ac;

    state.Init();

    ac = asyncCommit;
    asyncCommit = false; // force sync commit
    WriteState();
    Commit(false);
    asyncCommit = ac;

}
<commit_msg>Added Log_Debug()s.<commit_after>#include "PaxosAcceptor.h"
#include "PaxosProposer.h"
#include "Framework/Replication/ReplicationConfig.h"

PaxosAcceptor::PaxosAcceptor()
{
    onStateWritten = MFUNC(PaxosAcceptor, OnStateWritten);
}

void PaxosAcceptor::Init(QuorumContext* context_)
{
    context = context_;
    sendReply = false;

    ReadState();
}

void PaxosAcceptor::SetAsyncCommit(bool asyncCommit_)
{
    asyncCommit = asyncCommit_;
}

bool PaxosAcceptor::GetAsyncCommit()
{
    return asyncCommit;
}

void PaxosAcceptor::OnMessage(PaxosMessage& imsg)
{
    if (imsg.type == PAXOS_PREPARE_REQUEST)
        OnPrepareRequest(imsg);
    else if (imsg.type == PAXOS_PROPOSE_REQUEST)
        OnProposeRequest(imsg);
    else
        ASSERT_FAIL();
}

void PaxosAcceptor::OnCatchupComplete()
{
    ResetState();
}

void PaxosAcceptor::OnPrepareRequest(PaxosMessage& imsg)
{
    Log_Trace();

    senderID = imsg.nodeID;

    Log_Trace("state.promisedProposalID: %U msg.proposalID: %U",
     state.promisedProposalID, imsg.proposalID);

    if (imsg.paxosID != context->GetPaxosID() ||
     imsg.proposalID < state.promisedProposalID ||
     context->GetDatabase()->IsCommiting() ||
     context->IsPaxosBlocked())
    {
        Log_Debug("imsg.paxosID = %U", imsg.paxosID);
        Log_Debug("context->GetPaxosID() = %U", context->GetPaxosID());
        Log_Debug("imsg.proposalID = %U", imsg.proposalID);
        Log_Debug("state.promisedProposalID = %U", state.promisedProposalID);
        Log_Debug("context->GetDatabase()->IsCommiting() = %b", context->GetDatabase()->IsCommiting());
        Log_Debug("context->IsPaxosBlocked() = %b", context->IsPaxosBlocked());
        omsg.PrepareRejected(imsg.paxosID, MY_NODEID,
         imsg.proposalID, state.promisedProposalID);
        context->GetTransport()->SendMessage(senderID, omsg);
        return;
    }

    state.promisedProposalID = imsg.proposalID;

    if (!state.accepted)
    {
        omsg.PrepareCurrentlyOpen(imsg.paxosID, MY_NODEID, imsg.proposalID);
    }
    else
    {
        ASSERT(state.acceptedValue.GetLength() > 0);
        omsg.PreparePreviouslyAccepted(imsg.paxosID, MY_NODEID,
         imsg.proposalID, state.acceptedProposalID,
         state.acceptedRunID, state.acceptedValue);
    }

    WriteState();
    Commit(true);
}

void PaxosAcceptor::OnProposeRequest(PaxosMessage& imsg)
{
    Log_Trace();

    senderID = imsg.nodeID;

    Log_Trace("state.promisedProposalID: %U msg.proposalID: %U",
     state.promisedProposalID, imsg.proposalID);

    if (imsg.paxosID != context->GetPaxosID() ||
     imsg.proposalID < state.promisedProposalID ||
     context->GetDatabase()->IsCommiting() ||
     context->IsPaxosBlocked())
    {
        omsg.ProposeRejected(imsg.paxosID, MY_NODEID, imsg.proposalID);
        context->GetTransport()->SendMessage(senderID, omsg);
        return;
    }

    state.accepted = true;
    state.acceptedProposalID = imsg.proposalID;
    state.acceptedRunID = imsg.runID;
    ASSERT(imsg.value.GetLength() > 0);
    state.acceptedValue.Write(imsg.value);
    omsg.ProposeAccepted(imsg.paxosID, MY_NODEID, imsg.proposalID);

    WriteState();
    Commit(true);
}

void PaxosAcceptor::OnStateWritten()
{
    Log_Trace();

    if (!sendReply || writtenPaxosID != context->GetPaxosID())
        return;

    context->GetTransport()->SendMessage(senderID, omsg);
}

void PaxosAcceptor::ReadState()
{
    Log_Trace();

    QuorumDatabase* db;

    db = context->GetDatabase();

    context->SetPaxosID(db->GetPaxosID());
    state.accepted = db->GetAccepted();
    state.promisedProposalID = db->GetPromisedProposalID();
    if (state.accepted)
    {
        state.acceptedRunID = db->GetAcceptedRunID();
        state.acceptedProposalID = db->GetAcceptedProposalID();
        db->GetAcceptedValue(context->GetPaxosID(), state.acceptedValue);
        ASSERT(state.acceptedValue.GetLength() > 0);
    }
}

void PaxosAcceptor::WriteState()
{
    QuorumDatabase* db;

    db = context->GetDatabase();

    db->SetPaxosID(context->GetPaxosID());
    db->SetAccepted(state.accepted);
    db->SetPromisedProposalID(state.promisedProposalID);
    if (state.accepted)
    {
        db->SetAcceptedRunID(state.acceptedRunID);
        db->SetAcceptedProposalID(state.acceptedProposalID);
        ASSERT(state.acceptedValue.GetLength() > 0);
        db->SetAcceptedValue(context->GetPaxosID(), state.acceptedValue);
    }
}

void PaxosAcceptor::Commit(bool sendReply_)
{
    QuorumDatabase* db;

    db = context->GetDatabase();

    sendReply = sendReply_; // used in OnStateWritten()

    writtenPaxosID = context->GetPaxosID();

    if (asyncCommit)
    {
        db->Commit(onStateWritten);
    }
    else
    {
        db->Commit();
        OnStateWritten();
    }
}

void PaxosAcceptor::ResetState()
{
    bool ac;

    state.Init();

    ac = asyncCommit;
    asyncCommit = false; // force sync commit
    WriteState();
    Commit(false);
    asyncCommit = ac;

}
<|endoftext|>


<commit_before>/*
 * Copyright 2010 Google Inc.
 *
 * 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.
 */

// Author: jmarantz@google.com (Joshua Marantz)

#include "net/instaweb/util/public/string_util.h"
#include <algorithm>
#include <cctype>
#include <cstddef>
#include <vector>

#include "net/instaweb/util/public/string.h"

namespace net_instaweb {

GoogleString StrCat(const StringPiece& a,
                    const StringPiece& b,
                    const StringPiece& c,
                    const StringPiece& d,
                    const StringPiece& e,
                    const StringPiece& f,
                    const StringPiece& g,
                    const StringPiece& h) {
  GoogleString res;
  res.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() +
              g.size() + h.size());
  a.AppendToString(&res);
  b.AppendToString(&res);
  c.AppendToString(&res);
  d.AppendToString(&res);
  e.AppendToString(&res);
  f.AppendToString(&res);
  g.AppendToString(&res);
  h.AppendToString(&res);
  return res;
}

void StrAppend(GoogleString* target,
               const StringPiece& a,
               const StringPiece& b,
               const StringPiece& c,
               const StringPiece& d,
               const StringPiece& e,
               const StringPiece& f,
               const StringPiece& g,
               const StringPiece& h) {
  target->reserve(target->size() +
                  a.size() + b.size() + c.size() + d.size() + e.size() +
                  f.size() + g.size() + h.size());
  a.AppendToString(target);
  b.AppendToString(target);
  c.AppendToString(target);
  d.AppendToString(target);
  e.AppendToString(target);
  f.AppendToString(target);
  g.AppendToString(target);
  h.AppendToString(target);
}

void SplitStringPieceToVector(const StringPiece& sp,
                              const StringPiece& separators,
                              StringPieceVector* components,
                              bool omit_empty_strings) {
  size_t prev_pos = 0;
  size_t pos = 0;
  while ((pos = sp.find_first_of(separators, pos)) != StringPiece::npos) {
    if (!omit_empty_strings || (pos > prev_pos)) {
      components->push_back(sp.substr(prev_pos, pos - prev_pos));
    }
    ++pos;
    prev_pos = pos;
  }
  if (!omit_empty_strings || (prev_pos < sp.size())) {
    components->push_back(sp.substr(prev_pos, prev_pos - sp.size()));
  }
}

void SplitStringUsingSubstr(const GoogleString& full,
                            const GoogleString& substr,
                            StringVector* result) {
  GoogleString::size_type begin_index = 0;
  while (true) {
    const GoogleString::size_type end_index = full.find(substr, begin_index);
    if (end_index == GoogleString::npos) {
      const GoogleString term = full.substr(begin_index);
      result->push_back(term);
      return;
    }
    const GoogleString term = full.substr(begin_index, end_index - begin_index);
    if (!term.empty()) {
      result->push_back(term);
    }
    begin_index = end_index + substr.size();
  }
}

void BackslashEscape(const StringPiece& src,
                     const StringPiece& to_escape,
                     GoogleString* dest) {
  dest->reserve(dest->size() + src.size());
  for (const char *p = src.data(), *end = src.data() + src.size();
       p != end; ++p) {
    if (to_escape.find(*p) != StringPiece::npos) {
      dest->push_back('\\');
    }
    dest->push_back(*p);
  }
}

GoogleString CEscape(const StringPiece& src) {
  int len = src.length();
  const char* read = src.data();
  const char* end = read + len;
  int used = 0;
  char* dest = new char[len * 4 + 1];
  for (; read != end; ++read) {
    unsigned char ch = static_cast<unsigned char>(*read);
    switch (ch) {
      case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break;
      case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break;
      case '\t': dest[used++] = '\\'; dest[used++] = 't'; break;
      case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break;
      case '\'': dest[used++] = '\\'; dest[used++] = '\''; break;
      case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break;
      default:
        if (ch < 32 || ch >= 127) {
          std::snprintf(dest + used, 5, "\\%03o", ch);
          used += 4;
        } else {
          dest[used++] = ch;
        }
        break;
    }
  }
  GoogleString final(dest, used);
  delete[] dest;
  return final;
}

// From src/third_party/protobuf/src/google/protobuf/stubs/strutil.h
// but we don't need any other aspect of protobufs so we don't want to
// incur the link cost.
bool HasPrefixString(const StringPiece& str, const StringPiece& prefix) {
  return ((str.size() >= prefix.size()) &&
          (str.substr(0, prefix.size()) == prefix));
}

// From src/third_party/protobuf/src/google/protobuf/stubs/strutil.h
// but we don't need any other aspect of protobufs so we don't want to
// incur the link cost.
void UpperString(GoogleString* s) {
  GoogleString::iterator end = s->end();
  for (GoogleString::iterator i = s->begin(); i != end; ++i) {
    *i = UpperChar(*i);
  }
}

void LowerString(GoogleString* s) {
  GoogleString::iterator end = s->end();
  for (GoogleString::iterator i = s->begin(); i != end; ++i) {
    *i = LowerChar(*i);
  }
}

// ----------------------------------------------------------------------
// GlobalReplaceSubstring()
//    Replaces all instances of a substring in a string.  Returns the
//    number of replacements.
//
//    NOTE: The string pieces must not overlap s.
// ----------------------------------------------------------------------
int GlobalReplaceSubstring(const StringPiece& substring,
                           const StringPiece& replacement,
                           GoogleString* s) {
  CHECK(s != NULL);
  if (s->empty())
    return 0;
  GoogleString tmp;
  int num_replacements = 0;
  size_t pos = 0;
  for (size_t match_pos = s->find(substring.data(), pos, substring.length());
       match_pos != GoogleString::npos;
       pos = match_pos + substring.length(),
           match_pos = s->find(substring.data(), pos, substring.length())) {
    ++num_replacements;
    // Append the original content before the match.
    tmp.append(*s, pos, match_pos - pos);
    // Append the replacement for the match.
    tmp.append(replacement.begin(), replacement.end());
  }
  // Append the content after the last match. If no replacements were made, the
  // original string is left untouched.
  if (num_replacements > 0) {
    tmp.append(*s, pos, s->length() - pos);
    s->swap(tmp);
  }
  return num_replacements;
}

GoogleString JoinStringStar(const ConstStringStarVector& vector,
                            const StringPiece& delim) {
  GoogleString result;

  if (vector.size() > 0) {
    // Precompute resulting length so we can reserve() memory in one shot.
    int length = delim.size() * (vector.size() - 1);
    for (ConstStringStarVector::const_iterator iter = vector.begin();
         iter < vector.end(); ++iter) {
      length += (*iter)->size();
    }
    result.reserve(length);

    // Now combine everything.
    for (ConstStringStarVector::const_iterator iter = vector.begin();
         iter < vector.end(); ++iter) {
      if (iter != vector.begin()) {
        result.append(delim.data(), delim.size());
      }
      result.append(**iter);
    }
  }

  return result;
}

bool StringCaseEqual(const StringPiece& s1, const StringPiece& s2) {
  return ((s1.size() == s2.size()) && (0 == StringCaseCompare(s1, s2)));
}

bool StringCaseStartsWith(const StringPiece& str, const StringPiece& prefix) {
  return ((str.size() >= prefix.size()) &&
          (0 == StringCaseCompare(prefix, str.substr(0, prefix.size()))));
}

bool StringCaseEndsWith(const StringPiece& str, const StringPiece& suffix) {
  return ((str.size() >= suffix.size()) &&
          (0 == StringCaseCompare(suffix,
                                  str.substr(str.size() - suffix.size()))));
}

bool StringEqualConcat(const StringPiece& str, const StringPiece& first,
                       const StringPiece& second) {
  return (str.size() == first.size() + second.size()) &&
      str.starts_with(first) && str.ends_with(second);
}

void ParseShellLikeString(const StringPiece& input,
                          std::vector<GoogleString>* output) {
  output->clear();
  for (size_t index = 0; index < input.size();) {
    const char ch = input[index];
    // If we see a quoted section, treat it as a single item even if there are
    // spaces in it.
    if (ch == '"' || ch == '\'') {
      const char quote = ch;
      ++index;  // skip open quote
      output->push_back("");
      GoogleString& part = output->back();
      for (; index < input.size() && input[index] != quote; ++index) {
        if (input[index] == '\\') {
          ++index;  // skip backslash
          if (index >= input.size()) {
            break;
          }
        }
        part.push_back(input[index]);
      }
      ++index;  // skip close quote
    }
    // Without quotes, items are whitespace-separated.
    else if (!isspace(ch)) {
      output->push_back("");
      GoogleString& part = output->back();
      for (; index < input.size() && !isspace(input[index]); ++index) {
        part.push_back(input[index]);
      }
    }
    // Ignore whitespace (outside of quotes).
    else {
      ++index;
    }
  }
}

int CountSubstring(const StringPiece& text, const StringPiece& substring) {
  int number_of_occurrences = 0;
  size_t pos = 0;
  for (size_t match_pos = text.find(substring, pos);
       match_pos != StringPiece::npos;
       pos = match_pos + 1, match_pos = text.find(substring, pos)) {
    number_of_occurrences++;
  }
  return number_of_occurrences;
}

// In-place StringPiece whitespace trimming.  This mutates the StringPiece.
void TrimWhitespace(StringPiece* str) {
  while (str->size() && isspace(str->data()[0])) {
    str->remove_prefix(1);
  }

  int size = str->size();
  while (size && isspace(str->data()[size - 1])) {
    str->remove_suffix(1);
    size = str->size();
  }
}

void TrimLeadingWhitespace(StringPiece* str) {
  while (str->size() && isspace(str->data()[0])) {
    str->remove_prefix(1);
  }
}

// TODO(jmarantz): This is a very slow implementation.  But strncasecmp
// will fail test StringCaseTest.Locale.  If this shows up as a performance
// bottleneck then an SSE implementation would be better.
int StringCaseCompare(const StringPiece& s1, const StringPiece& s2) {
  for (int i = 0, n = std::min(s1.size(), s2.size()); i < n; ++i) {
    unsigned char c1 = UpperChar(s1[i]);
    unsigned char c2 = UpperChar(s2[i]);
    if (c1 < c2) {
      return -1;
    } else if (c1 > c2) {
      return 1;
    }
  }
  if (s1.size() < s2.size()) {
    return -1;
  } else if (s1.size() > s2.size()) {
    return 1;
  }
  return 0;
}

namespace {

// From Hypertext Transfer Protocol -- HTTP/1.1
// CTL            = <any US-ASCII control character
//                  (octets 0 - 31) and DEL (127)>
// SP             = <US-ASCII SP, space (32)>
// HT             = <US-ASCII HT, horizontal-tab (9)>
//        token          = 1*<any CHAR except CTLs or separators>
//        separators     = "(" | ")" | "<" | ">" | "@"
//                       | "," | ";" | ":" | "\" | <">
//                       | "/" | "[" | "]" | "?" | "="
//                       | "{" | "}" | SP | HT
const char separators[] = "()<>@,;:\\\"/[]?={}";

} // namespace

bool HasIllicitTokenCharacter(const StringPiece& str) {
  for (int i = 0, n = str.size(); i < n; ++i) {
    if (str[i] <= 32 || str[i] == 127) {
      return true;
    }
    for (int j = 0, m = STATIC_STRLEN(separators); j < m; ++j) {
      if (str[i] == separators[j]) {
        return true;
      }
    }
  }
  return false;
}

const StringPiece EmptyString::kEmptyString;

}  // namespace net_instaweb
<commit_msg>Windows build fix: switch from std::snprintf to base::snprintf.<commit_after>/*
 * Copyright 2010 Google Inc.
 *
 * 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.
 */

// Author: jmarantz@google.com (Joshua Marantz)

#include "net/instaweb/util/public/string_util.h"
#include <algorithm>
#include <cctype>
#include <cstddef>
#include <vector>

#include "net/instaweb/util/public/string.h"

namespace net_instaweb {

GoogleString StrCat(const StringPiece& a,
                    const StringPiece& b,
                    const StringPiece& c,
                    const StringPiece& d,
                    const StringPiece& e,
                    const StringPiece& f,
                    const StringPiece& g,
                    const StringPiece& h) {
  GoogleString res;
  res.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() +
              g.size() + h.size());
  a.AppendToString(&res);
  b.AppendToString(&res);
  c.AppendToString(&res);
  d.AppendToString(&res);
  e.AppendToString(&res);
  f.AppendToString(&res);
  g.AppendToString(&res);
  h.AppendToString(&res);
  return res;
}

void StrAppend(GoogleString* target,
               const StringPiece& a,
               const StringPiece& b,
               const StringPiece& c,
               const StringPiece& d,
               const StringPiece& e,
               const StringPiece& f,
               const StringPiece& g,
               const StringPiece& h) {
  target->reserve(target->size() +
                  a.size() + b.size() + c.size() + d.size() + e.size() +
                  f.size() + g.size() + h.size());
  a.AppendToString(target);
  b.AppendToString(target);
  c.AppendToString(target);
  d.AppendToString(target);
  e.AppendToString(target);
  f.AppendToString(target);
  g.AppendToString(target);
  h.AppendToString(target);
}

void SplitStringPieceToVector(const StringPiece& sp,
                              const StringPiece& separators,
                              StringPieceVector* components,
                              bool omit_empty_strings) {
  size_t prev_pos = 0;
  size_t pos = 0;
  while ((pos = sp.find_first_of(separators, pos)) != StringPiece::npos) {
    if (!omit_empty_strings || (pos > prev_pos)) {
      components->push_back(sp.substr(prev_pos, pos - prev_pos));
    }
    ++pos;
    prev_pos = pos;
  }
  if (!omit_empty_strings || (prev_pos < sp.size())) {
    components->push_back(sp.substr(prev_pos, prev_pos - sp.size()));
  }
}

void SplitStringUsingSubstr(const GoogleString& full,
                            const GoogleString& substr,
                            StringVector* result) {
  GoogleString::size_type begin_index = 0;
  while (true) {
    const GoogleString::size_type end_index = full.find(substr, begin_index);
    if (end_index == GoogleString::npos) {
      const GoogleString term = full.substr(begin_index);
      result->push_back(term);
      return;
    }
    const GoogleString term = full.substr(begin_index, end_index - begin_index);
    if (!term.empty()) {
      result->push_back(term);
    }
    begin_index = end_index + substr.size();
  }
}

void BackslashEscape(const StringPiece& src,
                     const StringPiece& to_escape,
                     GoogleString* dest) {
  dest->reserve(dest->size() + src.size());
  for (const char *p = src.data(), *end = src.data() + src.size();
       p != end; ++p) {
    if (to_escape.find(*p) != StringPiece::npos) {
      dest->push_back('\\');
    }
    dest->push_back(*p);
  }
}

GoogleString CEscape(const StringPiece& src) {
  int len = src.length();
  const char* read = src.data();
  const char* end = read + len;
  int used = 0;
  char* dest = new char[len * 4 + 1];
  for (; read != end; ++read) {
    unsigned char ch = static_cast<unsigned char>(*read);
    switch (ch) {
      case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break;
      case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break;
      case '\t': dest[used++] = '\\'; dest[used++] = 't'; break;
      case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break;
      case '\'': dest[used++] = '\\'; dest[used++] = '\''; break;
      case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break;
      default:
        if (ch < 32 || ch >= 127) {
          base::snprintf(dest + used, 5, "\\%03o", ch);
          used += 4;
        } else {
          dest[used++] = ch;
        }
        break;
    }
  }
  GoogleString final(dest, used);
  delete[] dest;
  return final;
}

// From src/third_party/protobuf/src/google/protobuf/stubs/strutil.h
// but we don't need any other aspect of protobufs so we don't want to
// incur the link cost.
bool HasPrefixString(const StringPiece& str, const StringPiece& prefix) {
  return ((str.size() >= prefix.size()) &&
          (str.substr(0, prefix.size()) == prefix));
}

// From src/third_party/protobuf/src/google/protobuf/stubs/strutil.h
// but we don't need any other aspect of protobufs so we don't want to
// incur the link cost.
void UpperString(GoogleString* s) {
  GoogleString::iterator end = s->end();
  for (GoogleString::iterator i = s->begin(); i != end; ++i) {
    *i = UpperChar(*i);
  }
}

void LowerString(GoogleString* s) {
  GoogleString::iterator end = s->end();
  for (GoogleString::iterator i = s->begin(); i != end; ++i) {
    *i = LowerChar(*i);
  }
}

// ----------------------------------------------------------------------
// GlobalReplaceSubstring()
//    Replaces all instances of a substring in a string.  Returns the
//    number of replacements.
//
//    NOTE: The string pieces must not overlap s.
// ----------------------------------------------------------------------
int GlobalReplaceSubstring(const StringPiece& substring,
                           const StringPiece& replacement,
                           GoogleString* s) {
  CHECK(s != NULL);
  if (s->empty())
    return 0;
  GoogleString tmp;
  int num_replacements = 0;
  size_t pos = 0;
  for (size_t match_pos = s->find(substring.data(), pos, substring.length());
       match_pos != GoogleString::npos;
       pos = match_pos + substring.length(),
           match_pos = s->find(substring.data(), pos, substring.length())) {
    ++num_replacements;
    // Append the original content before the match.
    tmp.append(*s, pos, match_pos - pos);
    // Append the replacement for the match.
    tmp.append(replacement.begin(), replacement.end());
  }
  // Append the content after the last match. If no replacements were made, the
  // original string is left untouched.
  if (num_replacements > 0) {
    tmp.append(*s, pos, s->length() - pos);
    s->swap(tmp);
  }
  return num_replacements;
}

GoogleString JoinStringStar(const ConstStringStarVector& vector,
                            const StringPiece& delim) {
  GoogleString result;

  if (vector.size() > 0) {
    // Precompute resulting length so we can reserve() memory in one shot.
    int length = delim.size() * (vector.size() - 1);
    for (ConstStringStarVector::const_iterator iter = vector.begin();
         iter < vector.end(); ++iter) {
      length += (*iter)->size();
    }
    result.reserve(length);

    // Now combine everything.
    for (ConstStringStarVector::const_iterator iter = vector.begin();
         iter < vector.end(); ++iter) {
      if (iter != vector.begin()) {
        result.append(delim.data(), delim.size());
      }
      result.append(**iter);
    }
  }

  return result;
}

bool StringCaseEqual(const StringPiece& s1, const StringPiece& s2) {
  return ((s1.size() == s2.size()) && (0 == StringCaseCompare(s1, s2)));
}

bool StringCaseStartsWith(const StringPiece& str, const StringPiece& prefix) {
  return ((str.size() >= prefix.size()) &&
          (0 == StringCaseCompare(prefix, str.substr(0, prefix.size()))));
}

bool StringCaseEndsWith(const StringPiece& str, const StringPiece& suffix) {
  return ((str.size() >= suffix.size()) &&
          (0 == StringCaseCompare(suffix,
                                  str.substr(str.size() - suffix.size()))));
}

bool StringEqualConcat(const StringPiece& str, const StringPiece& first,
                       const StringPiece& second) {
  return (str.size() == first.size() + second.size()) &&
      str.starts_with(first) && str.ends_with(second);
}

void ParseShellLikeString(const StringPiece& input,
                          std::vector<GoogleString>* output) {
  output->clear();
  for (size_t index = 0; index < input.size();) {
    const char ch = input[index];
    // If we see a quoted section, treat it as a single item even if there are
    // spaces in it.
    if (ch == '"' || ch == '\'') {
      const char quote = ch;
      ++index;  // skip open quote
      output->push_back("");
      GoogleString& part = output->back();
      for (; index < input.size() && input[index] != quote; ++index) {
        if (input[index] == '\\') {
          ++index;  // skip backslash
          if (index >= input.size()) {
            break;
          }
        }
        part.push_back(input[index]);
      }
      ++index;  // skip close quote
    }
    // Without quotes, items are whitespace-separated.
    else if (!isspace(ch)) {
      output->push_back("");
      GoogleString& part = output->back();
      for (; index < input.size() && !isspace(input[index]); ++index) {
        part.push_back(input[index]);
      }
    }
    // Ignore whitespace (outside of quotes).
    else {
      ++index;
    }
  }
}

int CountSubstring(const StringPiece& text, const StringPiece& substring) {
  int number_of_occurrences = 0;
  size_t pos = 0;
  for (size_t match_pos = text.find(substring, pos);
       match_pos != StringPiece::npos;
       pos = match_pos + 1, match_pos = text.find(substring, pos)) {
    number_of_occurrences++;
  }
  return number_of_occurrences;
}

// In-place StringPiece whitespace trimming.  This mutates the StringPiece.
void TrimWhitespace(StringPiece* str) {
  while (str->size() && isspace(str->data()[0])) {
    str->remove_prefix(1);
  }

  int size = str->size();
  while (size && isspace(str->data()[size - 1])) {
    str->remove_suffix(1);
    size = str->size();
  }
}

void TrimLeadingWhitespace(StringPiece* str) {
  while (str->size() && isspace(str->data()[0])) {
    str->remove_prefix(1);
  }
}

// TODO(jmarantz): This is a very slow implementation.  But strncasecmp
// will fail test StringCaseTest.Locale.  If this shows up as a performance
// bottleneck then an SSE implementation would be better.
int StringCaseCompare(const StringPiece& s1, const StringPiece& s2) {
  for (int i = 0, n = std::min(s1.size(), s2.size()); i < n; ++i) {
    unsigned char c1 = UpperChar(s1[i]);
    unsigned char c2 = UpperChar(s2[i]);
    if (c1 < c2) {
      return -1;
    } else if (c1 > c2) {
      return 1;
    }
  }
  if (s1.size() < s2.size()) {
    return -1;
  } else if (s1.size() > s2.size()) {
    return 1;
  }
  return 0;
}

namespace {

// From Hypertext Transfer Protocol -- HTTP/1.1
// CTL            = <any US-ASCII control character
//                  (octets 0 - 31) and DEL (127)>
// SP             = <US-ASCII SP, space (32)>
// HT             = <US-ASCII HT, horizontal-tab (9)>
//        token          = 1*<any CHAR except CTLs or separators>
//        separators     = "(" | ")" | "<" | ">" | "@"
//                       | "," | ";" | ":" | "\" | <">
//                       | "/" | "[" | "]" | "?" | "="
//                       | "{" | "}" | SP | HT
const char separators[] = "()<>@,;:\\\"/[]?={}";

} // namespace

bool HasIllicitTokenCharacter(const StringPiece& str) {
  for (int i = 0, n = str.size(); i < n; ++i) {
    if (str[i] <= 32 || str[i] == 127) {
      return true;
    }
    for (int j = 0, m = STATIC_STRLEN(separators); j < m; ++j) {
      if (str[i] == separators[j]) {
        return true;
      }
    }
  }
  return false;
}

const StringPiece EmptyString::kEmptyString;

}  // namespace net_instaweb
<|endoftext|>


<commit_before><commit_msg>encode keys of PropertyMap when saving as XML<commit_after><|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////

#include <cppcoro/static_thread_pool.hpp>
#include <cppcoro/task.hpp>
#include <cppcoro/sync_wait.hpp>
#include <cppcoro/when_all.hpp>

#include <vector>
#include <thread>
#include <cassert>
#include <chrono>
#include <iostream>
#include <numeric>

#include "doctest/doctest.h"

TEST_SUITE_BEGIN("static_thread_pool");

TEST_CASE("construct/destruct")
{
	cppcoro::static_thread_pool threadPool;
	CHECK(threadPool.thread_count() == std::thread::hardware_concurrency());
}

TEST_CASE("construct/destruct to specific thread count")
{
	cppcoro::static_thread_pool threadPool{ 5 };
	CHECK(threadPool.thread_count() == 5);
}

TEST_CASE("run one task")
{
	cppcoro::static_thread_pool threadPool{ 2 };

	auto initiatingThreadId = std::this_thread::get_id();

	cppcoro::sync_wait([&]() -> cppcoro::task<void>
	{
		co_await threadPool.schedule();
		if (std::this_thread::get_id() == initiatingThreadId)
		{
			FAIL("schedule() did not switch threads");
		}
	}());
}

TEST_CASE("launch many tasks remotely")
{
	cppcoro::static_thread_pool threadPool;

	auto makeTask = [&]() -> cppcoro::task<>
	{
		co_await threadPool.schedule();
	};

	std::vector<cppcoro::task<>> tasks;
	for (std::uint32_t i = 0; i < 100; ++i)
	{
		tasks.push_back(makeTask());
	}

	cppcoro::sync_wait(cppcoro::when_all(std::move(tasks)));
}

cppcoro::task<std::uint64_t> sum_of_squares(
	std::uint32_t start,
	std::uint32_t end,
	cppcoro::static_thread_pool& tp)
{
	co_await tp.schedule();

	auto count = end - start;
	if (count > 1000)
	{
		auto half = start + count / 2;
		auto[a, b] = co_await cppcoro::when_all(
			sum_of_squares(start, half, tp),
			sum_of_squares(half, end, tp));
		co_return a + b;
	}
	else
	{
		std::uint64_t sum = 0;
		for (std::uint64_t x = start; x < end; ++x)
		{
			sum += x * x;
		}
		co_return sum;
	}
}

TEST_CASE("launch sub-task with many sub-tasks")
{
	using namespace std::chrono_literals;

	constexpr std::uint64_t limit = 1'000'000'000;

	cppcoro::static_thread_pool tp;

	// Wait for the thread-pool thread to start up.
	std::this_thread::sleep_for(1ms);

	auto start = std::chrono::high_resolution_clock::now();

	auto result = cppcoro::sync_wait(sum_of_squares(0, limit , tp));

	auto end = std::chrono::high_resolution_clock::now();

	std::uint64_t sum = 0;
	for (std::uint64_t i = 0; i < limit; ++i)
	{
		sum += i * i;
	}

	auto end2 = std::chrono::high_resolution_clock::now();

	auto toNs = [](auto time)
	{
		return std::chrono::duration_cast<std::chrono::nanoseconds>(time).count();
	};

	std::cout
		<< "multi-threaded version took " << toNs(end - start) << "ns\n"
		<< "single-threaded version took " << toNs(end2 - end) << "ns" << std::endl;

	CHECK(result == sum);
}

struct fork_join_operation
{
	std::atomic<std::size_t> m_count;
	std::experimental::coroutine_handle<> m_coro;

	fork_join_operation() : m_count(1) {}

	void begin_work() noexcept
	{
		m_count.fetch_add(1, std::memory_order_relaxed);
	}

	void end_work() noexcept
	{
		if (m_count.fetch_sub(1, std::memory_order_acq_rel) == 1)
		{
			m_coro.resume();
		}
	}

	bool await_ready() noexcept { return m_count.load(std::memory_order_acquire) == 1; }

	bool await_suspend(std::experimental::coroutine_handle<> coro) noexcept
	{
		m_coro = coro;
		return m_count.fetch_sub(1, std::memory_order_acq_rel) != 1;
	}

	void await_resume() noexcept {};
};

template<typename FUNC, typename RANGE, typename SCHEDULER>
cppcoro::task<void> for_each_async(SCHEDULER& scheduler, RANGE& range, FUNC func)
{
	using reference_type = decltype(*range.begin());

	// TODO: Use awaiter_t here instead. This currently assumes that
	// result of scheduler.schedule() doesn't have an operator co_await().
	using schedule_operation = decltype(scheduler.schedule());

	struct work_operation
	{
		fork_join_operation& m_forkJoin;
		FUNC& m_func;
		reference_type m_value;
		schedule_operation m_scheduleOp;

		work_operation(fork_join_operation& forkJoin, SCHEDULER& scheduler, FUNC& func, reference_type&& value)
			: m_forkJoin(forkJoin)
			, m_func(func)
			, m_value(static_cast<reference_type&&>(value))
			, m_scheduleOp(scheduler.schedule())
		{
		}

		bool await_ready() noexcept { return false; }

		CPPCORO_NOINLINE
		void await_suspend(std::experimental::coroutine_handle<> coro) noexcept
		{
			fork_join_operation& forkJoin = m_forkJoin;
			FUNC& func = m_func;
			reference_type value = static_cast<reference_type&&>(m_value);

			static_assert(std::is_same_v<decltype(m_scheduleOp.await_suspend(coro)), void>);

			forkJoin.begin_work();

			// Schedule the next iteration of the loop to run
			m_scheduleOp.await_suspend(coro);

			func(static_cast<reference_type&&>(value));

			forkJoin.end_work();
		}

		void await_resume() noexcept {}
	};

	fork_join_operation forkJoin;

	for (auto&& x : range)
	{
		co_await work_operation{
			forkJoin,
			scheduler,
			func,
			static_cast<decltype(x)>(x)
		};
	}

	co_await forkJoin;
}

std::uint64_t collatz_distance(std::uint64_t number)
{
	std::uint64_t count = 0;
	while (number > 1)
	{
		if (number % 2 == 0) number /= 2;
		else number = number * 3 + 1;
		++count;
	}
	return count;
}

TEST_CASE("for_each_async")
{
	cppcoro::static_thread_pool tp;

	{
		std::vector<std::uint64_t> values(1'000'000);
		std::iota(values.begin(), values.end(), 1);

		cppcoro::sync_wait([&]() -> cppcoro::task<>
		{
			auto start = std::chrono::high_resolution_clock::now();

			co_await for_each_async(tp, values, [](std::uint64_t& value)
			{
				value = collatz_distance(value);
			});

			auto end = std::chrono::high_resolution_clock::now();

			std::cout << "for_each_async of " << values.size()
				<< " took " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
				<< "us" << std::endl;

			for (std::size_t i = 0; i < 1'000'000; ++i)
			{
				CHECK(values[i] == collatz_distance(i + 1));
			}
		}());
	}

	{
		std::vector<std::uint64_t> values(1'000'000);
		std::iota(values.begin(), values.end(), 1);

		auto start = std::chrono::high_resolution_clock::now();

		for (auto&& x : values)
		{
			x = collatz_distance(x);
		}

		auto end = std::chrono::high_resolution_clock::now();

		std::cout << "single-threaded for loop of " << values.size()
			<< " took " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
			<< "us" << std::endl;
	}

}

TEST_SUITE_END();
<commit_msg>Make for_each_async() execute the first iteration onto scheduler.<commit_after>///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////

#include <cppcoro/static_thread_pool.hpp>
#include <cppcoro/task.hpp>
#include <cppcoro/sync_wait.hpp>
#include <cppcoro/when_all.hpp>

#include <vector>
#include <thread>
#include <cassert>
#include <chrono>
#include <iostream>
#include <numeric>

#include "doctest/doctest.h"

TEST_SUITE_BEGIN("static_thread_pool");

TEST_CASE("construct/destruct")
{
	cppcoro::static_thread_pool threadPool;
	CHECK(threadPool.thread_count() == std::thread::hardware_concurrency());
}

TEST_CASE("construct/destruct to specific thread count")
{
	cppcoro::static_thread_pool threadPool{ 5 };
	CHECK(threadPool.thread_count() == 5);
}

TEST_CASE("run one task")
{
	cppcoro::static_thread_pool threadPool{ 2 };

	auto initiatingThreadId = std::this_thread::get_id();

	cppcoro::sync_wait([&]() -> cppcoro::task<void>
	{
		co_await threadPool.schedule();
		if (std::this_thread::get_id() == initiatingThreadId)
		{
			FAIL("schedule() did not switch threads");
		}
	}());
}

TEST_CASE("launch many tasks remotely")
{
	cppcoro::static_thread_pool threadPool;

	auto makeTask = [&]() -> cppcoro::task<>
	{
		co_await threadPool.schedule();
	};

	std::vector<cppcoro::task<>> tasks;
	for (std::uint32_t i = 0; i < 100; ++i)
	{
		tasks.push_back(makeTask());
	}

	cppcoro::sync_wait(cppcoro::when_all(std::move(tasks)));
}

cppcoro::task<std::uint64_t> sum_of_squares(
	std::uint32_t start,
	std::uint32_t end,
	cppcoro::static_thread_pool& tp)
{
	co_await tp.schedule();

	auto count = end - start;
	if (count > 1000)
	{
		auto half = start + count / 2;
		auto[a, b] = co_await cppcoro::when_all(
			sum_of_squares(start, half, tp),
			sum_of_squares(half, end, tp));
		co_return a + b;
	}
	else
	{
		std::uint64_t sum = 0;
		for (std::uint64_t x = start; x < end; ++x)
		{
			sum += x * x;
		}
		co_return sum;
	}
}

TEST_CASE("launch sub-task with many sub-tasks")
{
	using namespace std::chrono_literals;

	constexpr std::uint64_t limit = 1'000'000'000;

	cppcoro::static_thread_pool tp;

	// Wait for the thread-pool thread to start up.
	std::this_thread::sleep_for(1ms);

	auto start = std::chrono::high_resolution_clock::now();

	auto result = cppcoro::sync_wait(sum_of_squares(0, limit , tp));

	auto end = std::chrono::high_resolution_clock::now();

	std::uint64_t sum = 0;
	for (std::uint64_t i = 0; i < limit; ++i)
	{
		sum += i * i;
	}

	auto end2 = std::chrono::high_resolution_clock::now();

	auto toNs = [](auto time)
	{
		return std::chrono::duration_cast<std::chrono::nanoseconds>(time).count();
	};

	std::cout
		<< "multi-threaded version took " << toNs(end - start) << "ns\n"
		<< "single-threaded version took " << toNs(end2 - end) << "ns" << std::endl;

	CHECK(result == sum);
}

struct fork_join_operation
{
	std::atomic<std::size_t> m_count;
	std::experimental::coroutine_handle<> m_coro;

	fork_join_operation() : m_count(1) {}

	void begin_work() noexcept
	{
		m_count.fetch_add(1, std::memory_order_relaxed);
	}

	void end_work() noexcept
	{
		if (m_count.fetch_sub(1, std::memory_order_acq_rel) == 1)
		{
			m_coro.resume();
		}
	}

	bool await_ready() noexcept { return m_count.load(std::memory_order_acquire) == 1; }

	bool await_suspend(std::experimental::coroutine_handle<> coro) noexcept
	{
		m_coro = coro;
		return m_count.fetch_sub(1, std::memory_order_acq_rel) != 1;
	}

	void await_resume() noexcept {};
};

template<typename FUNC, typename RANGE, typename SCHEDULER>
cppcoro::task<void> for_each_async(SCHEDULER& scheduler, RANGE& range, FUNC func)
{
	using reference_type = decltype(*range.begin());

	// TODO: Use awaiter_t here instead. This currently assumes that
	// result of scheduler.schedule() doesn't have an operator co_await().
	using schedule_operation = decltype(scheduler.schedule());

	struct work_operation
	{
		fork_join_operation& m_forkJoin;
		FUNC& m_func;
		reference_type m_value;
		schedule_operation m_scheduleOp;

		work_operation(fork_join_operation& forkJoin, SCHEDULER& scheduler, FUNC& func, reference_type&& value)
			: m_forkJoin(forkJoin)
			, m_func(func)
			, m_value(static_cast<reference_type&&>(value))
			, m_scheduleOp(scheduler.schedule())
		{
		}

		bool await_ready() noexcept { return false; }

		CPPCORO_NOINLINE
		void await_suspend(std::experimental::coroutine_handle<> coro) noexcept
		{
			fork_join_operation& forkJoin = m_forkJoin;
			FUNC& func = m_func;
			reference_type value = static_cast<reference_type&&>(m_value);

			static_assert(std::is_same_v<decltype(m_scheduleOp.await_suspend(coro)), void>);

			forkJoin.begin_work();

			// Schedule the next iteration of the loop to run
			m_scheduleOp.await_suspend(coro);

			func(static_cast<reference_type&&>(value));

			forkJoin.end_work();
		}

		void await_resume() noexcept {}
	};

	co_await scheduler.schedule();

	fork_join_operation forkJoin;

	for (auto&& x : range)
	{
		co_await work_operation{
			forkJoin,
			scheduler,
			func,
			static_cast<decltype(x)>(x)
		};
	}

	co_await forkJoin;
}

std::uint64_t collatz_distance(std::uint64_t number)
{
	std::uint64_t count = 0;
	while (number > 1)
	{
		if (number % 2 == 0) number /= 2;
		else number = number * 3 + 1;
		++count;
	}
	return count;
}

TEST_CASE("for_each_async")
{
	cppcoro::static_thread_pool tp;

	{
		std::vector<std::uint64_t> values(1'000'000);
		std::iota(values.begin(), values.end(), 1);

		cppcoro::sync_wait([&]() -> cppcoro::task<>
		{
			auto start = std::chrono::high_resolution_clock::now();

			co_await for_each_async(tp, values, [](std::uint64_t& value)
			{
				value = collatz_distance(value);
			});

			auto end = std::chrono::high_resolution_clock::now();

			std::cout << "for_each_async of " << values.size()
				<< " took " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
				<< "us" << std::endl;

			for (std::size_t i = 0; i < 1'000'000; ++i)
			{
				CHECK(values[i] == collatz_distance(i + 1));
			}
		}());
	}

	{
		std::vector<std::uint64_t> values(1'000'000);
		std::iota(values.begin(), values.end(), 1);

		auto start = std::chrono::high_resolution_clock::now();

		for (auto&& x : values)
		{
			x = collatz_distance(x);
		}

		auto end = std::chrono::high_resolution_clock::now();

		std::cout << "single-threaded for loop of " << values.size()
			<< " took " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
			<< "us" << std::endl;
	}

}

TEST_SUITE_END();
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll S;
ll M;

ll rev(ll n) {
  string s = to_string(n);
  while ((ll)s.size() < S) {
    s = '0' + s;
  }
  reverse(s.begin(), s.end());
  return stoll(s);
}

ll rev2(ll n) {
  string s = to_string(n);
  reverse(s.begin(), s.end());
  return stoll(s);
}

int main () {
  ll D;
  cin >> D;
  S = to_string(D).size();
  M = 1;
  for (auto i = 0; i < (S+1)/2; ++i) {
    M *= 10;
  }
  bool ok = false;
  ll base;
  for (auto i = 1; i < M; ++i) {
    // cerr << "i = " << i << ", rev(" << i << ") = " << rev(i) << endl;
    if (i + D == rev(i)) {
      base = i;
      ok = true;
      break;
    }
  }
  // cerr << "base = " << base << endl;
  if (ok) {
    ll ans = 0;
    for (auto i = 0; i < M * 10; ++i) {
      ll add = i + rev(i);
      ll t = base + add;
      if (t + D == rev2(t)) {
        ++ans;
      }
    }
    cout << ans << endl;
  } else {
    cout << 0 << endl;
  }
}
<commit_msg>tried F.cpp to 'F'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll S;
ll M;

ll rev(ll n) {
  string s = to_string(n);
  while ((ll)s.size() < S) {
    s = '0' + s;
  }
  reverse(s.begin(), s.end());
  return stoll(s);
}

ll rev2(ll n) {
  string s = to_string(n);
  reverse(s.begin(), s.end());
  return stoll(s);
}

int main () {
  ll D;
  cin >> D;
  S = to_string(D).size();
  M = 1;
  for (auto i = 0; i < (S+1)/2; ++i) {
    M *= 10;
  }
  bool ok = false;
  ll base;
  for (auto i = 1; i < M; ++i) {
    // cerr << "i = " << i << ", rev(" << i << ") = " << rev(i) << endl;
    if (i + D == rev(i)) {
      base = i;
      ok = true;
      break;
    }
  }
  // cerr << "base = " << base << endl;
  set<ll> S;
  if (ok) {
    ll ans = 0;
    for (auto i = 0; i < M * 10; ++i) {
      ll add = i + rev(i);
      if (S.find(add) == S.end()) {
        S.insert(add);
        ll t = base + add;
        if (t + D == rev2(t)) {
          ++ans;
        }
      }
    }
    cout << ans << endl;
  } else {
    cout << 0 << endl;
  }
}
<|endoftext|>


<commit_before>// Copyright 2018 The gVisor Authors.
//
// 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.

// This test verifies that fork(2) in a signal handler will correctly
// restore floating point state after the signal handler returns in both
// the child and parent.
#include <sys/time.h>

#include "gtest/gtest.h"
#include "test/util/logging.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"

namespace gvisor {
namespace testing {

namespace {

#ifdef __x86_64__
#define GET_XMM(__var, __xmm) \
  asm volatile("movq %%" #__xmm ", %0" : "=r"(__var))
#define SET_XMM(__var, __xmm) asm volatile("movq %0, %%" #__xmm : : "r"(__var))
#define GET_FP0(__var) GET_XMM(__var, xmm0)
#define SET_FP0(__var) SET_XMM(__var, xmm0)
#elif __aarch64__
#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)
#define GET_FPREG(var, regname) \
  asm volatile("str " __stringify(regname) ", %0" : "=m"(var))
#define SET_FPREG(var, regname) \
  asm volatile("ldr " __stringify(regname) ", %0" : "=m"(var))
#define GET_FP0(var) GET_FPREG(var, d0)
#define SET_FP0(var) SET_FPREG(var, d0)
#endif

#define DEFAULT_MXCSR 0x1f80

int parent, child;

void sigusr1(int s, siginfo_t* siginfo, void* _uc) {
  // Fork and clobber %xmm0. The fpstate should be restored by sigreturn(2)
  // in both parent and child.
  child = fork();
  TEST_CHECK_MSG(child >= 0, "fork failed");

  uint64_t val = SIGUSR1;
  SET_FP0(val);
  uint64_t got;
  GET_FP0(got);
  TEST_CHECK_MSG(val == got, "Basic FP check failed in sigusr1()");

#ifdef __x86_64
  uint32_t mxcsr;
  __asm__("STMXCSR %0" : "=m"(mxcsr));
  TEST_CHECK_MSG(mxcsr == DEFAULT_MXCSR, "Unexpected mxcsr");
#endif
}

TEST(FPSigTest, Fork) {
  parent = getpid();
  pid_t parent_tid = gettid();

  struct sigaction sa = {};
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sa.sa_sigaction = sigusr1;
  ASSERT_THAT(sigaction(SIGUSR1, &sa, nullptr), SyscallSucceeds());

  // The amd64 ABI specifies that the XMM register set is caller-saved. This
  // implies that if there is any function call between SET_XMM and GET_XMM the
  // compiler might save/restore xmm0 implicitly. This defeats the entire
  // purpose of the test which is to verify that fpstate is restored by
  // sigreturn(2).
  //
  // This is the reason why 'tgkill(getpid(), gettid(), SIGUSR1)' is implemented
  // in inline assembly below.
  //
  // If the OS is broken and registers are clobbered by the child, using tgkill
  // to signal the current thread increases the likelihood that this thread will
  // be the one clobbered.

  uint64_t expected = 0xdeadbeeffacefeed;
  SET_FP0(expected);

#ifdef __x86_64__
  asm volatile(
      "movl %[killnr], %%eax;"
      "movl %[parent], %%edi;"
      "movl %[tid], %%esi;"
      "movl %[sig], %%edx;"
      "syscall;"
      :
      : [ killnr ] "i"(__NR_tgkill), [ parent ] "rm"(parent),
        [ tid ] "rm"(parent_tid), [ sig ] "i"(SIGUSR1)
      : "rax", "rdi", "rsi", "rdx",
        // Clobbered by syscall.
        "rcx", "r11");
#elif __aarch64__
  asm volatile(
      "mov x8, %0\n"
      "mov x0, %1\n"
      "mov x1, %2\n"
      "mov x2, %3\n"
      "svc #0\n" ::"r"(__NR_tgkill),
      "r"(parent), "r"(parent_tid), "r"(SIGUSR1));
#endif

  uint64_t got;
  GET_FP0(got);

  if (getpid() == parent) {  // Parent.
    int status;
    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  }

  // TEST_CHECK_MSG since this may run in the child.
  TEST_CHECK_MSG(expected == got, "Bad xmm0 value");

  if (getpid() != parent) {  // Child.
    _exit(0);
  }
}

#ifdef __x86_64__
TEST(FPSigTest, ForkWithZeroMxcsr) {
  parent = getpid();
  pid_t parent_tid = gettid();

  struct sigaction sa = {};
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sa.sa_sigaction = sigusr1;
  ASSERT_THAT(sigaction(SIGUSR1, &sa, nullptr), SyscallSucceeds());

  // The control bits of the MXCSR register are callee-saved (preserved across
  // calls), while the status bits are caller-saved (not preserved).
  uint32_t expected = 0, origin;
  __asm__("STMXCSR %0" : "=m"(origin));
  __asm__("LDMXCSR %0" : : "m"(expected));

  asm volatile(
      "movl %[killnr], %%eax;"
      "movl %[parent], %%edi;"
      "movl %[tid], %%esi;"
      "movl %[sig], %%edx;"
      "syscall;"
      :
      : [killnr] "i"(__NR_tgkill), [parent] "rm"(parent),
        [tid] "rm"(parent_tid), [sig] "i"(SIGUSR1)
      : "rax", "rdi", "rsi", "rdx",
        // Clobbered by syscall.
        "rcx", "r11");

  uint32_t got;
  __asm__("STMXCSR %0" : "=m"(got));
  __asm__("LDMXCSR %0" : : "m"(origin));

  if (getpid() == parent) {  // Parent.
    int status;
    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  }

  // TEST_CHECK_MSG since this may run in the child.
  TEST_CHECK_MSG(expected == got, "Bad mxcsr value");

  if (getpid() != parent) {  // Child.
    _exit(0);
  }
}
#endif

}  // namespace

}  // namespace testing
}  // namespace gvisor
<commit_msg>Skip fpsig_fork_test on ptrace platform.<commit_after>// Copyright 2018 The gVisor Authors.
//
// 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.

// This test verifies that fork(2) in a signal handler will correctly
// restore floating point state after the signal handler returns in both
// the child and parent.
#include <sys/time.h>

#include "gtest/gtest.h"
#include "test/util/logging.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"

namespace gvisor {
namespace testing {

namespace {

#ifdef __x86_64__
#define GET_XMM(__var, __xmm) \
  asm volatile("movq %%" #__xmm ", %0" : "=r"(__var))
#define SET_XMM(__var, __xmm) asm volatile("movq %0, %%" #__xmm : : "r"(__var))
#define GET_FP0(__var) GET_XMM(__var, xmm0)
#define SET_FP0(__var) SET_XMM(__var, xmm0)
#elif __aarch64__
#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)
#define GET_FPREG(var, regname) \
  asm volatile("str " __stringify(regname) ", %0" : "=m"(var))
#define SET_FPREG(var, regname) \
  asm volatile("ldr " __stringify(regname) ", %0" : "=m"(var))
#define GET_FP0(var) GET_FPREG(var, d0)
#define SET_FP0(var) SET_FPREG(var, d0)
#endif

#define DEFAULT_MXCSR 0x1f80

int parent, child;

void sigusr1(int s, siginfo_t* siginfo, void* _uc) {
  // Fork and clobber %xmm0. The fpstate should be restored by sigreturn(2)
  // in both parent and child.
  child = fork();
  TEST_CHECK_MSG(child >= 0, "fork failed");

  uint64_t val = SIGUSR1;
  SET_FP0(val);
  uint64_t got;
  GET_FP0(got);
  TEST_CHECK_MSG(val == got, "Basic FP check failed in sigusr1()");

#ifdef __x86_64
  uint32_t mxcsr;
  __asm__("STMXCSR %0" : "=m"(mxcsr));
  TEST_CHECK_MSG(mxcsr == DEFAULT_MXCSR, "Unexpected mxcsr");
#endif
}

TEST(FPSigTest, Fork) {
  // NOTE(b/238773725): This test fails on ptrace platform due to a kernel bug.
  SKIP_IF(GvisorPlatform() == Platform::kPtrace);
  parent = getpid();
  pid_t parent_tid = gettid();

  struct sigaction sa = {};
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sa.sa_sigaction = sigusr1;
  ASSERT_THAT(sigaction(SIGUSR1, &sa, nullptr), SyscallSucceeds());

  // The amd64 ABI specifies that the XMM register set is caller-saved. This
  // implies that if there is any function call between SET_XMM and GET_XMM the
  // compiler might save/restore xmm0 implicitly. This defeats the entire
  // purpose of the test which is to verify that fpstate is restored by
  // sigreturn(2).
  //
  // This is the reason why 'tgkill(getpid(), gettid(), SIGUSR1)' is implemented
  // in inline assembly below.
  //
  // If the OS is broken and registers are clobbered by the child, using tgkill
  // to signal the current thread increases the likelihood that this thread will
  // be the one clobbered.

  uint64_t expected = 0xdeadbeeffacefeed;
  SET_FP0(expected);

#ifdef __x86_64__
  asm volatile(
      "movl %[killnr], %%eax;"
      "movl %[parent], %%edi;"
      "movl %[tid], %%esi;"
      "movl %[sig], %%edx;"
      "syscall;"
      :
      : [ killnr ] "i"(__NR_tgkill), [ parent ] "rm"(parent),
        [ tid ] "rm"(parent_tid), [ sig ] "i"(SIGUSR1)
      : "rax", "rdi", "rsi", "rdx",
        // Clobbered by syscall.
        "rcx", "r11");
#elif __aarch64__
  asm volatile(
      "mov x8, %0\n"
      "mov x0, %1\n"
      "mov x1, %2\n"
      "mov x2, %3\n"
      "svc #0\n" ::"r"(__NR_tgkill),
      "r"(parent), "r"(parent_tid), "r"(SIGUSR1));
#endif

  uint64_t got;
  GET_FP0(got);

  if (getpid() == parent) {  // Parent.
    int status;
    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  }

  // TEST_CHECK_MSG since this may run in the child.
  TEST_CHECK_MSG(expected == got, "Bad xmm0 value");

  if (getpid() != parent) {  // Child.
    _exit(0);
  }
}

#ifdef __x86_64__
TEST(FPSigTest, ForkWithZeroMxcsr) {
  // NOTE(b/238773725): This test fails on ptrace platform due to a kernel bug.
  SKIP_IF(GvisorPlatform() == Platform::kPtrace);
  parent = getpid();
  pid_t parent_tid = gettid();

  struct sigaction sa = {};
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sa.sa_sigaction = sigusr1;
  ASSERT_THAT(sigaction(SIGUSR1, &sa, nullptr), SyscallSucceeds());

  // The control bits of the MXCSR register are callee-saved (preserved across
  // calls), while the status bits are caller-saved (not preserved).
  uint32_t expected = 0, origin;
  __asm__("STMXCSR %0" : "=m"(origin));
  __asm__("LDMXCSR %0" : : "m"(expected));

  asm volatile(
      "movl %[killnr], %%eax;"
      "movl %[parent], %%edi;"
      "movl %[tid], %%esi;"
      "movl %[sig], %%edx;"
      "syscall;"
      :
      : [killnr] "i"(__NR_tgkill), [parent] "rm"(parent),
        [tid] "rm"(parent_tid), [sig] "i"(SIGUSR1)
      : "rax", "rdi", "rsi", "rdx",
        // Clobbered by syscall.
        "rcx", "r11");

  uint32_t got;
  __asm__("STMXCSR %0" : "=m"(got));
  __asm__("LDMXCSR %0" : : "m"(origin));

  if (getpid() == parent) {  // Parent.
    int status;
    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  }

  // TEST_CHECK_MSG since this may run in the child.
  TEST_CHECK_MSG(expected == got, "Bad mxcsr value");

  if (getpid() != parent) {  // Child.
    _exit(0);
  }
}
#endif

}  // namespace

}  // namespace testing
}  // namespace gvisor
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

string rep(string c, int n) {
  string ans = "";
  for (auto i = 0; i < n; ++i) {
    ans += c;
  }
  return ans;
}

string repa(int n) {
  return rep("A", n);
}

string repb(int n) {
  return rep("B", n);
}

ll calc_K(ll A, ll B) {
  ll ub = 500000010;
  ll lb = 0;
  while (ub - lb > 1) {
    ll t = (ub+lb)/2;
    if (A <= (B+1) * t && B <= (A+1) * t) {
      ub = t;
    } else {
      lb = t;
    }
  }
  return ub;
}

string f(ll A, ll B, ll C, ll D) {
  ll K = calc_K(A, B);
  cerr << "K = " << K << endl;
  ll ub = A+B;
  ll lb = -1;
  while (ub - lb > 1) {
    ll t = (ub+lb)/2;
    ll b = t/(K+1);
    ll a = t - b;
    ll rema = A - a;
    ll remb = B - b;
    if (remb <= (rema+1) * K) {
      ub = t;
    } else {
      lb = t;
    }
  }
  ll L = ub;
  cerr << "L = " << L << endl;
  if (D <= L) {
    int back = (C/(K+1) - 1) * (K+1);
    C -= back;
    D -= back;
    string X = rep(repa(K) + "B", 100);
    return X.substr(C-1, D-C+1);
  } else if (C > L) {
    C = A+B+1-C;
    D = A+B+1-D;
    int back = (D/(K+1) - 1) * (K+1);
    C -= back;
    D -= back;
    cerr << "C = " << C << ", D = " << D << endl;
    string X = rep(repb(K) + "A", 100);
    cerr << "X = " << X << endl;
    string Y = X.substr(D-1, C-D+1);
    cerr << "Y = " << X << endl;
    reverse(Y.begin(), Y.end());
    return Y;
  } else {
    int rema = L%(K+1);
    int remb = (A+B-L)%(K+1);
    string X = repa(rema) + repb(remb);
    X = rep(repa(K) + "B", 100) + X + rep("A" + repb(K), 100);
    int back = L - (100 * (K+1) + rema);
    C -= back;
    D -= back;
    return X.substr(C-1, D-C+1);
  }
}

int main () {
  int Q;
  cin >> Q;
  int A[1010], B[1010], C[1010], D[1010];
  for (auto i = 0; i < Q; ++i) {
    cin >> A[i] >> B[i] >> C[i] >> D[i];
  }
  for (auto i = 0; i < Q; ++i) {
    string X = f(A[i], B[i], C[i], D[i]);
    cout << X << endl;
  }
}
<commit_msg>tried D.cpp to 'D'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

string rep(string c, int n) {
  string ans = "";
  for (auto i = 0; i < n; ++i) {
    ans += c;
  }
  return ans;
}

string repa(int n) {
  return rep("A", n);
}

string repb(int n) {
  return rep("B", n);
}

ll calc_K(ll A, ll B) {
  ll ub = 500000010;
  ll lb = 0;
  while (ub - lb > 1) {
    ll t = (ub+lb)/2;
    if (A <= (B+1) * t && B <= (A+1) * t) {
      ub = t;
    } else {
      lb = t;
    }
  }
  return ub;
}

string f(ll A, ll B, ll C, ll D) {
  ll K = calc_K(A, B);
  cerr << "K = " << K << endl;
  ll ub = A+B;
  ll lb = -1;
  while (ub - lb > 1) {
    ll t = (ub+lb)/2;
    ll b = t/(K+1);
    ll a = t - b;
    ll rema = A - a;
    ll remb = B - b;
    if (remb <= (rema+1) * K) {
      ub = t;
    } else {
      lb = t;
    }
  }
  ll L = ub;
  cerr << "L = " << L << endl;
  if (D <= L) {
    int back = (C/(K+1) - 1) * (K+1);
    C -= back;
    D -= back;
    string X = rep(repa(K) + "B", 100);
    return X.substr(C-1, D-C+1);
  } else if (C > L) {
    C = A+B+1-C;
    D = A+B+1-D;
    int back = (D/(K+1) - 1) * (K+1);
    C -= back;
    D -= back;
    cerr << "C = " << C << ", D = " << D << endl;
    string X = rep(repb(K) + "A", 100);
    cerr << "X = " << X << endl;
    string Y = X.substr(D-1, C-D+1);
    cerr << "Y = " << X << endl;
    reverse(Y.begin(), Y.end());
    return Y;
  } else {
    int rema = L%(K+1);
    int remb = (A+B-L)%(K+1);
    string X = repa(rema) + repb(remb);
    X = rep(repa(K) + "B", 100) + X + rep("A" + repb(K), 100);
    cerr << "X = " << X << endl;
    int back = L - (100 * (K+1) + rema);
    C -= back;
    D -= back;
    cerr << "C = " << C << ", D = " << D << endl;
    return X.substr(C-1, D-C+1);
  }
}

int main () {
  int Q;
  cin >> Q;
  int A[1010], B[1010], C[1010], D[1010];
  for (auto i = 0; i < Q; ++i) {
    cin >> A[i] >> B[i] >> C[i] >> D[i];
  }
  for (auto i = 0; i < Q; ++i) {
    string X = f(A[i], B[i], C[i], D[i]);
    cout << X << endl;
  }
}
<|endoftext|>


<commit_before>
/**
 * File    : A.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-2-24 20:50:09
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll N;

int main()
{
  cin >> N;
  if (N <= 9)
  {
    cout << N << endl;
    return 0;
  }
  string X = to_string(N);
  bool all_nine = true;
  for (auto x : X)
  {
    if (x != '9')
    {
      all_nine = false;
      break;
    }
  }
  int ans = 0;
  if (all_nine)
  {
    for (auto x : X)
    {
      ans += 9;
    }
  } else {
    int s = X.size();
    for (auto i = 0; i < s; i++)
    {
      if (i == 0)
      {
        ans += X[i] - '0' - 1;
      } else {
        ans += 9;
      }
    }
  }
  cout << ans << endl;
  return 0;
}<commit_msg>submit A.cpp to 'A - Digit Sum 2' (agc021) [C++14 (Clang 3.8.0)]<commit_after>
/**
 * File    : A.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-2-24 20:50:09
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll N;

int main()
{
  cin >> N;
  string X = to_string(N);
  bool all_nine = true;
  for (auto x : X)
  {
    if (x != '9')
    {
      all_nine = false;
      break;
    }
  }
  int ans = 0;
  for (auto x : X)
  {
    ans += x - '0';
  }
  int tans = 0;
  if (all_nine)
  {
    for (auto x : X)
    {
      tans += 9;
    }
  } else {
    int s = X.size();
    for (auto i = 0; i < s; i++)
    {
      if (i == 0)
      {
        tans += X[i] - '0' - 1;
      } else {
        tans += 9;
      }
    }
  }
  cout << max(ans, tans) << endl;
  return 0;
}<|endoftext|>


<commit_before>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-14 21:58:19
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int H, W;
string S[20];
typedef tuple<int, int> P;
vector<vector<P>> pairs;

void dfs(vector<P> temp, vector<bool> used, int R)
{
  if (R%2 == 1)
  {
    for (auto i = 0; i < H; i++)
    {
      if (!used[i])
      {
        vector<bool> n_used = used;
        n_used[i] = true;
        dfs(temp, n_used, R - 1);
      }
    }
    return;
  }
  if (R == 0)
  {
    pairs.push_back(temp);
    return;
  }
  assert(R >= 2);
  int first = -1;
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      first = i;
      used[i] = true;
      break;
    }
  }
  assert(first >= 0);
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      vector<bool> n_used = used;
      n_used[i] = true;
      vector<P> n_temp = temp;
      n_temp.push_back(P(first, i));
      dfs(n_temp, n_used, R - 2);
    }
  }
}

vector<string> make_strings(vector<P>& V)
{
  vector<int> X;
  int N = V.size();
  for (auto i = 0; i < N; i++)
  {
    X.push_back(get<0>(V[i]));
  }
  for (auto i = N-1; i >= 0; i--)
  {
    X.push_back(get<1>(V[i]));
  }
  vector<string> res;
  for (auto j = 0; j < W; j++)
  {
    string str = "";
    for (auto i : X)
    {
      string t = {S[i][j]};
      str += t;
    }
    res.push_back(str);
  }
  return res;
}

vector<string> reverse_strings(const vector<string>& V)
{
  vector<string> res;
  for (auto x : V)
  {
    reverse(x.begin(), x.end());
    res.push_back(x);
  }
  return res;
}

int main()
{
  cin >> H >> W;
  for (auto i = 0; i < H; i++)
  {
    cin >> S[i];
  }
  vector<P> emp_P;
  vector<bool> emp_used = vector<bool>(H, false);
  dfs(emp_P, emp_used, H);
#if DEBUG == 1
  cerr << "pairs.size() = " << pairs.size() << endl;
  if (pairs.size() < 5)
  {
    for (auto V : pairs)
    {
      for (auto e : V)
      {
        cerr << "[" << get<0>(e) << ", " << get<1>(e) << "] ";
      }
      cerr << endl;
    }
  }
#endif
  for (auto e : pairs)
  {
    vector<string> V1 = make_strings(e);
    vector<string> V2 = reverse_strings(V1);
    assert((int)V1.size() == W && (int)V2.size() == W);
#if DEBUG == 1
    if (pairs.size() < 5)
    {
      for (auto x : V1)
      {
        cerr << x << " ";
      }
      cerr << endl;
      for (auto x : V2)
      {
        cerr << x << " ";
      }
      cerr << endl;
    }
#endif
    vector<bool> used = vector<bool>(W, false);
    bool found = true;
    bool has_center = (W%2 == 0);
    for (auto i = 0; i < W; i++)
    {
      if (used[i])
      {
        continue;
      }
      found = false;
      used[i] = true;
      for (auto j = i + 1; j < W; j++)
      {
        if (!used[j] && V1[i] == V2[j])
        {
          used[j] = true;
          found = true;
          break;
        }
      }
      if (!has_center && V1[i] == V2[i])
      {
        has_center = true;
        found = true;
      }
      if (!found)
      {
        break;
      }
    }
    if (found)
    {
      cout << "YES" << endl;
      return 0;
    }
  }
  // assert(false);
  cout << "NO" << endl;
}<commit_msg>tried E.cpp to 'E'<commit_after>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-14 21:58:19
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int H, W;
string S[20];
typedef tuple<int, int> P;
vector<vector<P>> pairs;

void dfs(vector<P> temp, vector<bool> used, int R)
{
  if (R%2 == 1)
  {
    for (auto i = 0; i < H; i++)
    {
      if (!used[i])
      {
        vector<bool> n_used = used;
        n_used[i] = true;
        vector<P> n_temp = temp;
        n_temp.push_back(P(i, i));
        dfs(n_temp, n_used, R - 1);
      }
    }
    return;
  }
  if (R == 0)
  {
    reverse(temp.begin(), temp.end());
    pairs.push_back(temp);
    return;
  }
  assert(R >= 2);
  int first = -1;
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      first = i;
      used[i] = true;
      break;
    }
  }
  assert(first >= 0);
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      vector<bool> n_used = used;
      n_used[i] = true;
      vector<P> n_temp = temp;
      n_temp.push_back(P(first, i));
      dfs(n_temp, n_used, R - 2);
    }
  }
}

vector<string> make_strings(vector<P>& V)
{
  vector<int> X;
  int N = V.size();
  for (auto i = 0; i < N; i++)
  {
    X.push_back(get<0>(V[i]));
  }
  for (auto i = N-1; i >= 0; i--)
  {
    if (i == N-1 && get<0>(V[i]) == get<1>(V[i]))
    {
      continue;
    }
    X.push_back(get<1>(V[i]));
  }
  vector<string> res;
  for (auto j = 0; j < W; j++)
  {
    string str = "";
    for (auto i : X)
    {
      string t = {S[i][j]};
      str += t;
    }
    res.push_back(str);
  }
  return res;
}

vector<string> reverse_strings(const vector<string>& V)
{
  vector<string> res;
  for (auto x : V)
  {
    reverse(x.begin(), x.end());
    res.push_back(x);
  }
  return res;
}

int main()
{
  cin >> H >> W;
  for (auto i = 0; i < H; i++)
  {
    cin >> S[i];
  }
  vector<P> emp_P;
  vector<bool> emp_used = vector<bool>(H, false);
  dfs(emp_P, emp_used, H);
#if DEBUG == 1
  cerr << "pairs.size() = " << pairs.size() << endl;
  if (pairs.size() < 5)
  {
    for (auto V : pairs)
    {
      for (auto e : V)
      {
        cerr << "[" << get<0>(e) << ", " << get<1>(e) << "] ";
      }
      cerr << endl;
    }
  }
#endif
  for (auto e : pairs)
  {
    vector<string> V1 = make_strings(e);
    vector<string> V2 = reverse_strings(V1);
    assert((int)V1.size() == W && (int)V2.size() == W);
#if DEBUG == 1
    if (pairs.size() < 5)
    {
      for (auto x : V1)
      {
        cerr << x << " ";
      }
      cerr << endl;
      for (auto x : V2)
      {
        cerr << x << " ";
      }
      cerr << endl;
    }
#endif
    vector<bool> used = vector<bool>(W, false);
    bool found = true;
    bool has_center = (W%2 == 0);
    for (auto i = 0; i < W; i++)
    {
      if (used[i])
      {
        continue;
      }
      found = false;
      used[i] = true;
      for (auto j = i + 1; j < W; j++)
      {
        if (!used[j] && V1[i] == V2[j])
        {
          used[j] = true;
          found = true;
          break;
        }
      }
      if (!has_center && V1[i] == V2[i])
      {
        has_center = true;
        found = true;
      }
      if (!found)
      {
        break;
      }
    }
    if (found)
    {
      //cout << "YES" << endl;
      return 0;
    }
  }
  //cout << "NO" << endl;
}<|endoftext|>


<commit_before>
#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "BitFunnel/Index/Factories.h"
#include "BitFunnel/Index/IConfiguration.h"
#include "BitFunnel/Index/IIngestor.h"
#include "ChunkTaskProcessor.h"
#include "gtest/gtest.h"

namespace BitFunnel
{
    namespace ChunkTaskProcessorUnitTest
    {
        // Sets up and configures a `ChunkTaskProcessor` (according to
        // `filePaths` and `ngramSize`), and passes that task processor to the
        // `test` function, which is intended to contain all of the test logic
        // (i.e., the `ASSERT`s and `EXPECT`s that verify behavior of the task
        // processor.) See tests below for examples.
        static void RunTest(
            std::vector<std::string> const & filePaths,
            size_t ngramSize,
            std::function<void(ChunkTaskProcessor &)> const & test)
        {
            const std::unique_ptr<IConfiguration>
                configuration(Factories::CreateConfiguration(ngramSize));
            const std::unique_ptr<IIngestor> ingestor(
                Factories::CreateIngestor());

            ChunkTaskProcessor processor(filePaths, *configuration, *ingestor);

            test(processor);
        }

        TEST(ChunkTaskProcessorUnitTest, Trivial)
        {
            // TODO: What's the Bing style for lambda brace placement?
            RunTest({}, 1, [](ChunkTaskProcessor & processor)
            {
                // Throw when `taskId` is the size of the empty array (i.e.,
                // protect against boundary condition errors).
                EXPECT_ANY_THROW(processor.ProcessTask(0));
            });
        }

        TEST(ChunkTaskProcessorUnitTest, TestBadTaskIds)
        {
            const std::vector<std::string> filePaths { "fileThatDoesNotExist" };
            RunTest(filePaths, 3, [](ChunkTaskProcessor & processor) {
                // Throw when we try to read a file with an invalid name.
                EXPECT_ANY_THROW(processor.ProcessTask(0));

                // Throw for generic out-of-bounds errors.
                EXPECT_ANY_THROW(processor.ProcessTask(3));

                // Throw for negative numbers (in this case they get converted
                // to really big positive numbers, but we want to protect
                // against this no matter what).
                // This test broke the build and I'm commenting it out so that I
                // can build. TODO: figure out what this test was doing and fix
                // it for real. Note that I'm using break the build to mean
                // it broke the build compilation, not that the test fails.
                // EXPECT_ANY_THROW(processor.ProcessTask(-1));

                // Throw when `taskId` is the size of the array (i.e., protect
                // against boundary condition errors).
                EXPECT_ANY_THROW(processor.ProcessTask(1));
            });
        }
    }
}
<commit_msg>Fix MSVC compilation errors.<commit_after>
#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "BitFunnel/Index/Factories.h"
#include "BitFunnel/Index/IConfiguration.h"
#include "BitFunnel/Index/IIngestor.h"
#include "ChunkTaskProcessor.h"
#include "gtest/gtest.h"

namespace BitFunnel
{
    namespace ChunkTaskProcessorUnitTest
    {
        // Sets up and configures a `ChunkTaskProcessor` (according to
        // `filePaths` and `ngramSize`), and passes that task processor to the
        // `test` function, which is intended to contain all of the test logic
        // (i.e., the `ASSERT`s and `EXPECT`s that verify behavior of the task
        // processor.) See tests below for examples.
        static void RunTest(
            std::vector<std::string> const & filePaths,
            size_t ngramSize,
            std::function<void(ChunkTaskProcessor &)> const & test)
        {
            const std::unique_ptr<IConfiguration>
                configuration(Factories::CreateConfiguration(ngramSize));
            const std::unique_ptr<IIngestor> ingestor(
                Factories::CreateIngestor());

            ChunkTaskProcessor processor(filePaths, *configuration, *ingestor);

            test(processor);
        }

        TEST(ChunkTaskProcessorUnitTest, Trivial)
        {
            // TODO: What's the Bing style for lambda brace placement?
            RunTest({}, 1, [](ChunkTaskProcessor & processor)
            {
                // Throw when `taskId` is the size of the empty array (i.e.,
                // protect against boundary condition errors).
                EXPECT_ANY_THROW(processor.ProcessTask(0));
            });
        }

        TEST(ChunkTaskProcessorUnitTest, TestBadTaskIds)
        {
            const std::vector<std::string> filePaths { "fileThatDoesNotExist" };
            RunTest(filePaths, 3, [](ChunkTaskProcessor & processor) {
                // Throw when we try to read a file with an invalid name.
                EXPECT_ANY_THROW(processor.ProcessTask(0));

                // Throw for generic out-of-bounds errors.
                EXPECT_ANY_THROW(processor.ProcessTask(3));

                // Throw for negative numbers. On most platforms, this will end
                // up being a really large number. NOTE: Clang and GCC don't
                // warn about this case, but MSVC will error out because of the
                // signed/unsigned conversion.
#ifndef _MSC_VER
                EXPECT_ANY_THROW(processor.ProcessTask(-1));
#endif

                // Throw when `taskId` is the size of the array (i.e., protect
                // against boundary condition errors).
                EXPECT_ANY_THROW(processor.ProcessTask(1));
            });
        }
    }
}
<|endoftext|>