<commit_before>#include "twister.h"

const unsigned CYCLE = 0x100;

const unsigned C_TRANS_ = 0xff;
int block_units[][0x10] = {
	0x74, 0x63, 0x69, 0x67, 0x72, 0x68, 0x6e, 0x6c, 0x61, 0x67, 0x74, 0x6c, 0x69, 0x73, 0x61, 0x61, 0x6f, 0x6d, 0x6f, 0x72, 0x6e, 0x72, 0x69, 0x6d, 0x6e, 0x6e, 0x65, 0x74, 0x72, 0x6e, 0x6b, 0x73, 0x61, 0x6f, 0x65, 0x69, 0x73, 0x64, 0x6c, 0x65, 0x69, 0x6b, 0x68, 0x68, 0x68, 0x65, 0x72, 0x64, 0x66, 0x74, 0x61, 0x73, 0x6f, 0x69, 0x65, 0x74, 0x69, 0x68, 0x6e, 0x65, 0x62, 0x74, 0x6b, 0x65
  };
int triad_units[][0x03] = {
	0x74, 0x68, 0x65, 0x74, 0x68, 0x61, 0x65, 0x74, 0x68, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x65, 0x68, 0x61, 0x74, 0x68, 0x69, 0x73
};
const int transition_seq[] = { 0xce, 0xab, 0xdf, 0xcf, 0xee,
                               0xcf, 0xad, 0xdf, 0xff, 0xce,
                               0x32, 0x40, 0xd3, 0x27, 0x82,
                               0xda, 0xee, 0xff, 0xfc, 0xbf,
                               0x1c, 0x90, 0x13, 0x4a, 0xa5,
                               0xe0, 0x21, 0x9f, 0xe1, 0xc6,
                               0xe4, 0x38, 0x1f, 0x60, 0x24,
                               0x0c, 0x35, 0x51, 0x32, 0xcf,
                               0x12, 0x9a, 0x30, 0x44, 0x72,
                               0x04, 0x1c, 0x52, 0xca, 0xdf,
                               0x12, 0x0b, 0x30, 0xa0, 0x1e,
                               0xf2, 0xca, 0xa2, 0x51, 0xc6,
                               0xcb, 0xbd, 0xba, 0xac, 0xdf,
                               0xdf, 0xde, 0xcd, 0xfd, 0xca };

unsigned reflect(unsigned center, unsigned (*r)(unsigned))
{
  return (*r)(center)^center;
}
unsigned char base(unsigned char a, unsigned char (*s)(unsigned char), int pos)
{
	return (*s)(pos)^a;
}

void transHomExt(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^base(d, g, d);
    }
    data[i] = d;
  }
}
void transHom(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^(*g)(d);
    }
    data[i] = d;
  }
}

void trans(vector<unsigned char>& data, unsigned char (*f)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d);
    }
    data[i] = d;
  }
}

vector<double> f_dist(vector<unsigned char>& in)
{
  vector<double> fdist;
  fdist.resize(256);
  for(unsigned i = 0; i<in.size(); i++)
  {
    fdist[in[i]]++;
  }

  for(unsigned i=0; i<fdist.size(); i++)
  {
    fdist[i] = (fdist[i] / in.size()) * 100;
  }

  return fdist;
}

double s_entropy(vector<double> v)
{
  double entropy = 0;
  double p;

  for(unsigned i = 0; i < v.size(); i++)
  {
    p = v[i] / 100;
    if (p == 0) continue;
    entropy += p * std::log(p) / std::log(2);
  }
  return -entropy;
}
void rms(const string& s, string& r)
{
  for(unsigned int i=0; i<s.size(); i++)
  {
    if(::isspace(s[i])) continue;
    r+= s[i];
  }
}

double sw(double weight, int i, int j, int (*inv)(int, int))
{
  return weight*(*inv)(i, j);
}
void hPerm(int s, int n, void (*p)(int), void (*inv)(int, int))
{
  if(s == 1)
  {
    (*p)(n);
    return;
  }
  for(int i=0; i< s; i++)
  {
    hPerm(s-1, n, p, inv);
    if(s%2 == 1)
      (*inv)(0, s-1);
    else
      (*inv)(i, s-1);
  }
}

double ic(const string& t)
{
  string text; rms(t, text);
  vector<double> freq(256,0);
  for(unsigned int i=0; i<text.size(); i++)
  {
    if(text[i] == ' ') continue;
    freq[text[i]] ++;
  }
  double sum=0;
  for(unsigned int i=0; i<freq.size(); i++)
  {
    if(freq[i] != 0)
    {
      double c = freq[i];
      if(c != 0)
        sum += c * (c - 1);
    }
  }
  double ic = 26 * sum / (text.size() * (text.size() - 1));
  return ic;
}
<commit_msg>reflect , test<commit_after>#include "twister.h"

const unsigned CYCLE = 0x100;

const unsigned C_TRANS_ = 0xff;
int block_units[][0x10] = {
	0x74, 0x63, 0x69, 0x67, 0x72, 0x68, 0x6e, 0x6c, 0x61, 0x67, 0x74, 0x6c, 0x69, 0x73, 0x61, 0x61, 0x6f, 0x6d, 0x6f, 0x72, 0x6e, 0x72, 0x69, 0x6d, 0x6e, 0x6e, 0x65, 0x74, 0x72, 0x6e, 0x6b, 0x73, 0x61, 0x6f, 0x65, 0x69, 0x73, 0x64, 0x6c, 0x65, 0x69, 0x6b, 0x68, 0x68, 0x68, 0x65, 0x72, 0x64, 0x66, 0x74, 0x61, 0x73, 0x6f, 0x69, 0x65, 0x74, 0x69, 0x68, 0x6e, 0x65, 0x62, 0x74, 0x6b, 0x65
  };
int triad_units[][0x03] = {
	0x74, 0x68, 0x65, 0x74, 0x68, 0x61, 0x65, 0x74, 0x68, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x65, 0x68, 0x61, 0x74, 0x68, 0x69, 0x73
};
const int transition_seq[] = { 0xce, 0xab, 0xdf, 0xcf, 0xee,
                               0xcf, 0xad, 0xdf, 0xff, 0xce,
                               0x32, 0x40, 0xd3, 0x27, 0x82,
                               0xda, 0xee, 0xff, 0xfc, 0xbf,
                               0x1c, 0x90, 0x13, 0x4a, 0xa5,
                               0xe0, 0x21, 0x9f, 0xe1, 0xc6,
                               0xe4, 0x38, 0x1f, 0x60, 0x24,
                               0x0c, 0x35, 0x51, 0x32, 0xcf,
                               0x12, 0x9a, 0x30, 0x44, 0x72,
                               0x04, 0x1c, 0x52, 0xca, 0xdf,
                               0x12, 0x0b, 0x30, 0xa0, 0x1e,
                               0x03, 0x14, 0x09, 0x73, 0x23,
                               0xf2, 0xca, 0xa2, 0x51, 0xc6,
                               0xcb, 0xbd, 0xba, 0xac, 0xdf,
                               0xdf, 0xde, 0xcd, 0xfd, 0xca };

unsigned reflect(unsigned center, unsigned (*r)(unsigned))
{
  return (*r)(center)^center;
}
unsigned char base(unsigned char a, unsigned char (*s)(unsigned char), int pos)
{
	return (*s)(pos)^a;
}

void transHomExt(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^base(d, g, d);
    }
    data[i] = d;
  }
}
void transHom(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^(*g)(d);
    }
    data[i] = d;
  }
}

void trans(vector<unsigned char>& data, unsigned char (*f)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d);
    }
    data[i] = d;
  }
}

vector<double> f_dist(vector<unsigned char>& in)
{
  vector<double> fdist;
  fdist.resize(256);
  for(unsigned i = 0; i<in.size(); i++)
  {
    fdist[in[i]]++;
  }

  for(unsigned i=0; i<fdist.size(); i++)
  {
    fdist[i] = (fdist[i] / in.size()) * 100;
  }

  return fdist;
}

double s_entropy(vector<double> v)
{
  double entropy = 0;
  double p;

  for(unsigned i = 0; i < v.size(); i++)
  {
    p = v[i] / 100;
    if (p == 0) continue;
    entropy += p * std::log(p) / std::log(2);
  }
  return -entropy;
}
void rms(const string& s, string& r)
{
  for(unsigned int i=0; i<s.size(); i++)
  {
    if(::isspace(s[i])) continue;
    r+= s[i];
  }
}

double sw(double weight, int i, int j, int (*inv)(int, int))
{
  return weight*(*inv)(i, j);
}
void hPerm(int s, int n, void (*p)(int), void (*inv)(int, int))
{
  if(s == 1)
  {
    (*p)(n);
    return;
  }
  for(int i=0; i< s; i++)
  {
    hPerm(s-1, n, p, inv);
    if(s%2 == 1)
      (*inv)(0, s-1);
    else
      (*inv)(i, s-1);
  }
}

double ic(const string& t)
{
  string text; rms(t, text);
  vector<double> freq(256,0);
  for(unsigned int i=0; i<text.size(); i++)
  {
    if(text[i] == ' ') continue;
    freq[text[i]] ++;
  }
  double sum=0;
  for(unsigned int i=0; i<freq.size(); i++)
  {
    if(freq[i] != 0)
    {
      double c = freq[i];
      if(c != 0)
        sum += c * (c - 1);
    }
  }
  double ic = 26 * sum / (text.size() * (text.size() - 1));
  return ic;
}
<|endoftext|>


<commit_before>#include "twister.h"

#include "main.h"
#include "init.h"
#include "bitcoinrpc.h"

using namespace json_spirit;
using namespace std;

#include <boost/filesystem.hpp>

#include <time.h>

twister::twister()
{
}

// ===================== LIBTORRENT & DHT ===========================

#include "libtorrent/config.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/alert_types.hpp"

#define TORRENT_DISABLE_GEO_IP
#include "libtorrent/aux_/session_impl.hpp"

using namespace libtorrent;
static session *ses = NULL;

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::get_generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

int save_file(std::string const& filename, std::vector<char>& v)
{
	using namespace libtorrent;

	// TODO: don't use internal file type here. use fopen()
	file f;
	error_code ec;
	if (!f.open(filename, file::write_only, ec)) return -1;
	if (ec) return -1;
	file::iovec_t b = {&v[0], v.size()};
	size_type written = f.writev(0, &b, 1, ec);
	if (written != int(v.size())) return -3;
	if (ec) return -3;
	return 0;
}

