<commit_before>#include <iostream>
#include <cstdlib>
#include <ctime>
#include "graph.h"
#include "../test_helpers.h"

int main(int argc, char const *argv[]) {
  TestHelper th;

  {
    AdjacencyMatrixDiGraph g(10);
    g.add_edge({ 1, 2 });
    g.add_edge({ 2, 3 });
    g.add_edge({ 2, 8 });
    g.add_edge({ 2, 9 });
    g.add_edge({ 8, 5 });
    g.add_edge({ 5, 6 });
    g.add_edge({ 6, 1 });

    for (auto it = g.adjacent(2); !it.end(); ++it) {
      std::cout << (*it).second << " ";
    }
    std::cout << std::endl;

    std::cout << "All edges: ";
    for (auto it = g.edges(); !it.end(); ++it) {
      std::cout << "(" << (*it).first << "," << (*it).second << ") ";
    }
    std::cout << std::endl;
  }

  {
    WeightedAdjacencyListDiGraph wg;
    wg.set_edge_weight({ 1, 2 }, 1);
    wg.set_edge_weight({ 2, 3 }, 2);
    wg.set_edge_weight({ 2, 8 }, 3);
    wg.set_edge_weight({ 2, 9 }, 4);
    wg.set_edge_weight({ 8, 5 }, 5);
    wg.set_edge_weight({ 5, 6 }, 5);
    wg.set_edge_weight({ 6, 1 }, 7);

    for (auto it = wg.adjacent(2); !it.end(); ++it) {
      std::cout << (*it).first.second << "(" << (*it).second << ") ";
    }
    std::cout << std::endl;

    std::cout << "All edges: ";
    for (auto it = wg.edges(); !it.end(); ++it) {
      std::cout << "(" << (*it).first.first << ","
                << (*it).first.second << "):"
                << (*it).second << " ";
    }
    std::cout << std::endl;
  }

  th.summary();
  return 0;
}
<commit_msg>Fix broken graph tests<commit_after>#include <iostream>
#include <cstdlib>
#include <ctime>
#include "graph.h"
#include "../test_helpers.h"

int main(int argc, char const *argv[]) {
  TestHelper th;

  {
    AdjacencyMatrixDiGraph g(10);
    g.add_edge({ 1, 2 });
    g.add_edge({ 2, 3 });
    g.add_edge({ 2, 8 });
    g.add_edge({ 2, 9 });
    g.add_edge({ 8, 5 });
    g.add_edge({ 5, 6 });
    g.add_edge({ 6, 1 });

    for (auto it = g.adjacent(2); !it.end(); ++it) {
      std::cout << (*it).second << " ";
    }
    std::cout << std::endl;

    std::cout << "All edges: ";
    for (auto it = g.edges(); !it.end(); ++it) {
      std::cout << "(" << (*it).first << "," << (*it).second << ") ";
    }
    std::cout << std::endl;
  }

  {
    WeightedAdjacencyListDiGraph<int> wg;
    wg.set_edge_weight({ 1, 2 }, 1);
    wg.set_edge_weight({ 2, 3 }, 2);
    wg.set_edge_weight({ 2, 8 }, 3);
    wg.set_edge_weight({ 2, 9 }, 4);
    wg.set_edge_weight({ 8, 5 }, 5);
    wg.set_edge_weight({ 5, 6 }, 5);
    wg.set_edge_weight({ 6, 1 }, 7);

    for (auto it = wg.adjacent(2); !it.end(); ++it) {
      std::cout << (*it).first.second << "(" << (*it).second << ") ";
    }
    std::cout << std::endl;

    std::cout << "All edges: ";
    for (auto it = wg.edges(); !it.end(); ++it) {
      std::cout << "(" << (*it).first.first << ","
                << (*it).first.second << "):"
                << (*it).second << " ";
    }
    std::cout << std::endl;
  }

  th.summary();
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "assert.h"

#include "chainparams.h"
#include "main.h"
#include "util.h"

#include <boost/assign/list_of.hpp>

using namespace boost::assign;

struct SeedSpec6 {
    uint8_t addr[16];
    uint16_t port;
};

#include "chainparamsseeds.h"

//
// Main network
//

// Convert the pnSeeds6 array into usable address objects.
static void convertSeed6(std::vector<CAddress> &vSeedsOut, const SeedSpec6 *data, unsigned int count)
{
    // It'll only connect to one or two seed nodes because once it connects,
    // it'll get a pile of addresses with newer timestamps.
    // Seed nodes are given a random 'last seen time' of between one and two
    // weeks ago.
    const int64_t nOneWeek = 7*24*60*60;
    for (unsigned int i = 0; i < count; i++)
    {
        struct in6_addr ip;
        memcpy(&ip, data[i].addr, sizeof(ip));
        CAddress addr(CService(ip, data[i].port));
        addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
        vSeedsOut.push_back(addr);
    }
}

class CMainParams : public CChainParams {
public:
    CMainParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x1f;
        pchMessageStart[1] = 0x22;
        pchMessageStart[2] = 0x05;
        pchMessageStart[3] = 0x31;
        vAlertPubKey = ParseHex("");
        nDefaultPort = 31000;
        nRPCPort = 31500;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 16);

        // Build the genesis block. Note that the output of the genesis coinbase cannot
        // be spent as it did not originally exist in the database.
        //
        //CBlock(hash=000001faef25dec4fbcf906e6242621df2c183bf232f263d0ba5b101911e4563, ver=1, hashPrevBlock=0000000000000000000000000000000000000000000000000000000000000000, hashMerkleRoot=12630d16a97f24b287c8c2594dda5fb98c9e6c70fc61d44191931ea2aa08dc90, nTime=1393221600, nBits=1e0fffff, nNonce=164482, vtx=1, vchBlockSig=)
        //  Coinbase(hash=12630d16a9, nTime=1393221600, ver=1, vin.size=1, vout.size=1, nLockTime=0)
        //    CTxIn(COutPoint(0000000000, 4294967295), coinbase 00012a24323020466562203230313420426974636f696e2041544d7320636f6d6520746f20555341)
        //    CTxOut(empty)
        //  vMerkleTree: 12630d16a9
        const char* pszTimestamp = "2015 DarkSilk is Born";
        CTransaction txNew;
        txNew.nTime = 1438578382; //Change to current UNIX Time when generating genesis
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig = CScript() << 0 << CBigNum(42) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].SetEmpty();
        genesis.vtx.push_back(txNew);
        genesis.hashPrevBlock = 0;
        genesis.hashMerkleRoot = genesis.BuildMerkleTree();
        genesis.nVersion = 1;
        genesis.nTime    = 1438578382; //Change to current UNIX Time of generated genesis
        genesis.nBits    = 504365040;
        genesis.nNonce   = 1810177;

        hashGenesisBlock = genesis.GetHash();

        //// debug print

        /*
        printf("Gensis Hash: %s\n", genesis.GetHash().ToString().c_str());
        printf("Gensis Hash Merkle: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("Gensis nTime: %u\n", genesis.nTime);
        printf("Gensis nBits: %08x\n", genesis.nBits);
        printf("Gensis Nonce: %u\n\n\n", genesis.nNonce);
        */

        assert(hashGenesisBlock == uint256("0xfa5e0f06963f850fe0896359c6ed1495d8414525d9a78e62b483243bf2e0cbc4"));
        assert(genesis.hashMerkleRoot == uint256("0xfb3953d6e08d7ccd5230ee997430e1b3eac702b8f149146a6c2239fd51207934"));

        base58Prefixes[PUBKEY_ADDRESS] = list_of(30);                     //DarkSilk addresses start with 'D'
        base58Prefixes[SCRIPT_ADDRESS] = list_of(10);                     //DarkSilk script addresses start with '5'
        base58Prefixes[SECRET_KEY] =     list_of(140);                    //DarkSilk private keys start with 'dskey'
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x02)(0xFE)(0x52)(0x7D); //DarkSilk BIP32 pubkeys start with 'drks'
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x02)(0xFE)(0x52)(0x8C); //DarkSilk BIP32 prvkeys start with 'drky'

        convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));

        nLastPOWBlock = 420001;
    }

    virtual const CBlock& GenesisBlock() const { return genesis; }
    virtual Network NetworkID() const { return CChainParams::MAIN; }

    virtual const vector<CAddress>& FixedSeeds() const {
        return vFixedSeeds;
    }
protected:
    CBlock genesis;
    vector<CAddress> vFixedSeeds;
};
static CMainParams mainParams;

//
// Testnet
//

class CTestNetParams : public CMainParams {
public:
    CTestNetParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x1f;
        pchMessageStart[1] = 0x22;
        pchMessageStart[2] = 0x05;
        pchMessageStart[3] = 0x30;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 16);
        vAlertPubKey = ParseHex("");
        nDefaultPort = 31750;
        nRPCPort = 31800;
        strDataDir = "testnet";

        // Modify the testnet genesis block so the timestamp is valid for a later start.
        genesis.nTime = 1438578972;
        genesis.nBits  = 0;
        genesis.nNonce = 0;
        hashGenesisBlock = genesis.GetHash();

        //printf("Test Gensis Hash: %s\n", genesis.GetHash().ToString().c_str());
        assert(hashGenesisBlock == uint256("0x5df91956099936ddb98e30a242ae10f1464665d843b30d40ee406a70bc340dc6"));

        vFixedSeeds.clear();
        vSeeds.clear();

        base58Prefixes[PUBKEY_ADDRESS] = list_of(30);                     //DarkSilk addresses start with 'D'
        base58Prefixes[SCRIPT_ADDRESS] = list_of(10);                     //DarkSilk script addresses start with '5'
        base58Prefixes[SECRET_KEY] =     list_of(140);                    //DarkSilk private keys start with 'dskey'
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x02)(0xFE)(0x52)(0x7D); //DarkSilk BIP32 pubkeys start with 'drks'
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x02)(0xFE)(0x52)(0x8C); //DarkSilk BIP32 prvkeys start with 'drky'

        convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));

        nLastPOWBlock = 0x7fffffff;
    }
    virtual Network NetworkID() const { return CChainParams::TESTNET; }
};
static CTestNetParams testNetParams;

static CChainParams *pCurrentParams = &mainParams;

const CChainParams &Params() {
    return *pCurrentParams;
}

void SelectParams(CChainParams::Network network) {
    switch (network) {
        case CChainParams::MAIN:
            pCurrentParams = &mainParams;
            break;
        case CChainParams::TESTNET:
            pCurrentParams = &testNetParams;
            break;
        default:
            assert(false && "Unimplemented network");
            return;
    }
}

bool SelectParamsFromCommandLine() {

    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet) {
        SelectParams(CChainParams::TESTNET);
    } else {
        SelectParams(CChainParams::MAIN);
    }
    return true;
}
<commit_msg>Update chainparams.cpp<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "assert.h"

#include "chainparams.h"
#include "main.h"
#include "util.h"

#include <boost/assign/list_of.hpp>

using namespace boost::assign;

struct SeedSpec6 {
    uint8_t addr[16];
    uint16_t port;
};

#include "chainparamsseeds.h"

//
// Main network
//

