<commit_before>#include "functions.h"

const double twopi = 2*datum::pi;
const double sq_twopi = sqrt(twopi);
const double loginvtwopi = log(1/twopi);
const double loginvsqtwopi = log(1/sq_twopi);

/////////////////////////////////////////////////////////////////////////////////////////////////
double logdF1(unsigned row, const unsigned &cause, const unsigned &indiv, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(cause);
  double cond_mean = as_scalar(cond_sig.proj*u);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = alp - gam;
  double inner = pow((alpgam-cond_mean),2)*as_scalar(cond_sig.inv);

  double logpdf = loginvsqtwopi + cond_sig.loginvsqdet + log(data.dalphaMarg_get(row, cause, indiv)) - 0.5*inner;

  double logdF1 = log(data.piMarg_get(row, cause, indiv)) + logpdf;
  return(logdF1);
};

rowvec dlogdF1du(unsigned row, const unsigned &cause, const unsigned &indiv, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(cause);
  double cond_mean = as_scalar(cond_sig.proj*u);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = (alp - gam);
  rowvec dinnerdu = (alpgam - cond_mean)*as_scalar(cond_sig.inv)*cond_sig.proj;

  rowvec dlogdF1du = data.dlogpiduMargAll_get(row, cause, indiv)) + dinnerdu;
  return(dlogdF1du);
};

/////////////////////////////////////////////////////////////////////////////////////////////////
double logdF2(unsigned row, const irowvec &causes, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(causes);
  vec cond_mean = cond_sig.proj*u;

  vec alp = data.alpha_get(row, causes);
  vec gam = data.gamma_get(row, causes);
  vec c_alpgam = (alp - gam) - cond_mean;
  double inner = as_scalar(c_alpgam.t()*cond_sig.inv*c_alpgam);

  double logpdf = loginvtwopi + cond_sig.loginvsqdet + log(data.dalphaMarg_get(row, causes(0), 1)) + log(data.dalphaMarg_get(row, causes(1), 2)) - 0.5*inner;

  double logdF2 = log(data.piMarg_get(row, causes(0), 1)) + log(data.piMarg_get(row, causes(1), 2)) + logpdf;
  return(logdF2);
};

rowvec dlogdF2du(unsigned row, const irowvec &causes, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(causes);
  vec cond_mean = cond_sig.proj*u;

  vec alp = data.alphaMarg_get(row, causes);
  vec gam = data.gammaMarg_get(row, causes);
  vec c_alpgam = (alp - gam) - cond_mean;

  rowvec dinnerdu = c_alpgam.t()*cond_sig.inv*cond_sig.proj;

  rowvec dlogdF2du = data.dlogpiduMarg_get(row, causes(0), 1)) + data.dlogpiduMarg_get(row, causes(1), 2)) + innerdu;
  return(dlogdF2du);
};

/////////////////////////////////////////////////////////////////////////////////////////////////

/* Marginal */
double F1(unsigned row, unsigned cause, unsigned indiv, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(cause);
  double cond_mean = as_scalar(cond_sig.proj*u);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = alp - gam;

  double F1 = data.piMarg_get(row, cause, indiv)*pn(alpgam, cond_mean, as_scalar(cond_sig.vcov));
  return(F1);
};

/* Full follow-up */
double F1(unsigned row, unsigned cause, unsigned indiv, const DataPairs &data){
  double F1 = data.piMarg_get(row, cause, indiv);
  return(F1);
};

/* Conditional on other individual */
double F1(unsigned row, unsigned cause, unsigned indiv, unsigned cond_cause, const DataPairs &data, const gmat &sigma, vec u){

  // Other individual
  unsigned cond_indiv;
  if (indiv==1){
    cond_indiv=2;
  }
  else {
    cond_indiv=1;
  }

  // Alpgam of other individual
  double cond_alp = data.alphaMarg_get(row, cond_cause, cond_indiv);
  double cond_gam = data.gammaMarg_get(row, cond_cause, cond_indiv);
  double cond_alpgam = cond_alp - cond_gam;

  vec vcond_alpgam(1); vcond_alpgam(0) = cond_alpgam;

  // Joining u vector and alpgam from other individual
  vec alpgamu = join_cols(vcond_alpgam, u);

  // Attaining variance covariance matrix etc. (conditional on u and other individual)
  vmat cond_sig = sigma(cause,cond_cause);
  double cond_mean = as_scalar(cond_sig.proj*alpgamu);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = alp - gam;

  double F1 = data.piMarg_get(row, cause, indiv)*pn(alpgam, cond_mean, as_scalar(cond_sig.vcov));
  return(F1);
};

/////////////////////////////////////////////////////////////////////////////////////////////////
double F2(unsigned row, irowvec causes, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(causes);
  vec cond_mean = cond_sig.proj*u;

  vec alp = data.alpha_get(row, causes);
  vec gam = data.gamma_get(row, causes);
  vec alpgam = alp - gam;

  double F2 = data.piMarg_get(row, causes(0), 1)*data.piMarg_get(row, causes(1), 2)*pn(alpgam, cond_mean,cond_sig.vcov);
  return(F2);
};
<commit_msg>update get functions<commit_after>#include "functions.h"

const double twopi = 2*datum::pi;
const double sq_twopi = sqrt(twopi);
const double loginvtwopi = log(1/twopi);
const double loginvsqtwopi = log(1/sq_twopi);

/////////////////////////////////////////////////////////////////////////////////////////////////
double logdF1(unsigned row, const unsigned &cause, const unsigned &indiv, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(cause);
  double cond_mean = as_scalar(cond_sig.proj*u);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = alp - gam;
  double inner = pow((alpgam-cond_mean),2)*as_scalar(cond_sig.inv);

  double logpdf = loginvsqtwopi + cond_sig.loginvsqdet + log(data.dalphaMarg_get(row, cause, indiv)) - 0.5*inner;

  double logdF1 = log(data.piMarg_get(row, cause, indiv)) + logpdf;
  return(logdF1);
};

rowvec dlogdF1du(unsigned row, const unsigned &cause, const unsigned &indiv, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(cause);
  double cond_mean = as_scalar(cond_sig.proj*u);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = (alp - gam);
  rowvec dinnerdu = (alpgam - cond_mean)*as_scalar(cond_sig.inv)*cond_sig.proj;

  rowvec dlogdF1du = data.dlogpiduMargAll_get(row, cause, indiv) + dinnerdu;
  return(dlogdF1du);
};

/////////////////////////////////////////////////////////////////////////////////////////////////
double logdF2(unsigned row, const irowvec &causes, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(causes);
  vec cond_mean = cond_sig.proj*u;

  vec alp = data.alpha_get(row, causes);
  vec gam = data.gamma_get(row, causes);
  vec c_alpgam = (alp - gam) - cond_mean;
  double inner = as_scalar(c_alpgam.t()*cond_sig.inv*c_alpgam);

  double logpdf = loginvtwopi + cond_sig.loginvsqdet + log(data.dalphaMarg_get(row, causes(0), 1)) + log(data.dalphaMarg_get(row, causes(1), 2)) - 0.5*inner;

  double logdF2 = log(data.piMarg_get(row, causes(0), 1)) + log(data.piMarg_get(row, causes(1), 2)) + logpdf;
  return(logdF2);
};

rowvec dlogdF2du(unsigned row, const irowvec &causes, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(causes);
  vec cond_mean = cond_sig.proj*u;

  vec alp = data.alpha_get(row, causes);
  vec gam = data.gamma_get(row, causes);
  vec c_alpgam = (alp - gam) - cond_mean;

  rowvec dinnerdu = c_alpgam.t()*cond_sig.inv*cond_sig.proj;

  rowvec dlogdF2du = data.dlogpiduMarg_get(row, causes(0), 1)) + data.dlogpiduMarg_get(row, causes(1), 2)) + innerdu;
  return(dlogdF2du);
};

/////////////////////////////////////////////////////////////////////////////////////////////////

/* Marginal */
double F1(unsigned row, unsigned cause, unsigned indiv, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(cause);
  double cond_mean = as_scalar(cond_sig.proj*u);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = alp - gam;

  double F1 = data.piMarg_get(row, cause, indiv)*pn(alpgam, cond_mean, as_scalar(cond_sig.vcov));
  return(F1);
};

/* Full follow-up */
double F1(unsigned row, unsigned cause, unsigned indiv, const DataPairs &data){
  double F1 = data.piMarg_get(row, cause, indiv);
  return(F1);
};

/* Conditional on other individual */
double F1(unsigned row, unsigned cause, unsigned indiv, unsigned cond_cause, const DataPairs &data, const gmat &sigma, vec u){

  // Other individual
  unsigned cond_indiv;
  if (indiv==1){
    cond_indiv=2;
  }
  else {
    cond_indiv=1;
  }

  // Alpgam of other individual
  double cond_alp = data.alphaMarg_get(row, cond_cause, cond_indiv);
  double cond_gam = data.gammaMarg_get(row, cond_cause, cond_indiv);
  double cond_alpgam = cond_alp - cond_gam;

  vec vcond_alpgam(1); vcond_alpgam(0) = cond_alpgam;

  // Joining u vector and alpgam from other individual
  vec alpgamu = join_cols(vcond_alpgam, u);

  // Attaining variance covariance matrix etc. (conditional on u and other individual)
  vmat cond_sig = sigma(cause,cond_cause);
  double cond_mean = as_scalar(cond_sig.proj*alpgamu);

  double alp = data.alphaMarg_get(row, cause, indiv);
  double gam = data.gammaMarg_get(row, cause, indiv);
  double alpgam = alp - gam;

  double F1 = data.piMarg_get(row, cause, indiv)*pn(alpgam, cond_mean, as_scalar(cond_sig.vcov));
  return(F1);
};

/////////////////////////////////////////////////////////////////////////////////////////////////
double F2(unsigned row, irowvec causes, const DataPairs &data, const gmat &sigma, vec u){

  // Attaining variance covariance matrix etc. (conditional on u)
  vmat cond_sig = sigma(causes);
  vec cond_mean = cond_sig.proj*u;

  vec alp = data.alpha_get(row, causes);
  vec gam = data.gamma_get(row, causes);
  vec alpgam = alp - gam;

  double F2 = data.piMarg_get(row, causes(0), 1)*data.piMarg_get(row, causes(1), 2)*pn(alpgam, cond_mean,cond_sig.vcov);
  return(F2);
};
<|endoftext|>


<commit_before>#include "generator.h"
#include "gameengine.h"
#include "algorithm.h"
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>

static unsigned int getDistance (unsigned int start, unsigned int end, void* customData);
static unsigned int getPathCost (unsigned int index, void* customData);
static unsigned int findNeighbours4 (unsigned int index, unsigned int* neighbours, void* customData);
static unsigned int findNeighbours8 (unsigned int index, unsigned int* neighbours, void* customData);

void Generator::generate () {
    unsigned int seed = time(0);
    //srand(1439294983);
    srand (seed);

    m_map = new unsigned char[m_mapHeight*m_mapWidth];
    memset (m_map, ' ', m_mapHeight*m_mapWidth);

    for (unsigned r = 0; r < m_roomTarget; r++) {
        while (!generateRoom ());
    }
    for (size_t ii = 0; ii < m_rooms.size()-1; ii++) {
        connectRooms (m_rooms[ii], m_rooms[ii+1]);
    }

    placePlayer();
    placeDownStair();
    placeOrcs();
    ///loadMap ();
    createEntitiesFromMap();
    std::cout << "Created with seed " << seed << std::endl;
}