void ThreadWaitExtIP()
{
    RenameThread("wait-extip");

    std::string ipStr;

    // wait up to 5 seconds for bitcoin to get the external IP
    for( int i = 0; i < 10; i++ ) {
        const CNetAddr paddrPeer("8.8.8.8");
        CAddress addr( GetLocalAddress(&paddrPeer) );
        if( addr.IsValid() ) {
            ipStr = addr.ToStringIP();
            break;
        }
        MilliSleep(500);
    }

    error_code ec;
    int listen_port = GetListenPort() + LIBTORRENT_PORT_OFFSET;
    std::string bind_to_interface = "";

    printf("Creating new libtorrent session ext_ip=%s port=%d\n", ipStr.c_str(), listen_port);

    ses = new session(fingerprint("TW", LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)
            , session::add_default_plugins
            , alert::dht_notification
            , ipStr.size() ? ipStr.c_str() : NULL );

    std::vector<char> in;
    boost::filesystem::path sesStatePath = GetDataDir() / "ses_state";
    if (load_file(sesStatePath.string(), in, ec) == 0)
    {
            lazy_entry e;
            if (lazy_bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
                    ses->load_state(e);
    }

    ses->start_upnp();
    ses->start_natpmp();

    ses->listen_on(std::make_pair(listen_port, listen_port)
            , ec, bind_to_interface.c_str());
    if (ec)
    {
            fprintf(stderr, "failed to listen%s%s on ports %d-%d: %s\n"
                    , bind_to_interface.empty() ? "" : " on ", bind_to_interface.c_str()
                    , listen_port, listen_port+1, ec.message().c_str());
    }

    ses->start_dht();

    //ses->set_settings(settings);

    printf("libtorrent + dht started\n");
}

void ThreadMaintainDHTNodes()
{
    RenameThread("maintain-dht-nodes");

    while(1) {
        MilliSleep(5000);

        if( ses ) {
            session_status ss = ses->status();
            if( ss.dht_nodes == 0 && vNodes.size() ) {
                printf("ThreadMaintainDHTNodes: no dht_nodes, trying to add some...\n");
                LOCK(cs_vNodes);
                BOOST_FOREACH(CNode* pnode, vNodes) {
                    BOOST_FOREACH(CAddress const &knownAddr, pnode->setAddrKnown) {
                        std::string addr = knownAddr.ToStringIP();
                        int port = knownAddr.GetPort() + LIBTORRENT_PORT_OFFSET;
                        printf("Adding dht node %s:%d\n", addr.c_str(), port);
                        ses->add_dht_node(std::pair<std::string, int>(addr, port));
                    }
                }
            }
        }
    }
}

void ThreadSessionAlerts()
{
    while(!ses) {
        MilliSleep(200);
    }
    while (ses) {
        alert const* a = ses->wait_for_alert(seconds(10));
        if (a == 0) continue;

        std::deque<alert*> alerts;
        ses->pop_alerts(&alerts);
        std::string now = time_now_string();
        for (std::deque<alert*>::iterator i = alerts.begin()
                , end(alerts.end()); i != end; ++i)
        {
                // make sure to delete each alert
                std::auto_ptr<alert> a(*i);

                dht_reply_data_alert const* rd = alert_cast<dht_reply_data_alert>(*i);
                if (rd)
                {
                    for (entry::list_type::const_iterator j = rd->m_lst.begin()
                         , end(rd->m_lst.end()); j != end; ++j) {
                        if( j->type() == entry::dictionary_t ) {
                            entry const *p = j->find_key("p");
                            //entry const *sig_p = j->find_key("sig_p"); // already verified in dht_get.cpp
                            entry const *sig_user = j->find_key("sig_user");
                            if( p && sig_user ) {
                                printf("ThreadSessionAlerts: dht data reply with sig_user=%s\n",
                                       sig_user->string().c_str());
                                entry const *v = p->find_key("v");
                                if( v ) {
                                    if( v->type() == entry::string_t ) {
                                        printf("ThreadSessionAlerts: dht data reply value '%s'\n",
                                               v->string().c_str());
                                    }
                                }
                            } else {
                                printf("ThreadSessionAlerts: Error: p, sig_p or sig_user missing\n");
                            }
                        } else {
                            printf("ThreadSessionAlerts: Error: non-dictionary returned by dht data reply\n");
                        }
                    }
                    continue;
                }

                /*
                save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(*i);
                if (rd) {
                    if (!rd->resume_data) continue;

                    torrent_handle h = rd->handle;
                    torrent_status st = h.status(torrent_handle::query_save_path);
                    std::vector<char> out;
                    bencode(std::back_inserter(out), *rd->resume_data);
                    save_file(combine_path(st.save_path, combine_path(".resume", to_hex(st.info_hash.to_string()) + ".resume")), out);
                }
                */
        }
    }
}

void startSessionTorrent(boost::thread_group& threadGroup)
{
    printf("startSessionTorrent (waiting for external IP)\n");

    threadGroup.create_thread(boost::bind(&ThreadWaitExtIP));
    threadGroup.create_thread(boost::bind(&ThreadMaintainDHTNodes));
    threadGroup.create_thread(boost::bind(&ThreadSessionAlerts));
}

void stopSessionTorrent()
{
    if( ses ){
            ses->pause();

            printf("\nsaving session state\n");

            entry session_state;
            ses->save_state(session_state);

	    std::vector<char> out;
	    bencode(std::back_inserter(out), session_state);
	    boost::filesystem::path sesStatePath = GetDataDir() / "ses_state";
	    save_file(sesStatePath.string(), out);

	    delete ses;
	    ses = NULL;
    }
    printf("libtorrent + dht stopped\n");
}

std::string createSignature(std::string const &strMessage, std::string const &strUsername)
{
    if (pwalletMain->IsLocked()) {
        printf("createSignature: Error please enter the wallet passphrase with walletpassphrase first.\n");
        return std::string();
    }

    CKeyID keyID;
    if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) {
        printf("createSignature: user '%s' unknown.\n", strUsername.c_str());
        return std::string();
    }

    CKey key;
    if (!pwalletMain->GetKey(keyID, key)) {
        printf("createSignature: private key not available for user '%s'.\n", strUsername.c_str());
        return std::string();
    }

    CHashWriter ss(SER_GETHASH, 0);
    ss << strMessageMagic;
    ss << strMessage;

    vector<unsigned char> vchSig;
    if (!key.SignCompact(ss.GetHash(), vchSig)) {
        printf("createSignature: sign failed.\n");
        return std::string();
    }

    return std::string((const char *)&vchSig[0], vchSig.size());
}

bool verifySignature(std::string const &strMessage, std::string const &strUsername, std::string const &strSign)
{
    CPubKey pubkey;
    {
      CKeyID keyID;
      if( pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) {
        if( !pwalletMain->GetPubKey(keyID, pubkey) ) {
            // error? should not have failed.
        }
      }
    }

    if( !pubkey.IsValid() ) {
      CTransaction txOut;
      uint256 hashBlock;
      uint256 userhash = SerializeHash(strUsername);
      if( !GetTransaction(userhash, txOut, hashBlock) ) {
          //printf("verifySignature: user unknown '%s'\n", strUsername.c_str());
          return false;
      }

      std::vector< std::vector<unsigned char> > vData;
      if( !txOut.pubKey.ExtractPushData(vData) || vData.size() < 1 ) {
          printf("verifySignature: broken pubkey for user '%s'\n", strUsername.c_str());
          return false;
      }
      pubkey = CPubKey(vData[0]);
      if( !pubkey.IsValid() ) {
          printf("verifySignature: invalid pubkey for user '%s'\n", strUsername.c_str());
          return false;
      }
    }

    vector<unsigned char> vchSig((const unsigned char*)strSign.data(),
                                 (const unsigned char*)strSign.data() + strSign.size());

    CHashWriter ss(SER_GETHASH, 0);
    ss << strMessageMagic;
    ss << strMessage;

    CPubKey pubkeyRec;
    if (!pubkeyRec.RecoverCompact(ss.GetHash(), vchSig))
        return false;

    return (pubkeyRec.GetID() == pubkey.GetID());
}

int getBestHeight()
{
    return nBestHeight;
}

Value dhtput(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 5 || params.size() > 6)
        throw runtime_error(
            "dhtput <username> <resource> <s(ingle)/m(ulti)> <value> <sig_user> <seq>\n"
            "Sign a message with the private key of an address");

    EnsureWalletIsUnlocked();

    string strUsername = params[0].get_str();
    string strResource = params[1].get_str();
    string strMulti    = params[2].get_str();
    string strValue    = params[3].get_str();
    string strSigUser  = params[4].get_str();

    // Test for private key here to avoid going into dht
    CKeyID keyID;
    if( !pwalletMain->GetKeyIdFromUsername(strSigUser, keyID) )
      throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: no sig_user in wallet");
    CKey key;
    if (!pwalletMain->GetKey(keyID, key))
        throw JSONRPCError(RPC_WALLET_ERROR, "Private key of sig_user not available");

    bool multi = (strMulti == "m");
    if( !multi && params.size() != 6 )
        throw JSONRPCError(RPC_WALLET_ERROR, "Seq parameter required for single");

    int seq = -1;
    if( params.size() == 6 ) seq = atoi( params[5].get_str().c_str() );

    if( !multi && strUsername != strSigUser )
        throw JSONRPCError(RPC_WALLET_ERROR, "Username must be the same as sig_user for single");

    entry value = entry::string_type(strValue);
    int timeutc = time(NULL);

    ses->dht_putData(strUsername, strResource, multi, value, strSigUser, timeutc, seq);
    return Value();
}

Value dhtget(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 3)
        throw runtime_error(
            "dhtget <username> <resource> <s(ingle)/m(ulti)>\n"
            "Sign a message with the private key of an address");

    string strUsername = params[0].get_str();
    string strResource = params[1].get_str();
    string strMulti    = params[2].get_str();

    bool multi = (strMulti == "m");

    ses->dht_getData(strUsername, strResource, multi);
    return Value();
}

<commit_msg>return dhtget data to json<commit_after>#include "twister.h"

#include "main.h"
#include "init.h"
#include "bitcoinrpc.h"

using namespace json_spirit;
using namespace std;

#include <boost/filesystem.hpp>

#include <time.h>

twister::twister()
{
}

// ===================== LIBTORRENT & DHT ===========================

#include "libtorrent/config.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/alert_types.hpp"

#define TORRENT_DISABLE_GEO_IP
#include "libtorrent/aux_/session_impl.hpp"

using namespace libtorrent;
static session *ses = NULL;

static CCriticalSection cs_dhtgetMap;
static map<uint256, alert_manager*> m_dhtgetMap;

uint256 dhtTargetHash(std::string const &username, std::string const &resource, std::string const &type)
{
    CHashWriter ss(SER_GETHASH, 0);
    ss << username;
    ss << resource;
    ss << type;

    return ss.GetHash();
}

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::get_generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

int save_file(std::string const& filename, std::vector<char>& v)
{
	using namespace libtorrent;

	// TODO: don't use internal file type here. use fopen()
	file f;
	error_code ec;
	if (!f.open(filename, file::write_only, ec)) return -1;
	if (ec) return -1;
	file::iovec_t b = {&v[0], v.size()};
	size_type written = f.writev(0, &b, 1, ec);
	if (written != int(v.size())) return -3;
	if (ec) return -3;
	return 0;
}