// Convert the pnSeeds6 array into usable address objects.
static void convertSeed6(std::vector<CAddress> &vSeedsOut, const SeedSpec6 *data, unsigned int count)
{
    // It'll only connect to one or two seed nodes because once it connects,
    // it'll get a pile of addresses with newer timestamps.
    // Seed nodes are given a random 'last seen time' of between one and two
    // weeks ago.
    const int64_t nOneWeek = 7*24*60*60;
    for (unsigned int i = 0; i < count; i++)
    {
        struct in6_addr ip;
        memcpy(&ip, data[i].addr, sizeof(ip));
        CAddress addr(CService(ip, data[i].port));
        addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
        vSeedsOut.push_back(addr);
    }
}

class CMainParams : public CChainParams {
public:
    CMainParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x1f;
        pchMessageStart[1] = 0x22;
        pchMessageStart[2] = 0x05;
        pchMessageStart[3] = 0x31;
        vAlertPubKey = ParseHex("");
        nDefaultPort = 31000;
        nRPCPort = 31500;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 16);

        // Build the genesis block. Note that the output of the genesis coinbase cannot
        // be spent as it did not originally exist in the database.

        const char* pszTimestamp = "2015 DarkSilk is Born";
        CTransaction txNew;
        txNew.nTime = 1438578382; //Change to current UNIX Time when generating genesis
        txNew.vin.resize(1);
        txNew.vout.resize(1);
        txNew.vin[0].scriptSig = CScript() << 0 << CBigNum(42) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
        txNew.vout[0].SetEmpty();
        genesis.vtx.push_back(txNew);
        genesis.hashPrevBlock = 0;
        genesis.hashMerkleRoot = genesis.BuildMerkleTree();
        genesis.nVersion = 1;
        genesis.nTime    = 1438578382; //Change to current UNIX Time of generated genesis
        genesis.nBits    = 504365040;
        genesis.nNonce   = 1810177;

        hashGenesisBlock = genesis.GetHash();

        //// debug print

        /*
        printf("Gensis Hash: %s\n", genesis.GetHash().ToString().c_str());
        printf("Gensis Hash Merkle: %s\n", genesis.hashMerkleRoot.ToString().c_str());
        printf("Gensis nTime: %u\n", genesis.nTime);
        printf("Gensis nBits: %08x\n", genesis.nBits);
        printf("Gensis Nonce: %u\n\n\n", genesis.nNonce);
        */

        assert(hashGenesisBlock == uint256("0xfa5e0f06963f850fe0896359c6ed1495d8414525d9a78e62b483243bf2e0cbc4"));
        assert(genesis.hashMerkleRoot == uint256("0xfb3953d6e08d7ccd5230ee997430e1b3eac702b8f149146a6c2239fd51207934"));

        base58Prefixes[PUBKEY_ADDRESS] = list_of(30);                     //DarkSilk addresses start with 'D'
        base58Prefixes[SCRIPT_ADDRESS] = list_of(10);                     //DarkSilk script addresses start with '5'
        base58Prefixes[SECRET_KEY] =     list_of(140);                    //DarkSilk private keys start with 'dskey'
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x02)(0xFE)(0x52)(0x7D); //DarkSilk BIP32 pubkeys start with 'drks'
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x02)(0xFE)(0x52)(0x8C); //DarkSilk BIP32 prvkeys start with 'drky'

        convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));

        nLastPOWBlock = 420001;
    }

    virtual const CBlock& GenesisBlock() const { return genesis; }
    virtual Network NetworkID() const { return CChainParams::MAIN; }

    virtual const vector<CAddress>& FixedSeeds() const {
        return vFixedSeeds;
    }
protected:
    CBlock genesis;
    vector<CAddress> vFixedSeeds;
};
static CMainParams mainParams;

//
// Testnet
//

class CTestNetParams : public CMainParams {
public:
    CTestNetParams() {
        // The message start string is designed to be unlikely to occur in normal data.
        // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
        // a large 4-byte int at any alignment.
        pchMessageStart[0] = 0x1f;
        pchMessageStart[1] = 0x22;
        pchMessageStart[2] = 0x05;
        pchMessageStart[3] = 0x30;
        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 16);
        vAlertPubKey = ParseHex("");
        nDefaultPort = 31750;
        nRPCPort = 31800;
        strDataDir = "testnet";

        // Modify the testnet genesis block so the timestamp is valid for a later start.
        genesis.nTime = 1438578972;
        genesis.nBits  = 0;
        genesis.nNonce = 0;
        hashGenesisBlock = genesis.GetHash();

        //printf("Test Gensis Hash: %s\n", genesis.GetHash().ToString().c_str());
        assert(hashGenesisBlock == uint256("0x5df91956099936ddb98e30a242ae10f1464665d843b30d40ee406a70bc340dc6"));

        vFixedSeeds.clear();
        vSeeds.clear();

        base58Prefixes[PUBKEY_ADDRESS] = list_of(30);                     //DarkSilk addresses start with 'D'
        base58Prefixes[SCRIPT_ADDRESS] = list_of(10);                     //DarkSilk script addresses start with '5'
        base58Prefixes[SECRET_KEY] =     list_of(140);                    //DarkSilk private keys start with 'dskey'
        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x02)(0xFE)(0x52)(0x7D); //DarkSilk BIP32 pubkeys start with 'drks'
        base58Prefixes[EXT_SECRET_KEY] = list_of(0x02)(0xFE)(0x52)(0x8C); //DarkSilk BIP32 prvkeys start with 'drky'

        convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));

        nLastPOWBlock = 0x7fffffff;
    }
    virtual Network NetworkID() const { return CChainParams::TESTNET; }
};
static CTestNetParams testNetParams;

static CChainParams *pCurrentParams = &mainParams;

const CChainParams &Params() {
    return *pCurrentParams;
}

void SelectParams(CChainParams::Network network) {
    switch (network) {
        case CChainParams::MAIN:
            pCurrentParams = &mainParams;
            break;
        case CChainParams::TESTNET:
            pCurrentParams = &testNetParams;
            break;
        default:
            assert(false && "Unimplemented network");
            return;
    }
}