void Generator::createEntitiesFromMap () {
    EntityId l_entity = 0;

    for (unsigned int yy = 0; yy < m_mapHeight; yy++) {
        for (unsigned int xx = 0; xx < m_mapWidth; xx++) {
            switch (getByCoordinate(xx, yy)) {
                case 'W':
                case 'C':
                    m_engine->getEntities()->createWallPrefab (xx, yy);
                    break;
                case 'P':
                    m_engine->getEntities()->createPlayerPrefab (xx, yy);
                    //m_engine->getEntities()->createTilePrefab (xx, yy);
                    l_entity = m_engine->getEntities()->createMarkerPrefab (xx, yy);
                    m_engine->getEntities()->getSprites()->get(l_entity)->sprite = '<';
                    break;
                case 'O':
                    m_engine->getEntities()->createEnemyPrefab (xx, yy);
                    m_engine->getEntities()->createTilePrefab (xx, yy);
                    break;
                case '.':
                    m_engine->getEntities()->createTilePrefab (xx, yy);
                    break;
                case 'X':
                    break;
                default:
                    l_entity = m_engine->getEntities()->createMarkerPrefab (xx, yy);
                    m_engine->getEntities()->getSprites()->get(l_entity)->sprite = getByCoordinate (xx, yy);
                    break;
            }
        }
    }
}

bool Generator::generateRoom () {
    unsigned int width  = rand() % 6 + 5;
    unsigned int height = rand() % 6 + 5;
    unsigned int left   = rand() % (m_mapWidth - width - 1) + 2;
    unsigned int top    = rand() % (m_mapHeight - height - 1) + 2;

    if (left+width >= m_mapWidth || left < 1 ||
        top+height >= m_mapHeight || top < 1) {
            return false;
    }

    for (unsigned int yy = top-2; yy <= top+height+1; yy++) {
        for (unsigned int xx = left-2; xx <= left+width+1; xx++) {
            if (getByCoordinate (xx, yy) != ' ') return false;
        }
    }

    for (unsigned int yy = top-2; yy <= top+height+1; yy++) {
        for (unsigned int xx = left-2; xx <= left+width+1; xx++) {
            if (yy < top || yy >= top+height || xx < left || xx >= left+width) {
                getByCoordinate(xx, yy) = 'X';
            } else if (yy == top || yy == top+height-1 || xx == left || xx == left+width-1) {
                if ((yy <= top+1 || yy >= top+height-2) && (xx <= left+1 || xx >= left+width-2)) {
                    getByCoordinate(xx, yy) = 'C';
                } else {
                    getByCoordinate(xx, yy) = 'W';
                }
            } else {
                getByCoordinate(xx, yy) = '.';
            }
        }
    }

    Room l_room;
    l_room.x = left;
    l_room.y = top;
    l_room.width = width;
    l_room.height = height;
    l_room.midX = left + (width/2);
    l_room.midY = top + (height/2);
    l_room.index = CoordToIndex (l_room.midX, l_room.midY);
    m_rooms.push_back (l_room);

/*
    if (!m_playerPlaced) {
        getByCoordinate(l_room.midX, l_room.midY) = 'P';
        //m_map[(top+height/2)*m_mapWidth+(left+width/2)] = 'P';
        m_playerPlaced = true;
    }
*/
    return true;
}

void Generator::connectRooms (Room& start, Room& end)
{
    Algorithm algo;
    algo.setCustomData (this);
    algo.setCostFunction (getPathCost);
    algo.setDistanceFunction (getDistance);
    algo.setNeighbourFunction (findNeighbours4);
    algo.setNumNeighbours (4);

    PathVector l_path;
    algo.findPath (start.index, end.index, l_path);
    //std::cout << "Found a " << l_path.size() << " tile corridor" << std::endl;

    for (size_t ii = 0; ii < l_path.size(); ii++) {
        unsigned char& tile = getByIndex(l_path[ii]);
        unsigned int x, y;
        IndexToCoord (l_path[ii], x, y);

        // Create tiles and doors
        if (tile == 'W' || tile == 'D') {
            tile = 'D';
        } else {
            tile = '.';
        }
    }

    for (size_t ii = 0; ii < l_path.size(); ii++) {
        // Wall of neighbours if necessary
        unsigned int neighbours[8] = {0};
        size_t count = findNeighbours8 (l_path[ii], neighbours, this);
        for (size_t ii = 0; ii < count; ii++) {
            unsigned char& adj = getByIndex (neighbours[ii]);
            if (adj == ' ' || adj == 'X') {
                adj = 'W';
            }
        }
    }
}

void Generator::placePlayer()
{
    m_playerRoom = rand() % m_rooms.size();
    getByCoordinate (m_rooms[m_playerRoom].midX, m_rooms[m_playerRoom].midY) = 'P';
}

void Generator::placeDownStair()
{
    if (m_rooms.size() < 2) return; // No point
    unsigned int room = m_playerRoom;
    while (room == m_playerRoom) room = rand() % m_rooms.size();
    getByCoordinate (m_rooms[room].midX, m_rooms[room].midY) = '>';
}

void Generator::placeOrcs()
{
    if (m_rooms.size() < 2) return; // No point

    for (size_t ii = 0; ii < m_rooms.size(); ii++) {
        unsigned int room = m_playerRoom;
        std::cout << "Finding room..." << std::endl;
        while (1) {
            room = rand() % m_rooms.size();
            if (m_playerRoom == room) continue;
            unsigned int x, y;
            x = m_rooms[room].x + (rand() % m_rooms[room].width-2) + 1;
            y = m_rooms[room].y + (rand() % m_rooms[room].height-2) + 1;
            unsigned char& tile = getByCoordinate (x, y);
            if (tile == '.') {
                tile = 'O';
                break;
            }
        }
    }
}

void Generator::loadMap ()
{
    std::ifstream file ("../maps/test.map");
    char line[m_mapWidth];
    int lineCnt = 0;
    do {
        memset (line, ' ', sizeof (line));
        file.getline (line, sizeof (line));
        memcpy (m_map+(m_mapWidth*lineCnt), line, sizeof(line));
        lineCnt++;
    } while (file.gcount() > 0);
}

unsigned int getPathCost (unsigned int index, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned char point = l_gen->getByIndex(index);
    unsigned int cost = 0;
    switch (point) {
        case ' ':
            cost = 3;
            break;
        case 'W':
        case 'X':
        case 'D':
            cost = 5;
            break;
        case '.':
            cost = 0;
            break;
        case 'C':
            cost = 999;
            break;
        default:
            cost = 999;
            break;
    }
    //std::cout << "Returning cost: " << cost << std::endl;
    return cost;
}