void ThreadWaitExtIP()
{
    RenameThread("wait-extip");

    std::string ipStr;

    // wait up to 5 seconds for bitcoin to get the external IP
    for( int i = 0; i < 10; i++ ) {
        const CNetAddr paddrPeer("8.8.8.8");
        CAddress addr( GetLocalAddress(&paddrPeer) );
        if( addr.IsValid() ) {
            ipStr = addr.ToStringIP();
            break;
        }
        MilliSleep(500);
    }

    error_code ec;
    int listen_port = GetListenPort() + LIBTORRENT_PORT_OFFSET;
    std::string bind_to_interface = "";

    printf("Creating new libtorrent session ext_ip=%s port=%d\n", ipStr.c_str(), listen_port);

    ses = new session(fingerprint("TW", LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)
            , session::add_default_plugins
            , alert::dht_notification
            , ipStr.size() ? ipStr.c_str() : NULL );

    std::vector<char> in;
    boost::filesystem::path sesStatePath = GetDataDir() / "ses_state";
    if (load_file(sesStatePath.string(), in, ec) == 0)
    {
            lazy_entry e;
            if (lazy_bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
                    ses->load_state(e);
    }

    ses->start_upnp();
    ses->start_natpmp();

    ses->listen_on(std::make_pair(listen_port, listen_port)
            , ec, bind_to_interface.c_str());
    if (ec)
    {
            fprintf(stderr, "failed to listen%s%s on ports %d-%d: %s\n"
                    , bind_to_interface.empty() ? "" : " on ", bind_to_interface.c_str()
                    , listen_port, listen_port+1, ec.message().c_str());
    }

    ses->start_dht();

    //ses->set_settings(settings);

    printf("libtorrent + dht started\n");
}

void ThreadMaintainDHTNodes()
{
    RenameThread("maintain-dht-nodes");

    while(1) {
        MilliSleep(5000);

        if( ses ) {
            session_status ss = ses->status();
            if( ss.dht_nodes == 0 && vNodes.size() ) {
                printf("ThreadMaintainDHTNodes: no dht_nodes, trying to add some...\n");
                LOCK(cs_vNodes);
                BOOST_FOREACH(CNode* pnode, vNodes) {
                    BOOST_FOREACH(CAddress const &knownAddr, pnode->setAddrKnown) {
                        std::string addr = knownAddr.ToStringIP();
                        int port = knownAddr.GetPort() + LIBTORRENT_PORT_OFFSET;
                        printf("Adding dht node %s:%d\n", addr.c_str(), port);
                        ses->add_dht_node(std::pair<std::string, int>(addr, port));
                    }
                }
            }
        }
    }
}

void ThreadSessionAlerts()
{
    while(!ses) {
        MilliSleep(200);
    }
    while (ses) {
        alert const* a = ses->wait_for_alert(seconds(10));
        if (a == 0) continue;

        std::deque<alert*> alerts;
        ses->pop_alerts(&alerts);
        std::string now = time_now_string();
        for (std::deque<alert*>::iterator i = alerts.begin()
                , end(alerts.end()); i != end; ++i)
        {
                // make sure to delete each alert
                std::auto_ptr<alert> a(*i);

                dht_reply_data_alert const* rd = alert_cast<dht_reply_data_alert>(*i);
                if (rd)
                {
                    if( rd->m_lst.size() ) {
                        // use first one to recover target
                        entry const *p = rd->m_lst.begin()->find_key("p");
                        if( p && p->type() == entry::dictionary_t ) {
                            entry const *target = p->find_key("target");
                            if( target && target->type() == entry::dictionary_t ) {
                                entry const *n = target->find_key("n");
                                entry const *r = target->find_key("r");
                                entry const *t = target->find_key("t");
                                if( n && n->type() == entry::string_t &&
                                    r && r->type() == entry::string_t &&
                                    t && t->type() == entry::string_t) {
                                    uint256 th = dhtTargetHash(n->string(), r->string(), t->string());

                                    LOCK(cs_dhtgetMap);
                                    std::map<uint256, alert_manager*>::iterator mi = m_dhtgetMap.find(th);
                                    if( mi != m_dhtgetMap.end() ) {
                                        alert_manager *am = (*mi).second;
                                        am->post_alert(*rd);
                                    } else {
                                        printf("ThreadSessionAlerts: received dht [%s,%s,%s] but no alert_manager registered\n",
                                               n->string().c_str(), r->string().c_str(), t->string().c_str() );
                                    }
                                }
                            }
                        }
                    }
                    continue;
                }

                /*
                save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(*i);
                if (rd) {
                    if (!rd->resume_data) continue;

                    torrent_handle h = rd->handle;
                    torrent_status st = h.status(torrent_handle::query_save_path);
                    std::vector<char> out;
                    bencode(std::back_inserter(out), *rd->resume_data);
                    save_file(combine_path(st.save_path, combine_path(".resume", to_hex(st.info_hash.to_string()) + ".resume")), out);
                }
                */
        }
    }
}

void startSessionTorrent(boost::thread_group& threadGroup)
{
    printf("startSessionTorrent (waiting for external IP)\n");

    threadGroup.create_thread(boost::bind(&ThreadWaitExtIP));
    threadGroup.create_thread(boost::bind(&ThreadMaintainDHTNodes));
    threadGroup.create_thread(boost::bind(&ThreadSessionAlerts));
}

void stopSessionTorrent()
{
    if( ses ){
            ses->pause();

            printf("\nsaving session state\n");

            entry session_state;
            ses->save_state(session_state);

	    std::vector<char> out;
	    bencode(std::back_inserter(out), session_state);
	    boost::filesystem::path sesStatePath = GetDataDir() / "ses_state";
	    save_file(sesStatePath.string(), out);

	    delete ses;
	    ses = NULL;
    }
    printf("libtorrent + dht stopped\n");
}

std::string createSignature(std::string const &strMessage, std::string const &strUsername)
{
    if (pwalletMain->IsLocked()) {
        printf("createSignature: Error please enter the wallet passphrase with walletpassphrase first.\n");
        return std::string();
    }

    CKeyID keyID;
    if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) {
        printf("createSignature: user '%s' unknown.\n", strUsername.c_str());
        return std::string();
    }

    CKey key;
    if (!pwalletMain->GetKey(keyID, key)) {
        printf("createSignature: private key not available for user '%s'.\n", strUsername.c_str());
        return std::string();
    }

    CHashWriter ss(SER_GETHASH, 0);
    ss << strMessageMagic;
    ss << strMessage;

    vector<unsigned char> vchSig;
    if (!key.SignCompact(ss.GetHash(), vchSig)) {
        printf("createSignature: sign failed.\n");
        return std::string();
    }

    return std::string((const char *)&vchSig[0], vchSig.size());
}

bool verifySignature(std::string const &strMessage, std::string const &strUsername, std::string const &strSign)
{
    CPubKey pubkey;
    {
      CKeyID keyID;
      if( pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) {
        if( !pwalletMain->GetPubKey(keyID, pubkey) ) {
            // error? should not have failed.
        }
      }
    }

    if( !pubkey.IsValid() ) {
      CTransaction txOut;
      uint256 hashBlock;
      uint256 userhash = SerializeHash(strUsername);
      if( !GetTransaction(userhash, txOut, hashBlock) ) {
          //printf("verifySignature: user unknown '%s'\n", strUsername.c_str());
          return false;
      }

      std::vector< std::vector<unsigned char> > vData;
      if( !txOut.pubKey.ExtractPushData(vData) || vData.size() < 1 ) {
          printf("verifySignature: broken pubkey for user '%s'\n", strUsername.c_str());
          return false;
      }
      pubkey = CPubKey(vData[0]);
      if( !pubkey.IsValid() ) {
          printf("verifySignature: invalid pubkey for user '%s'\n", strUsername.c_str());
          return false;
      }
    }

    vector<unsigned char> vchSig((const unsigned char*)strSign.data(),
                                 (const unsigned char*)strSign.data() + strSign.size());

    CHashWriter ss(SER_GETHASH, 0);
    ss << strMessageMagic;
    ss << strMessage;

    CPubKey pubkeyRec;
    if (!pubkeyRec.RecoverCompact(ss.GetHash(), vchSig))
        return false;

    return (pubkeyRec.GetID() == pubkey.GetID());
}

int getBestHeight()
{
    return nBestHeight;
}

Value dhtput(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 5 || params.size() > 6)
        throw runtime_error(
            "dhtput <username> <resource> <s(ingle)/m(ulti)> <value> <sig_user> <seq>\n"
            "Sign a message with the private key of an address");

    EnsureWalletIsUnlocked();

    string strUsername = params[0].get_str();
    string strResource = params[1].get_str();
    string strMulti    = params[2].get_str();
    string strValue    = params[3].get_str();
    string strSigUser  = params[4].get_str();

    // Test for private key here to avoid going into dht
    CKeyID keyID;
    if( !pwalletMain->GetKeyIdFromUsername(strSigUser, keyID) )
      throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: no sig_user in wallet");
    CKey key;
    if (!pwalletMain->GetKey(keyID, key))
        throw JSONRPCError(RPC_WALLET_ERROR, "Private key of sig_user not available");

    bool multi = (strMulti == "m");
    if( !multi && params.size() != 6 )
        throw JSONRPCError(RPC_WALLET_ERROR, "Seq parameter required for single");

    int seq = -1;
    if( params.size() == 6 ) seq = atoi( params[5].get_str().c_str() );

    if( !multi && strUsername != strSigUser )
        throw JSONRPCError(RPC_WALLET_ERROR, "Username must be the same as sig_user for single");

    entry value = entry::string_type(strValue);
    int timeutc = time(NULL);

    ses->dht_putData(strUsername, strResource, multi, value, strSigUser, timeutc, seq);
    return Value();
}

Value dhtget(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 3)
        throw runtime_error(
            "dhtget <username> <resource> <s(ingle)/m(ulti)>\n"
            "Sign a message with the private key of an address");

    string strUsername = params[0].get_str();
    string strResource = params[1].get_str();
    string strMulti    = params[2].get_str();

    bool multi = (strMulti == "m");

    alert_manager am(10, alert::dht_notification);
    uint256 th = dhtTargetHash(strUsername,strResource,strMulti);

    {
        LOCK(cs_dhtgetMap);
        m_dhtgetMap[th] = &am;
    }

    ses->dht_getData(strUsername, strResource, multi);

    Value ret;

    if( am.wait_for_alert(seconds(10)) ) {
        std::auto_ptr<alert> a(am.get());

        dht_reply_data_alert const* rd = alert_cast<dht_reply_data_alert>(&(*a));
        entry const *p = rd->m_lst.begin()->find_key("p");

        // FIXME: temporary. implement proper parsing/conversion
        ret = rd->m_lst.begin()->find_key("sig_p")->string();
    }

    {
        LOCK(cs_dhtgetMap);
        m_dhtgetMap.erase(th);
    }

    return ret;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: wintypes.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SV_WINTYPES_HXX
#define _SV_WINTYPES_HXX

#include <tools/wintypes.hxx>

// --------------------------------------------
// - prominent place for ListBox window types -
// --------------------------------------------

enum ProminentEntry { PROMINENT_TOP, PROMINENT_MIDDLE };

#endif // _SV_WINTYPES_HXX

<commit_msg>clean up merge in copied file<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: wintypes.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SV_WINTYPES_HXX
#define _SV_WINTYPES_HXX

#include <tools/wintypes.hxx>

#endif // _SV_WINTYPES_HXX

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hatch.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 11:59:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _VCOMPAT_HXX
#include <tools/vcompat.hxx>
#endif
#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_HATCX_HXX
#include <hatch.hxx>
#endif

DBG_NAME( Hatch );

// --------------
// - ImplHatch -
// --------------

ImplHatch::ImplHatch() :
    mnRefCount  ( 1 ),
    maColor     ( COL_BLACK ),
    meStyle     ( HATCH_SINGLE ),
    mnDistance  ( 1 ),
    mnAngle     ( 0 )
{
}

// -----------------------------------------------------------------------

ImplHatch::ImplHatch( const ImplHatch& rImplHatch ) :
    mnRefCount  ( 1 ),
    maColor     ( rImplHatch.maColor ),
    meStyle     ( rImplHatch.meStyle ),
    mnDistance  ( rImplHatch.mnDistance ),
    mnAngle     ( rImplHatch.mnAngle )
{
}

// ---------
// - Hatch -
// ---------

Hatch::Hatch()
{
    DBG_CTOR( Hatch, NULL );
    mpImplHatch = new ImplHatch;
}

// -----------------------------------------------------------------------

Hatch::Hatch( const Hatch& rHatch )
{
    DBG_CTOR( Hatch, NULL );
    DBG_CHKOBJ( &rHatch, Hatch, NULL );
    mpImplHatch = rHatch.mpImplHatch;
    mpImplHatch->mnRefCount++;
}

// -----------------------------------------------------------------------

Hatch::Hatch( HatchStyle eStyle, const Color& rColor,
              long nDistance, USHORT nAngle10 )
{
    DBG_CTOR( Hatch, NULL );
    mpImplHatch = new ImplHatch;
    mpImplHatch->maColor = rColor;
    mpImplHatch->meStyle = eStyle;
    mpImplHatch->mnDistance = nDistance;
    mpImplHatch->mnAngle = nAngle10;
}

// -----------------------------------------------------------------------

Hatch::~Hatch()
{
    DBG_DTOR( Hatch, NULL );
    if( !( --mpImplHatch->mnRefCount ) )
        delete mpImplHatch;
}

// -----------------------------------------------------------------------

Hatch& Hatch::operator=( const Hatch& rHatch )
{
    DBG_CHKTHIS( Hatch, NULL );
    DBG_CHKOBJ( &rHatch, Hatch, NULL );

    rHatch.mpImplHatch->mnRefCount++;

    if( !( --mpImplHatch->mnRefCount ) )
        delete mpImplHatch;

    mpImplHatch = rHatch.mpImplHatch;
    return *this;
}

// -----------------------------------------------------------------------

BOOL Hatch::operator==( const Hatch& rHatch ) const
{
    DBG_CHKTHIS( Hatch, NULL );
    DBG_CHKOBJ( &rHatch, Hatch, NULL );

    return( mpImplHatch == rHatch.mpImplHatch ||
            ( mpImplHatch->maColor == rHatch.mpImplHatch->maColor &&
              mpImplHatch->meStyle == rHatch.mpImplHatch->meStyle &&
              mpImplHatch->mnDistance == rHatch.mpImplHatch->mnDistance &&
              mpImplHatch->mnAngle == rHatch.mpImplHatch->mnAngle ) );
}

// -----------------------------------------------------------------------