bool SelectParamsFromCommandLine() {

    bool fTestNet = GetBoolArg("-testnet", false);

    if (fTestNet) {
        SelectParams(CChainParams::TESTNET);
    } else {
        SelectParams(CChainParams::MAIN);
    }
    return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    // How many times we expect transactions after the last checkpoint to
    // be slower. This number is a compromise, as it can't be accurate for
    // every system. When reindexing from a fast disk with a slow CPU, it
    // can be up to 20, while when downloading from a slow network with a
    // fast multicore CPU, it won't be much higher than 1.
    static const double fSigcheckVerificationFactor = 5.0;

    struct CCheckpointData {
        const MapCheckpoints *mapCheckpoints;
        int64 nTimeLastCheckpoint;
        int64 nTransactionsLastCheckpoint;
        double fTransactionsPerDay;
    };

    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        ( 0, uint256("0x0e286802e2a399cad2f4a6e41f0584a162dddfb303b78839b690e77dee2310e1"))
        ( 50, uint256("0x3145c1a9874355a6dd6974788581d12454542de407c1ed7a6e749faa24ae9f80"))
        ( 100, uint256("0x59cc0628179755b56e89eb279962749a4c29b03b15c4707ef13cd929d1184e17"))
        ( 150, uint256("0x177a415b863f283337fca2eabeb37d9050ed6a28f026edd3089f4bd1cf6983e4"))
        ( 200, uint256("0x62b166411cd77b7ec40700ad3bf0655f2ee9c9070cde51d3cdfefd5a0991633a"))
        ( 400, uint256("0xe409b3dd7afc41681fb95dd3b0ecb1965756612765be0d5b8b20fadc876e44e2"))
        ( 500, uint256("0x177c4ac380ef413f297e69e6d98b11c546ac21299e7fb96f5e729dc74e6d2840"))
        ( 600, uint256("0x871b47e02d586ac2f8458b4b8bf3b821752ad79ba82be8af42b397b72588d7dc"))
        ( 700, uint256("0xef95e03d8d34efde9dcff9c69dc06139cd5ebc799672d37e09f1cdac2dfa696d"))
        ( 800, uint256("0xdb8228716e3ee18b15dbc63812043504ca5a53a7efdbe85a71917a85b3446f42"))
        ( 1000, uint256("0x8b43e13cdb15c856161194bd39e3c61f65a1b8b1ea6bb417be64777b5c8f184e"))
        ( 1500, uint256("0xfcba0ff54c6b784cd0571ce4deb8bce5239cadc10cf3585c3b5cca6548bac5e7"))
        ( 2500, uint256("0x18c7ea7311df97744082ccfee0bb6ec6198ee5063f6262777eb379817f4dd420"))
        ( 5000, uint256("0x97f43986ccd5b8fcb655187a3c5f5dee1fc6c06d30f19489c0a32fb79b705dd3"))
        ( 7500, uint256("0x6dcdc428bacafef41b5a7d9d465f83dd4d0cbe582beecc04f54fb010999c5760"))
        ( 9000, uint256("0x9d73d2ddffb61293561100150ad36002697cdbff0cd6514698933ac0f2271359"))
        ( 10000, uint256("0xdbc365e31501d29778a92978ae4ea6618434a42ea7d17e4f196a1e02f96fdbe6"))
        ( 11000, uint256("0xa44804e286cdadf919b370f1701c59c9da6f05831b8f386968cbcb2efd9dbe53"))
        ( 12000, uint256("0x190ca505a4d75a22bfdac780583c35f0aac4fa6412f4af07df01ccf66defa391"))
        ( 13000, uint256("0x4c64525e39e243d7e0348fca39a893f1a0ca51762ad10384ac9d32cdc1d28af8"))
        ;

    static const CCheckpointData data = {
            &mapCheckpoints,
            1410302539, // * UNIX timestamp of last checkpoint block
            2179203,    // * total number of transactions between genesis and last checkpoint
                        //   (the tx=... number in the SetBestChain debug.log lines)
            8000.0     // * estimated number of transactions per day after checkpoint
        };

    static MapCheckpoints mapCheckpointsTestnet =
        boost::assign::map_list_of
        (   546, uint256("0xa0fea99a6897f531600c8ae53367b126824fd6a847b2b2b73817a95b8e27e602"))
        ;
    static const CCheckpointData dataTestnet = {
        &mapCheckpointsTestnet,
        1365458829,
        547,
        576
    };

    const CCheckpointData &Checkpoints() {
        if (fTestNet)
            return dataTestnet;
        else
            return data;
    }

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (!GetBoolArg("-checkpoints", true))
            return true;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
        if (i == checkpoints.end()) return true;
        return hash == i->second;
    }

    // Guess how far we are in the verification process at the given block index
    double GuessVerificationProgress(CBlockIndex *pindex) {
        if (pindex==NULL)
            return 0.0;

        int64 nNow = time(NULL);

        double fWorkBefore = 0.0; // Amount of work done before pindex
        double fWorkAfter = 0.0;  // Amount of work left after pindex (estimated)
        // Work is defined as: 1.0 per transaction before the last checkoint, and
        // fSigcheckVerificationFactor per transaction after.

        const CCheckpointData &data = Checkpoints();

        if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
            double nCheapBefore = pindex->nChainTx;
            double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
            double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore;
            fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
        } else {
            double nCheapBefore = data.nTransactionsLastCheckpoint;
            double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
            double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
            fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
        }

        return fWorkBefore / (fWorkBefore + fWorkAfter);
    }

    int GetTotalBlocksEstimate()
    {
        if (!GetBoolArg("-checkpoints", true))
            return 0;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        return checkpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (!GetBoolArg("-checkpoints", true))
            return NULL;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<commit_msg>Added checkpoints up to block 16000<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    // How many times we expect transactions after the last checkpoint to
    // be slower. This number is a compromise, as it can't be accurate for
    // every system. When reindexing from a fast disk with a slow CPU, it
    // can be up to 20, while when downloading from a slow network with a
    // fast multicore CPU, it won't be much higher than 1.
    static const double fSigcheckVerificationFactor = 5.0;

    struct CCheckpointData {
        const MapCheckpoints *mapCheckpoints;
        int64 nTimeLastCheckpoint;
        int64 nTransactionsLastCheckpoint;
        double fTransactionsPerDay;
    };

    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        ( 0, uint256("0x0e286802e2a399cad2f4a6e41f0584a162dddfb303b78839b690e77dee2310e1"))
        ( 50, uint256("0x3145c1a9874355a6dd6974788581d12454542de407c1ed7a6e749faa24ae9f80"))
        ( 100, uint256("0x59cc0628179755b56e89eb279962749a4c29b03b15c4707ef13cd929d1184e17"))
        ( 150, uint256("0x177a415b863f283337fca2eabeb37d9050ed6a28f026edd3089f4bd1cf6983e4"))
        ( 200, uint256("0x62b166411cd77b7ec40700ad3bf0655f2ee9c9070cde51d3cdfefd5a0991633a"))
        ( 400, uint256("0xe409b3dd7afc41681fb95dd3b0ecb1965756612765be0d5b8b20fadc876e44e2"))
        ( 500, uint256("0x177c4ac380ef413f297e69e6d98b11c546ac21299e7fb96f5e729dc74e6d2840"))
        ( 600, uint256("0x871b47e02d586ac2f8458b4b8bf3b821752ad79ba82be8af42b397b72588d7dc"))
        ( 700, uint256("0xef95e03d8d34efde9dcff9c69dc06139cd5ebc799672d37e09f1cdac2dfa696d"))
        ( 800, uint256("0xdb8228716e3ee18b15dbc63812043504ca5a53a7efdbe85a71917a85b3446f42"))
        ( 1000, uint256("0x8b43e13cdb15c856161194bd39e3c61f65a1b8b1ea6bb417be64777b5c8f184e"))
        ( 1500, uint256("0xfcba0ff54c6b784cd0571ce4deb8bce5239cadc10cf3585c3b5cca6548bac5e7"))
        ( 2500, uint256("0x18c7ea7311df97744082ccfee0bb6ec6198ee5063f6262777eb379817f4dd420"))
        ( 5000, uint256("0x97f43986ccd5b8fcb655187a3c5f5dee1fc6c06d30f19489c0a32fb79b705dd3"))
        ( 7500, uint256("0x6dcdc428bacafef41b5a7d9d465f83dd4d0cbe582beecc04f54fb010999c5760"))
        ( 9000, uint256("0x9d73d2ddffb61293561100150ad36002697cdbff0cd6514698933ac0f2271359"))
        ( 10000, uint256("0xdbc365e31501d29778a92978ae4ea6618434a42ea7d17e4f196a1e02f96fdbe6"))
        ( 11000, uint256("0xa44804e286cdadf919b370f1701c59c9da6f05831b8f386968cbcb2efd9dbe53"))
        ( 12000, uint256("0x190ca505a4d75a22bfdac780583c35f0aac4fa6412f4af07df01ccf66defa391"))
        ( 13000, uint256("0x4c64525e39e243d7e0348fca39a893f1a0ca51762ad10384ac9d32cdc1d28af8"))
        ( 14000, uint256("0x0f1dbf47e04a3273951d907d2edf583690e6839f1bd1dc2da2d0674815ff98d9"))
        ( 15000, uint256("0x369a6d6c51920ace864469898918da9fc6b22c58ef416c8f2a573f7e3b5c9b37"))
        ( 16000, uint256("0x2eaadf4e77d6ed0a5d4317ba5f053ef57465c02ef027fe893fe4ade19e97012b"))

        ;

    static const CCheckpointData data = {
            &mapCheckpoints,
            1410302539, // * UNIX timestamp of last checkpoint block
            2179203,    // * total number of transactions between genesis and last checkpoint
                        //   (the tx=... number in the SetBestChain debug.log lines)
            8000.0     // * estimated number of transactions per day after checkpoint
        };

    static MapCheckpoints mapCheckpointsTestnet =
        boost::assign::map_list_of
        (   546, uint256("0xa0fea99a6897f531600c8ae53367b126824fd6a847b2b2b73817a95b8e27e602"))
        ;
    static const CCheckpointData dataTestnet = {
        &mapCheckpointsTestnet,
        1365458829,
        547,
        576
    };

    const CCheckpointData &Checkpoints() {
        if (fTestNet)
            return dataTestnet;
        else
            return data;
    }

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (!GetBoolArg("-checkpoints", true))
            return true;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
        if (i == checkpoints.end()) return true;
        return hash == i->second;
    }

    // Guess how far we are in the verification process at the given block index
    double GuessVerificationProgress(CBlockIndex *pindex) {
        if (pindex==NULL)
            return 0.0;

        int64 nNow = time(NULL);

        double fWorkBefore = 0.0; // Amount of work done before pindex
        double fWorkAfter = 0.0;  // Amount of work left after pindex (estimated)
        // Work is defined as: 1.0 per transaction before the last checkoint, and
        // fSigcheckVerificationFactor per transaction after.

        const CCheckpointData &data = Checkpoints();

        if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
            double nCheapBefore = pindex->nChainTx;
            double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
            double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore;
            fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
        } else {
            double nCheapBefore = data.nTransactionsLastCheckpoint;
            double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
            double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
            fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
        }

        return fWorkBefore / (fWorkBefore + fWorkAfter);
    }

    int GetTotalBlocksEstimate()
    {
        if (!GetBoolArg("-checkpoints", true))
            return 0;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        return checkpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (!GetBoolArg("-checkpoints", true))
            return NULL;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2001-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 */

#ifndef __BASE__CHUNK_GENERATOR_HH__
#define __BASE__CHUNK_GENERATOR_HH__

/**
 * @file
 * Declaration and inline definition of ChunkGenerator object.
 */

#include <algorithm>

#include "base/intmath.hh"
#include "base/types.hh"

/**
 * This class takes an arbitrary memory region (address/length pair)
 * and generates a series of appropriately (e.g. block- or page-)
 * aligned chunks covering the same region.
 *
 * Example usage:

\code
    for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
        doSomethingChunky(gen.addr(), gen.size());
    }
\endcode
 */
class ChunkGenerator
{
  private:
    /** The starting address of the current chunk. */
    Addr curAddr;
    /** The starting address of the next chunk (after the current one). */
    Addr nextAddr;
    /** The size of the current chunk (in bytes). */
    unsigned  curSize;
    /** The number of bytes remaining in the region after the current chunk. */
    unsigned  sizeLeft;
    /** The start address so we can calculate offset in writing block. */
    const Addr startAddr;
    /** The maximum chunk size, e.g., the cache block size or page size. */
    const unsigned chunkSize;

  public:
    /**
     * Constructor.
     * @param _startAddr The starting address of the region.
     * @param totalSize The total size of the region.
     * @param _chunkSize The size/alignment of chunks into which
     *    the region should be decomposed.
     */
    ChunkGenerator(Addr _startAddr, unsigned totalSize, unsigned _chunkSize)
        : startAddr(_startAddr), chunkSize(_chunkSize)
    {
        // chunkSize must be a power of two
        assert(chunkSize == 0 || isPowerOf2(chunkSize));

        // set up initial chunk.
        curAddr = startAddr;

        if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
        {
            nextAddr = startAddr + totalSize;
        }
        else
        {
            // nextAddr should be *next* chunk start
            nextAddr = roundUp(startAddr, chunkSize);
            if (curAddr == nextAddr) {
                // ... even if startAddr is already chunk-aligned
                nextAddr += chunkSize;
            }
        }

        // how many bytes are left between curAddr and the end of this chunk?
        unsigned left_in_chunk = nextAddr - curAddr;
        curSize = std::min(totalSize, left_in_chunk);
        sizeLeft = totalSize - curSize;
    }

    /** Return starting address of current chunk. */
    Addr addr() const { return curAddr; }
    /** Return size in bytes of current chunk. */
    unsigned size() const { return curSize; }

    /** Number of bytes we have already chunked up. */
    unsigned complete() const { return curAddr - startAddr; }

    /**
     * Are we done?  That is, did the last call to next() advance
     * past the end of the region?
     * @return True if yes, false if more to go.
     */
    bool done() const { return (curSize == 0); }

    /**
     * Advance generator to next chunk.
     * @return True if successful, false if unsuccessful
     * (because we were at the last chunk).
     */
    bool
    next()
    {
        if (sizeLeft == 0) {
            curSize = 0;
            return false;
        }

        curAddr = nextAddr;
        curSize = std::min(sizeLeft, chunkSize);
        sizeLeft -= curSize;
        nextAddr += curSize;
        return true;
    }
};

#endif // __BASE__CHUNK_GENERATOR_HH__
<commit_msg>base: add new ChunkGenerator method to identify last chunk<commit_after>/*
 * Copyright (c) 2001-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 */

#ifndef __BASE__CHUNK_GENERATOR_HH__
#define __BASE__CHUNK_GENERATOR_HH__

/**
 * @file
 * Declaration and inline definition of ChunkGenerator object.
 */

#include <algorithm>

#include "base/intmath.hh"
#include "base/types.hh"

/**
 * This class takes an arbitrary memory region (address/length pair)
 * and generates a series of appropriately (e.g. block- or page-)
 * aligned chunks covering the same region.
 *
 * Example usage:

\code
    for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
        doSomethingChunky(gen.addr(), gen.size());
    }
\endcode
 */
class ChunkGenerator
{
  private:
    /** The starting address of the current chunk. */
    Addr curAddr;
    /** The starting address of the next chunk (after the current one). */
    Addr nextAddr;
    /** The size of the current chunk (in bytes). */
    unsigned  curSize;
    /** The number of bytes remaining in the region after the current chunk. */
    unsigned  sizeLeft;
    /** The start address so we can calculate offset in writing block. */
    const Addr startAddr;
    /** The maximum chunk size, e.g., the cache block size or page size. */
    const unsigned chunkSize;

  public:
    /**
     * Constructor.
     * @param _startAddr The starting address of the region.
     * @param totalSize The total size of the region.
     * @param _chunkSize The size/alignment of chunks into which
     *    the region should be decomposed.
     */
    ChunkGenerator(Addr _startAddr, unsigned totalSize, unsigned _chunkSize)
        : startAddr(_startAddr), chunkSize(_chunkSize)
    {
        // chunkSize must be a power of two
        assert(chunkSize == 0 || isPowerOf2(chunkSize));

        // set up initial chunk.
        curAddr = startAddr;

        if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
        {
            nextAddr = startAddr + totalSize;
        }
        else
        {
            // nextAddr should be *next* chunk start
            nextAddr = roundUp(startAddr, chunkSize);
            if (curAddr == nextAddr) {
                // ... even if startAddr is already chunk-aligned
                nextAddr += chunkSize;
            }
        }

        // how many bytes are left between curAddr and the end of this chunk?
        unsigned left_in_chunk = nextAddr - curAddr;
        curSize = std::min(totalSize, left_in_chunk);
        sizeLeft = totalSize - curSize;
    }

    /** Return starting address of current chunk. */
    Addr addr() const { return curAddr; }
    /** Return size in bytes of current chunk. */
    unsigned size() const { return curSize; }

    /** Number of bytes we have already chunked up. */
    unsigned complete() const { return curAddr - startAddr; }

    /**
     * Are we done?  That is, did the last call to next() advance
     * past the end of the region?
     * @return True if yes, false if more to go.
     */
    bool done() const { return (curSize == 0); }

    /**
     * Is this the last chunk?
     * @return True if yes, false if more to go.
     */
    bool last() const { return (sizeLeft == 0); }

    /**
     * Advance generator to next chunk.
     * @return True if successful, false if unsuccessful
     * (because we were at the last chunk).
     */
    bool
    next()
    {
        if (sizeLeft == 0) {
            curSize = 0;
            return false;
        }

        curAddr = nextAddr;
        curSize = std::min(sizeLeft, chunkSize);
        sizeLeft -= curSize;
        nextAddr += curSize;
        return true;
    }
};

#endif // __BASE__CHUNK_GENERATOR_HH__
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/arena_planner.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <set>
#include <type_traits>
#include <utility>

namespace tflite {
namespace {

constexpr int32_t kNodeNotAssigned = std::numeric_limits<int32_t>::max();

}  // namespace

ArenaPlanner::ArenaPlanner(TfLiteContext* context,
                           std::unique_ptr<GraphInfo> graph_info,
                           bool preserve_inputs, bool preserve_intermediates,
                           int tensor_alignment)
    : context_(context),
      graph_info_(std::move(graph_info)),
      arena_(kDefaultArenaAlignment),
      persistent_arena_(kDefaultArenaAlignment),
      preserve_inputs_(preserve_inputs),
      preserve_intermediates_(preserve_intermediates),
      tensor_alignment_(tensor_alignment) {}

ArenaPlanner::~ArenaPlanner() {}

std::intptr_t ArenaPlanner::BasePointer(TfLiteAllocationType type) {
  if (type == kTfLiteArenaRwPersistent) {
    return persistent_arena_.BasePointer();
  }
  if (type == kTfLiteArenaRw) {
    return arena_.BasePointer();
  }
  return 0;
}

TfLiteStatus ArenaPlanner::ResetAllocations() {
  TF_LITE_ENSURE_STATUS(arena_.ClearPlan());
  TF_LITE_ENSURE_STATUS(persistent_arena_.ClearPlan());
  allocs_.clear();
  allocs_.resize(graph_info_->num_tensors());
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ResetAllocationsAfter(int node) {
  for (int i = 0; i < static_cast<int>(allocs_.size()); ++i) {
    if (allocs_[i].first_node > node && allocs_[i].size > 0) {
      TfLiteTensor& tensor = *graph_info_->tensor(i);
      if (tensor.allocation_type == kTfLiteArenaRw) {
        TF_LITE_ENSURE_STATUS(arena_.Deallocate(context_, allocs_[i]));
        allocs_[i].reset();
        tensor.data.raw = nullptr;
      }
    }
  }

  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::PlanAllocations() {
  // Invalidate any existing data.
  TF_LITE_ENSURE_STATUS(ResetAllocations());
  // Maybe other verb instead of 'Assigned'
  alloc_node_.assign(graph_info_->num_tensors(), kNodeNotAssigned);
  dealloc_node_.assign(graph_info_->num_tensors(), kNodeNotAssigned);

  // Keeps track of references to each tensor.
  std::vector<int> refcounts(graph_info_->num_tensors(), 0);

  auto allocate = [this](int node, int tensor) -> TfLiteStatus {
    if (alloc_node_[tensor] != kNodeNotAssigned) {
      // Tensor has already been allocated.
      return kTfLiteOk;
    }
    TF_LITE_ENSURE(context_, dealloc_node_[tensor] == kNodeNotAssigned);
    alloc_node_[tensor] = node;
    return kTfLiteOk;
  };

  auto deallocate = [this](int node, int tensor) -> TfLiteStatus {
    if (alloc_node_[tensor] == kNodeNotAssigned) {
      // We don't need to deallocate the tensor, that is never allocated.
      // This happened with the constant tensors.
      return kTfLiteOk;
    }
    TF_LITE_ENSURE(context_, dealloc_node_[tensor] == kNodeNotAssigned);
    dealloc_node_[tensor] = node;
    return kTfLiteOk;
  };

  // We must make sure the output tensors are never overwritten. We do that by
  // artificially adding one to their ref-counts so they are never selected
  // for deallocation.
  for (int tensor_index : graph_info_->outputs()) {
    refcounts[tensor_index]++;
  }

  // Variable tensors also should be ensured to be never overwritten and need to
  // be alive all the time.
  for (int tensor_index : graph_info_->variables()) {
    refcounts[tensor_index]++;
  }

  // Queue all graph inputs for allocation. If preserve_inputs_ is true, make
  // sure they never be overwritten.
  for (int tensor_index : graph_info_->inputs()) {
    if (tensor_index != kTfLiteOptionalTensor) {
      if (preserve_inputs_) {
        refcounts[tensor_index]++;
      }
      TF_LITE_ENSURE_STATUS(allocate(0, tensor_index));
    }
  }

  // Queue all graph variable tensors for allocation.
  for (int tensor_index : graph_info_->variables()) {
    if (tensor_index != kTfLiteOptionalTensor) {
      // Increase the reference count for input tensors by one, so it will
      // never be deallocated.
      TF_LITE_ENSURE_STATUS(allocate(0, tensor_index));
    }
  }

  // Count references to node input tensors.
  for (size_t i = 0; i < graph_info_->num_execution_nodes(); ++i) {
    const TfLiteNode& node = graph_info_->node(i);
    TfLiteIntArray* node_inputs = node.inputs;
    for (int j = 0; j < node_inputs->size; ++j) {
      int tensor_index = node_inputs->data[j];
      if (tensor_index != kTfLiteOptionalTensor) {
        refcounts[tensor_index]++;
      }
    }
  }

  // Queue all graph inputs for allocation.
  for (int tensor_index : graph_info_->inputs()) {
    if (tensor_index != kTfLiteOptionalTensor) {
      TF_LITE_ENSURE_STATUS(allocate(0, tensor_index));
    }
  }
  // Go through the graph in execution order.
  for (size_t i = 0; i < graph_info_->num_execution_nodes(); ++i) {
    const TfLiteNode& node = graph_info_->node(i);

    // First queue output tensors for allocation.
    TfLiteIntArray* node_outputs = node.outputs;
    for (int j = 0; j < node_outputs->size; ++j) {
      int tensor_index = node_outputs->data[j];
      TF_LITE_ENSURE_STATUS(allocate(i, tensor_index));
    }

    // Then update the ref-counts of the node's inputs, and if necessary queue
    // them for deallocation.
    if (!preserve_intermediates_) {
      TfLiteIntArray* node_inputs = node.inputs;
      for (int j = 0; j < node_inputs->size; ++j) {
        int tensor_index = node_inputs->data[j];
        if (tensor_index != kTfLiteOptionalTensor) {
          refcounts[tensor_index]--;
          if (refcounts[tensor_index] == 0) {
            TF_LITE_ENSURE_STATUS(deallocate(i, tensor_index));
          }
        }
      }
    }
  }

  // Note that graph outputs will never be scheduled for deallocation. We
  // could do that here for completeness, but it won't have any effect.
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ExecuteAllocations(int first_node, int last_node) {
  // Grow the size of `allocs_` if necessary. This allows allocating temporary
  // tensors in op's `prepare` function.
  TF_LITE_ENSURE(context_, graph_info_->num_tensors() >= allocs_.size());
  alloc_node_.resize(graph_info_->num_tensors(), kNodeNotAssigned);
  dealloc_node_.resize(graph_info_->num_tensors(), kNodeNotAssigned);
  allocs_.resize(graph_info_->num_tensors());
  // Set allocation and deallocation for temporary tensors.
  for (size_t i = first_node; i <= static_cast<size_t>(last_node) &&
                              i < graph_info_->num_execution_nodes();
       ++i) {
    const TfLiteNode& node = graph_info_->node(i);
    TfLiteIntArray* node_temporaries = node.temporaries;
    for (int j = 0; j < node_temporaries->size; ++j) {
      int tensor_index = node_temporaries->data[j];
      alloc_node_[tensor_index] = i;
      if (!preserve_intermediates_) {
        dealloc_node_[tensor_index] = i;
      }
    }
  }

  TF_LITE_ENSURE_STATUS(CalculateAllocations(first_node, last_node));
  TF_LITE_ENSURE_STATUS(Commit());

  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    // TODO(ahentz): we could do this only for the tensors that were modified
    // in CalculateAllocations(), instead of redoing it for tensors that
    // already had proper pointers. However we must be very careful, because
    // SimpleMemoryArena::Commit() could move the base pointer.
    TF_LITE_ENSURE_STATUS(ResolveTensorAllocation(i));
  }

  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ReleaseNonPersistentMemory() {
  // Clear non-persistent arena's buffer.
  TF_LITE_ENSURE_STATUS(arena_.ReleaseBuffer());
  // Set data pointers for all non-persistent tensors to nullptr.
  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    TfLiteTensor& tensor = *graph_info_->tensor(i);
    if (tensor.allocation_type == kTfLiteArenaRw) {
      tensor.data.raw = nullptr;
    }
  }
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::AcquireNonPersistentMemory() {
  // First commit arena_ to allocate underlying buffer.
  TF_LITE_ENSURE_STATUS(arena_.Commit(context_));
  // Resolve allocations for all tensors not on the persistent arena.
  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    TfLiteTensor& tensor = *graph_info_->tensor(i);
    if (tensor.allocation_type == kTfLiteArenaRw) {
      TF_LITE_ENSURE_STATUS(ResolveTensorAllocation(i));
    }
  }
  return kTfLiteOk;
}

bool ArenaPlanner::HasNonPersistentMemory() {
  return arena_.GetBufferSize() != 0;
}

TfLiteStatus ArenaPlanner::Commit() {
  TF_LITE_ENSURE_STATUS(arena_.Commit(context_));
  TF_LITE_ENSURE_STATUS(persistent_arena_.Commit(context_));
  return kTfLiteOk;
}

std::vector<int32_t> ArenaPlanner::CreateTensorAllocationVector(int first_node,
                                                                int last_node) {
  auto tensor_compare = [this](int idx1, int idx2) {
    // Tensors that have lifespan through the whole model inference time are
    // allocated at the beginning of memory slice. Their respective order
    // doesn't matter in fact, so here they are sorted by index.
    if (this->alloc_node_[idx1] == 0 &&
        this->dealloc_node_[idx1] == kNodeNotAssigned) {
      if (this->alloc_node_[idx2] == 0 &&
          this->dealloc_node_[idx2] == kNodeNotAssigned) {
        return idx1 < idx2;
      }
      return true;
    }
    if (this->alloc_node_[idx2] == 0 &&
        this->dealloc_node_[idx2] == kNodeNotAssigned) {
      return false;
    }

    // All other tensors are sorted in non-increasing order of their size.
    auto size1 = this->graph_info_->tensor(idx1)->bytes;
    auto size2 = this->graph_info_->tensor(idx2)->bytes;
    if (size1 != size2) {
      return size1 > size2;
    }
    // Tensors with equal size are sorted in order of their allocation time.
    return this->alloc_node_[idx1] < this->alloc_node_[idx2];
  };

  std::vector<int32_t> tensor_order;
  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    if (alloc_node_[i] >= first_node && alloc_node_[i] <= last_node) {
      tensor_order.push_back(i);
    }
  }
  // Indices of tensors in order their allocation offsets will be calculated.
  std::sort(tensor_order.begin(), tensor_order.end(), tensor_compare);

  return tensor_order;
}

TfLiteStatus ArenaPlanner::CalculateAllocations(int first_node, int last_node) {
  // Indices of tensors in order their allocation offsets will be calculated.
  const std::vector<int32_t> tensor_order =
      CreateTensorAllocationVector(first_node, last_node);

  // Deallocate if the tensor was already allocated.
  for (const auto& tensor_index : tensor_order) {
    TfLiteTensor& tensor = *graph_info_->tensor(tensor_index);
    if (tensor.allocation_type == kTfLiteArenaRw &&
        allocs_[tensor_index].size != 0) {
      TF_LITE_ENSURE_STATUS(arena_.Deallocate(context_, allocs_[tensor_index]));
    }
  }

  // Vector of ids of already allocated tensors, ordered by offset.
  for (const auto& tensor_index : tensor_order) {
    TfLiteTensor& tensor = *graph_info_->tensor(tensor_index);
    if (tensor.allocation_type == kTfLiteArenaRw) {
      TF_LITE_ENSURE_STATUS(
          arena_.Allocate(context_, tensor_alignment_, tensor.bytes,
                          tensor_index, alloc_node_[tensor_index],
                          dealloc_node_[tensor_index], &allocs_[tensor_index]));
    }
    // Check allocs_[].size to prevent from reallocation of persistent tensors.
    if (tensor.allocation_type == kTfLiteArenaRwPersistent &&
        allocs_[tensor_index].size == 0) {
      TF_LITE_ENSURE_STATUS(persistent_arena_.Allocate(
          context_, tensor_alignment_, tensor.bytes, tensor_index,
          /*first_node=*/alloc_node_[tensor_index],
          /*last_node=*/std::numeric_limits<int32_t>::max(),
          &allocs_[tensor_index]));
    }
  }
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ResolveTensorAllocation(int tensor_index) {
  TfLiteTensor& tensor = *graph_info_->tensor(tensor_index);
  if (tensor.allocation_type == kTfLiteArenaRw) {
    // Skip resolution if the size of the tensor is zero, leaving it as a
    // nullptr.
    if (allocs_[tensor_index].size != 0) {
      TF_LITE_ENSURE_STATUS(arena_.ResolveAlloc(context_, allocs_[tensor_index],
                                                &tensor.data.raw));
    }
  }
  if (tensor.allocation_type == kTfLiteArenaRwPersistent) {
    TF_LITE_ENSURE_STATUS(persistent_arena_.ResolveAlloc(
        context_, allocs_[tensor_index], &tensor.data.raw));
  }
  return kTfLiteOk;
}

}  // namespace tflite
<commit_msg>Improve code quality in ArenaPlanner's PlanAllocations method.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/arena_planner.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <set>
#include <type_traits>
#include <utility>

namespace tflite {
namespace {

constexpr int32_t kNodeNotAssigned = std::numeric_limits<int32_t>::max();

}  // namespace

ArenaPlanner::ArenaPlanner(TfLiteContext* context,
                           std::unique_ptr<GraphInfo> graph_info,
                           bool preserve_inputs, bool preserve_intermediates,
                           int tensor_alignment)
    : context_(context),
      graph_info_(std::move(graph_info)),
      arena_(kDefaultArenaAlignment),
      persistent_arena_(kDefaultArenaAlignment),
      preserve_inputs_(preserve_inputs),
      preserve_intermediates_(preserve_intermediates),
      tensor_alignment_(tensor_alignment) {}

ArenaPlanner::~ArenaPlanner() {}

std::intptr_t ArenaPlanner::BasePointer(TfLiteAllocationType type) {
  if (type == kTfLiteArenaRwPersistent) {
    return persistent_arena_.BasePointer();
  }
  if (type == kTfLiteArenaRw) {
    return arena_.BasePointer();
  }
  return 0;
}

TfLiteStatus ArenaPlanner::ResetAllocations() {
  TF_LITE_ENSURE_STATUS(arena_.ClearPlan());
  TF_LITE_ENSURE_STATUS(persistent_arena_.ClearPlan());
  allocs_.clear();
  allocs_.resize(graph_info_->num_tensors());
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ResetAllocationsAfter(int node) {
  for (int i = 0; i < static_cast<int>(allocs_.size()); ++i) {
    if (allocs_[i].first_node > node && allocs_[i].size > 0) {
      TfLiteTensor& tensor = *graph_info_->tensor(i);
      if (tensor.allocation_type == kTfLiteArenaRw) {
        TF_LITE_ENSURE_STATUS(arena_.Deallocate(context_, allocs_[i]));
        allocs_[i].reset();
        tensor.data.raw = nullptr;
      }
    }
  }

  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::PlanAllocations() {
  // Invalidate any existing data.
  TF_LITE_ENSURE_STATUS(ResetAllocations());
  // Maybe other verb instead of 'Assigned'
  alloc_node_.assign(graph_info_->num_tensors(), kNodeNotAssigned);
  dealloc_node_.assign(graph_info_->num_tensors(), kNodeNotAssigned);

  // Keeps track of references to each tensor.
  std::vector<int> refcounts(graph_info_->num_tensors(), 0);

  auto allocate = [this](int node, int tensor) -> TfLiteStatus {
    if (alloc_node_[tensor] != kNodeNotAssigned) {
      // Tensor has already been allocated.
      return kTfLiteOk;
    }
    TF_LITE_ENSURE(context_, dealloc_node_[tensor] == kNodeNotAssigned);
    alloc_node_[tensor] = node;
    return kTfLiteOk;
  };

  auto deallocate = [this](int node, int tensor) -> TfLiteStatus {
    if (alloc_node_[tensor] == kNodeNotAssigned) {
      // We don't need to deallocate the tensor, that is never allocated.
      // This happened with the constant tensors.
      return kTfLiteOk;
    }
    TF_LITE_ENSURE(context_, dealloc_node_[tensor] == kNodeNotAssigned);
    dealloc_node_[tensor] = node;
    return kTfLiteOk;
  };

  // We must make sure the output tensors are never overwritten. We do that by
  // artificially adding one to their ref-counts so they are never selected
  // for deallocation.
  for (int tensor_index : graph_info_->outputs()) {
    refcounts[tensor_index]++;
  }

  // Variable tensors also should be ensured to be never overwritten and need to
  // be alive all the time.
  for (int tensor_index : graph_info_->variables()) {
    // Increase the reference count for variable tensors by one, so it will
    // never be deallocated.
    refcounts[tensor_index]++;
    // `variables` is a subgraph-level list and it should never be
    // kTfLiteOptionalTensor.
    TF_LITE_ENSURE(context_, tensor_index != kTfLiteOptionalTensor);
    // Variable tensor should be allocated at the very beginning.
    TF_LITE_ENSURE_STATUS(allocate(0, tensor_index));
  }

  // Queue all graph inputs for allocation. If preserve_inputs_ is true, make
  // sure they never be overwritten.
  for (int tensor_index : graph_info_->inputs()) {
    if (tensor_index != kTfLiteOptionalTensor) {
      if (preserve_inputs_) {
        refcounts[tensor_index]++;
      }
      TF_LITE_ENSURE_STATUS(allocate(0, tensor_index));
    }
  }

  // Count references to node input tensors.
  for (size_t i = 0; i < graph_info_->num_execution_nodes(); ++i) {
    const TfLiteNode& node = graph_info_->node(i);
    TfLiteIntArray* node_inputs = node.inputs;
    for (int j = 0; j < node_inputs->size; ++j) {
      int tensor_index = node_inputs->data[j];
      if (tensor_index != kTfLiteOptionalTensor) {
        refcounts[tensor_index]++;
      }
    }
  }

  // Go through the graph in execution order.
  for (size_t i = 0; i < graph_info_->num_execution_nodes(); ++i) {
    const TfLiteNode& node = graph_info_->node(i);

    // First queue output tensors for allocation.
    TfLiteIntArray* node_outputs = node.outputs;
    for (int j = 0; j < node_outputs->size; ++j) {
      int tensor_index = node_outputs->data[j];
      TF_LITE_ENSURE_STATUS(allocate(i, tensor_index));
    }

    // Then update the ref-counts of the node's inputs, and if necessary queue
    // them for deallocation.
    if (!preserve_intermediates_) {
      TfLiteIntArray* node_inputs = node.inputs;
      for (int j = 0; j < node_inputs->size; ++j) {
        int tensor_index = node_inputs->data[j];
        if (tensor_index != kTfLiteOptionalTensor) {
          refcounts[tensor_index]--;
          if (refcounts[tensor_index] == 0) {
            TF_LITE_ENSURE_STATUS(deallocate(i, tensor_index));
          }
        }
      }
    }
  }

  // Note that graph outputs will never be scheduled for deallocation. We
  // could do that here for completeness, but it won't have any effect.
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ExecuteAllocations(int first_node, int last_node) {
  // Grow the size of `allocs_` if necessary. This allows allocating temporary
  // tensors in op's `prepare` function.
  TF_LITE_ENSURE(context_, graph_info_->num_tensors() >= allocs_.size());
  alloc_node_.resize(graph_info_->num_tensors(), kNodeNotAssigned);
  dealloc_node_.resize(graph_info_->num_tensors(), kNodeNotAssigned);
  allocs_.resize(graph_info_->num_tensors());
  // Set allocation and deallocation for temporary tensors.
  for (size_t i = first_node; i <= static_cast<size_t>(last_node) &&
                              i < graph_info_->num_execution_nodes();
       ++i) {
    const TfLiteNode& node = graph_info_->node(i);
    TfLiteIntArray* node_temporaries = node.temporaries;
    for (int j = 0; j < node_temporaries->size; ++j) {
      int tensor_index = node_temporaries->data[j];
      alloc_node_[tensor_index] = i;
      if (!preserve_intermediates_) {
        dealloc_node_[tensor_index] = i;
      }
    }
  }

  TF_LITE_ENSURE_STATUS(CalculateAllocations(first_node, last_node));
  TF_LITE_ENSURE_STATUS(Commit());

  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    // TODO(ahentz): we could do this only for the tensors that were modified
    // in CalculateAllocations(), instead of redoing it for tensors that
    // already had proper pointers. However we must be very careful, because
    // SimpleMemoryArena::Commit() could move the base pointer.
    TF_LITE_ENSURE_STATUS(ResolveTensorAllocation(i));
  }

  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ReleaseNonPersistentMemory() {
  // Clear non-persistent arena's buffer.
  TF_LITE_ENSURE_STATUS(arena_.ReleaseBuffer());
  // Set data pointers for all non-persistent tensors to nullptr.
  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    TfLiteTensor& tensor = *graph_info_->tensor(i);
    if (tensor.allocation_type == kTfLiteArenaRw) {
      tensor.data.raw = nullptr;
    }
  }
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::AcquireNonPersistentMemory() {
  // First commit arena_ to allocate underlying buffer.
  TF_LITE_ENSURE_STATUS(arena_.Commit(context_));
  // Resolve allocations for all tensors not on the persistent arena.
  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    TfLiteTensor& tensor = *graph_info_->tensor(i);
    if (tensor.allocation_type == kTfLiteArenaRw) {
      TF_LITE_ENSURE_STATUS(ResolveTensorAllocation(i));
    }
  }
  return kTfLiteOk;
}

bool ArenaPlanner::HasNonPersistentMemory() {
  return arena_.GetBufferSize() != 0;
}

TfLiteStatus ArenaPlanner::Commit() {
  TF_LITE_ENSURE_STATUS(arena_.Commit(context_));
  TF_LITE_ENSURE_STATUS(persistent_arena_.Commit(context_));
  return kTfLiteOk;
}

std::vector<int32_t> ArenaPlanner::CreateTensorAllocationVector(int first_node,
                                                                int last_node) {
  auto tensor_compare = [this](int idx1, int idx2) {
    // Tensors that have lifespan through the whole model inference time are
    // allocated at the beginning of memory slice. Their respective order
    // doesn't matter in fact, so here they are sorted by index.
    if (this->alloc_node_[idx1] == 0 &&
        this->dealloc_node_[idx1] == kNodeNotAssigned) {
      if (this->alloc_node_[idx2] == 0 &&
          this->dealloc_node_[idx2] == kNodeNotAssigned) {
        return idx1 < idx2;
      }
      return true;
    }
    if (this->alloc_node_[idx2] == 0 &&
        this->dealloc_node_[idx2] == kNodeNotAssigned) {
      return false;
    }

    // All other tensors are sorted in non-increasing order of their size.
    auto size1 = this->graph_info_->tensor(idx1)->bytes;
    auto size2 = this->graph_info_->tensor(idx2)->bytes;
    if (size1 != size2) {
      return size1 > size2;
    }
    // Tensors with equal size are sorted in order of their allocation time.
    return this->alloc_node_[idx1] < this->alloc_node_[idx2];
  };

  std::vector<int32_t> tensor_order;
  for (int i = 0; i < static_cast<int>(graph_info_->num_tensors()); ++i) {
    if (alloc_node_[i] >= first_node && alloc_node_[i] <= last_node) {
      tensor_order.push_back(i);
    }
  }
  // Indices of tensors in order their allocation offsets will be calculated.
  std::sort(tensor_order.begin(), tensor_order.end(), tensor_compare);

  return tensor_order;
}

TfLiteStatus ArenaPlanner::CalculateAllocations(int first_node, int last_node) {
  // Indices of tensors in order their allocation offsets will be calculated.
  const std::vector<int32_t> tensor_order =
      CreateTensorAllocationVector(first_node, last_node);

  // Deallocate if the tensor was already allocated.
  for (const auto& tensor_index : tensor_order) {
    TfLiteTensor& tensor = *graph_info_->tensor(tensor_index);
    if (tensor.allocation_type == kTfLiteArenaRw &&
        allocs_[tensor_index].size != 0) {
      TF_LITE_ENSURE_STATUS(arena_.Deallocate(context_, allocs_[tensor_index]));
    }
  }

  // Vector of ids of already allocated tensors, ordered by offset.
  for (const auto& tensor_index : tensor_order) {
    TfLiteTensor& tensor = *graph_info_->tensor(tensor_index);
    if (tensor.allocation_type == kTfLiteArenaRw) {
      TF_LITE_ENSURE_STATUS(
          arena_.Allocate(context_, tensor_alignment_, tensor.bytes,
                          tensor_index, alloc_node_[tensor_index],
                          dealloc_node_[tensor_index], &allocs_[tensor_index]));
    }
    // Check allocs_[].size to prevent from reallocation of persistent tensors.
    if (tensor.allocation_type == kTfLiteArenaRwPersistent &&
        allocs_[tensor_index].size == 0) {
      TF_LITE_ENSURE_STATUS(persistent_arena_.Allocate(
          context_, tensor_alignment_, tensor.bytes, tensor_index,
          /*first_node=*/alloc_node_[tensor_index],
          /*last_node=*/std::numeric_limits<int32_t>::max(),
          &allocs_[tensor_index]));
    }
  }
  return kTfLiteOk;
}

TfLiteStatus ArenaPlanner::ResolveTensorAllocation(int tensor_index) {
  TfLiteTensor& tensor = *graph_info_->tensor(tensor_index);
  if (tensor.allocation_type == kTfLiteArenaRw) {
    // Skip resolution if the size of the tensor is zero, leaving it as a
    // nullptr.
    if (allocs_[tensor_index].size != 0) {
      TF_LITE_ENSURE_STATUS(arena_.ResolveAlloc(context_, allocs_[tensor_index],
                                                &tensor.data.raw));
    }
  }
  if (tensor.allocation_type == kTfLiteArenaRwPersistent) {
    TF_LITE_ENSURE_STATUS(persistent_arena_.ResolveAlloc(
        context_, allocs_[tensor_index], &tensor.data.raw));
  }
  return kTfLiteOk;
}

}  // namespace tflite
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    // How many times we expect transactions after the last checkpoint to
    // be slower. This number is a compromise, as it can't be accurate for
    // every system. When reindexing from a fast disk with a slow CPU, it
    // can be up to 20, while when downloading from a slow network with a
    // fast multicore CPU, it won't be much higher than 1.
    static const double fSigcheckVerificationFactor = 5.0;

    struct CCheckpointData {
        const MapCheckpoints *mapCheckpoints;
        int64 nTimeLastCheckpoint;
        int64 nTransactionsLastCheckpoint;
        double fTransactionsPerDay;
    };

    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (  1500, uint256("0x841a2965955dd288cfa707a755d05a54e45f8bd476835ec9af4402a2b59a2967"))
        (  4032, uint256("0x9ce90e427198fc0ef05e5905ce3503725b80e26afd35a987965fd7e3d9cf0846"))
        (  8064, uint256("0xeb984353fc5190f210651f150c40b8a4bab9eeeff0b729fcb3987da694430d70"))
        ( 16128, uint256("0x602edf1859b7f9a6af809f1d9b0e6cb66fdc1d4d9dcd7a4bec03e12a1ccd153d"))
        ( 23420, uint256("0xd80fdf9ca81afd0bd2b2a90ac3a9fe547da58f2530ec874e978fce0b5101b507"))
        ( 50000, uint256("0x69dc37eb029b68f075a5012dcc0419c127672adb4f3a32882b2b3e71d07a20a6"))
        ( 80000, uint256("0x4fcb7c02f676a300503f49c764a89955a8f920b46a8cbecb4867182ecdb2e90a"))
        (120000, uint256("0xbd9d26924f05f6daa7f0155f32828ec89e8e29cee9e7121b026a7a3552ac6131"))
        (161500, uint256("0xdbe89880474f4bb4f75c227c77ba1cdc024991123b28b8418dbbf7798471ff43"))
        (179620, uint256("0x2ad9c65c990ac00426d18e446e0fd7be2ffa69e9a7dcb28358a50b2b78b9f709"))
        (240000, uint256("0x7140d1c4b4c2157ca217ee7636f24c9c73db39c4590c4e6eab2e3ea1555088aa"))
        (383640, uint256("0x2b6809f094a9215bafc65eb3f110a35127a34be94b7d0590a096c3f126c6f364"))
        (409004, uint256("0x487518d663d9f1fa08611d9395ad74d982b667fbdc0e77e9cf39b4f1355908a3"))
        ;
    static const CCheckpointData data = {
        &mapCheckpoints,
        1376885874, // * UNIX timestamp of last checkpoint block
        1859062,    // * total number of transactions between genesis and last checkpoint
                    //   (the tx=... number in the SetBestChain debug.log lines)
        7000.0     // * estimated number of transactions per day after checkpoint
    };

    static MapCheckpoints mapCheckpointsTestnet =
        boost::assign::map_list_of
        (   546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70"))
        ( 35000, uint256("2af959ab4f12111ce947479bfcef16702485f04afd95210aa90fde7d1e4a64ad"))
        ;
    static const CCheckpointData dataTestnet = {
        &mapCheckpointsTestnet,
        1369685559,
        37581,
        300
    };

    const CCheckpointData &Checkpoints() {
        if (fTestNet)
            return dataTestnet;
        else
            return data;
    }

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return true;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
        if (i == checkpoints.end()) return true;
        return hash == i->second;
    }

    // Guess how far we are in the verification process at the given block index
    double GuessVerificationProgress(CBlockIndex *pindex) {
        if (pindex==NULL)
            return 0.0;

        int64 nNow = time(NULL);

        double fWorkBefore = 0.0; // Amount of work done before pindex
        double fWorkAfter = 0.0;  // Amount of work left after pindex (estimated)
        // Work is defined as: 1.0 per transaction before the last checkoint, and
        // fSigcheckVerificationFactor per transaction after.

        const CCheckpointData &data = Checkpoints();

        if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
            double nCheapBefore = pindex->nChainTx;
            double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
            double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore;
            fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
        } else {
            double nCheapBefore = data.nTransactionsLastCheckpoint;
            double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
            double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
            fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
        }

        return fWorkBefore / (fWorkBefore + fWorkAfter);
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return 0;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        return checkpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return NULL;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<commit_msg>Litecoin: Checkpoint at block 456000<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    // How many times we expect transactions after the last checkpoint to
    // be slower. This number is a compromise, as it can't be accurate for
    // every system. When reindexing from a fast disk with a slow CPU, it
    // can be up to 20, while when downloading from a slow network with a
    // fast multicore CPU, it won't be much higher than 1.
    static const double fSigcheckVerificationFactor = 5.0;

    struct CCheckpointData {
        const MapCheckpoints *mapCheckpoints;
        int64 nTimeLastCheckpoint;
        int64 nTransactionsLastCheckpoint;
        double fTransactionsPerDay;
    };

    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (  1500, uint256("0x841a2965955dd288cfa707a755d05a54e45f8bd476835ec9af4402a2b59a2967"))
        (  4032, uint256("0x9ce90e427198fc0ef05e5905ce3503725b80e26afd35a987965fd7e3d9cf0846"))
        (  8064, uint256("0xeb984353fc5190f210651f150c40b8a4bab9eeeff0b729fcb3987da694430d70"))
        ( 16128, uint256("0x602edf1859b7f9a6af809f1d9b0e6cb66fdc1d4d9dcd7a4bec03e12a1ccd153d"))
        ( 23420, uint256("0xd80fdf9ca81afd0bd2b2a90ac3a9fe547da58f2530ec874e978fce0b5101b507"))
        ( 50000, uint256("0x69dc37eb029b68f075a5012dcc0419c127672adb4f3a32882b2b3e71d07a20a6"))
        ( 80000, uint256("0x4fcb7c02f676a300503f49c764a89955a8f920b46a8cbecb4867182ecdb2e90a"))
        (120000, uint256("0xbd9d26924f05f6daa7f0155f32828ec89e8e29cee9e7121b026a7a3552ac6131"))
        (161500, uint256("0xdbe89880474f4bb4f75c227c77ba1cdc024991123b28b8418dbbf7798471ff43"))
        (179620, uint256("0x2ad9c65c990ac00426d18e446e0fd7be2ffa69e9a7dcb28358a50b2b78b9f709"))
        (240000, uint256("0x7140d1c4b4c2157ca217ee7636f24c9c73db39c4590c4e6eab2e3ea1555088aa"))
        (383640, uint256("0x2b6809f094a9215bafc65eb3f110a35127a34be94b7d0590a096c3f126c6f364"))
        (409004, uint256("0x487518d663d9f1fa08611d9395ad74d982b667fbdc0e77e9cf39b4f1355908a3"))
        (456000, uint256("0xbf34f71cc6366cd487930d06be22f897e34ca6a40501ac7d401be32456372004"))
        ;
    static const CCheckpointData data = {
        &mapCheckpoints,
        1383887110, // * UNIX timestamp of last checkpoint block
        2179203,    // * total number of transactions between genesis and last checkpoint
                    //   (the tx=... number in the SetBestChain debug.log lines)
        8000.0     // * estimated number of transactions per day after checkpoint
    };

    static MapCheckpoints mapCheckpointsTestnet =
        boost::assign::map_list_of
        (   546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70"))
        ( 35000, uint256("2af959ab4f12111ce947479bfcef16702485f04afd95210aa90fde7d1e4a64ad"))
        ;
    static const CCheckpointData dataTestnet = {
        &mapCheckpointsTestnet,
        1369685559,
        37581,
        300
    };

    const CCheckpointData &Checkpoints() {
        if (fTestNet)
            return dataTestnet;
        else
            return data;
    }

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return true;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
        if (i == checkpoints.end()) return true;
        return hash == i->second;
    }

    // Guess how far we are in the verification process at the given block index
    double GuessVerificationProgress(CBlockIndex *pindex) {
        if (pindex==NULL)
            return 0.0;

        int64 nNow = time(NULL);

        double fWorkBefore = 0.0; // Amount of work done before pindex
        double fWorkAfter = 0.0;  // Amount of work left after pindex (estimated)
        // Work is defined as: 1.0 per transaction before the last checkoint, and
        // fSigcheckVerificationFactor per transaction after.

        const CCheckpointData &data = Checkpoints();

        if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
            double nCheapBefore = pindex->nChainTx;
            double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
            double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore;
            fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
        } else {
            double nCheapBefore = data.nTransactionsLastCheckpoint;
            double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
            double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
            fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
            fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
        }

        return fWorkBefore / (fWorkBefore + fWorkAfter);
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return 0;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        return checkpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL; // Testnet has no checkpoints
        if (!GetBoolArg("-checkpoints", true))
            return NULL;

        const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<|endoftext|>


<commit_before>#include "common.h"
#include "emulationexception.h"

namespace remu {

Framebuffer::Framebuffer(size_t mem_size)
  : emu(nullptr)
  , mem_size(mem_size)
  , framebuffer(nullptr)
  , fb_bpp(0)
  , fb_pitch(0)
  , fb_size(0)
  , fb_address(0)
  , fb_palette()
  , error(0)
  , surface(nullptr)
  , width(0)
  , height(0)
  , depth(0)
{ }

/**
 * Initialises the framebuffer interface
 * @param fb  Reference to the framebuffer structure
 * @param emu Reference to the emulator structure
 */
void
fb_init(Framebuffer* fb, Emulator* emu, Memory *mem)
{
  assert(fb);
  assert(emu);
  assert(mem);

  fb->emu = emu;
  fb->mem = mem;

  mem->addRegion(fb);

  /* Create the window */
  SDL_Init(SDL_INIT_EVERYTHING);
  fb->width = 640;
  fb->height = 480;
  fb->depth = 32;
  fb->surface =
    SDL_SetVideoMode(fb->width, fb->height, fb->depth, SDL_SWSURFACE);

  /* Set the window caption */
  SDL_WM_SetCaption("Remu", "Remu");
}

/**
 * Cleans up memory used by the framebuffer
 * @param fb  Reference to the framebuffer structure
 */
void
fb_destroy(Framebuffer* fb)
{
  if (!fb || !fb->emu->isGraphicsEnabled())
  {
    return;
  }

  /* Destroy SDL */
  SDL_FreeSurface(fb->surface);
  SDL_Quit();
  fb->surface = 0;

  /* Free framebuffer */
  if (fb->framebuffer)
  {
    free(fb->framebuffer);
    fb->framebuffer = NULL;
  }
}

/*
 * Set the pixel at (x, y) to the given value
 * NOTE: The surface must be locked before calling this!
 */
void
put_pixel(SDL_Surface *surface, int x, int y, uint32_t pixel)
{
  int bpp = surface->format->BytesPerPixel;

  /* Here p is the address to the pixel we want to set */
  uint8_t* p = (uint8_t*)surface->pixels + y * surface->pitch + x * bpp;

  switch(bpp)
  {
    case 1:
    {
      *p = pixel;
      break;
    }
    case 2:
    {
      *(uint16_t*)p = pixel;
      break;
    }
    case 3:
    {
      if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
      {
        p[0] = (pixel >> 16) & 0xff;
        p[1] = (pixel >> 8) & 0xff;
        p[2] = pixel & 0xff;
      }
      else
      {
        p[0] = pixel & 0xff;
        p[1] = (pixel >> 8) & 0xff;
        p[2] = (pixel >> 16) & 0xff;
      }
      break;
    }
    case 4:
    {
      *(uint32_t*)p = pixel;
      break;
    }
  }
}

/**
 * Gets the specified pixel colour at a particular location and converts
 * it to the output format.
 *
 * @param fb Reference to the framebuffer structure
 * @param x X position
 * @param y Y position
 */
uint32_t fb_get_pixel(Framebuffer* fb, uint32_t x, uint32_t y)
{
  assert(fb);

  if (!fb->framebuffer)
  {
    return SDL_MapRGB(fb->surface->format, 0xff, 0x00, 0xff);
  }

  switch (fb->fb_bpp)
  {
    case 1: // 1 byte per pixel - 8 bit colour
    {
      uint8_t key = fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp];
      uint16_t value = fb->fb_palette[key];

      /* Format: RRRRRGGGGGGBBBBB */
      uint32_t r = (value >> 11) & 0x1F;
      uint32_t g = (value >> 5) & 0x3F;
      uint32_t b = value & 0x1F;

      /* Map to [0-255] */
      r = (r * 255) / 31;
      g = (g * 255) / 63;
      b = (b * 255) / 31;

      /* Return colour */
      return SDL_MapRGB(fb->surface->format, r, g, b);
    }
    case 2: // 2 bytes per pixel - R5G6B5
    {
      uint16_t value =
        fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp] +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 1] << 8);

      /* Format: BBBBBGGGGGGRRRRR */
      uint32_t r = value & 0x1F;
      uint32_t g = (value >> 5) & 0x3F;
      uint32_t b = (value >> 11) & 0x1F;

      /* Map to [0-255] */
      r = (r * 255) / 31;
      g = (g * 255) / 63;
      b = (b * 255) / 31;

      /* Return colour */
      return SDL_MapRGB(fb->surface->format, r, g, b);
    }
    case 3: // 3 bytes per pixel - RGB8
    case 4: // 4 bytes per pixel - XRGB8
    {
      uint32_t value =
        fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp] +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 1] << 8) +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 2] << 16) +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 3] << 24);

      /* Format: BBBBBBBBGGGGGGGGRRRRRRRR */
      return SDL_MapRGB(fb->surface->format,
        value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF);
    }
    default:
    {
      fb->emu->error("Unsupported pixel format");
      break;
    }
  }

  return 0;
}