unsigned int findNeighbours4 (unsigned int index, unsigned int* neighbours, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned int indexX, indexY;
    l_gen->IndexToCoord (index, indexX, indexY);

    unsigned int count = 0;

    if (l_gen->isValidCoordinate (indexX-1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY);
    if (l_gen->isValidCoordinate (indexX+1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY);
    if (l_gen->isValidCoordinate (indexX, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY-1);
    if (l_gen->isValidCoordinate (indexX, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY+1);
    //std::cout << "Return " << count << " neightbours" << std::endl;

    return count;
}

unsigned int findNeighbours8 (unsigned int index, unsigned int* neighbours, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned int indexX, indexY;
    l_gen->IndexToCoord (index, indexX, indexY);

    unsigned int count = 0;

    if (l_gen->isValidCoordinate (indexX-1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY);
    if (l_gen->isValidCoordinate (indexX+1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY);
    if (l_gen->isValidCoordinate (indexX, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY-1);
    if (l_gen->isValidCoordinate (indexX, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY+1);
    if (l_gen->isValidCoordinate (indexX-1, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY-1);
    if (l_gen->isValidCoordinate (indexX+1, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY-1);
    if (l_gen->isValidCoordinate (indexX-1, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY+1);
    if (l_gen->isValidCoordinate (indexX+1, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY+1);

    //std::cout << "Return " << count << " neightbours" << std::endl;

    return count;
}

unsigned int getDistance (unsigned int start, unsigned int end, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned int startX, startY;
    unsigned int endX, endY;
    unsigned int distance = 0;
    l_gen->IndexToCoord (start, startX, startY);
    l_gen->IndexToCoord (end, endX, endY);
    distance = (abs (startX-endX)+abs(startY-endY));
    //std::cout << "Returning distance: " << distance << std::endl;
    return distance;
}
<commit_msg>Random number of orcs<commit_after>#include "generator.h"
#include "gameengine.h"
#include "algorithm.h"
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>

static unsigned int getDistance (unsigned int start, unsigned int end, void* customData);
static unsigned int getPathCost (unsigned int index, void* customData);
static unsigned int findNeighbours4 (unsigned int index, unsigned int* neighbours, void* customData);
static unsigned int findNeighbours8 (unsigned int index, unsigned int* neighbours, void* customData);

void Generator::generate () {
    unsigned int seed = time(0);
    //srand(1439294983);
    srand (seed);

    m_map = new unsigned char[m_mapHeight*m_mapWidth];
    memset (m_map, ' ', m_mapHeight*m_mapWidth);

    for (unsigned r = 0; r < m_roomTarget; r++) {
        while (!generateRoom ());
    }
    for (size_t ii = 0; ii < m_rooms.size()-1; ii++) {
        connectRooms (m_rooms[ii], m_rooms[ii+1]);
    }

    placePlayer();
    placeDownStair();
    placeOrcs();
    ///loadMap ();
    createEntitiesFromMap();
    std::cout << "Created with seed " << seed << std::endl;
}

void Generator::createEntitiesFromMap () {
    EntityId l_entity = 0;

    for (unsigned int yy = 0; yy < m_mapHeight; yy++) {
        for (unsigned int xx = 0; xx < m_mapWidth; xx++) {
            switch (getByCoordinate(xx, yy)) {
                case 'W':
                case 'C':
                    m_engine->getEntities()->createWallPrefab (xx, yy);
                    break;
                case 'P':
                    m_engine->getEntities()->createPlayerPrefab (xx, yy);
                    //m_engine->getEntities()->createTilePrefab (xx, yy);
                    l_entity = m_engine->getEntities()->createMarkerPrefab (xx, yy);
                    m_engine->getEntities()->getSprites()->get(l_entity)->sprite = '<';
                    break;
                case 'O':
                    m_engine->getEntities()->createEnemyPrefab (xx, yy);
                    m_engine->getEntities()->createTilePrefab (xx, yy);
                    break;
                case '.':
                    m_engine->getEntities()->createTilePrefab (xx, yy);
                    break;
                case 'X':
                    break;
                default:
                    l_entity = m_engine->getEntities()->createMarkerPrefab (xx, yy);
                    m_engine->getEntities()->getSprites()->get(l_entity)->sprite = getByCoordinate (xx, yy);
                    break;
            }
        }
    }
}

bool Generator::generateRoom () {
    unsigned int width  = rand() % 6 + 5;
    unsigned int height = rand() % 6 + 5;
    unsigned int left   = rand() % (m_mapWidth - width - 1) + 2;
    unsigned int top    = rand() % (m_mapHeight - height - 1) + 2;

    if (left+width >= m_mapWidth || left < 1 ||
        top+height >= m_mapHeight || top < 1) {
            return false;
    }

    for (unsigned int yy = top-2; yy <= top+height+1; yy++) {
        for (unsigned int xx = left-2; xx <= left+width+1; xx++) {
            if (getByCoordinate (xx, yy) != ' ') return false;
        }
    }

    for (unsigned int yy = top-2; yy <= top+height+1; yy++) {
        for (unsigned int xx = left-2; xx <= left+width+1; xx++) {
            if (yy < top || yy >= top+height || xx < left || xx >= left+width) {
                getByCoordinate(xx, yy) = 'X';
            } else if (yy == top || yy == top+height-1 || xx == left || xx == left+width-1) {
                if ((yy <= top+1 || yy >= top+height-2) && (xx <= left+1 || xx >= left+width-2)) {
                    getByCoordinate(xx, yy) = 'C';
                } else {
                    getByCoordinate(xx, yy) = 'W';
                }
            } else {
                getByCoordinate(xx, yy) = '.';
            }
        }
    }

    Room l_room;
    l_room.x = left;
    l_room.y = top;
    l_room.width = width;
    l_room.height = height;
    l_room.midX = left + (width/2);
    l_room.midY = top + (height/2);
    l_room.index = CoordToIndex (l_room.midX, l_room.midY);
    m_rooms.push_back (l_room);

/*
    if (!m_playerPlaced) {
        getByCoordinate(l_room.midX, l_room.midY) = 'P';
        //m_map[(top+height/2)*m_mapWidth+(left+width/2)] = 'P';
        m_playerPlaced = true;
    }
*/
    return true;
}

void Generator::connectRooms (Room& start, Room& end)
{
    Algorithm algo;
    algo.setCustomData (this);
    algo.setCostFunction (getPathCost);
    algo.setDistanceFunction (getDistance);
    algo.setNeighbourFunction (findNeighbours4);
    algo.setNumNeighbours (4);

    PathVector l_path;
    algo.findPath (start.index, end.index, l_path);
    //std::cout << "Found a " << l_path.size() << " tile corridor" << std::endl;

    for (size_t ii = 0; ii < l_path.size(); ii++) {
        unsigned char& tile = getByIndex(l_path[ii]);
        unsigned int x, y;
        IndexToCoord (l_path[ii], x, y);

        // Create tiles and doors
        if (tile == 'W' || tile == 'D') {
            tile = 'D';
        } else {
            tile = '.';
        }
    }

    for (size_t ii = 0; ii < l_path.size(); ii++) {
        // Wall of neighbours if necessary
        unsigned int neighbours[8] = {0};
        size_t count = findNeighbours8 (l_path[ii], neighbours, this);
        for (size_t ii = 0; ii < count; ii++) {
            unsigned char& adj = getByIndex (neighbours[ii]);
            if (adj == ' ' || adj == 'X') {
                adj = 'W';
            }
        }
    }
}

void Generator::placePlayer()
{
    m_playerRoom = rand() % m_rooms.size();
    getByCoordinate (m_rooms[m_playerRoom].midX, m_rooms[m_playerRoom].midY) = 'P';
}

void Generator::placeDownStair()
{
    if (m_rooms.size() < 2) return; // No point
    unsigned int room = m_playerRoom;
    while (room == m_playerRoom) room = rand() % m_rooms.size();
    getByCoordinate (m_rooms[room].midX, m_rooms[room].midY) = '>';
}

void Generator::placeOrcs()
{
    if (m_rooms.size() < 2) return; // No point

    unsigned int numOrcs = rand() % (m_rooms.size() * 2) + m_rooms.size();
    for (size_t ii = 0; ii < numOrcs; ii++) {
        unsigned int room = 0;
        while (1) {
            room = rand() % m_rooms.size();
            if (m_playerRoom == room) continue;
            unsigned int x, y;
            x = m_rooms[room].x + (rand() % m_rooms[room].width-2) + 1;
            y = m_rooms[room].y + (rand() % m_rooms[room].height-2) + 1;
            unsigned char& tile = getByCoordinate (x, y);
            if (tile == '.') {
                tile = 'O';
                break;
            }
        }
    }
}

void Generator::loadMap ()
{
    std::ifstream file ("../maps/test.map");
    char line[m_mapWidth];
    int lineCnt = 0;
    do {
        memset (line, ' ', sizeof (line));
        file.getline (line, sizeof (line));
        memcpy (m_map+(m_mapWidth*lineCnt), line, sizeof(line));
        lineCnt++;
    } while (file.gcount() > 0);
}

unsigned int getPathCost (unsigned int index, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned char point = l_gen->getByIndex(index);
    unsigned int cost = 0;
    switch (point) {
        case ' ':
            cost = 3;
            break;
        case 'W':
        case 'X':
        case 'D':
            cost = 5;
            break;
        case '.':
            cost = 0;
            break;
        case 'C':
            cost = 999;
            break;
        default:
            cost = 999;
            break;
    }
    //std::cout << "Returning cost: " << cost << std::endl;
    return cost;
}

unsigned int findNeighbours4 (unsigned int index, unsigned int* neighbours, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned int indexX, indexY;
    l_gen->IndexToCoord (index, indexX, indexY);

    unsigned int count = 0;

    if (l_gen->isValidCoordinate (indexX-1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY);
    if (l_gen->isValidCoordinate (indexX+1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY);
    if (l_gen->isValidCoordinate (indexX, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY-1);
    if (l_gen->isValidCoordinate (indexX, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY+1);
    //std::cout << "Return " << count << " neightbours" << std::endl;

    return count;
}

unsigned int findNeighbours8 (unsigned int index, unsigned int* neighbours, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned int indexX, indexY;
    l_gen->IndexToCoord (index, indexX, indexY);

    unsigned int count = 0;

    if (l_gen->isValidCoordinate (indexX-1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY);
    if (l_gen->isValidCoordinate (indexX+1, indexY))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY);
    if (l_gen->isValidCoordinate (indexX, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY-1);
    if (l_gen->isValidCoordinate (indexX, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX, indexY+1);
    if (l_gen->isValidCoordinate (indexX-1, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY-1);
    if (l_gen->isValidCoordinate (indexX+1, indexY-1))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY-1);
    if (l_gen->isValidCoordinate (indexX-1, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX-1, indexY+1);
    if (l_gen->isValidCoordinate (indexX+1, indexY+1))
        neighbours[count++] = l_gen->CoordToIndex (indexX+1, indexY+1);

    //std::cout << "Return " << count << " neightbours" << std::endl;

    return count;
}

unsigned int getDistance (unsigned int start, unsigned int end, void* customData)
{
    Generator* l_gen = static_cast<Generator*> (customData);
    unsigned int startX, startY;
    unsigned int endX, endY;
    unsigned int distance = 0;
    l_gen->IndexToCoord (start, startX, startY);
    l_gen->IndexToCoord (end, endX, endY);
    distance = (abs (startX-endX)+abs(startY-endY));
    //std::cout << "Returning distance: " << distance << std::endl;
    return distance;
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <getopt.h>

/** @file main.cpp
 *
 * This file is the main() routine and scaffolding for producing
 * builtin_compiler (which doesn't include builtins itself and is used
 * to generate the profile information for builtin_function.cpp), and
 * for glsl_compiler (which does include builtins and can be used to
 * offline compile GLSL code and examine the resulting GLSL IR.
 */

#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "standalone_scaffolding.h"

static int glsl_version = 330;

static void
initialize_context(struct gl_context *ctx, gl_api api)
{
   initialize_context_to_defaults(ctx, api);

   /* The standalone compiler needs to claim support for almost
    * everything in order to compile the built-in functions.
    */
   ctx->Const.GLSLVersion = glsl_version;
   ctx->Extensions.ARB_ES3_compatibility = true;

   switch (ctx->Const.GLSLVersion) {
   case 100:
      ctx->Const.MaxClipPlanes = 0;
      ctx->Const.MaxCombinedTextureImageUnits = 8;
      ctx->Const.MaxDrawBuffers = 2;
      ctx->Const.MinProgramTexelOffset = 0;
      ctx->Const.MaxProgramTexelOffset = 0;
      ctx->Const.MaxLights = 0;
      ctx->Const.MaxTextureCoordUnits = 0;
      ctx->Const.MaxTextureUnits = 8;

      ctx->Const.VertexProgram.MaxAttribs = 8;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 0;
      ctx->Const.VertexProgram.MaxUniformComponents = 128 * 4;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 32;

      ctx->Const.FragmentProgram.MaxTextureImageUnits =
         ctx->Const.MaxCombinedTextureImageUnits;
      ctx->Const.FragmentProgram.MaxUniformComponents = 16 * 4;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 110:
   case 120:
      ctx->Const.MaxClipPlanes = 6;
      ctx->Const.MaxCombinedTextureImageUnits = 2;
      ctx->Const.MaxDrawBuffers = 1;
      ctx->Const.MinProgramTexelOffset = 0;
      ctx->Const.MaxProgramTexelOffset = 0;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 2;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 0;
      ctx->Const.VertexProgram.MaxUniformComponents = 512;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 32;

      ctx->Const.FragmentProgram.MaxTextureImageUnits =
         ctx->Const.MaxCombinedTextureImageUnits;
      ctx->Const.FragmentProgram.MaxUniformComponents = 64;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 130:
   case 140:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxCombinedTextureImageUnits = 16;
      ctx->Const.MaxDrawBuffers = 8;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 8;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 64;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 1024;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 150:
   case 330:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxDrawBuffers = 8;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 8;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 64;

      ctx->Const.GeometryProgram.MaxTextureImageUnits = 16;
      ctx->Const.GeometryProgram.MaxUniformComponents = 1024;
      ctx->Const.GeometryProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.GeometryProgram.MaxOutputComponents = 128;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 1024;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.GeometryProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxCombinedTextureImageUnits =
         ctx->Const.VertexProgram.MaxTextureImageUnits
         + ctx->Const.GeometryProgram.MaxTextureImageUnits
         + ctx->Const.FragmentProgram.MaxTextureImageUnits;

      ctx->Const.MaxGeometryOutputVertices = 256;
      ctx->Const.MaxGeometryTotalOutputComponents = 1024;

//      ctx->Const.MaxGeometryVaryingComponents = 64;

      ctx->Const.MaxVarying = 60 / 4;
      break;
   case 300:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxCombinedTextureImageUnits = 32;
      ctx->Const.MaxDrawBuffers = 4;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 0;
      ctx->Const.MaxTextureCoordUnits = 0;
      ctx->Const.MaxTextureUnits = 0;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 16 * 4;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 224;
      ctx->Const.FragmentProgram.MaxInputComponents = 15 * 4;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.FragmentProgram.MaxInputComponents / 4;
      break;
   }

   ctx->Driver.NewShader = _mesa_new_shader;
}

/* Returned string will have 'ctx' as its ralloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
{
	char *text = NULL;
	size_t size;
	size_t total_read = 0;
	FILE *fp = fopen(file_name, "rb");

	if (!fp) {
		return NULL;
	}

	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0L, SEEK_SET);

	text = (char *) ralloc_size(ctx, size + 1);
	if (text != NULL) {
		do {
			size_t bytes = fread(text + total_read,
					     1, size - total_read, fp);
			if (bytes < size - total_read) {
				free(text);
				text = NULL;
				break;
			}

			if (bytes == 0) {
				break;
			}

			total_read += bytes;
		} while (total_read < size);

		text[total_read] = '\0';
	}

	fclose(fp);

	return text;
}

int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;

const struct option compiler_opts[] = {
   { "dump-ast", no_argument, &dump_ast, 1 },
   { "dump-hir", no_argument, &dump_hir, 1 },
   { "dump-lir", no_argument, &dump_lir, 1 },
   { "link",     no_argument, &do_link,  1 },
   { "version",  required_argument, NULL, 'v' },
   { NULL, 0, NULL, 0 }
};

/**
 * \brief Print proper usage and exit with failure.
 */
void
usage_fail(const char *name)
{

   const char *header =
      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
      "\n"
      "Possible options are:\n";
   printf(header, name, name);
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
      printf("    --%s\n", o->name);
   }
   exit(EXIT_FAILURE);
}

void
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
   struct _mesa_glsl_parse_state *state =
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);

   _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);

   /* Print out the resulting IR */
   if (!state->error && dump_lir) {
      _mesa_print_ir(shader->ir, state);
   }

   return;
}

int
main(int argc, char **argv)
{
   int status = EXIT_SUCCESS;
   struct gl_context local_ctx;
   struct gl_context *ctx = &local_ctx;
   bool glsl_es = false;

   int c;
   int idx = 0;
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) {
      switch (c) {
      case 'v':
         glsl_version = strtol(optarg, NULL, 10);
         switch (glsl_version) {
         case 100:
         case 300:
            glsl_es = true;
            break;
         case 110:
         case 120:
         case 130:
         case 140:
         case 150:
         case 330:
            glsl_es = false;
            break;
         default:
            fprintf(stderr, "Unrecognized GLSL version `%s'\n", optarg);
            usage_fail(argv[0]);
            break;
         }
         break;
      default:
         break;
      }
   }

   if (argc <= optind)
      usage_fail(argv[0]);

   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);

   struct gl_shader_program *whole_program;

   whole_program = rzalloc (NULL, struct gl_shader_program);
   assert(whole_program != NULL);
   whole_program->InfoLog = ralloc_strdup(whole_program, "");

   for (/* empty */; argc > optind; optind++) {
      whole_program->Shaders =
	 reralloc(whole_program, whole_program->Shaders,
		  struct gl_shader *, whole_program->NumShaders + 1);
      assert(whole_program->Shaders != NULL);

      struct gl_shader *shader = rzalloc(whole_program, gl_shader);

      whole_program->Shaders[whole_program->NumShaders] = shader;
      whole_program->NumShaders++;

      const unsigned len = strlen(argv[optind]);
      if (len < 6)
	 usage_fail(argv[0]);

      const char *const ext = & argv[optind][len - 5];
      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
	 shader->Type = GL_VERTEX_SHADER;
      else if (strncmp(".geom", ext, 5) == 0)
	 shader->Type = GL_GEOMETRY_SHADER;
      else if (strncmp(".frag", ext, 5) == 0)
	 shader->Type = GL_FRAGMENT_SHADER;
      else
	 usage_fail(argv[0]);

      shader->Source = load_text_file(whole_program, argv[optind]);
      if (shader->Source == NULL) {
	 printf("File \"%s\" does not exist.\n", argv[optind]);
	 exit(EXIT_FAILURE);
      }

      compile_shader(ctx, shader);

      if (!shader->CompileStatus) {
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
	 status = EXIT_FAILURE;
	 break;
      }
   }

   if ((status == EXIT_SUCCESS) && do_link)  {
      link_shaders(ctx, whole_program);
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;

      if (strlen(whole_program->InfoLog) > 0)
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
   }

   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
      ralloc_free(whole_program->_LinkedShaders[i]);

   ralloc_free(whole_program);
   _mesa_glsl_release_types();
   _mesa_glsl_release_builtin_functions();

   return status;
}
<commit_msg>glsl_compiler: Always log the compiler diagnostics<commit_after>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <getopt.h>

/** @file main.cpp
 *
 * This file is the main() routine and scaffolding for producing
 * builtin_compiler (which doesn't include builtins itself and is used
 * to generate the profile information for builtin_function.cpp), and
 * for glsl_compiler (which does include builtins and can be used to
 * offline compile GLSL code and examine the resulting GLSL IR.
 */

#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "standalone_scaffolding.h"

static int glsl_version = 330;

static void
initialize_context(struct gl_context *ctx, gl_api api)
{
   initialize_context_to_defaults(ctx, api);

   /* The standalone compiler needs to claim support for almost
    * everything in order to compile the built-in functions.
    */
   ctx->Const.GLSLVersion = glsl_version;
   ctx->Extensions.ARB_ES3_compatibility = true;

   switch (ctx->Const.GLSLVersion) {
   case 100:
      ctx->Const.MaxClipPlanes = 0;
      ctx->Const.MaxCombinedTextureImageUnits = 8;
      ctx->Const.MaxDrawBuffers = 2;
      ctx->Const.MinProgramTexelOffset = 0;
      ctx->Const.MaxProgramTexelOffset = 0;
      ctx->Const.MaxLights = 0;
      ctx->Const.MaxTextureCoordUnits = 0;
      ctx->Const.MaxTextureUnits = 8;

      ctx->Const.VertexProgram.MaxAttribs = 8;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 0;
      ctx->Const.VertexProgram.MaxUniformComponents = 128 * 4;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 32;

      ctx->Const.FragmentProgram.MaxTextureImageUnits =
         ctx->Const.MaxCombinedTextureImageUnits;
      ctx->Const.FragmentProgram.MaxUniformComponents = 16 * 4;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 110:
   case 120:
      ctx->Const.MaxClipPlanes = 6;
      ctx->Const.MaxCombinedTextureImageUnits = 2;
      ctx->Const.MaxDrawBuffers = 1;
      ctx->Const.MinProgramTexelOffset = 0;
      ctx->Const.MaxProgramTexelOffset = 0;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 2;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 0;
      ctx->Const.VertexProgram.MaxUniformComponents = 512;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 32;

      ctx->Const.FragmentProgram.MaxTextureImageUnits =
         ctx->Const.MaxCombinedTextureImageUnits;
      ctx->Const.FragmentProgram.MaxUniformComponents = 64;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 130:
   case 140:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxCombinedTextureImageUnits = 16;
      ctx->Const.MaxDrawBuffers = 8;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 8;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 64;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 1024;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 150:
   case 330:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxDrawBuffers = 8;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 8;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 64;

      ctx->Const.GeometryProgram.MaxTextureImageUnits = 16;
      ctx->Const.GeometryProgram.MaxUniformComponents = 1024;
      ctx->Const.GeometryProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.GeometryProgram.MaxOutputComponents = 128;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 1024;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.GeometryProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxCombinedTextureImageUnits =
         ctx->Const.VertexProgram.MaxTextureImageUnits
         + ctx->Const.GeometryProgram.MaxTextureImageUnits
         + ctx->Const.FragmentProgram.MaxTextureImageUnits;

      ctx->Const.MaxGeometryOutputVertices = 256;
      ctx->Const.MaxGeometryTotalOutputComponents = 1024;

//      ctx->Const.MaxGeometryVaryingComponents = 64;

      ctx->Const.MaxVarying = 60 / 4;
      break;
   case 300:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxCombinedTextureImageUnits = 32;
      ctx->Const.MaxDrawBuffers = 4;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 0;
      ctx->Const.MaxTextureCoordUnits = 0;
      ctx->Const.MaxTextureUnits = 0;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 16 * 4;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 224;
      ctx->Const.FragmentProgram.MaxInputComponents = 15 * 4;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.FragmentProgram.MaxInputComponents / 4;
      break;
   }

   ctx->Driver.NewShader = _mesa_new_shader;
}

/* Returned string will have 'ctx' as its ralloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
{
	char *text = NULL;
	size_t size;
	size_t total_read = 0;
	FILE *fp = fopen(file_name, "rb");

	if (!fp) {
		return NULL;
	}

	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0L, SEEK_SET);

	text = (char *) ralloc_size(ctx, size + 1);
	if (text != NULL) {
		do {
			size_t bytes = fread(text + total_read,
					     1, size - total_read, fp);
			if (bytes < size - total_read) {
				free(text);
				text = NULL;
				break;
			}

			if (bytes == 0) {
				break;
			}

			total_read += bytes;
		} while (total_read < size);

		text[total_read] = '\0';
	}

	fclose(fp);

	return text;
}

int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;

const struct option compiler_opts[] = {
   { "dump-ast", no_argument, &dump_ast, 1 },
   { "dump-hir", no_argument, &dump_hir, 1 },
   { "dump-lir", no_argument, &dump_lir, 1 },
   { "link",     no_argument, &do_link,  1 },
   { "version",  required_argument, NULL, 'v' },
   { NULL, 0, NULL, 0 }
};

/**
 * \brief Print proper usage and exit with failure.
 */
void
usage_fail(const char *name)
{

   const char *header =
      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
      "\n"
      "Possible options are:\n";
   printf(header, name, name);
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
      printf("    --%s\n", o->name);
   }
   exit(EXIT_FAILURE);
}

void
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
   struct _mesa_glsl_parse_state *state =
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);

   _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);

   /* Print out the resulting IR */
   if (!state->error && dump_lir) {
      _mesa_print_ir(shader->ir, state);
   }

   return;
}

int
main(int argc, char **argv)
{
   int status = EXIT_SUCCESS;
   struct gl_context local_ctx;
   struct gl_context *ctx = &local_ctx;
   bool glsl_es = false;

   int c;
   int idx = 0;
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) {
      switch (c) {
      case 'v':
         glsl_version = strtol(optarg, NULL, 10);
         switch (glsl_version) {
         case 100:
         case 300:
            glsl_es = true;
            break;
         case 110:
         case 120:
         case 130:
         case 140:
         case 150:
         case 330:
            glsl_es = false;
            break;
         default:
            fprintf(stderr, "Unrecognized GLSL version `%s'\n", optarg);
            usage_fail(argv[0]);
            break;
         }
         break;
      default:
         break;
      }
   }

   if (argc <= optind)
      usage_fail(argv[0]);

   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);

   struct gl_shader_program *whole_program;

   whole_program = rzalloc (NULL, struct gl_shader_program);
   assert(whole_program != NULL);
   whole_program->InfoLog = ralloc_strdup(whole_program, "");

   for (/* empty */; argc > optind; optind++) {
      whole_program->Shaders =
	 reralloc(whole_program, whole_program->Shaders,
		  struct gl_shader *, whole_program->NumShaders + 1);
      assert(whole_program->Shaders != NULL);

      struct gl_shader *shader = rzalloc(whole_program, gl_shader);

      whole_program->Shaders[whole_program->NumShaders] = shader;
      whole_program->NumShaders++;

      const unsigned len = strlen(argv[optind]);
      if (len < 6)
	 usage_fail(argv[0]);

      const char *const ext = & argv[optind][len - 5];
      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
	 shader->Type = GL_VERTEX_SHADER;
      else if (strncmp(".geom", ext, 5) == 0)
	 shader->Type = GL_GEOMETRY_SHADER;
      else if (strncmp(".frag", ext, 5) == 0)
	 shader->Type = GL_FRAGMENT_SHADER;
      else
	 usage_fail(argv[0]);

      shader->Source = load_text_file(whole_program, argv[optind]);
      if (shader->Source == NULL) {
	 printf("File \"%s\" does not exist.\n", argv[optind]);
	 exit(EXIT_FAILURE);
      }

      compile_shader(ctx, shader);

      if (strlen(shader->InfoLog) > 0)
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);

      if (!shader->CompileStatus) {
	 status = EXIT_FAILURE;
	 break;
      }
   }

   if ((status == EXIT_SUCCESS) && do_link)  {
      link_shaders(ctx, whole_program);
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;

      if (strlen(whole_program->InfoLog) > 0)
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
   }

   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
      ralloc_free(whole_program->_LinkedShaders[i]);

   ralloc_free(whole_program);
   _mesa_glsl_release_types();
   _mesa_glsl_release_builtin_functions();

   return status;
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS pchfix02 (1.13.4); FILE MERGED 2006/09/01 17:35:34 kaib 1.13.4.1: #i68856# Added header markers and pch files<commit_after><|endoftext|>


<commit_before>// https://github.com/KubaO/stackoverflown/tree/master/questions/metaproxy-32612309
#include <QtCore>
#include <QMetaProperty>
#include <functional>
#include <private/qmetaobjectbuilder_p.h>

class ObjectA : public QObject {
    Q_OBJECT
    Q_PROPERTY(int a MEMBER m_a NOTIFY aChanged)
    Q_PROPERTY(QString b READ b WRITE setB NOTIFY bChanged)
    int m_a;
    QString m_b;
public:
    ObjectA(QObject * parent = 0) : QObject(parent) {}
    QString b() const { return m_b; }
    Q_SLOT void setB(const QString & b) { if (m_b == b) return; emit bChanged(m_b = b); }
    Q_SLOT void slot(const QString & a, int c) {}
    Q_SIGNAL void aChanged(int a0);
    Q_SIGNAL void bChanged(const QString & b0);
};

class ObjectB : public ObjectA {
    Q_OBJECT
    Q_PROPERTY(QStringList c MEMBER m_c NOTIFY cChanged)
    QStringList m_c;
public:
    ObjectB(QObject * parent = 0) : ObjectA(parent) {}
    Q_SIGNAL void cChanged(const QStringList &);
    Q_SLOT void setC(const QStringList & c) { m_c = c; emit cChanged(c); }
};

struct CacheEntry {
    int typeId { 0 };
    void * value { nullptr };
    void setValue(void * src) {
        Q_ASSERT(value);
        qDebug() << "setting value" << QMetaType::typeName(typeId) << "@" << value;
        QMetaType::destruct(typeId, value);
        QMetaType::construct(typeId, value, src);
    }
    ~CacheEntry() {
        if (value) QMetaType::destroy(typeId, value);
    }
};
Q_DECLARE_TYPEINFO(CacheEntry, Q_MOVABLE_TYPE);

void dumpMethods(const QMetaObject * o) {
    qDebug() << o->className() << "has" << o->methodCount() << "methods";
    for (int i = 0; i < o->methodCount(); ++i) {
        qDebug() << "method" << i << o->method(i).name();
    }
}

/// Add all metaobjects in order from most base to most derived class,
/// with exception of QObject itself
void addMetaObjects(QMetaObjectBuilder & b, const QMetaObject * derived) {
    using Q = QMetaObjectBuilder;
    if (!derived->superClass()) return;
    addMetaObjects(b, derived->superClass());
    b.addMetaObject(derived, Q::AddMembers(Q::AllMembers) & ~Q::AddMembers(Q::SuperClass | Q::StaticMetacall));
}

class PropertyProxy : public QObject {
    QScopedPointer<QMetaObject, QScopedPointerPodDeleter> m_o;
    QPointer<QObject> m_target;
    QVector<CacheEntry> m_cache; // cache of property values
    typedef std::function<void(void**)> Slot;
    QVector<Slot> m_slots;

    int methodCount() const {
        return m_target->metaObject()->methodCount() + m_slots.size();
    }
    void readProperty(void * dst, int id) {
        void * args[1] = { dst };
        QObject * target = m_target;
        auto read = [&args, id, target]{
            target->qt_metacall(QMetaObject::ReadProperty, id, args);
        };
        if (target->thread() == QThread::currentThread()) {
            read();
        } else {
            QObject sig;
            connect(&sig, &QObject::destroyed, target, read, Qt::BlockingQueuedConnection);
        }
    }
public:
    Q_OBJECT_CHECK
    const QMetaObject *metaObject() const Q_DECL_OVERRIDE {
        return m_o.data();
    }
    int qt_metacall(QMetaObject::Call _c, int _id, void **_a) Q_DECL_OVERRIDE {
        qDebug() << __FUNCTION__ << _c << _id << _a;
        if (_c == QMetaObject::InvokeMetaMethod) {
            _id = m_target->QObject::qt_metacall(_c, _id, _a);
            if (_id < 0) return _id;
            if (_id < methodCount())
                qt_static_metacall(this, _c, _id, _a);
            _id -= methodCount();
            return _id;
        }
        return m_target->qt_metacall(_c, _id, _a);
    }
    static void qt_static_metacall(QObject *_o, QMetaObject::Call c, int id, void **a) {
        qDebug() << __FUNCTION__ << c << id << a;
        if (c != QMetaObject::InvokeMetaMethod) return;
        auto o = static_cast<PropertyProxy*>(_o);
        int targetMethodCount = o->m_target->metaObject()->methodCount() - QObject::staticMetaObject.methodCount();
        if (id < targetMethodCount) {
            id += QObject::staticMetaObject.methodCount();
            o->m_target->qt_metacall(c, id, a);
            return;
        }
        id -= targetMethodCount;
        Q_ASSERT(id >= 0 && id < o->m_slots.count());
        qDebug() << "calling slot" << id;
        o->m_slots.at(id)(a);
    }

    PropertyProxy(QObject * target, QObject * parent = 0) : QObject(parent), m_target(target) {
        typedef QMetaObjectBuilder Q;
        auto tmobj = target->metaObject();
        qDebug() << "target has" << tmobj->methodCount() << "methods";
        dumpMethods(tmobj);
        QMetaObjectBuilder b;
        b.setSuperClass(&QObject::staticMetaObject);
        b.setStaticMetacallFunction(qt_static_metacall);
        addMetaObjects(b, tmobj);
        int n = 0;
        for (int i = 0; i < tmobj->propertyCount(); ++i) {
            auto prop = tmobj->property(i);
            if (prop.isReadable() && prop.hasNotifySignal()) {
                m_cache.push_back(CacheEntry());
                m_slots.push_back(Slot());
                auto & entry = m_cache.last();
                entry.typeId = prop.userType();
                entry.value = QMetaType(prop.userType()).create();
                if (!entry.value) {
                    qWarning() << "PropertyProxy: cannot create an instance of the value of property" << prop.name()
                               << "of type" << QMetaType::typeName(prop.userType()) << "(" << prop.userType() << ")";
                }
                readProperty(entry.value, i);
                m_slots.last() = [this, n, prop](void ** args){
                    qDebug() << "notify slot" << n << "for" << prop.name();
                    m_cache[n].setValue(args[1]);
                };
                // create a slot that will be notified of the change of property value
                QByteArray s("void __pnslot__");
                s.append(prop.name());
                s.append("(");
                s.append(prop.typeName());
                s.append(")");
                QMetaMethodBuilder m = b.addSlot(s);
                int index = m.index() + QObject::metaObject()->methodCount();
                qDebug() << "adding notification slot" << s << "at index" << index;
                QMetaObject::connect(target, prop.notifySignalIndex(), this, index);
                n++;
            }
            else if (prop.isReadable()) {
                qWarning() << "PropertyProxy: skipping non-notifying property" << prop.name() << "of" << target;
            }
        }
        m_o.reset(b.toMetaObject());
        dumpMethods(m_o.data());
    }
};

int main(int argc, char ** argv) {
    QCoreApplication app{argc, argv};
    ObjectB b;
    PropertyProxy p(&b);
    b.setObjectName("yay");

}

#include "main.moc"
<commit_msg>Forward property reads and writes.<commit_after>// https://github.com/KubaO/stackoverflown/tree/master/questions/metaproxy-32612309
#include <QtCore>
#include <QMetaProperty>
#include <functional>
#include <private/qmetaobjectbuilder_p.h>

class ObjectA : public QObject {
    Q_OBJECT
    Q_PROPERTY(int a MEMBER m_a NOTIFY aChanged)
    Q_PROPERTY(QString b READ b WRITE setB NOTIFY bChanged)
    int m_a;
    QString m_b;
public:
    ObjectA(QObject * parent = 0) : QObject(parent) {}
    QString b() const { return m_b; }
    Q_SLOT void setB(const QString & b) { if (m_b == b) return; emit bChanged(m_b = b); }
    Q_SLOT void slot(const QString & a, int c) {}
    Q_SIGNAL void aChanged(int a0);
    Q_SIGNAL void bChanged(const QString & b0);
};

class ObjectB : public ObjectA {
    Q_OBJECT
    Q_PROPERTY(QStringList c MEMBER m_c NOTIFY cChanged)
    QStringList m_c;
public:
    ObjectB(QObject * parent = 0) : ObjectA(parent) {}
    Q_SIGNAL void cChanged(const QStringList &);
    Q_SLOT void setC(const QStringList & c) { m_c = c; emit cChanged(c); }
};

struct CacheEntry {
    int typeId { 0 };
    void * value { nullptr };
    int slotIndex { -1 };
    void setValue(void * src) {
        Q_ASSERT(value);
        qDebug() << "setting value" << QMetaType::typeName(typeId) << "@" << value;
        QMetaType::destruct(typeId, value);
        QMetaType::construct(typeId, value, src);
    }
    void getValue(void * dst) const {
        Q_ASSERT(value);
        qDebug() << "getting value" << QMetaType::typeName(typeId) << "@" << value;
        QMetaType::destruct(typeId, dst);
        QMetaType::construct(typeId, dst, value);
    }
    ~CacheEntry() {
        if (value) QMetaType::destroy(typeId, value);
    }
};
Q_DECLARE_TYPEINFO(CacheEntry, Q_MOVABLE_TYPE);

void dumpMethods(const QMetaObject * o) {
    qDebug() << o->className() << "has" << o->methodCount() << "methods";
    for (int i = 0; i < o->methodCount(); ++i) {
        qDebug() << "method" << i << o->method(i).name();
    }
}

/// Add all metaobjects in order from most base to most derived class,
/// with exception of QObject itself
void addMetaObjects(QMetaObjectBuilder & b, const QMetaObject * derived) {
    using Q = QMetaObjectBuilder;
    if (!derived->superClass()) return;
    addMetaObjects(b, derived->superClass());
    b.addMetaObject(derived, Q::AddMembers(Q::AllMembers) & ~Q::AddMembers(Q::SuperClass | Q::StaticMetacall));
}

class PropertyProxy : public QObject {
    QScopedPointer<QMetaObject, QScopedPointerPodDeleter> m_o;
    QPointer<QObject> m_target;
    QVector<CacheEntry> m_cache; // cache of property values
    typedef std::function<void(void**)> Slot;
    QVector<Slot> m_slots;

    int methodCount() const {
        return m_target->metaObject()->methodCount() + m_slots.size();
    }
    void readProperty(void * dst, int id, bool warn = false) {
        void * args[1] = { dst };
        QObject * target = m_target;
        auto read = [&args, id, target]{
            target->qt_metacall(QMetaObject::ReadProperty, id, args);
        };
        if (target->thread() == QThread::currentThread()) {
            read();
        } else {
            if (warn) qWarning() << "blocking to read the property";
            QObject sig;
            connect(&sig, &QObject::destroyed, target, read, Qt::BlockingQueuedConnection);
        }
    }
    void writeProperty(void * src, int id) {
        QObject * target = m_target;
        if (target->thread() == QThread::currentThread()) {
            void * args[1] = { src };
            target->qt_metacall(QMetaObject::WriteProperty, id, args);
        } else {
            struct Data {
                int typeId;
                void * args[1] = { buf() };
                void * m_buf;
                void * buf() { return reinterpret_cast<void*>(&m_buf); }
                Data(int typeId, void * src) : typeId(typeId) {
                    QMetaType::construct(typeId, buf(), src);
                }
                ~Data() { QMetaType::destruct(typeId, buf()); }
                static Data * make(int typeId, void * src) {
                    Data * d = reinterpret_cast<Data*>(malloc(sizeof(Data) + QMetaType::sizeOf(typeId)));
                    return new (d) Data(typeId, src);
                }
                static void free(Data * d) {
                    d->~Data();
                    ::free(d);
                }
            };
            auto typeId = m_cache.at(id).typeId;
            QSharedPointer<Data> d(Data::make(typeId, src), Data::free);
            QObject sig;
            connect(&sig, &QObject::destroyed, target, [d, id, target]{
                target->qt_metacall(QMetaObject::WriteProperty, id, d->args);
            });
        }
    }

public:
    Q_OBJECT_CHECK
    const QMetaObject *metaObject() const Q_DECL_OVERRIDE {
        return m_o.data();
    }
    int qt_metacall(QMetaObject::Call _c, int _id, void **_a) Q_DECL_OVERRIDE {
        qDebug() << __FUNCTION__ << _c << _id << _a;
        if (_c == QMetaObject::InvokeMetaMethod) {
            _id = m_target->QObject::qt_metacall(_c, _id, _a);
            if (_id < 0) return _id;
            if (_id < methodCount())
                qt_static_metacall(this, _c, _id, _a);
            _id -= methodCount();
            return _id;
        }
        else if (_c == QMetaObject::ReadProperty) {
            if (_id < m_o->propertyCount()) {
                auto prop = m_o->property(_id);
                if (prop.isReadable()) {
                    if (prop.hasNotifySignal()) {
                        m_cache.at(_id).getValue(_a[0]);
                    } else {
                        readProperty(_a[0], _id, true);
                    }
                }
            }
            _id -= m_o->propertyCount();
            return _id;
        }
        else if (_c == QMetaObject::WriteProperty) {
            if (_id < m_o->propertyCount()) {
                auto prop = m_o->property(_id);
                if (prop.isWritable())
                    writeProperty(_a[0], _id);
            }
            _id -= m_o->propertyCount();
            return _id;
        }
        return m_target->qt_metacall(_c, _id, _a);
    }
    static void qt_static_metacall(QObject *_o, QMetaObject::Call c, int id, void **a) {
        qDebug() << __FUNCTION__ << c << id << a;
        if (c != QMetaObject::InvokeMetaMethod) return;
        auto o = static_cast<PropertyProxy*>(_o);
        int targetMethodCount = o->m_target->metaObject()->methodCount() - QObject::staticMetaObject.methodCount();
        if (id < targetMethodCount) {
            id += QObject::staticMetaObject.methodCount();
            o->m_target->qt_metacall(c, id, a);
            return;
        }
        id -= targetMethodCount;
        Q_ASSERT(id >= 0 && id < o->m_slots.count());
        qDebug() << "calling slot" << id;
        o->m_slots.at(id)(a);
    }

    PropertyProxy(QObject * target, QObject * parent = 0) : QObject(parent), m_target(target) {
        typedef QMetaObjectBuilder Q;
        auto tmobj = target->metaObject();
        qDebug() << "target has" << tmobj->methodCount() << "methods";
        dumpMethods(tmobj);
        QMetaObjectBuilder b;
        b.setSuperClass(&QObject::staticMetaObject);
        b.setStaticMetacallFunction(qt_static_metacall);
        addMetaObjects(b, tmobj);
        int n = 0;
        m_cache.resize(tmobj->propertyCount());
        for (int i = 0; i < tmobj->propertyCount(); ++i) {
            auto prop = tmobj->property(i);
            if (prop.isReadable() && prop.hasNotifySignal()) {
                auto & entry = m_cache[i];
                entry.typeId = prop.userType();
                entry.value = QMetaType(prop.userType()).create();
                if (!entry.value) {
                    qWarning() << "PropertyProxy: cannot create an instance of the value of property" << prop.name()
                               << "of type" << QMetaType::typeName(prop.userType()) << "(" << prop.userType() << ")";
                }
                readProperty(entry.value, i);
                m_slots.push_back(Slot());
                m_slots.last() = [this, n, i, prop](void ** args){
                    qDebug() << "notify slot" << n << "for" << prop.name() << "index" << i;
                    m_cache[i].setValue(args[1]);
                };
                // create a slot that will be notified of the change of property value
                QByteArray s("void __pnslot__");
                s.append(prop.name());
                s.append("(");
                s.append(prop.typeName());
                s.append(")");
                QMetaMethodBuilder m = b.addSlot(s);
                int index = m.index() + QObject::metaObject()->methodCount();
                entry.slotIndex = index;
                qDebug() << "adding notification slot" << s << "at index" << index;
                QMetaObject::connect(target, prop.notifySignalIndex(), this, index);
                n++;
            }
            else if (prop.isReadable()) {
                qWarning() << "PropertyProxy: skipping non-notifying property" << prop.name() << "of" << target;
            }
        }
        m_o.reset(b.toMetaObject());
        dumpMethods(m_o.data());
    }
};

int main(int argc, char ** argv) {
    QCoreApplication app{argc, argv};
    ObjectB b;
    PropertyProxy p(&b);
    b.setObjectName("yay");
    Q_ASSERT(b.objectName() == "yay");
    p.setProperty("objectName", "foo");
    Q_ASSERT(b.objectName() == "foo");
}

#include "main.moc"
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include "AliITSClusterFinderSPD.h"
#include "AliITSMapA1.h"
#include "AliITS.h"
#include "AliRun.h"

ClassImp(AliITSClusterFinderSPD)

//----------------------------------------------------------
AliITSClusterFinderSPD::AliITSClusterFinderSPD
(AliITSsegmentation *seg, TClonesArray *digits, TClonesArray *recp)
{
  // constructor
    fSegmentation=seg;
    fDigits=digits;
    fClusters=recp;
    fNclusters= fClusters->GetEntriesFast();
    SetDx();
    SetDz();
    SetMap();
    SetNCells();
}

//_____________________________________________________________________________
AliITSClusterFinderSPD::AliITSClusterFinderSPD()
{
  // constructor
  fSegmentation=0;
  fDigits=0;
  fClusters=0;
  fNclusters=0;
  fMap=0;
  SetDx();
  SetDz();
  SetNCells();

}

//_____________________________________________________________________________
AliITSClusterFinderSPD::~AliITSClusterFinderSPD()
{
  // destructor
  if (fMap) delete fMap;

}
//__________________________________________________________________________
AliITSClusterFinderSPD::AliITSClusterFinderSPD(const AliITSClusterFinderSPD &source){
  //     Copy Constructor
  if(&source == this) return;
  this->fClusters = source.fClusters ;
  this->fNclusters = source.fNclusters ;
  this->fMap = source.fMap ;
  this->fDz = source.fDz ;
  this->fDx = source.fDx ;
  this->fMinNCells = source.fMinNCells ;
  return;
}

//_________________________________________________________________________
AliITSClusterFinderSPD&
  AliITSClusterFinderSPD::operator=(const AliITSClusterFinderSPD &source) {
  //    Assignment operator
  if(&source == this) return *this;
  this->fClusters = source.fClusters ;
  this->fNclusters = source.fNclusters ;
  this->fMap = source.fMap ;
  this->fDz = source.fDz ;
  this->fDx = source.fDx ;
  this->fMinNCells = source.fMinNCells ;
  return *this;
}

//_____________________________________________________________________________
void AliITSClusterFinderSPD::SetMap()
{
  // set map

  if(!fMap) fMap=new AliITSMapA1(fSegmentation,fDigits);

}

//_____________________________________________________________________________

void AliITSClusterFinderSPD::Find1DClusters()
{
  // Find one dimensional clusters, i.e.
  // in r*phi(x) direction for each colunm in z direction

  AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");

  // retrieve the parameters
  Int_t fNofPixels = fSegmentation->Npz();
  Int_t fMaxNofSamples = fSegmentation->Npx();

  // read in digits -> do not apply threshold
  // signal in fired pixels is always 1

  fMap->FillMap();

  Int_t nofFoundClusters = 0;

  Int_t k,it,m;
  for(k=0;k<fNofPixels;k++) {

    Int_t mmax = 10;  // a size of the window for the cluster finding

    for(it=0;it<fMaxNofSamples;it++) {

      Int_t lclx = 0;
      Int_t xstart = 0;
      Int_t xstop = 0;
      Int_t id = 0;
      Int_t ilcl =0;

      for(m=0;m<mmax;m++) {  // find the cluster inside the window
	id = it+m;
	if(id >= fMaxNofSamples) break;    // ! no possible for the fadc

	if(fMap->TestHit(k,id) == kUnused) {   // start of the cluster
	  lclx += 1;
	  if(lclx == 1) xstart = id;

	}

	if(lclx > 0 && fMap->TestHit(k,id) == kEmpty) {
	  // end of cluster if a gap exists
	  xstop = id-1;
	  ilcl = 1;
	  break;
	}

      }   //  end of m-loop

      if(lclx == 0 && ilcl == 0) it = id; // no cluster in the window,
      // continue the "it" loop

      if(id >= fMaxNofSamples && lclx == 0) break; // the x row finished

      if(id < fMaxNofSamples && ilcl == 0 && lclx > 0) {
	                           // cluster end is outside of the window,
	mmax += 5;                 // increase mmax and repeat the cluster
	                           // finding
	it -= 1;
      }

      if(id >= fMaxNofSamples && lclx > 0) {  // the x row finished but
	xstop = fMaxNofSamples - 1;           // the end cluster exists
	ilcl = 1;
      }

      // ---  Calculate z and x coordinates for one dimensional clusters

      if(ilcl == 1) {         // new cluster exists
	it = id;
	mmax = 10;
	    nofFoundClusters++;
	    Float_t clusterCharge = 0.;
            Float_t zpitch = fSegmentation->Dpz(k+1);
	    Float_t clusterZ, dummyX;
            Int_t dummy=0;
            fSegmentation->GetPadCxz(dummy,k,dummyX,clusterZ);
            Float_t zstart = clusterZ - 0.5*zpitch;
            Float_t zstop = clusterZ + 0.5*zpitch;
	    Float_t clusterX = 0.;
            Int_t xstartfull = xstart;
            Int_t xstopfull = xstop;
	    Int_t clusterSizeX = lclx;
	    Int_t clusterSizeZ = 1;

            Int_t its;
	    for(its=xstart; its<=xstop; its++) {
              Int_t firedpixel=0;
              if (fMap->GetHitIndex(k,its)>=0) firedpixel=1;
	      clusterCharge += firedpixel;
              clusterX +=its + 0.5;
	    }
            Float_t fRphiPitch = fSegmentation->Dpx(dummy);
	    clusterX /= (clusterSizeX/fRphiPitch); // center of gravity for x

	    //printf("ClusterZ ClusterX %f %f \n",clusterZ, clusterX);

            // Int_t nclusters = fClusters->GetEntriesFast();
	    //	    	    cout << nclusters << " clusters" << endl;
	    //            cout<< "Create point"<<endl;

	    // Write the points (coordinates and some cluster information) to the
	    // AliITSRawClusterSPD object

	    AliITSRawClusterSPD *clust = new AliITSRawClusterSPD(clusterZ,clusterX,clusterCharge,clusterSizeZ,clusterSizeX,xstart,xstop,xstartfull,xstopfull,zstart,zstop,k);
	    // fClusters->Add(point);
	    iTS->AddCluster(0,clust);
	    //    	    cout << "Cluster at Ladder: " << fLadder << ", Detector: " <<fDetector<<endl;

	    // cout<<" end of cluster finding for Z pixel "<<endl;

      }    // new cluster (ilcl=1)
    } // X direction loop (it)
  } // Z direction loop (k)

  //fMap->ClearMap();
  return;

}

//_____________________________________________________________________________
void  AliITSClusterFinderSPD::GroupClusters()
{
  // Find two dimensional clusters, i.e. group one dimensional clusters
  // into two dimensional ones (go both in x and z directions).

  // get number of clusters for this module
  Int_t nofClusters = fClusters->GetEntriesFast();
  nofClusters -= fNclusters;

  AliITSRawClusterSPD *clusterI;
  AliITSRawClusterSPD *clusterJ;

  Int_t *label=new Int_t[nofClusters];
  Int_t i,j;
  for(i=0; i<nofClusters; i++) label[i] = 0;
  for(i=0; i<nofClusters; i++) {
    if(label[i] != 0) continue;
    for(j=i+1; j<nofClusters; j++) {
      if(label[j] != 0) continue;
      clusterI = (AliITSRawClusterSPD*) fClusters->At(i);
      clusterJ = (AliITSRawClusterSPD*) fClusters->At(j);
      Bool_t pair = clusterI->Brother(clusterJ,fDz,fDx);
      if(pair) {

	//    if((clusterI->XStop() == clusterJ->XStart()-1)||(clusterI->XStart()==clusterJ->XStop()+1)) cout<<"!! Diagonal cluster"<<endl;
	/*
	      cout << "clusters " << i << "," << j << " before grouping" << endl;
	      clusterI->PrintInfo();
	      clusterJ->PrintInfo();
	*/
	clusterI->Add(clusterJ);
	//        cout << "remove cluster " << j << endl;
	label[j] = 1;
	fClusters->RemoveAt(j);
	/*
	  cout << "cluster  " << i << " after grouping" << endl;
	  clusterI->PrintInfo();
	*/
      }  // pair
    } // J clusters
    label[i] = 1;
  } // I clusters
  fClusters->Compress();
  //  Int_t totalNofClusters = fClusters->GetEntriesFast();
  //  cout << " Nomber of clusters at the group end ="<< totalNofClusters<<endl;

  delete [] label;

  return;

}
//_____________________________________________________________________________

void AliITSClusterFinderSPD::TracksInCluster()
{

  // Find tracks creating one cluster

  // get number of clusters for this module
  Int_t nofClusters = fClusters->GetEntriesFast();
  nofClusters -= fNclusters;

  Int_t i, ix, iz, jx, jz, xstart, xstop, zstart, zstop, nclx, nclz;
  //  Int_t signal, track0, track1, track2;
  Int_t trmax = 100;
  Int_t cltracks[trmax], itr, tracki, ii, is, js, ie, ntr, tr0, tr1, tr2;

  for(i=0; i<nofClusters; i++) {
    ii = 0;
    memset(cltracks,-1,sizeof(int)*trmax);
    tr0=tr1=tr2=-1;

    AliITSRawClusterSPD *clusterI = (AliITSRawClusterSPD*) fClusters->At(i);

    nclx = clusterI->NclX();
    nclz = clusterI->NclZ();
    xstart = clusterI->XStartf();
    xstop = clusterI->XStopf();
    zstart = clusterI->Zend()-nclz+1;
    zstop = clusterI->Zend();

    Int_t ind;

     for(iz=0; iz<nclz; iz++) {
         jz = zstart + iz;
       for(ix=0; ix<nclx; ix++) {
	 jx = xstart + ix;
	 ind = fMap->GetHitIndex(jz,jx);
	 if(ind == 0 && iz >= 0 && ix > 0) {
          continue;
         }
	 if(ind == 0 && iz > 0 && ix >= 0) {
          continue;
         }
	 if(ind == 0 && iz == 0 && ix == 0 && i > 0) {
          continue;
         }

        AliITSdigitSPD *dig = (AliITSdigitSPD*)fMap->GetHit(jz,jx);
	/*
         signal=dig->fSignal;
         track0=dig->fTracks[0];
         track1=dig->fTracks[1];
         track2=dig->fTracks[2];
	*/
          for(itr=0; itr<3; itr++) {
	    tracki = dig->fTracks[itr];
            if(tracki >= 0) {
	      ii += 1;
             cltracks[ii-1] = tracki;
            }
	  }
       } // ix pixel
     }  // iz pixel

     for(is=0; is<trmax; is++) {
         if(cltracks[is]<0) continue;
       for(js=is+1; js<trmax; js++) {
         if(cltracks[js]<0) continue;
         if(cltracks[js]==cltracks[is]) cltracks[js]=-5;
       }
     }

     ntr = 0;
     for(ie=0; ie<trmax; ie++) {
       if(cltracks[ie] >= 0) {
        ntr=ntr+1;
        if(ntr==1) tr0=cltracks[ie];
        if(ntr==2) tr1=cltracks[ie];
        if(ntr==3) tr2=cltracks[ie];
       }
     }
     // if delta ray only
     if(ntr == 0) ntr = 1;

     clusterI->SetNTracks(ntr);
     clusterI->SetTracks(tr0,tr1,tr2);

  } // I cluster

}
//_____________________________________________________________________________

void AliITSClusterFinderSPD::GetRecPoints()
{
  // get rec points
  AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");

  // get number of clusters for this module
  Int_t nofClusters = fClusters->GetEntriesFast();
  nofClusters -= fNclusters;
  const Float_t kconv = 1.0e-4;
  const Float_t kRMSx = 12.0*kconv; // microns -> cm ITS TDR Table 1.3
  const Float_t kRMSz = 70.0*kconv; // microns -> cm ITS TDR Table 1.3

  Float_t spdLength = fSegmentation->Dz();
  Float_t spdWidth = fSegmentation->Dx();

  Int_t i;
  Int_t track0, track1, track2;

  for(i=0; i<nofClusters; i++) {

    AliITSRawClusterSPD *clusterI = (AliITSRawClusterSPD*) fClusters->At(i);
    clusterI->GetTracks(track0, track1, track2);
    AliITSRecPoint rnew;

    rnew.SetX((clusterI->X() - spdWidth/2)*kconv);
    rnew.SetZ((clusterI->Z() - spdLength/2)*kconv);
    rnew.SetQ(1.);
    rnew.SetdEdX(0.);
    rnew.SetSigmaX2(kRMSx*kRMSx);
    rnew.SetSigmaZ2(kRMSz*kRMSz);
    rnew.fTracks[0]=track0;
    rnew.fTracks[1]=track1;
    rnew.fTracks[2]=track2;
    iTS->AddRecPoint(rnew);
  } // I clusters

  fMap->ClearMap();

}
//_____________________________________________________________________________

void AliITSClusterFinderSPD::FindRawClusters()
{
  // find raw clusters
  Find1DClusters();
  GroupClusters();
  TracksInCluster();
  GetRecPoints();

}

<commit_msg>Changed line "Int_t trmax = 100;" to "const Int_t trmax = 100;" in void AliITSClusterFinderSPD::TracksInCluster(). Needed for compilation by some compilers since the size of the Int_t array cltracks depends on it.<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include "AliITSClusterFinderSPD.h"
#include "AliITSMapA1.h"
#include "AliITS.h"
#include "AliRun.h"

ClassImp(AliITSClusterFinderSPD)

//----------------------------------------------------------
AliITSClusterFinderSPD::AliITSClusterFinderSPD
(AliITSsegmentation *seg, TClonesArray *digits, TClonesArray *recp)
{
  // constructor
    fSegmentation=seg;
    fDigits=digits;
    fClusters=recp;
    fNclusters= fClusters->GetEntriesFast();
    SetDx();
    SetDz();
    SetMap();
    SetNCells();
}

//_____________________________________________________________________________
AliITSClusterFinderSPD::AliITSClusterFinderSPD()
{
  // constructor
  fSegmentation=0;
  fDigits=0;
  fClusters=0;
  fNclusters=0;
  fMap=0;
  SetDx();
  SetDz();
  SetNCells();

}

//_____________________________________________________________________________
AliITSClusterFinderSPD::~AliITSClusterFinderSPD()
{
  // destructor
  if (fMap) delete fMap;

}
//__________________________________________________________________________
AliITSClusterFinderSPD::AliITSClusterFinderSPD(const AliITSClusterFinderSPD &source){
  //     Copy Constructor
  if(&source == this) return;
  this->fClusters = source.fClusters ;
  this->fNclusters = source.fNclusters ;
  this->fMap = source.fMap ;
  this->fDz = source.fDz ;
  this->fDx = source.fDx ;
  this->fMinNCells = source.fMinNCells ;
  return;
}

//_________________________________________________________________________
AliITSClusterFinderSPD&
  AliITSClusterFinderSPD::operator=(const AliITSClusterFinderSPD &source) {
  //    Assignment operator
  if(&source == this) return *this;
  this->fClusters = source.fClusters ;
  this->fNclusters = source.fNclusters ;
  this->fMap = source.fMap ;
  this->fDz = source.fDz ;
  this->fDx = source.fDx ;
  this->fMinNCells = source.fMinNCells ;
  return *this;
}

//_____________________________________________________________________________
void AliITSClusterFinderSPD::SetMap()
{
  // set map

  if(!fMap) fMap=new AliITSMapA1(fSegmentation,fDigits);

}

//_____________________________________________________________________________

void AliITSClusterFinderSPD::Find1DClusters()
{
  // Find one dimensional clusters, i.e.
  // in r*phi(x) direction for each colunm in z direction

  AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");

  // retrieve the parameters
  Int_t fNofPixels = fSegmentation->Npz();
  Int_t fMaxNofSamples = fSegmentation->Npx();

  // read in digits -> do not apply threshold
  // signal in fired pixels is always 1

  fMap->FillMap();

  Int_t nofFoundClusters = 0;

  Int_t k,it,m;
  for(k=0;k<fNofPixels;k++) {

    Int_t mmax = 10;  // a size of the window for the cluster finding

    for(it=0;it<fMaxNofSamples;it++) {

      Int_t lclx = 0;
      Int_t xstart = 0;
      Int_t xstop = 0;
      Int_t id = 0;
      Int_t ilcl =0;

      for(m=0;m<mmax;m++) {  // find the cluster inside the window
	id = it+m;
	if(id >= fMaxNofSamples) break;    // ! no possible for the fadc

	if(fMap->TestHit(k,id) == kUnused) {   // start of the cluster
	  lclx += 1;
	  if(lclx == 1) xstart = id;

	}

	if(lclx > 0 && fMap->TestHit(k,id) == kEmpty) {
	  // end of cluster if a gap exists
	  xstop = id-1;
	  ilcl = 1;
	  break;
	}

      }   //  end of m-loop

      if(lclx == 0 && ilcl == 0) it = id; // no cluster in the window,
      // continue the "it" loop

      if(id >= fMaxNofSamples && lclx == 0) break; // the x row finished

      if(id < fMaxNofSamples && ilcl == 0 && lclx > 0) {
	                           // cluster end is outside of the window,
	mmax += 5;                 // increase mmax and repeat the cluster
	                           // finding
	it -= 1;
      }

      if(id >= fMaxNofSamples && lclx > 0) {  // the x row finished but
	xstop = fMaxNofSamples - 1;           // the end cluster exists
	ilcl = 1;
      }

      // ---  Calculate z and x coordinates for one dimensional clusters

      if(ilcl == 1) {         // new cluster exists
	it = id;
	mmax = 10;
	    nofFoundClusters++;
	    Float_t clusterCharge = 0.;
            Float_t zpitch = fSegmentation->Dpz(k+1);
	    Float_t clusterZ, dummyX;
            Int_t dummy=0;
            fSegmentation->GetPadCxz(dummy,k,dummyX,clusterZ);
            Float_t zstart = clusterZ - 0.5*zpitch;
            Float_t zstop = clusterZ + 0.5*zpitch;
	    Float_t clusterX = 0.;
            Int_t xstartfull = xstart;
            Int_t xstopfull = xstop;
	    Int_t clusterSizeX = lclx;
	    Int_t clusterSizeZ = 1;

            Int_t its;
	    for(its=xstart; its<=xstop; its++) {
              Int_t firedpixel=0;
              if (fMap->GetHitIndex(k,its)>=0) firedpixel=1;
	      clusterCharge += firedpixel;
              clusterX +=its + 0.5;
	    }
            Float_t fRphiPitch = fSegmentation->Dpx(dummy);
	    clusterX /= (clusterSizeX/fRphiPitch); // center of gravity for x

	    //printf("ClusterZ ClusterX %f %f \n",clusterZ, clusterX);

            // Int_t nclusters = fClusters->GetEntriesFast();
	    //	    	    cout << nclusters << " clusters" << endl;
	    //            cout<< "Create point"<<endl;

	    // Write the points (coordinates and some cluster information) to the
	    // AliITSRawClusterSPD object

	    AliITSRawClusterSPD *clust = new AliITSRawClusterSPD(clusterZ,clusterX,clusterCharge,clusterSizeZ,clusterSizeX,xstart,xstop,xstartfull,xstopfull,zstart,zstop,k);
	    // fClusters->Add(point);
	    iTS->AddCluster(0,clust);
	    //    	    cout << "Cluster at Ladder: " << fLadder << ", Detector: " <<fDetector<<endl;

	    // cout<<" end of cluster finding for Z pixel "<<endl;

      }    // new cluster (ilcl=1)
    } // X direction loop (it)
  } // Z direction loop (k)

  //fMap->ClearMap();
  return;

}

//_____________________________________________________________________________
void  AliITSClusterFinderSPD::GroupClusters()
{
  // Find two dimensional clusters, i.e. group one dimensional clusters
  // into two dimensional ones (go both in x and z directions).

  // get number of clusters for this module
  Int_t nofClusters = fClusters->GetEntriesFast();
  nofClusters -= fNclusters;

  AliITSRawClusterSPD *clusterI;
  AliITSRawClusterSPD *clusterJ;

  Int_t *label=new Int_t[nofClusters];
  Int_t i,j;
  for(i=0; i<nofClusters; i++) label[i] = 0;
  for(i=0; i<nofClusters; i++) {
    if(label[i] != 0) continue;
    for(j=i+1; j<nofClusters; j++) {
      if(label[j] != 0) continue;
      clusterI = (AliITSRawClusterSPD*) fClusters->At(i);
      clusterJ = (AliITSRawClusterSPD*) fClusters->At(j);
      Bool_t pair = clusterI->Brother(clusterJ,fDz,fDx);
      if(pair) {

	//    if((clusterI->XStop() == clusterJ->XStart()-1)||(clusterI->XStart()==clusterJ->XStop()+1)) cout<<"!! Diagonal cluster"<<endl;
	/*
	      cout << "clusters " << i << "," << j << " before grouping" << endl;
	      clusterI->PrintInfo();
	      clusterJ->PrintInfo();
	*/
	clusterI->Add(clusterJ);
	//        cout << "remove cluster " << j << endl;
	label[j] = 1;
	fClusters->RemoveAt(j);
	/*
	  cout << "cluster  " << i << " after grouping" << endl;
	  clusterI->PrintInfo();
	*/
      }  // pair
    } // J clusters
    label[i] = 1;
  } // I clusters
  fClusters->Compress();
  //  Int_t totalNofClusters = fClusters->GetEntriesFast();
  //  cout << " Nomber of clusters at the group end ="<< totalNofClusters<<endl;

  delete [] label;

  return;

}
//_____________________________________________________________________________

void AliITSClusterFinderSPD::TracksInCluster()
{

  // Find tracks creating one cluster

  // get number of clusters for this module
  Int_t nofClusters = fClusters->GetEntriesFast();
  nofClusters -= fNclusters;

  Int_t i, ix, iz, jx, jz, xstart, xstop, zstart, zstop, nclx, nclz;
  //  Int_t signal, track0, track1, track2;
  const Int_t trmax = 100;
  Int_t cltracks[trmax], itr, tracki, ii, is, js, ie, ntr, tr0, tr1, tr2;

  for(i=0; i<nofClusters; i++) {
    ii = 0;
    memset(cltracks,-1,sizeof(int)*trmax);
    tr0=tr1=tr2=-1;

    AliITSRawClusterSPD *clusterI = (AliITSRawClusterSPD*) fClusters->At(i);

    nclx = clusterI->NclX();
    nclz = clusterI->NclZ();
    xstart = clusterI->XStartf();
    xstop = clusterI->XStopf();
    zstart = clusterI->Zend()-nclz+1;
    zstop = clusterI->Zend();

    Int_t ind;

     for(iz=0; iz<nclz; iz++) {
         jz = zstart + iz;
       for(ix=0; ix<nclx; ix++) {
	 jx = xstart + ix;
	 ind = fMap->GetHitIndex(jz,jx);
	 if(ind == 0 && iz >= 0 && ix > 0) {
          continue;
         }
	 if(ind == 0 && iz > 0 && ix >= 0) {
          continue;
         }
	 if(ind == 0 && iz == 0 && ix == 0 && i > 0) {
          continue;
         }

        AliITSdigitSPD *dig = (AliITSdigitSPD*)fMap->GetHit(jz,jx);
	/*
         signal=dig->fSignal;
         track0=dig->fTracks[0];
         track1=dig->fTracks[1];
         track2=dig->fTracks[2];
	*/
          for(itr=0; itr<3; itr++) {
	    tracki = dig->fTracks[itr];
            if(tracki >= 0) {
	      ii += 1;
             cltracks[ii-1] = tracki;
            }
	  }
       } // ix pixel
     }  // iz pixel

     for(is=0; is<trmax; is++) {
         if(cltracks[is]<0) continue;
       for(js=is+1; js<trmax; js++) {
         if(cltracks[js]<0) continue;
         if(cltracks[js]==cltracks[is]) cltracks[js]=-5;
       }
     }

     ntr = 0;
     for(ie=0; ie<trmax; ie++) {
       if(cltracks[ie] >= 0) {
        ntr=ntr+1;
        if(ntr==1) tr0=cltracks[ie];
        if(ntr==2) tr1=cltracks[ie];
        if(ntr==3) tr2=cltracks[ie];
       }
     }
     // if delta ray only
     if(ntr == 0) ntr = 1;

     clusterI->SetNTracks(ntr);
     clusterI->SetTracks(tr0,tr1,tr2);

  } // I cluster

}
//_____________________________________________________________________________

void AliITSClusterFinderSPD::GetRecPoints()
{
  // get rec points
  AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");

  // get number of clusters for this module
  Int_t nofClusters = fClusters->GetEntriesFast();
  nofClusters -= fNclusters;
  const Float_t kconv = 1.0e-4;
  const Float_t kRMSx = 12.0*kconv; // microns -> cm ITS TDR Table 1.3
  const Float_t kRMSz = 70.0*kconv; // microns -> cm ITS TDR Table 1.3

  Float_t spdLength = fSegmentation->Dz();
  Float_t spdWidth = fSegmentation->Dx();

  Int_t i;
  Int_t track0, track1, track2;

  for(i=0; i<nofClusters; i++) {

    AliITSRawClusterSPD *clusterI = (AliITSRawClusterSPD*) fClusters->At(i);
    clusterI->GetTracks(track0, track1, track2);
    AliITSRecPoint rnew;

    rnew.SetX((clusterI->X() - spdWidth/2)*kconv);
    rnew.SetZ((clusterI->Z() - spdLength/2)*kconv);
    rnew.SetQ(1.);
    rnew.SetdEdX(0.);
    rnew.SetSigmaX2(kRMSx*kRMSx);
    rnew.SetSigmaZ2(kRMSz*kRMSz);
    rnew.fTracks[0]=track0;
    rnew.fTracks[1]=track1;
    rnew.fTracks[2]=track2;
    iTS->AddRecPoint(rnew);
  } // I clusters

  fMap->ClearMap();

}
//_____________________________________________________________________________

void AliITSClusterFinderSPD::FindRawClusters()
{
  // find raw clusters
  Find1DClusters();
  GroupClusters();
  TracksInCluster();
  GetRecPoints();

}

<|endoftext|>