void Hatch::ImplMakeUnique()
{
    if( mpImplHatch->mnRefCount != 1 )
    {
        if( mpImplHatch->mnRefCount )
            mpImplHatch->mnRefCount--;

        mpImplHatch = new ImplHatch( *mpImplHatch );
    }
}

// -----------------------------------------------------------------------

void Hatch::SetStyle( HatchStyle eStyle )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->meStyle = eStyle;
}

// -----------------------------------------------------------------------

void Hatch::SetColor( const Color& rColor )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->maColor = rColor;
}

// -----------------------------------------------------------------------

void Hatch::SetDistance( long nDistance )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->mnDistance = nDistance;
}

// -----------------------------------------------------------------------

void Hatch::SetAngle( USHORT nAngle10 )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->mnAngle = nAngle10;
}

// -----------------------------------------------------------------------

SvStream& operator>>( SvStream& rIStm, ImplHatch& rImplHatch )
{
    VersionCompat   aCompat( rIStm, STREAM_READ );
    UINT16          nTmp16;

    rIStm >> nTmp16; rImplHatch.meStyle = (HatchStyle) nTmp16;
    rIStm >> rImplHatch.maColor >> rImplHatch.mnDistance >> rImplHatch.mnAngle;

    return rIStm;
}

// -----------------------------------------------------------------------

SvStream& operator<<( SvStream& rOStm, const ImplHatch& rImplHatch )
{
    VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );

    rOStm << (UINT16) rImplHatch.meStyle << rImplHatch.maColor;
    rOStm << rImplHatch.mnDistance << rImplHatch.mnAngle;

    return rOStm;
}

// -----------------------------------------------------------------------

SvStream& operator>>( SvStream& rIStm, Hatch& rHatch )
{
    rHatch.ImplMakeUnique();
    return( rIStm >> *rHatch.mpImplHatch );
}

// -----------------------------------------------------------------------

SvStream& operator<<( SvStream& rOStm, const Hatch& rHatch )
{
    return( rOStm << *rHatch.mpImplHatch );
}
<commit_msg>INTEGRATION: CWS warnings01 (1.3.70); FILE MERGED 2005/11/04 17:25:00 pl 1.3.70.1: #i55991# removed warnings for linux/solaris<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hatch.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 19:23:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _VCOMPAT_HXX
#include <tools/vcompat.hxx>
#endif
#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_HATCX_HXX
#include <hatch.hxx>
#endif

DBG_NAME( Hatch )

// --------------
// - ImplHatch -
// --------------

ImplHatch::ImplHatch() :
    mnRefCount  ( 1 ),
    maColor     ( COL_BLACK ),
    meStyle     ( HATCH_SINGLE ),
    mnDistance  ( 1 ),
    mnAngle     ( 0 )
{
}

// -----------------------------------------------------------------------

ImplHatch::ImplHatch( const ImplHatch& rImplHatch ) :
    mnRefCount  ( 1 ),
    maColor     ( rImplHatch.maColor ),
    meStyle     ( rImplHatch.meStyle ),
    mnDistance  ( rImplHatch.mnDistance ),
    mnAngle     ( rImplHatch.mnAngle )
{
}

// ---------
// - Hatch -
// ---------

Hatch::Hatch()
{
    DBG_CTOR( Hatch, NULL );
    mpImplHatch = new ImplHatch;
}

// -----------------------------------------------------------------------

Hatch::Hatch( const Hatch& rHatch )
{
    DBG_CTOR( Hatch, NULL );
    DBG_CHKOBJ( &rHatch, Hatch, NULL );
    mpImplHatch = rHatch.mpImplHatch;
    mpImplHatch->mnRefCount++;
}

// -----------------------------------------------------------------------

Hatch::Hatch( HatchStyle eStyle, const Color& rColor,
              long nDistance, USHORT nAngle10 )
{
    DBG_CTOR( Hatch, NULL );
    mpImplHatch = new ImplHatch;
    mpImplHatch->maColor = rColor;
    mpImplHatch->meStyle = eStyle;
    mpImplHatch->mnDistance = nDistance;
    mpImplHatch->mnAngle = nAngle10;
}

// -----------------------------------------------------------------------

Hatch::~Hatch()
{
    DBG_DTOR( Hatch, NULL );
    if( !( --mpImplHatch->mnRefCount ) )
        delete mpImplHatch;
}

// -----------------------------------------------------------------------

Hatch& Hatch::operator=( const Hatch& rHatch )
{
    DBG_CHKTHIS( Hatch, NULL );
    DBG_CHKOBJ( &rHatch, Hatch, NULL );

    rHatch.mpImplHatch->mnRefCount++;

    if( !( --mpImplHatch->mnRefCount ) )
        delete mpImplHatch;

    mpImplHatch = rHatch.mpImplHatch;
    return *this;
}

// -----------------------------------------------------------------------

BOOL Hatch::operator==( const Hatch& rHatch ) const
{
    DBG_CHKTHIS( Hatch, NULL );
    DBG_CHKOBJ( &rHatch, Hatch, NULL );

    return( mpImplHatch == rHatch.mpImplHatch ||
            ( mpImplHatch->maColor == rHatch.mpImplHatch->maColor &&
              mpImplHatch->meStyle == rHatch.mpImplHatch->meStyle &&
              mpImplHatch->mnDistance == rHatch.mpImplHatch->mnDistance &&
              mpImplHatch->mnAngle == rHatch.mpImplHatch->mnAngle ) );
}

// -----------------------------------------------------------------------

void Hatch::ImplMakeUnique()
{
    if( mpImplHatch->mnRefCount != 1 )
    {
        if( mpImplHatch->mnRefCount )
            mpImplHatch->mnRefCount--;

        mpImplHatch = new ImplHatch( *mpImplHatch );
    }
}

// -----------------------------------------------------------------------

void Hatch::SetStyle( HatchStyle eStyle )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->meStyle = eStyle;
}

// -----------------------------------------------------------------------

void Hatch::SetColor( const Color& rColor )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->maColor = rColor;
}

// -----------------------------------------------------------------------

void Hatch::SetDistance( long nDistance )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->mnDistance = nDistance;
}

// -----------------------------------------------------------------------

void Hatch::SetAngle( USHORT nAngle10 )
{
    DBG_CHKTHIS( Hatch, NULL );
    ImplMakeUnique();
    mpImplHatch->mnAngle = nAngle10;
}

// -----------------------------------------------------------------------

SvStream& operator>>( SvStream& rIStm, ImplHatch& rImplHatch )
{
    VersionCompat   aCompat( rIStm, STREAM_READ );
    UINT16          nTmp16;

    rIStm >> nTmp16; rImplHatch.meStyle = (HatchStyle) nTmp16;
    rIStm >> rImplHatch.maColor >> rImplHatch.mnDistance >> rImplHatch.mnAngle;

    return rIStm;
}

// -----------------------------------------------------------------------

SvStream& operator<<( SvStream& rOStm, const ImplHatch& rImplHatch )
{
    VersionCompat aCompat( rOStm, STREAM_WRITE, 1 );

    rOStm << (UINT16) rImplHatch.meStyle << rImplHatch.maColor;
    rOStm << rImplHatch.mnDistance << rImplHatch.mnAngle;

    return rOStm;
}

// -----------------------------------------------------------------------

SvStream& operator>>( SvStream& rIStm, Hatch& rHatch )
{
    rHatch.ImplMakeUnique();
    return( rIStm >> *rHatch.mpImplHatch );
}

// -----------------------------------------------------------------------

SvStream& operator<<( SvStream& rOStm, const Hatch& rHatch )
{
    return( rOStm << *rHatch.mpImplHatch );
}
<|endoftext|>


<commit_before>#include<malloc.h>
#include<stdio.h>
#include <iostream>

using namespace std;
#define OK 0
#define ERROR 1
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量

typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码，如OK等

struct SqStack
{
     SElemType *base; // 在栈构造之前和销毁之后，base的值为NULL
     SElemType *top; // 栈顶指针
     int stacksize;  // 当前已分配的存储空间，以元素为单位

     SqStack()
	{
	// 构造一个空栈S，该栈预定义大小为STACK_INIT_SIZE
	// 请补全代码
		base=(SElemType*) malloc(STACK_INIT_SIZE*(sizeof(SElemType)));
		if(base==NULL)return;
		top=base+1;
		stacksize=STACK_INIT_SIZE;
		//printf("DDD");
		return;
	}

	Status Push(SElemType e)
	{
		// 在栈S中插入元素e为新的栈顶元素
		// 请补全代码
		if(top-base>=stacksize*4){

			base=(SElemType *) realloc(base,(stacksize+STACKINCREMENT)*sizeof(SElemType));

			if(base==NULL){

				return ERROR;
			}
		}else{

			*top=e;
			top++;
		}

		return OK;

	}

	Status Pop(SElemType &e)
	{
		// 若栈不空，则删除S的栈顶元素，用e返回其值，并返回OK；否则返回ERROR
		// 请补全代码
		if( top-base<=1){
			return ERROR;
		}

		e=*(--top);

		return OK;
	}

	Status GetTop(SElemType &e)
	{
	// 若栈不空，则用e返回S的栈顶元素，并返回OK；否则返回ERROR
	// 请补全代码
		if( top-base<=1){
			return ERROR;
		}

		e=*(top-1);

		return OK;

	}

	int StackLength()
	{
	// 返回栈S的元素个数
	// 请补全代码

		return top-base-1;

	}

	Status StackTraverse(void fn(SElemType& e))
	{
	// 从栈顶到栈底依次输出栈中的每个元素
		SElemType *p = (SElemType *)malloc(sizeof(SElemType));
		p = top;        //请填空
		if(StackLength() ==0 )printf("The Stack is Empty!"); //请填空
		else
		{

			p--;
			while(p-base>=1)            //请填空
			{
				fn(*p);
				p--;               //请填空
			}
		}
		printf("\n");
		return OK;
	}

	int StackEmpty(){

		if(StackLength()>0){
			return 0;
		}else{
			return 1;
		}
	}
}; // 顺序栈

void fun(SElemType &e){

	printf("%d",e);
}

void check()
 { // 对于输入的任意一个字符串，检验括号是否配对
   SqStack s;
   SElemType ch[80],*p,e;

    //printf("请输入表达式\n");
     scanf("%s",ch);
     p=ch;
     while(*p) {

     	s.StackTraverse(fun);// 没到串尾

     	printf("%c",*p);
       switch(*p)
       {
         case '(':
         case '[':s.Push(*p) ;p++;
                  break; // 左括号入栈，且p++
         case ')':
         case ']':if(!s.StackEmpty()) // 栈不空
                  {
                   s.Pop(e); // 弹出栈顶元素
                    if(*p==')'&&e!='('||*p==']'&&e!='[') {
                      printf("isn't matched pairs\n");
                      exit(ERROR);
                    }
                    else
                    {
                     p++;
                      break; // 跳出switch语句
                    }
                  }
                  else // 栈空
                  {
                    printf("lack of left parenthesis\n");
                    exit(ERROR);
                  }
         default: p++; break; // 其它字符不处理，指针向后移
       }
   }

     if(s.StackEmpty()) // 字符串结束时栈空
       printf("matching\n");
     else
       printf("lack of right parenthesis\n");
   }

int main()
{

	check();
}
<commit_msg>update uoj8586<commit_after>#include<malloc.h>
#include<stdio.h>
#include <iostream>

using namespace std;
#define OK 0
#define ERROR 1
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量

typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码，如OK等

struct SqStack
{
     SElemType *base; // 在栈构造之前和销毁之后，base的值为NULL
     SElemType *top; // 栈顶指针
     int stacksize;  // 当前已分配的存储空间，以元素为单位

     SqStack()
	{
	// 构造一个空栈S，该栈预定义大小为STACK_INIT_SIZE
	// 请补全代码
		base=(SElemType*) malloc(STACK_INIT_SIZE*(sizeof(SElemType)));
		if(base==NULL)return;
		top=base+1;
		stacksize=STACK_INIT_SIZE;
		//printf("DDD");
		return;
	}