/**
 * Updates the display, displaying the framebuffer and handling events
 */
void Framebuffer::tick()
{
  assert(emu->isGraphicsEnabled());

  /* Handle all SDL events */
  SDL_Event event;
  while (SDL_PollEvent(&event))
  {
    if (event.type == SDL_QUIT)
    {
      emu->terminate();
    }

    /* Route keyboard presses to the NES module if enabled */
    if (event.type == SDL_KEYDOWN)
    {
      dispatchKeyDown(event.key.keysym.sym);
    }
    else if (event.type == SDL_KEYUP)
    {
      dispatchKeyUp(event.key.keysym.sym);
    }
  }

  /* Lock the surface */
  if (SDL_MUSTLOCK(surface))
  {
    SDL_LockSurface(surface);
  }

  /* Copy the pixels to SDL */
  for (uint32_t y = 0; y < height; ++y)
  {
    for (uint32_t x = 0; x < width; ++x)
    {
      put_pixel(surface, x, y, fb_get_pixel(this, x, y));
    }
  }

  /* Unlock the surface */
  if (SDL_MUSTLOCK(surface))
  {
    SDL_UnlockSurface(surface);
  }

  /* Display to screen */
  SDL_Flip(surface);
}

/**
 * Handles a framebuffer request received through the mailbox interface
 *
 * @param fb   Framebuffer structure
 * @param addr Address received from the mailbox
 */
void
fb_request(Framebuffer *fb, uint32_t addr)
{
  size_t i;
  framebuffer_req_t req;

  assert(fb);

  /* Clear error flag */
  fb->error = 0;

  /* Graphic flag must be set*/
  if (!fb->emu->isGraphicsEnabled())
  {
    fb->emu->error("Graphic mode must be enabled for framebuffer");
    fb->error = 1;
    return;
  }

  /* Check whether address is valid */
  if (addr < 0x40000000)
  {
    fb->emu->error("Invalid framebuffer address");
    fb->error = 1;
    return;
  }

  /* Respond to the framebuffer request */
  addr -= 0x40000000;
  for (i = 0; i < sizeof(req.data) / sizeof(req.data[0]); ++i)
  {
    req.data[i] = fb->mem->readDwordLe(addr + (i << 2));
  }

  /* Free old framebuffer */
  if (fb->framebuffer)
  {
    free(fb->framebuffer);
    fb->framebuffer = NULL;
  }

  /* Read palette if 8 bit colour
   * We're assuming that the palette comes immediately after the request */
  if (req.fb.depth == 8)
  {
    for (i = 0; i < 256; ++i)
    {
      fb->fb_palette[i] = fb->mem->readWordLe(addr + sizeof(req) + i * 2);
    }
  }

  /* Allocate a nice frame buffer, placed after the main memory */
  fb->fb_bpp = req.fb.depth >> 3;
  fb->fb_pitch = req.fb.virt_width * fb->fb_bpp;
  req.fb.pitch = fb->fb_pitch + (4 - (fb->fb_pitch % 4)) % 4;
  req.fb.size = fb->fb_size = fb->fb_pitch * req.fb.virt_height;
  fb->framebuffer = static_cast<uint8_t*>( malloc(fb->fb_size) );
  req.fb.addr = fb->fb_address = fb->mem_size;
  fb->width = req.fb.virt_width;
  fb->height = req.fb.virt_height;

  fb->base = fb->fb_address;
  fb->length = fb->fb_size;

  assert(fb->framebuffer);
  memset(fb->framebuffer, 0, fb->fb_size);

  /* Write back structure into memory */
  for (i = 0; i < sizeof(req.data) / sizeof(req.data[0]); ++i)
  {
    fb->mem->writeDwordLe(addr + (i << 2), req.data[i]);
  }

  /* Change the window caption */
  SDL_WM_SetCaption("Remu", "Remu");

  /* Change the window size */
  fb->surface = SDL_SetVideoMode(fb->width, fb->height, fb->depth, SDL_SWSURFACE);
}