	Status Push(SElemType e)
	{
		// 在栈S中插入元素e为新的栈顶元素
		// 请补全代码
		if(top-base>=stacksize*4){

			base=(SElemType *) realloc(base,(stacksize+STACKINCREMENT)*sizeof(SElemType));

			if(base==NULL){

				return ERROR;
			}
		}else{

			*top=e;
			top++;
		}

		return OK;

	}

	Status Pop(SElemType &e)
	{
		// 若栈不空，则删除S的栈顶元素，用e返回其值，并返回OK；否则返回ERROR
		// 请补全代码
		if( top-base<=1){
			return ERROR;
		}

		e=*(--top);

		return OK;
	}

	Status GetTop(SElemType &e)
	{
	// 若栈不空，则用e返回S的栈顶元素，并返回OK；否则返回ERROR
	// 请补全代码
		if( top-base<=1){
			return ERROR;
		}

		e=*(top-1);

		return OK;

	}

	int StackLength()
	{
	// 返回栈S的元素个数
	// 请补全代码

		return top-base-1;

	}

	Status StackTraverse(void fn(SElemType& e))
	{
	// 从栈顶到栈底依次输出栈中的每个元素
		SElemType *p = (SElemType *)malloc(sizeof(SElemType));
		p = top;        //请填空
		if(StackLength() ==0 )printf("The Stack is Empty!"); //请填空
		else
		{

			p--;
			while(p-base>=1)            //请填空
			{
				fn(*p);
				p--;               //请填空
			}
		}
		printf("\n");
		return OK;
	}

	int StackEmpty(){

		if(StackLength()>0){
			return 0;
		}else{
			return 1;
		}
	}
}; // 顺序栈

void fun(SElemType &e){

	printf("%d",e);
}

void check()
 { // 对于输入的任意一个字符串，检验括号是否配对
   SqStack s;
   SElemType ch[80],*p,e;

    //printf("请输入表达式\n");
     scanf("%s",ch);
     p=ch;
     while(*p) {

     	s.StackTraverse(fun);// 没到串尾

     	printf("%c\n",*p);
       switch(*p)
       {
         case '(':
         case '[':s.Push(*p) ;p++;
                  break; // 左括号入栈，且p++
         case ')':
         case ']':if(!s.StackEmpty()) // 栈不空
                  {
                   s.Pop(e); // 弹出栈顶元素
                    if(*p==')'&&e!='('||*p==']'&&e!='[') {
                      printf("isn't matched pairs\n");
                      exit(ERROR);
                    }
                    else
                    {
                     p++;
                      break; // 跳出switch语句
                    }
                  }
                  else // 栈空
                  {
                    printf("lack of left parenthesis\n");
                    exit(ERROR);
                  }
         default: p++; break; // 其它字符不处理，指针向后移
       }
   }

     if(s.StackEmpty()) // 字符串结束时栈空
       printf("matching\n");
     else
       printf("lack of right parenthesis\n");
   }

int main()
{

	check();
}
<|endoftext|>


<commit_before>#include "stdio.h"
#include "stdlib.h"
#include <iostream>
#define  MAXSTRLEN  255                   // 用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN+1];	// 0号单元存放串的长度

void get_next(SString T,int next[]){

	int i,j;
	next[1]=0;
	j=0;

	while(i<T[0]){

		if(j == 0 || T[i]==T[j]){
			++i;
			++j;
			next[i]=j;}
		else{
			j=next[j];
		printf("%d\n ??",j);	}
	}
}
int  main(){
	int next[MAXSTRLEN];
	SString S;
	int n,i,j;
	char ch;
	scanf("%d",&n);    // 指定要验证NEXT值的字符串个数
	ch=getchar();
	for(i=1;i<=n;i++)
	{
		ch=getchar();
		for(j=1;j<=MAXSTRLEN&&(ch!='\n');j++)    // 录入字符串
		{
			S[j]=ch;
			ch=getchar();
		}
		S[0]=j-1;    // S[0]用于存储字符串中字符个数
		//printf("%s",S+1);
		get_next(S,next);
		printf("NEXT J is:");
		for(j=1;j<=S[0];j++)
			printf("%d",next[j]);
		printf("\n");
	}
}

<commit_msg>update uoj8591<commit_after>#include <cstdio>
#include <cstdlib>
#include <iostream>
#define  MAXSTRLEN  255                   // 用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN+1];	// 0号单元存放串的长度

void get_next(SString T,int next[]){

	int i,j;
	next[1]=0;
	j=0;

	while(i<T[0]){

		if(j == 0 || T[i]==T[j]){
			++i;
			++j;
			next[i]=j;}
		else{
			j=next[j]i;	}
	}
}
int  main(){
	int next[MAXSTRLEN];
	SString S;
	int n,i,j;
	char ch;
	scanf("%d",&n);    // 指定要验证NEXT值的字符串个数
	ch=getchar();
	for(i=1;i<=n;i++)
	{
		ch=getchar();
		for(j=1;j<=MAXSTRLEN&&(ch!='\n');j++)    // 录入字符串
		{
			S[j]=ch;
			ch=getchar();
		}
		S[0]=j-1;    // S[0]用于存储字符串中字符个数
		//printf("%s",S+1);
		get_next(S,next);
		printf("NEXT J is:");
		for(j=1;j<=S[0];j++)
			printf("%d",next[j]);
		printf("\n");
	}
}

<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[200005];
int q[200005];
int a[200005];
int g[200005];
int n;

void Init(){

    REP(i,1,n){scanf("%d",&(a[i]));g[i]=a[i]+i;}
    REP(i,n+1,n+n/2){a[i]=a[i-n];g[i]=a[i]+i;}
	return ;
}

void Solve(){

	q[1]=1;
    int head=1,tail=1;
    REP(i,2,n+n/2)
    {
        while(i-q[head]>n/2)head++;
        dp[i]=g[i]+a[q[head]]-q[head];
        while(a[i]-i>=a[q[tail]]-q[tail]&&tail>=head)tail--;
        q[++tail]=i;
    }
    int ans=0;
    REP(i,2,n+n/2)
        ans=max(ans,dp[i]);
    printf("%d",(ans));
	return ;
}
int main(){

	freopen("uoj8613.in","r",stdin);

	while((scanf("%d",&n))&&n)
	Init(),Solve();
	return 0;
}<commit_msg>update uoj8613<commit_after>#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[200005];
int q[200005];
int a[200005];
int g[200005];
int n;

void Init(){

    REP(i,1,n){scanf("%d",&(a[i]));g[i]=a[i]+i;}
    REP(i,n+1,n+n/2){a[i]=a[i-n];g[i]=a[i]+i;}
	return ;
}

void Solve(){

	q[1]=1;
    int head=1,tail=1;
    REP(i,2,n+n/2)
    {
        while(i-q[head]>n/2)head++;
        dp[i]=g[i]+a[q[head]]-q[head];
        while(a[i]-i>=a[q[tail]]-q[tail]&&tail>=head)tail--;
        q[++tail]=i;
    }
    int ans=0;
    REP(i,2,n+n/2)
        ans=max(ans,dp[i]);
    printf("%d\n",(ans));
	return ;
}
int main(){

	freopen("uoj8613.in","r",stdin);

	while((scanf("%d",&n))&&n)
	Init(),Solve();
	return 0;
}<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[200005];
int q[200005];
int a[200005];
int g[200005];
int n;

void Init(){

    REP(i,1,n+1){scanf("%d",&(a[i]));g[i]=a[i]+i;}
    REP(i,n+1,n+n/2+1){a[i]=a[i-n];g[i]=a[i]+i;}
	return ;
}

void Solve(){

	q[1]=1;
    int head=1,tail=1;
    for(int i=2;i<=n+n/2;i++)
    {
        while(i-q[head]>n/2)head++;
        dp[i]=g[i]+a[q[head]]-q[head];
        while(a[i]-i>=a[q[tail]]-q[tail]&&tail>=head)tail--;
        q[++tail]=i;
    }
    int ans=0;
    for(int i=2;i<=n+n/2;i++)
        ans=max(ans,dp[i]);
    printf("%d",(ans));
	return ;
}

int main(){

	freopen("uoj8613.in","r",stdin);

	while(scanf("%d",&(n))&&n)
	Init(),Solve();
	return 0;
}<commit_msg>update uoj8613<commit_after>#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[200005];
int q[200005];
int a[200005];
int g[200005];
int n;

void Init(){

    REP(i,1,n+1){scanf("%d",&(a[i]));g[i]=a[i]+i;}
    REP(i,n+1,n+n/2+1){a[i]=a[i-n];g[i]=a[i]+i;}
	return ;
}

void Solve(){

	q[1]=1;
    int head=1,tail=1;
    for(int i=2;i<=n+n/2;i++)
    {
        while(i-q[head]>n/2)head++;
        dp[i]=g[i]+a[q[head]]-q[head];
        while(a[i]-i>=a[q[tail]]-q[tail]&&tail>=head)tail--;
        q[++tail]=i;
    }
    int ans=0;
    for(int i=2;i<=n+n/2;i++)
        ans=max(ans,dp[i]);
    printf("%d",(ans));
	return ;
}
int main(){

	freopen("uoj8613.in","r",stdin);

	while(scanf("%d",&(n))&&n)
	Init(),Solve();
	return 0;
}<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>
#include <map>

// Loriano: let's try Armadillo quick code
#include <armadillo>
#include <cassert>

#include <getopt.h>
#include <unistd.h>
#include <alloca.h>

#include <pcafitter_private.hpp>

std::string pcafitter::paramidxtostring (int i)
{
  switch (i)
  {
    case PTIDX:
      return "pt";
      break;
    case PHIIDX:
      return "phi";
      break;
    case ETAIDX:
      return "eta";
      break;
    case Z0IDX:
      return "z0";
      break;
    case D0IDX:
      return "d0";
      break;
    default:
      return "";
      break;
  }
}

void pcafitter::computeparameters (const arma::mat & cmtx,
    const arma::rowvec & q,
    const arma::mat & coord,
    double * ptcmp, double * phicmp,
    double * etacmp, double * z0cmp,
    double * d0cmp)
{
  for (int i=0; i<(int)coord.n_rows; ++i)
  {
    // pt
    ptcmp[i] = q(PTIDX);
    for (int k=0; k<(3*COORDIM); ++k)
      ptcmp[i] += cmtx(PTIDX,k)*coord(i,k);

    // phi
    phicmp[i] = q(PHIIDX);
    for (int k=0; k<(3*COORDIM); ++k)
      phicmp[i] += cmtx(PHIIDX,k)*coord(i,k);

    // eta
    etacmp[i] = q(ETAIDX);
    for (int k=0; k<(3*COORDIM); ++k)
      etacmp[i] += cmtx(ETAIDX,k)*coord(i,k);

    // z0
    z0cmp[i] = q(Z0IDX);
    for (int k=0; k<(3*COORDIM); ++k)
      z0cmp[i] += cmtx(Z0IDX,k)*coord(i,k);

    // d0
    d0cmp[i] = q(D0IDX);
    for (int k=0; k<(3*COORDIM); ++k)
      d0cmp[i] += cmtx(D0IDX,k)*coord(i,k);
  }
}

void pcafitter::readarmmat (const char * fname, arma::mat & cmtx)
{
  int n, m;
  std::ifstream myfilec(fname, std::ios::binary | std::ios::in);
  myfilec.read((char *)&n, sizeof(n));
  myfilec.read((char *)&m, sizeof(m));
  cmtx.set_size(n, m);
  for (int i=0; i<(int)cmtx.n_rows; i++)
  {
    for (int j=0; j<(int)cmtx.n_cols; j++)
    {
      double v;
      myfilec.read((char *)&v, sizeof(v));

      cmtx(i, j) = v;
    }
  }
  myfilec.close();
}

void pcafitter::readarmvct (const char * fname, arma::rowvec & q)
{
  int n;
  std::ifstream myfileq(fname, std::ios::binary);
  myfileq.read((char*)&(n), sizeof(n));
  q.set_size(n);
  for (int i=0; i<(int)q.n_cols; i++)
  {
    double v;
    myfileq.read((char*)&v, sizeof(v));

    q(i) = v;
  }
  myfileq.close();
}