uint64_t Framebuffer::readIo(uint64_t addr, unsigned int size)
{
  throw EmulationException("Read unimplemented for framebuffer @ %08llx:%xB", addr, size);
}

void Framebuffer::writeIo(uint64_t address, uint64_t val, unsigned int size)
{
  switch(size) {
    case sizeof(uint16_t): {
      const uint32_t addr = address - fb_address;
      framebuffer[addr + 0] = (val >> 0) & 0xFF;
      framebuffer[addr + 1] = (val >> 8) & 0xFF;
      return;
    }

    case sizeof(uint32_t): {
      const uint32_t addr = address - fb_address;
      framebuffer[addr + 0] = (val >> 0) & 0xFF;
      framebuffer[addr + 1] = (val >> 8) & 0xFF;
      framebuffer[addr + 2] = (val >> 16) & 0xFF;
      framebuffer[addr + 3] = (val >> 24) & 0xFF;
      return;
    }

    default: {
      throw EmulationException("Read unimplemented for framebuffer @ %08lx:%xB", address, size);
    }
  }
}

} /*namespace remu*/

<commit_msg>Fix message for exception<commit_after>#include "common.h"
#include "emulationexception.h"

namespace remu {

Framebuffer::Framebuffer(size_t mem_size)
  : emu(nullptr)
  , mem_size(mem_size)
  , framebuffer(nullptr)
  , fb_bpp(0)
  , fb_pitch(0)
  , fb_size(0)
  , fb_address(0)
  , fb_palette()
  , error(0)
  , surface(nullptr)
  , width(0)
  , height(0)
  , depth(0)
{ }

/**
 * Initialises the framebuffer interface
 * @param fb  Reference to the framebuffer structure
 * @param emu Reference to the emulator structure
 */
void
fb_init(Framebuffer* fb, Emulator* emu, Memory *mem)
{
  assert(fb);
  assert(emu);
  assert(mem);

  fb->emu = emu;
  fb->mem = mem;

  mem->addRegion(fb);

  /* Create the window */
  SDL_Init(SDL_INIT_EVERYTHING);
  fb->width = 640;
  fb->height = 480;
  fb->depth = 32;
  fb->surface =
    SDL_SetVideoMode(fb->width, fb->height, fb->depth, SDL_SWSURFACE);

  /* Set the window caption */
  SDL_WM_SetCaption("Remu", "Remu");
}

/**
 * Cleans up memory used by the framebuffer
 * @param fb  Reference to the framebuffer structure
 */
void
fb_destroy(Framebuffer* fb)
{
  if (!fb || !fb->emu->isGraphicsEnabled())
  {
    return;
  }

  /* Destroy SDL */
  SDL_FreeSurface(fb->surface);
  SDL_Quit();
  fb->surface = 0;

  /* Free framebuffer */
  if (fb->framebuffer)
  {
    free(fb->framebuffer);
    fb->framebuffer = NULL;
  }
}

/*
 * Set the pixel at (x, y) to the given value
 * NOTE: The surface must be locked before calling this!
 */
void
put_pixel(SDL_Surface *surface, int x, int y, uint32_t pixel)
{
  int bpp = surface->format->BytesPerPixel;

  /* Here p is the address to the pixel we want to set */
  uint8_t* p = (uint8_t*)surface->pixels + y * surface->pitch + x * bpp;

  switch(bpp)
  {
    case 1:
    {
      *p = pixel;
      break;
    }
    case 2:
    {
      *(uint16_t*)p = pixel;
      break;
    }
    case 3:
    {
      if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
      {
        p[0] = (pixel >> 16) & 0xff;
        p[1] = (pixel >> 8) & 0xff;
        p[2] = pixel & 0xff;
      }
      else
      {
        p[0] = pixel & 0xff;
        p[1] = (pixel >> 8) & 0xff;
        p[2] = (pixel >> 16) & 0xff;
      }
      break;
    }
    case 4:
    {
      *(uint32_t*)p = pixel;
      break;
    }
  }
}

/**
 * Gets the specified pixel colour at a particular location and converts
 * it to the output format.
 *
 * @param fb Reference to the framebuffer structure
 * @param x X position
 * @param y Y position
 */
uint32_t fb_get_pixel(Framebuffer* fb, uint32_t x, uint32_t y)
{
  assert(fb);

  if (!fb->framebuffer)
  {
    return SDL_MapRGB(fb->surface->format, 0xff, 0x00, 0xff);
  }

  switch (fb->fb_bpp)
  {
    case 1: // 1 byte per pixel - 8 bit colour
    {
      uint8_t key = fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp];
      uint16_t value = fb->fb_palette[key];

      /* Format: RRRRRGGGGGGBBBBB */
      uint32_t r = (value >> 11) & 0x1F;
      uint32_t g = (value >> 5) & 0x3F;
      uint32_t b = value & 0x1F;

      /* Map to [0-255] */
      r = (r * 255) / 31;
      g = (g * 255) / 63;
      b = (b * 255) / 31;

      /* Return colour */
      return SDL_MapRGB(fb->surface->format, r, g, b);
    }
    case 2: // 2 bytes per pixel - R5G6B5
    {
      uint16_t value =
        fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp] +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 1] << 8);

      /* Format: BBBBBGGGGGGRRRRR */
      uint32_t r = value & 0x1F;
      uint32_t g = (value >> 5) & 0x3F;
      uint32_t b = (value >> 11) & 0x1F;

      /* Map to [0-255] */
      r = (r * 255) / 31;
      g = (g * 255) / 63;
      b = (b * 255) / 31;

      /* Return colour */
      return SDL_MapRGB(fb->surface->format, r, g, b);
    }
    case 3: // 3 bytes per pixel - RGB8
    case 4: // 4 bytes per pixel - XRGB8
    {
      uint32_t value =
        fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp] +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 1] << 8) +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 2] << 16) +
        (fb->framebuffer[y * fb->fb_pitch + x * fb->fb_bpp + 3] << 24);

      /* Format: BBBBBBBBGGGGGGGGRRRRRRRR */
      return SDL_MapRGB(fb->surface->format,
        value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF);
    }
    default:
    {
      fb->emu->error("Unsupported pixel format");
      break;
    }
  }

  return 0;
}

/**
 * Updates the display, displaying the framebuffer and handling events
 */
void Framebuffer::tick()
{
  assert(emu->isGraphicsEnabled());

  /* Handle all SDL events */
  SDL_Event event;
  while (SDL_PollEvent(&event))
  {
    if (event.type == SDL_QUIT)
    {
      emu->terminate();
    }

    /* Route keyboard presses to the NES module if enabled */
    if (event.type == SDL_KEYDOWN)
    {
      dispatchKeyDown(event.key.keysym.sym);
    }
    else if (event.type == SDL_KEYUP)
    {
      dispatchKeyUp(event.key.keysym.sym);
    }
  }

  /* Lock the surface */
  if (SDL_MUSTLOCK(surface))
  {
    SDL_LockSurface(surface);
  }

  /* Copy the pixels to SDL */
  for (uint32_t y = 0; y < height; ++y)
  {
    for (uint32_t x = 0; x < width; ++x)
    {
      put_pixel(surface, x, y, fb_get_pixel(this, x, y));
    }
  }

  /* Unlock the surface */
  if (SDL_MUSTLOCK(surface))
  {
    SDL_UnlockSurface(surface);
  }

  /* Display to screen */
  SDL_Flip(surface);
}

/**
 * Handles a framebuffer request received through the mailbox interface
 *
 * @param fb   Framebuffer structure
 * @param addr Address received from the mailbox
 */