void pcafitter::writearmmat (const char * fname, arma::mat & cmtx)
{
  std::ofstream myfilec(fname, std::ios::binary);
  myfilec.write((const char*)&(cmtx.n_rows), sizeof(cmtx.n_rows));
  myfilec.write((const char*)&(cmtx.n_cols), sizeof(cmtx.n_cols));
  for (int i=0; i<(int)cmtx.n_rows; i++)
    for (int j=0; j<(int)cmtx.n_cols; j++)
      myfilec.write((const char*)&(cmtx(i, j)), sizeof(cmtx(i, j)));
  myfilec.close();
}

void pcafitter::writearmvct (const char * fname, arma::rowvec & q)
{
  std::ofstream myfileq(fname, std::ios::binary);
  myfileq.write((const char*)&(q.n_cols), sizeof(q.n_cols));
  for (int i=0; i<(int)q.n_cols; i++)
    myfileq.write((const char*)&(q(i)), sizeof(q(i)));
  myfileq.close();
}

int pcafitter::numofline (const char * fname)
{
  int number_of_lines = 0;
  std::string line;
  std::ifstream myfile(fname);

  while (std::getline(myfile, line))
    ++number_of_lines;

  myfile.close();

  return number_of_lines;
}

void pcafitter::writetofile (const char * fname,
    const arma::rowvec & vec)
{
  std::ofstream myfile(fname);

  for (int i=0; i<(int)vec.n_cols; i++)
    myfile << vec(i) << std::endl;

  myfile.close();
}

void pcafitter::readingfromfile (const char * filename,
    arma::rowvec & ptin, arma::rowvec & phiin,
    arma::rowvec & d0in, arma::rowvec & etain,
    arma::rowvec & z0in, arma::mat & coordin,
    arma::mat & layer, arma::mat & ladder,
    arma::mat & module,
    std::map<std::string, int> & subsectors,
    std::map<std::string, int> & subladders,
    std::vector<std::string> & subsectorslist,
    std::vector<std::string> & subladderslist,
    int num_of_ent)
{

  std::string line;
  std::ifstream mytfp;
  mytfp.open (filename, std::ios::in);

  std::getline (mytfp, line);
  for (int i = 0; i < num_of_ent; ++i)
  {
    int fake1, fake2;
    // valori aggiunti solo di controllo
    mytfp >> fake1 >> fake2 ;
#ifdef DEBUG
    std::cout << fake1 << " " << fake2 << std::endl;
#endif
    std::ostringstream osss, ossl;
    osss << std::setfill('0');
    ossl << std::setfill('0');

    for (int j = 0; j < COORDIM; ++j)
    {
      int a, b, c;
      mytfp >> coordin(i, j*3) >>
               coordin(i, j*3+1) >>
               coordin(i, j*3+2) >>
               a >> b >> c;

      layer(i, j) = a;
      ladder(i, j) = b;
      module(i, j) = c;

      osss << std::setw(2) << layer(i, j);
      osss << std::setw(2) << ladder(i, j);
      if (j != COORDIM-1)
        osss<<"-";

      ossl << std::setw(2) << layer(i, j);
      ossl << std::setw(2) << ladder(i, j);
      ossl << std::setw(2) << module(i, j);
      if (j != COORDIM-1)
        ossl<<"-";

    }

    subsectorslist.push_back(osss.str());
    subladderslist.push_back(ossl.str());

    std::map<std::string, int>::iterator its = subsectors.find(osss.str());
    if (its == subsectors.end())
      subsectors[osss.str()] = 1;
    else
      subsectors[osss.str()] += 1;

    std::map<std::string, int>::iterator itl = subladders.find(ossl.str());
    if (itl == subladders.end())
      subladders[ossl.str()] = 1;
    else
      subladders[ossl.str()] += 1;

    mytfp >> ptin(i) >>
             phiin(i) >>
             d0in(i) >>
             etain(i) >>
             z0in(i);
  }

  mytfp.close();
}

void pcafitter::select_bigger_sub (
    const std::map<std::string, int> & sublist,
    bool verbose, int & maxnumber, std::string & slctsubsec )
{
  maxnumber = -1;
  std::map<std::string, int>::const_iterator it = sublist.begin();
  for (; it != sublist.end(); ++it)
  {
    if (it->second > maxnumber)
    {
      maxnumber = it->second;
      slctsubsec = it->first;
    }

    if (verbose)
      std::cout << "Subsector " << it->first << " has " <<
          it->second << " tracks " << std::endl;
  }
}

void pcafitter::extract_sub (const std::vector<std::string> & sublist,
    const std::string & slctsubsec,
    const arma::rowvec & ptin,
    const arma::rowvec & phiin,
    const arma::rowvec & d0in,
    const arma::rowvec & etain,
    const arma::rowvec & z0in,
    const arma::mat & coordin,
    arma::rowvec & pt,
    arma::rowvec & phi,
    arma::rowvec & d0,
    arma::rowvec & eta,
    arma::rowvec & z0,
    arma::mat & coord)
{
  int dim = 0;

  std::vector<std::string>::const_iterator it = sublist.begin();
  for (; it != sublist.end(); ++it)
    if (*it == slctsubsec)
      dim++;

  coord.set_size(dim,3*COORDIM);
  pt.set_size(dim);
  phi.set_size(dim);
  d0.set_size(dim);
  eta.set_size(dim);
  z0.set_size(dim);

  int k = 0;
  it = sublist.begin();
  for (int i=0; it != sublist.end(); ++it, ++i)
  {
    if (*it == slctsubsec)
    {
      for (int j = 0; j < 3*COORDIM; ++j)
        coord(k,j) = coordin(i,j);

      pt(k) = ptin(i);
      phi(k) = phiin(i);
      d0(k) = d0in(i);
      eta(k) = etain(i);
      z0(k) = z0in(i);

      ++k;
    }
  }
}

void pcafitter::compute_pca_constants (
    const arma::rowvec & pt,
    const arma::rowvec & phi,
    const arma::rowvec & d0,
    const arma::rowvec & eta,
    const arma::rowvec & z0,
    const arma::mat & coord,
    arma::mat & cmtx,
    arma::rowvec & q)
{
  arma::mat v = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  v = arma::cov(coord);

#ifdef DEBUG
  /* correlation matrix ricorda su dati standardizzati coincide con la matrice
   *   di covarianza :
   *   z = x -<x> / sigma */
  arma::mat corr = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);

  for (int i=0; i<(3*COORDIM); ++i)
    for (int j=0; j<(3*COORDIM); ++j)
      corr(i,j) = v(i,j) / sqrt(v(i,i)*v(j,j));

  std::cout << "Correlation matrix: " << std::endl;
  std::cout << corr;
#endif

  arma::mat vi = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  vi = v.i();

#ifdef DEBUG
  std::cout << "inverse by cov matrix: " << std::endl;
  std::cout << v * vi ;
#endif

  // and so on ...
  arma::mat hcap = arma::zeros<arma::mat>(3*COORDIM,PARAMDIM);
  arma::rowvec paramm = arma::zeros<arma::rowvec>(PARAMDIM);
  arma::rowvec coordm = arma::zeros<arma::rowvec>(3*COORDIM);
  double sum = 1.0e0;

  for (int l=0; l<(int)coord.n_rows; ++l)
  {
    sum += 1.0e0;
    for (int i=0; i<(3*COORDIM); ++i)
      coordm(i) += (coord(l,i)-coordm(i))/sum;

    paramm(PTIDX) += (pt(l)-paramm(0))/sum;
    paramm(PHIIDX) += (phi(l)-paramm(PHIIDX))/sum;
    paramm(D0IDX) += (d0(l)-paramm(D0IDX))/sum;
    paramm(ETAIDX) += (eta(l)-paramm(ETAIDX))/sum;
    paramm(Z0IDX) += (z0(l)-paramm(Z0IDX))/sum;

    for (int i=0; i<(3*COORDIM); ++i)
    {
      hcap(i,PTIDX) += ((coord(l,i) - coordm(i))*
                    (pt(l) - paramm(PTIDX))-
                    (sum-1.0e0)*hcap(i,PTIDX)/sum)/(sum-1.0e0);

      hcap(i,PHIIDX) += ((coord(l,i) - coordm(i))*
                    (phi(l) - paramm(PHIIDX))-
                    (sum-1.0e0)*hcap(i,PHIIDX)/sum)/(sum-1.0e0);

      hcap(i,D0IDX) += ((coord(l,i) - coordm(i))*
                    (d0(l) - paramm(D0IDX))-
                    (sum-1.0e0)*hcap(i,D0IDX)/sum)/(sum-1.0e0);

      hcap(i,ETAIDX) += ((coord(l,i) - coordm(i))*
                    (eta(l) - paramm(ETAIDX))-
                    (sum-1.0e0)*hcap(i,ETAIDX)/sum)/(sum-1.0e0);

      hcap(i,Z0IDX) += ((coord(l,i) - coordm(i))*
                    (z0(l) - paramm(Z0IDX))-
                    (sum-1.0e0)*hcap(i,Z0IDX)/sum)/(sum-1.0e0);

    }
  }

  for (int i=0; i<PARAMDIM; ++i)
    for (int l=0; l<(3*COORDIM); ++l)
      for (int m=0; m<(3*COORDIM); ++m)
        cmtx(i,l) += vi(l,m) * hcap (m,i);

#ifdef DEBUG
  std::cout << "C matrix: " << std::endl;
  std::cout << cmtx;
#endif

  for (int i=0; i<PARAMDIM; ++i)
  {
    q(i) = paramm(i);
    for (int l=0; l<(3*COORDIM); ++l)
      q(i) -= cmtx(i,l)*coordm[l];
  }

#ifdef DEBUG
  std::cout << "Q vector: " << std::endl;
  for (int i=0; i<PARAMDIM; ++i)
    std::cout << q(i) << std::endl;
#endif

}
<commit_msg>backup<commit_after>#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>
#include <map>

// Loriano: let's try Armadillo quick code
#include <armadillo>
#include <cassert>

#include <getopt.h>
#include <unistd.h>
#include <alloca.h>

#include <pcafitter_private.hpp>

std::string pcafitter::paramidxtostring (int i)
{
  switch (i)
  {
    case PTIDX:
      return "pt";
      break;
    case PHIIDX:
      return "phi";
      break;
    case ETAIDX:
      return "eta";
      break;
    case Z0IDX:
      return "z0";
      break;
    case D0IDX:
      return "d0";
      break;
    default:
      return "";
      break;
  }
}

void pcafitter::computeparameters (const arma::mat & cmtx,
    const arma::rowvec & q,
    const arma::mat & coord,
    double * ptcmp, double * phicmp,
    double * etacmp, double * z0cmp,
    double * d0cmp)
{
  for (int i=0; i<(int)coord.n_rows; ++i)
  {
    // pt
    ptcmp[i] = q(PTIDX);
    for (int k=0; k<(3*COORDIM); ++k)
      ptcmp[i] += cmtx(PTIDX,k)*coord(i,k);

    // phi
    phicmp[i] = q(PHIIDX);
    for (int k=0; k<(3*COORDIM); ++k)
      phicmp[i] += cmtx(PHIIDX,k)*coord(i,k);

    // eta
    etacmp[i] = q(ETAIDX);
    for (int k=0; k<(3*COORDIM); ++k)
      etacmp[i] += cmtx(ETAIDX,k)*coord(i,k);

    // z0
    z0cmp[i] = q(Z0IDX);
    for (int k=0; k<(3*COORDIM); ++k)
      z0cmp[i] += cmtx(Z0IDX,k)*coord(i,k);

    // d0
    d0cmp[i] = q(D0IDX);
    for (int k=0; k<(3*COORDIM); ++k)
      d0cmp[i] += cmtx(D0IDX,k)*coord(i,k);
  }
}

void pcafitter::readarmmat (const char * fname, arma::mat & cmtx)
{
  int n, m;
  std::ifstream myfilec(fname, std::ios::binary | std::ios::in);
  myfilec.read((char *)&n, sizeof(n));
  myfilec.read((char *)&m, sizeof(m));
  cmtx.set_size(n, m);
  for (int i=0; i<(int)cmtx.n_rows; i++)
  {
    for (int j=0; j<(int)cmtx.n_cols; j++)
    {
      double v;
      myfilec.read((char *)&v, sizeof(v));

      cmtx(i, j) = v;
    }
  }
  myfilec.close();
}

void pcafitter::readarmvct (const char * fname, arma::rowvec & q)
{
  int n;
  std::ifstream myfileq(fname, std::ios::binary);
  myfileq.read((char*)&(n), sizeof(n));
  q.set_size(n);
  for (int i=0; i<(int)q.n_cols; i++)
  {
    double v;
    myfileq.read((char*)&v, sizeof(v));

    q(i) = v;
  }
  myfileq.close();
}

void pcafitter::writearmmat (const char * fname, arma::mat & cmtx)
{
  std::ofstream myfilec(fname, std::ios::binary);
  myfilec.write((const char*)&(cmtx.n_rows), sizeof(cmtx.n_rows));
  myfilec.write((const char*)&(cmtx.n_cols), sizeof(cmtx.n_cols));
  for (int i=0; i<(int)cmtx.n_rows; i++)
    for (int j=0; j<(int)cmtx.n_cols; j++)
      myfilec.write((const char*)&(cmtx(i, j)), sizeof(cmtx(i, j)));
  myfilec.close();
}

void pcafitter::writearmvct (const char * fname, arma::rowvec & q)
{
  std::ofstream myfileq(fname, std::ios::binary);
  myfileq.write((const char*)&(q.n_cols), sizeof(q.n_cols));
  for (int i=0; i<(int)q.n_cols; i++)
    myfileq.write((const char*)&(q(i)), sizeof(q(i)));
  myfileq.close();
}

int pcafitter::numofline (const char * fname)
{
  int number_of_lines = 0;
  std::string line;
  std::ifstream myfile(fname);

  while (std::getline(myfile, line))
    ++number_of_lines;

  myfile.close();

  return number_of_lines;
}

void pcafitter::writetofile (const char * fname,
    const arma::rowvec & vec)
{
  std::ofstream myfile(fname);

  for (int i=0; i<(int)vec.n_cols; i++)
    myfile << vec(i) << std::endl;

  myfile.close();
}

void pcafitter::readingfromfile (const char * filename,
    arma::rowvec & ptin, arma::rowvec & phiin,
    arma::rowvec & d0in, arma::rowvec & etain,
    arma::rowvec & z0in, arma::mat & coordin,
    arma::mat & layer, arma::mat & ladder,
    arma::mat & module,
    std::map<std::string, int> & subsectors,
    std::map<std::string, int> & subladders,
    std::vector<std::string> & subsectorslist,
    std::vector<std::string> & subladderslist,
    int num_of_ent)
{

  std::string line;
  std::ifstream mytfp;
  mytfp.open (filename, std::ios::in);

  std::getline (mytfp, line);
  for (int i = 0; i < num_of_ent; ++i)
  {
    int fake1, fake2;
    // valori aggiunti solo di controllo
    mytfp >> fake1 >> fake2 ;
#ifdef DEBUG
    std::cout << fake1 << " " << fake2 << std::endl;
#endif
    std::ostringstream osss, ossl;
    osss << std::setfill('0');
    ossl << std::setfill('0');

    for (int j = 0; j < COORDIM; ++j)
    {
      int a, b, c;
      mytfp >> coordin(i, j*3) >>
               coordin(i, j*3+1) >>
               coordin(i, j*3+2) >>
               a >> b >> c;

      layer(i, j) = a;
      ladder(i, j) = b;
      module(i, j) = c;

      osss << std::setw(2) << layer(i, j);
      osss << std::setw(2) << ladder(i, j);
      if (j != COORDIM-1)
        osss<<"-";

      ossl << std::setw(2) << layer(i, j);
      ossl << std::setw(2) << ladder(i, j);
      ossl << std::setw(2) << module(i, j);
      if (j != COORDIM-1)
        ossl<<"-";

    }

    subsectorslist.push_back(osss.str());
    subladderslist.push_back(ossl.str());

    std::map<std::string, int>::iterator its = subsectors.find(osss.str());
    if (its == subsectors.end())
      subsectors[osss.str()] = 1;
    else
      subsectors[osss.str()] += 1;

    std::map<std::string, int>::iterator itl = subladders.find(ossl.str());
    if (itl == subladders.end())
      subladders[ossl.str()] = 1;
    else
      subladders[ossl.str()] += 1;

    mytfp >> ptin(i) >>
             phiin(i) >>
             d0in(i) >>
             etain(i) >>
             z0in(i);
  }

  mytfp.close();
}

void pcafitter::select_bigger_sub (
    const std::map<std::string, int> & sublist,
    bool verbose, int & maxnumber, std::string & slctsubsec )
{
  maxnumber = -1;
  std::map<std::string, int>::const_iterator it = sublist.begin();
  for (; it != sublist.end(); ++it)
  {
    if (it->second > maxnumber)
    {
      maxnumber = it->second;
      slctsubsec = it->first;
    }

    if (verbose)
      std::cout << "Subsector " << it->first << " has " <<
          it->second << " tracks " << std::endl;
  }
}

void pcafitter::extract_sub (const std::vector<std::string> & sublist,
    const std::string & slctsubsec,
    const arma::rowvec & ptin,
    const arma::rowvec & phiin,
    const arma::rowvec & d0in,
    const arma::rowvec & etain,
    const arma::rowvec & z0in,
    const arma::mat & coordin,
    arma::rowvec & pt,
    arma::rowvec & phi,
    arma::rowvec & d0,
    arma::rowvec & eta,
    arma::rowvec & z0,
    arma::mat & coord)
{
  int dim = 0;

  std::vector<std::string>::const_iterator it = sublist.begin();
  for (; it != sublist.end(); ++it)
    if (*it == slctsubsec)
      dim++;

  coord.set_size(dim,3*COORDIM);
  pt.set_size(dim);
  phi.set_size(dim);
  d0.set_size(dim);
  eta.set_size(dim);
  z0.set_size(dim);

  int k = 0;
  it = sublist.begin();
  for (int i=0; it != sublist.end(); ++it, ++i)
  {
    if (*it == slctsubsec)
    {
      for (int j = 0; j < 3*COORDIM; ++j)
        coord(k,j) = coordin(i,j);

      pt(k) = ptin(i);
      phi(k) = phiin(i);
      d0(k) = d0in(i);
      eta(k) = etain(i);
      z0(k) = z0in(i);

      ++k;
    }
  }
}

void pcafitter::compute_pca_constants (
    const arma::rowvec & pt,
    const arma::rowvec & phi,
    const arma::rowvec & d0,
    const arma::rowvec & eta,
    const arma::rowvec & z0,
    const arma::mat & coord,
    arma::mat & cmtx,
    arma::rowvec & q)
{
  arma::mat v = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  v = arma::cov(coord);

#ifdef DEBUG
  /* correlation matrix ricorda su dati standardizzati coincide con la matrice
   *   di covarianza :
   *   z = x -<x> / sigma */
  arma::mat corr = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);

  for (int i=0; i<(3*COORDIM); ++i)
    for (int j=0; j<(3*COORDIM); ++j)
      corr(i,j) = v(i,j) / sqrt(v(i,i)*v(j,j));

  std::cout << "Correlation matrix: " << std::endl;
  std::cout << corr;
#endif

  arma::mat vi = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  vi = arma::inv(v);
  //vi = v.i();

#ifdef DEBUG
  std::cout << "inverse by cov matrix: " << std::endl;
  std::cout << v * vi ;
#endif

  // and so on ...
  arma::mat hcap = arma::zeros<arma::mat>(3*COORDIM,PARAMDIM);
  arma::rowvec paramm = arma::zeros<arma::rowvec>(PARAMDIM);
  arma::rowvec coordm = arma::zeros<arma::rowvec>(3*COORDIM);
  double sum = 1.0e0;

  for (int l=0; l<(int)coord.n_rows; ++l)
  {
    sum += 1.0e0;
    for (int i=0; i<(3*COORDIM); ++i)
      coordm(i) += (coord(l,i)-coordm(i))/sum;

    paramm(PTIDX) += (pt(l)-paramm(PTIDX))/sum;
    paramm(PHIIDX) += (phi(l)-paramm(PHIIDX))/sum;
    paramm(D0IDX) += (d0(l)-paramm(D0IDX))/sum;
    paramm(ETAIDX) += (eta(l)-paramm(ETAIDX))/sum;
    paramm(Z0IDX) += (z0(l)-paramm(Z0IDX))/sum;

    for (int i=0; i<(3*COORDIM); ++i)
    {
      hcap(i,PTIDX) += ((coord(l,i) - coordm(i))*
                    (pt(l) - paramm(PTIDX))-
                    (sum-1.0e0)*hcap(i,PTIDX)/sum)/(sum-1.0e0);

      hcap(i,PHIIDX) += ((coord(l,i) - coordm(i))*
                    (phi(l) - paramm(PHIIDX))-
                    (sum-1.0e0)*hcap(i,PHIIDX)/sum)/(sum-1.0e0);

      hcap(i,D0IDX) += ((coord(l,i) - coordm(i))*
                    (d0(l) - paramm(D0IDX))-
                    (sum-1.0e0)*hcap(i,D0IDX)/sum)/(sum-1.0e0);

      hcap(i,ETAIDX) += ((coord(l,i) - coordm(i))*
                    (eta(l) - paramm(ETAIDX))-
                    (sum-1.0e0)*hcap(i,ETAIDX)/sum)/(sum-1.0e0);

      hcap(i,Z0IDX) += ((coord(l,i) - coordm(i))*
                    (z0(l) - paramm(Z0IDX))-
                    (sum-1.0e0)*hcap(i,Z0IDX)/sum)/(sum-1.0e0);

    }
  }

  for (int i=0; i<PARAMDIM; ++i)
    for (int l=0; l<(3*COORDIM); ++l)
      for (int m=0; m<(3*COORDIM); ++m)
        cmtx(i,l) += vi(l,m) * hcap (m,i);

#ifdef DEBUG
  std::cout << "C matrix: " << std::endl;
  std::cout << cmtx;
#endif

  for (int i=0; i<PARAMDIM; ++i)
  {
    q(i) = paramm(i);
    for (int l=0; l<(3*COORDIM); ++l)
      q(i) -= cmtx(i,l)*coordm(l);
  }

#ifdef DEBUG
  std::cout << "Q vector: " << std::endl;
  for (int i=0; i<PARAMDIM; ++i)
    std::cout << q(i) << std::endl;
#endif

}
<|endoftext|>


<commit_before>/*
    SWARM

    Copyright (C) 2012-2020 Torbjorn Rognes and Frederic Mahe

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: Torbjorn Rognes <torognes@ifi.uio.no>,
    Department of Informatics, University of Oslo,
    PO Box 1080 Blindern, NO-0316 Oslo, Norway
*/

#include "swarm.h"

inline void nt_set(char * seq, unsigned int pos, unsigned int base)
{
  unsigned int whichlong = pos >> 5;
  uint64_t shift = (pos & 31) << 1;
  uint64_t mask = 3ULL << shift;
  uint64_t x = (reinterpret_cast<uint64_t *>(seq))[whichlong];
  x &= ~ mask;
  x |= (static_cast<uint64_t>(base)) << shift;
  (reinterpret_cast<uint64_t *>(seq))[whichlong] = x;
}

inline void seq_copy(char * a,
                     unsigned int a_start,
                     char * b,
                     unsigned int b_start,
                     unsigned int length)
{
  /* copy part of the compressed sequence b to a */
  for(auto i = 0U; i < length; i++) {
    nt_set(a, a_start + i, nt_extract(b, b_start + i));
  }
}

inline bool seq_identical(char * a,
                          unsigned int a_start,
                          char * b,
                          unsigned int b_start,
                          unsigned int length)
{
  /* compare parts of two compressed sequences a and b */
  /* return false if different, true if identical */

  bool equal {true};
  for(auto i = 0U; i < length; i++) {
    equal = equal && (nt_extract(a, a_start + i) ==
                      nt_extract(b, b_start + i));
  }
  return equal;
}