void
fb_request(Framebuffer *fb, uint32_t addr)
{
  size_t i;
  framebuffer_req_t req;

  assert(fb);

  /* Clear error flag */
  fb->error = 0;

  /* Graphic flag must be set*/
  if (!fb->emu->isGraphicsEnabled())
  {
    fb->emu->error("Graphic mode must be enabled for framebuffer");
    fb->error = 1;
    return;
  }

  /* Check whether address is valid */
  if (addr < 0x40000000)
  {
    fb->emu->error("Invalid framebuffer address");
    fb->error = 1;
    return;
  }

  /* Respond to the framebuffer request */
  addr -= 0x40000000;
  for (i = 0; i < sizeof(req.data) / sizeof(req.data[0]); ++i)
  {
    req.data[i] = fb->mem->readDwordLe(addr + (i << 2));
  }

  /* Free old framebuffer */
  if (fb->framebuffer)
  {
    free(fb->framebuffer);
    fb->framebuffer = NULL;
  }

  /* Read palette if 8 bit colour
   * We're assuming that the palette comes immediately after the request */
  if (req.fb.depth == 8)
  {
    for (i = 0; i < 256; ++i)
    {
      fb->fb_palette[i] = fb->mem->readWordLe(addr + sizeof(req) + i * 2);
    }
  }

  /* Allocate a nice frame buffer, placed after the main memory */
  fb->fb_bpp = req.fb.depth >> 3;
  fb->fb_pitch = req.fb.virt_width * fb->fb_bpp;
  req.fb.pitch = fb->fb_pitch + (4 - (fb->fb_pitch % 4)) % 4;
  req.fb.size = fb->fb_size = fb->fb_pitch * req.fb.virt_height;
  fb->framebuffer = static_cast<uint8_t*>( malloc(fb->fb_size) );
  req.fb.addr = fb->fb_address = fb->mem_size;
  fb->width = req.fb.virt_width;
  fb->height = req.fb.virt_height;

  fb->base = fb->fb_address;
  fb->length = fb->fb_size;

  assert(fb->framebuffer);
  memset(fb->framebuffer, 0, fb->fb_size);

  /* Write back structure into memory */
  for (i = 0; i < sizeof(req.data) / sizeof(req.data[0]); ++i)
  {
    fb->mem->writeDwordLe(addr + (i << 2), req.data[i]);
  }

  /* Change the window caption */
  SDL_WM_SetCaption("Remu", "Remu");

  /* Change the window size */
  fb->surface = SDL_SetVideoMode(fb->width, fb->height, fb->depth, SDL_SWSURFACE);
}

uint64_t Framebuffer::readIo(uint64_t addr, unsigned int size)
{
  throw EmulationException("Read unimplemented for framebuffer @ %08llx:%xB", addr, size);
}

void Framebuffer::writeIo(uint64_t address, uint64_t val, unsigned int size)
{
  switch(size) {
    case sizeof(uint16_t): {
      const uint32_t addr = address - fb_address;
      framebuffer[addr + 0] = (val >> 0) & 0xFF;
      framebuffer[addr + 1] = (val >> 8) & 0xFF;
      return;
    }

    case sizeof(uint32_t): {
      const uint32_t addr = address - fb_address;
      framebuffer[addr + 0] = (val >> 0) & 0xFF;
      framebuffer[addr + 1] = (val >> 8) & 0xFF;
      framebuffer[addr + 2] = (val >> 16) & 0xFF;
      framebuffer[addr + 3] = (val >> 24) & 0xFF;
      return;
    }

    default: {
      throw EmulationException("Write unimplemented for framebuffer @ %08lx:%xB <- %lx", address, size, val);
    }
  }
}

} /*namespace remu*/

<|endoftext|>