void generate_variant_sequence(char * seed_sequence,
                               unsigned int seed_seqlen,
                               struct var_s * var,
                               char * seq,
                               unsigned int * seqlen)
{
  /* generate the actual sequence of a variant */

  assert((var->type == substitution) ||
         (var->type == deletion) ||
         (var->type == insertion));

  switch (var->type)
    {
    case substitution:
      memcpy(seq, seed_sequence, nt_bytelength(seed_seqlen));
      nt_set(seq, var->pos, var->base);
      * seqlen = seed_seqlen;
      break;

    case deletion:
      seq_copy(seq, 0,
               seed_sequence, 0,
               var->pos);
      seq_copy(seq, var->pos,
               seed_sequence, var->pos + 1,
               seed_seqlen - var->pos - 1);
      * seqlen = seed_seqlen - 1;
      break;

    case insertion:
      seq_copy(seq, 0,
               seed_sequence, 0,
               var->pos);
      nt_set(seq, var->pos, var->base);
      seq_copy(seq, var->pos + 1,
               seed_sequence, var->pos,
               seed_seqlen - var->pos);
      * seqlen = seed_seqlen + 1;
      break;
    }
}

bool check_variant(char * seed_sequence,
                   unsigned int seed_seqlen,
                   var_s * var,
                   char * amp_sequence,
                   unsigned int amp_seqlen)
{
  /* make sure seed with given variant is really identical to amp */
  /* we know the hashes are identical */

  assert((var->type == substitution) ||
         (var->type == deletion) ||
         (var->type == insertion));

  bool equal {false};

  switch (var->type)
    {
    case substitution:
      equal = ((seed_seqlen == amp_seqlen) &&
               (seq_identical(seed_sequence, 0,
                              amp_sequence, 0,
                              var->pos)) &&
               (nt_extract(amp_sequence, var->pos) == var->base) &&
               (seq_identical(seed_sequence, var->pos + 1,
                              amp_sequence,  var->pos + 1,
                              seed_seqlen - var->pos - 1)));
      break;

    case deletion:
      equal = (((seed_seqlen - 1) == amp_seqlen) &&
               (seq_identical(seed_sequence, 0,
                              amp_sequence, 0,
                              var->pos)) &&
               (seq_identical(seed_sequence, var->pos + 1,
                              amp_sequence,  var->pos,
                              seed_seqlen - var->pos - 1)));
      break;

    case insertion:
      equal = (((seed_seqlen + 1) == amp_seqlen) &&
               (seq_identical(seed_sequence, 0,
                              amp_sequence, 0,
                              var->pos)) &&
               (nt_extract(amp_sequence, var->pos) == var->base) &&
               (seq_identical(seed_sequence, var->pos,
                              amp_sequence,  var->pos + 1,
                              seed_seqlen - var->pos)));
      break;
    }

  return equal;
}

inline void add_variant(uint64_t hash,
                        unsigned char type,
                        unsigned int pos,
                        unsigned char base,
                        var_s * variant_list,
                        unsigned int * variant_count)
{
#ifdef HASHSTATS
  tries++;
#endif
  var_s * v = variant_list + (*variant_count)++;
  v->hash = hash;
  v->type = type;
  v->pos = pos;
  v->base = base;
}

void generate_variants(char * sequence,
                       unsigned int seqlen,
                       uint64_t hash,
                       var_s * variant_list,
                       unsigned int * variant_count)
{
  /* substitutions */

  for(auto i = 0U; i < seqlen; i++)
    {
      unsigned char base = nt_extract(sequence, i);
      uint64_t hash1 = hash ^ zobrist_value(i, base);
      for(unsigned char v = 0; v < 4; v ++) {
        if (v != base)
          {
            uint64_t hash2 = hash1 ^ zobrist_value(i, v);
            add_variant(hash2, substitution, i, v,
                        variant_list, variant_count);
          }
      }
    }

  /* deletions */

  hash = zobrist_hash_delete_first(reinterpret_cast<unsigned char *>(sequence), seqlen);
  add_variant(hash, deletion, 0, 0, variant_list, variant_count);
  unsigned char base_deleted = nt_extract(sequence, 0);
  for(auto i = 1U; i < seqlen; i++)
    {
      unsigned char v = nt_extract(sequence, i);
      if (v != base_deleted)
        {
          hash ^= zobrist_value(i - 1, base_deleted) ^ zobrist_value(i - 1, v);
          add_variant(hash, deletion, i, 0, variant_list, variant_count);
          base_deleted = v;
        }
    }

  /* insertions */

  hash = zobrist_hash_insert_first(reinterpret_cast<unsigned char *>(sequence), seqlen);
  for(unsigned char v = 0; v < 4; v++)
    {
      uint64_t hash1 = hash ^ zobrist_value(0, v);
      add_variant(hash1, insertion, 0, v, variant_list, variant_count);
    }
  for(auto i = 0U; i < seqlen; i++)
    {
      unsigned char base = nt_extract(sequence, i);
      hash ^= zobrist_value(i, base) ^ zobrist_value(i+1, base);
      for(unsigned char v = 0; v < 4; v++) {
        if (v != base)
          {
            uint64_t hash1 = hash ^ zobrist_value(i + 1, v);
            add_variant(hash1, insertion, i + 1, v,
                        variant_list, variant_count);
          }
      }
    }
}
<commit_msg>avoid magic numbers<commit_after>/*
    SWARM

    Copyright (C) 2012-2020 Torbjorn Rognes and Frederic Mahe

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: Torbjorn Rognes <torognes@ifi.uio.no>,
    Department of Informatics, University of Oslo,
    PO Box 1080 Blindern, NO-0316 Oslo, Norway
*/

#include "swarm.h"

inline void nt_set(char * seq, unsigned int pos, unsigned int base)
{
  constexpr auto divider {5U};
  constexpr auto max_range {31U};
  constexpr auto two_bits {3ULL};  // '... 0011' in binary
  unsigned int whichlong = pos >> divider;
  uint64_t shift = (pos & max_range) << 1;  // 0, 2, 4, 6, ..., 60, 62
  uint64_t mask = two_bits << shift;
  uint64_t x = (reinterpret_cast<uint64_t *>(seq))[whichlong];
  x &= ~ mask;
  x |= (static_cast<uint64_t>(base)) << shift;
  (reinterpret_cast<uint64_t *>(seq))[whichlong] = x;
}

inline void seq_copy(char * a,
                     unsigned int a_start,
                     char * b,
                     unsigned int b_start,
                     unsigned int length)
{
  /* copy part of the compressed sequence b to a */
  for(auto i = 0U; i < length; i++) {
    nt_set(a, a_start + i, nt_extract(b, b_start + i));
  }
}

inline bool seq_identical(char * a,
                          unsigned int a_start,
                          char * b,
                          unsigned int b_start,
                          unsigned int length)
{
  /* compare parts of two compressed sequences a and b */
  /* return false if different, true if identical */

  bool equal {true};
  for(auto i = 0U; i < length; i++) {
    equal = equal && (nt_extract(a, a_start + i) ==
                      nt_extract(b, b_start + i));
  }
  return equal;
}

void generate_variant_sequence(char * seed_sequence,
                               unsigned int seed_seqlen,
                               struct var_s * var,
                               char * seq,
                               unsigned int * seqlen)
{
  /* generate the actual sequence of a variant */

  assert((var->type == substitution) ||
         (var->type == deletion) ||
         (var->type == insertion));

  switch (var->type)
    {
    case substitution:
      memcpy(seq, seed_sequence, nt_bytelength(seed_seqlen));
      nt_set(seq, var->pos, var->base);
      * seqlen = seed_seqlen;
      break;

    case deletion:
      seq_copy(seq, 0,
               seed_sequence, 0,
               var->pos);
      seq_copy(seq, var->pos,
               seed_sequence, var->pos + 1,
               seed_seqlen - var->pos - 1);
      * seqlen = seed_seqlen - 1;
      break;

    case insertion:
      seq_copy(seq, 0,
               seed_sequence, 0,
               var->pos);
      nt_set(seq, var->pos, var->base);
      seq_copy(seq, var->pos + 1,
               seed_sequence, var->pos,
               seed_seqlen - var->pos);
      * seqlen = seed_seqlen + 1;
      break;
    }
}

bool check_variant(char * seed_sequence,
                   unsigned int seed_seqlen,
                   var_s * var,
                   char * amp_sequence,
                   unsigned int amp_seqlen)
{
  /* make sure seed with given variant is really identical to amp */
  /* we know the hashes are identical */

  assert((var->type == substitution) ||
         (var->type == deletion) ||
         (var->type == insertion));

  bool equal {false};

  switch (var->type)
    {
    case substitution:
      equal = ((seed_seqlen == amp_seqlen) &&
               (seq_identical(seed_sequence, 0,
                              amp_sequence, 0,
                              var->pos)) &&
               (nt_extract(amp_sequence, var->pos) == var->base) &&
               (seq_identical(seed_sequence, var->pos + 1,
                              amp_sequence,  var->pos + 1,
                              seed_seqlen - var->pos - 1)));
      break;

    case deletion:
      equal = (((seed_seqlen - 1) == amp_seqlen) &&
               (seq_identical(seed_sequence, 0,
                              amp_sequence, 0,
                              var->pos)) &&
               (seq_identical(seed_sequence, var->pos + 1,
                              amp_sequence,  var->pos,
                              seed_seqlen - var->pos - 1)));
      break;

    case insertion:
      equal = (((seed_seqlen + 1) == amp_seqlen) &&
               (seq_identical(seed_sequence, 0,
                              amp_sequence, 0,
                              var->pos)) &&
               (nt_extract(amp_sequence, var->pos) == var->base) &&
               (seq_identical(seed_sequence, var->pos,
                              amp_sequence,  var->pos + 1,
                              seed_seqlen - var->pos)));
      break;
    }

  return equal;
}

inline void add_variant(uint64_t hash,
                        unsigned char type,
                        unsigned int pos,
                        unsigned char base,
                        var_s * variant_list,
                        unsigned int * variant_count)
{
#ifdef HASHSTATS
  tries++;
#endif
  var_s * v = variant_list + (*variant_count)++;
  v->hash = hash;
  v->type = type;
  v->pos = pos;
  v->base = base;
}

void generate_variants(char * sequence,
                       unsigned int seqlen,
                       uint64_t hash,
                       var_s * variant_list,
                       unsigned int * variant_count)
{
  /* substitutions */

  for(auto i = 0U; i < seqlen; i++)
    {
      unsigned char base = nt_extract(sequence, i);
      uint64_t hash1 = hash ^ zobrist_value(i, base);
      for(unsigned char v = 0; v < 4; v ++) {
        if (v != base)
          {
            uint64_t hash2 = hash1 ^ zobrist_value(i, v);
            add_variant(hash2, substitution, i, v,
                        variant_list, variant_count);
          }
      }
    }

  /* deletions */

  hash = zobrist_hash_delete_first(reinterpret_cast<unsigned char *>(sequence), seqlen);
  add_variant(hash, deletion, 0, 0, variant_list, variant_count);
  unsigned char base_deleted = nt_extract(sequence, 0);
  for(auto i = 1U; i < seqlen; i++)
    {
      unsigned char v = nt_extract(sequence, i);
      if (v != base_deleted)
        {
          hash ^= zobrist_value(i - 1, base_deleted) ^ zobrist_value(i - 1, v);
          add_variant(hash, deletion, i, 0, variant_list, variant_count);
          base_deleted = v;
        }
    }

  /* insertions */

  hash = zobrist_hash_insert_first(reinterpret_cast<unsigned char *>(sequence), seqlen);
  for(unsigned char v = 0; v < 4; v++)
    {
      uint64_t hash1 = hash ^ zobrist_value(0, v);
      add_variant(hash1, insertion, 0, v, variant_list, variant_count);
    }
  for(auto i = 0U; i < seqlen; i++)
    {
      unsigned char base = nt_extract(sequence, i);
      hash ^= zobrist_value(i, base) ^ zobrist_value(i+1, base);
      for(unsigned char v = 0; v < 4; v++) {
        if (v != base)
          {
            uint64_t hash1 = hash ^ zobrist_value(i + 1, v);
            add_variant(hash1, insertion, i + 1, v,
                        variant_list, variant_count);
          }
      }
    }
}
<|endoftext|>