<commit_before>// $Id: elem_refinement.C,v 1.2 2003-05-29 15:54:06 benkirk Exp $

// The Next Great Finite Element Library.
// Copyright (C) 2002  Benjamin S. Kirk, John W. Peterson

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm>
#include <iterator>
#include <set>

// Local includes
#include "elem.h"
#include "mesh_base.h"

//--------------------------------------------------------------------
// Elem methods

/**
 * The following functions only apply when
 * AMR is enabled and thus are not present
 * otherwise.
 */
#ifdef ENABLE_AMR

void Elem::refine (MeshBase& mesh)
{
  assert (this->refinement_flag() == Elem::REFINE);
  assert (this->active());
  assert (_children == NULL);

  // Two big prime numbers less than
  // sqrt(max_unsigned_int) for key creation.
  const unsigned int bp1 = 65449;
  const unsigned int bp2 = 48661;

  // Create my children
  {
    _children = new Elem*[this->n_children()];

    for (unsigned int c=0; c<this->n_children(); c++)
      {
	_children[c] = Elem::build(this->type(), this);
	_children[c]->set_refinement_flag(Elem::JUST_REFINED);
      }
  }

  // Compute new nodal locations
  // and asssign nodes to children
  {
    // Make these static.  It is unlikely the
    // sizes will change from call to call, so having these
    // static should save on reallocations
    std::vector<std::vector<Point> >        p    (this->n_children());
    std::vector<std::vector<unsigned int> > keys (this->n_children());
    std::vector<std::vector<Node*> >        nodes(this->n_children());

    // compute new nodal locations
    for (unsigned int c=0; c<this->n_children(); c++)
      {
	p[c].resize    (this->child(c)->n_nodes());
	keys[c].resize (this->child(c)->n_nodes());
	nodes[c].resize(this->child(c)->n_nodes());

      for (unsigned int nc=0; nc<this->child(c)->n_nodes(); nc++)
	{
	  // zero entries
	  p[c][nc].zero();
	  keys[c][nc]  = 0;
	  nodes[c][nc] = NULL;

	  for (unsigned int n=0; n<this->n_nodes(); n++)
	    {
	      // The value from the embedding matrix
	      const float em_val = this->embedding_matrix(c,nc,n);

	      if (em_val != 0.)
		{
		  p[c][nc].add_scaled (this->point(n), em_val);

		  // We may have found the node, in which case we
		  // won't need to look it up later.
		  if (em_val == 1.)
		    nodes[c][nc] = this->get_node(n);

		  // Otherwise build the key to look for the node
		  else
		    {
		      // An unsigned int associated with the
		      // address of the node n.  We can't use the
		      // node number since they can change.
		      const unsigned int n_id =

#if SIZEOF_INT == SIZEOF_VOID_P

			// 32-bit machines
			reinterpret_cast<unsigned int>(this->get_node(n));

#elif SIZEOF_LONG_LONG_INT == SIZEOF_VOID_P

		        // 64-bit machines
 		        // Another big prime number less than max_unsigned_int
		        // for key creation on 64-bit machines
		        const unsigned int bp3 = 4294967291;
		        static_cast<long long unsigned int>(this->get_node(n))%
			bp3;

#else
			// Huh?
		        0; error();

#endif
		      // Compute the key for this new node nc.  This will
		      // be used to locate the node if it already exists
		      // in the mesh.
		      keys[c][nc] +=
			(((static_cast<unsigned int>(em_val*100000.)%bp1) *
			  (n_id%bp1))%bp1)*bp2;
		    }
		}
	    }
	}

      // assign nodes to children & add them to the mesh
      for (unsigned int nc=0; nc<this->child(c)->n_nodes(); nc++)
	{
	  if (nodes[c][nc] != NULL)
	    {
	      this->child(c)->set_node(nc) = nodes[c][nc];
	    }
	  else
	    {
	      this->child(c)->set_node(nc) =
		mesh.mesh_refinement.add_point(p[c][nc],
					       keys[c][nc]);
	    }
	}

	mesh.add_elem(this->child(c),
		      mesh.mesh_refinement.new_element_number());
      }
  }

  // Possibly add boundary information
  for (unsigned int s=0; s<this->n_neighbors(); s++)
    if (this->neighbor(s) == NULL)
      {
	const short int id = mesh.boundary_info.boundary_id(this, s);

	if (id != mesh.boundary_info.invalid_id)
	  for (unsigned int sc=0; sc<this->n_children_per_side(s); sc++)
	    mesh.boundary_info.add_side(this->child(this->side_children_matrix(s,sc)),
					s,
					id);
      }

  // Un-set my refinement flag now
  this->set_refinement_flag(Elem::DO_NOTHING);

  assert (!this->active());
}

void Elem::coarsen()
{
  assert (this->refinement_flag() == Elem::COARSEN);
  assert (!this->active());

  // Delete the storage for my children
  delete [] _children;

  _children = NULL;

  this->set_refinement_flag(Elem::DO_NOTHING);

  assert (this->active());
}

#endif // #ifdef ENABLE_AMR

<commit_msg>64-bit fix for SGI<commit_after>// $Id: elem_refinement.C,v 1.3 2003-05-29 16:58:49 benkirk Exp $

// The Next Great Finite Element Library.
// Copyright (C) 2002  Benjamin S. Kirk, John W. Peterson

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm>
#include <iterator>
#include <set>

// Local includes
#include "elem.h"
#include "mesh_base.h"

//--------------------------------------------------------------------
// Elem methods

/**
 * The following functions only apply when
 * AMR is enabled and thus are not present
 * otherwise.
 */
#ifdef ENABLE_AMR

void Elem::refine (MeshBase& mesh)
{
  assert (this->refinement_flag() == Elem::REFINE);
  assert (this->active());
  assert (_children == NULL);

  // Two big prime numbers less than
  // sqrt(max_unsigned_int) for key creation.
  const unsigned int bp1 = 65449;
  const unsigned int bp2 = 48661;

  // Create my children
  {
    _children = new Elem*[this->n_children()];

    for (unsigned int c=0; c<this->n_children(); c++)
      {
	_children[c] = Elem::build(this->type(), this);
	_children[c]->set_refinement_flag(Elem::JUST_REFINED);
      }
  }

  // Compute new nodal locations
  // and asssign nodes to children
  {
    // Make these static.  It is unlikely the
    // sizes will change from call to call, so having these
    // static should save on reallocations
    std::vector<std::vector<Point> >        p    (this->n_children());
    std::vector<std::vector<unsigned int> > keys (this->n_children());
    std::vector<std::vector<Node*> >        nodes(this->n_children());

    // compute new nodal locations
    for (unsigned int c=0; c<this->n_children(); c++)
      {
	p[c].resize    (this->child(c)->n_nodes());
	keys[c].resize (this->child(c)->n_nodes());
	nodes[c].resize(this->child(c)->n_nodes());

      for (unsigned int nc=0; nc<this->child(c)->n_nodes(); nc++)
	{
	  // zero entries
	  p[c][nc].zero();
	  keys[c][nc]  = 0;
	  nodes[c][nc] = NULL;

	  for (unsigned int n=0; n<this->n_nodes(); n++)
	    {
	      // The value from the embedding matrix
	      const float em_val = this->embedding_matrix(c,nc,n);

	      if (em_val != 0.)
		{
		  p[c][nc].add_scaled (this->point(n), em_val);

		  // We may have found the node, in which case we
		  // won't need to look it up later.
		  if (em_val == 1.)
		    nodes[c][nc] = this->get_node(n);

		  // Otherwise build the key to look for the node
		  else
		    {
		      // An unsigned int associated with the
		      // address of the node n.  We can't use the
		      // node number since they can change.

#if SIZEOF_INT == SIZEOF_VOID_P

		      // 32-bit machines
		      const unsigned int n_id =
			reinterpret_cast<unsigned int>(this->get_node(n));

#elif SIZEOF_LONG_LONG_INT == SIZEOF_VOID_P

		      // 64-bit machines
		      // Another big prime number less than max_unsigned_int
		      // for key creation on 64-bit machines
		      const unsigned int bp3 = 4294967291;
		      const unsigned int n_id =
		        reinterpret_cast<long long unsigned int>(this->get_node(n))%bp3;

#else
		      // Huh?
		      DIE HERE...  CANNOT COMPILE

#endif
		      // Compute the key for this new node nc.  This will
		      // be used to locate the node if it already exists
		      // in the mesh.
			keys[c][nc] +=
			(((static_cast<unsigned int>(em_val*100000.)%bp1) *
			  (n_id%bp1))%bp1)*bp2;
		    }
		}
	    }
	}

      // assign nodes to children & add them to the mesh
      for (unsigned int nc=0; nc<this->child(c)->n_nodes(); nc++)
	{
	  if (nodes[c][nc] != NULL)
	    {
	      this->child(c)->set_node(nc) = nodes[c][nc];
	    }
	  else
	    {
	      this->child(c)->set_node(nc) =
		mesh.mesh_refinement.add_point(p[c][nc],
					       keys[c][nc]);
	    }
	}

	mesh.add_elem(this->child(c),
		      mesh.mesh_refinement.new_element_number());
      }
  }

  // Possibly add boundary information
  for (unsigned int s=0; s<this->n_neighbors(); s++)
    if (this->neighbor(s) == NULL)
      {
	const short int id = mesh.boundary_info.boundary_id(this, s);

	if (id != mesh.boundary_info.invalid_id)
	  for (unsigned int sc=0; sc<this->n_children_per_side(s); sc++)
	    mesh.boundary_info.add_side(this->child(this->side_children_matrix(s,sc)),
					s,
					id);
      }

  // Un-set my refinement flag now
  this->set_refinement_flag(Elem::DO_NOTHING);

  assert (!this->active());
}

void Elem::coarsen()
{
  assert (this->refinement_flag() == Elem::COARSEN);
  assert (!this->active());

  // Delete the storage for my children
  delete [] _children;

  _children = NULL;

  this->set_refinement_flag(Elem::DO_NOTHING);

  assert (this->active());
}

#endif // #ifdef ENABLE_AMR

<|endoftext|>


<commit_before>//individual.cpp
#include <vector>
#include <cstdlib>
#include <iostream>

#include "../headers/individual.hpp"
#include "../headers/utils.hpp"

Individual::Individual(bool grow, int maxDepth, int numberOfXs){
    expression = new Node(grow, maxDepth, numberOfXs);
}

Individual::~Individual(){
    delete expression;
}

Node *Individual::crossover(double crossover_rate, Individual parent){
    //falta implementar aqui
}

void Individual::mutation(double mutation_rate){
    //falta implementar aqui
}

double Individual::fitness(std::vector<utils::DataPoint> points){

    double mse = 0.0;

    for(int i=0; i<points.size(); i++)
        mse += utils::uPow((expression->eval(points[i])-points[i].y ), 2);

    this->mse_value = utils::uSqrt(mse/(double)points.size());

    return this->mse_value;
}

void Individual::print_expression_d(){
    expression->print_node_d();
}

void Individual::print_fitness_d(){
    std::cout << mse_value << endl;
}
<commit_msg>1.3 Mutação e crossover<commit_after>//individual.cpp
#include <vector>
#include <cstdlib>
#include <iostream>
#include <stack>

#include "../headers/individual.hpp"

using namespace utils;

    //--------------------CONSTRUTOR E DESTRUTOR--------------------------//

Individual::Individual(bool grow, int maxDepth, int numberOfXs){

    //construtor. recebe a profundidade máxima, o estilo de crescimento
    //e o número de variáveis que a árvore terá, e chama o construtor da
    //expressão interna.
    expression = new Node(grow, maxDepth, numberOfXs);
}

Individual::~Individual(){

    //destrutor, que deleta o Node *expression, que é alocado
    //dinâmicamente

    delete expression;
}

    //-------------OPERAÇÕES GENÉTICAS SOBRE O INDIVÍDUO------------------//

Individual *Individual::crossover(double crossover_rate, Individual *parent){

    Individual *thisParent = this->get_copy();
    Individual *thatParent = parent->get_copy();

    Node *thisPartition = thisParent->expression;
    Node *parentPartition = thatParent->expression;

    while (thisPartition!=NULL){
        if (thisPartition->get_left()==NULL || thisPartition->get_right()==NULL)
            break;
        if (random()%100 < crossover_rate){
            while (parentPartition!=NULL){
                if (parentPartition->get_left()==NULL || parentPartition->get_right()==NULL)
                    break;
                if (random()%100 < crossover_rate){
                    //é preciso ser uma cópia aqui porque o método de
                    //"setar" ponteiros deleta o ponteiro atual antes
                    //de atribuir o novo
                    thisPartition->set_left(parentPartition->get_left()->get_copy());
                    thisPartition->set_right(parentPartition->get_right()->get_copy());
                    thisPartition->copyInformation(parentPartition);

                    break;
                }
                parentPartition = random()%2==1 ? parentPartition->get_right() : parentPartition->get_left();
            }
            break;
        }
        thisPartition = random()%2==1 ? thisPartition->get_right() : thisPartition->get_left();
    }
    delete thatParent;
    return thisParent;
}

void Individual::mutation(double mutation_rate){

    Node *partition;
    stack<Node *>pilha;

    pilha.push(this->expression);

    while (!pilha.empty()){
        partition = pilha.top();
        pilha.pop();

        if (random()%100 <= mutation_rate){
            switch(random()%utils::SIZETYPE){
                case VAR: //cte fun1 fun2
                    partition->makeThisVar();
                    break;
                case CTE:
                    partition->makeThisCte();
                    break;
                case FUN1:
                    partition->makeThisFunc1(false);
                    break;
                case FUN2:
                    partition->makeThisFunc2(false);
                    break;
                default:
                    std::cout << "Erro mutation" << std::endl;
            }
        }

        if (partition->get_left()!=NULL)  pilha.push(partition->get_left());
        if (partition->get_right()!=NULL) pilha.push(partition->get_right());
    }
}

double Individual::fitness(std::vector<DataPoint> points){

    //método que recebe o conjunto de pontos que devem ser testados, e
    //calcula o mse.

    this->mse_value = 0.0;

    for(int i=0; i<points.size(); i++)
        this->mse_value += uPow((expression->eval(points[i])-points[i].y ), 2);

    this->mse_value = uSqrt(this->mse_value/(double)points.size());

    return this->mse_value;
}

Individual *Individual::get_copy(){
    Individual *aux = new Individual(false, 0, 1);

    aux->expression = this->expression->get_copy();
    aux->mse_value = this->mse_value;

    return aux;
}

    //----------------------MÉTODOS DE DEBUG------------------------------//

void Individual::print_expression_d(){

    expression->println_node_d();
}

double Individual::get_fitness(){

    return mse_value;
}
<|endoftext|>


<commit_before>/*
 * assembler32.cpp
 *
 *  Created on: Jul 23, 2014
 *      Author: Pimenta
 */

#include <cstdint>
#include <cstdio>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

static fstream f;
static string buf;
static set<string> exported;
static map<string, uword_t> symbols;
static map<string, set<uword_t>> references;
static set<uword_t> relatives;
static uword_t mem_size = 0;
static uword_t* mem = new uword_t[MEM_WORDS];
static int currentLine = 1, lastTokenLine = 1, currentTokenLine = 1;

inline static void readToken() {
  buf = "";
  lastTokenLine = currentTokenLine;

  for (char c = f.get(); f.good(); c = f.get()) {
    if (c == '/') { // comment found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
      // ignoring comment
      for (c = f.get(); c != '\r' && c != '\n' && f.good(); c = f.get());
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      currentLine++;
    }
    else if (c == '\r' || c == '\n') { // line break found
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      if (buf.size()) { // token was read
        currentTokenLine = currentLine++;
        return;
      }
      currentLine++;
    }
    else if (c == ' ' || c == '\t') { // white space found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
    }
    else { // concatenating the character read
      buf += c;
    }
  }

  currentTokenLine = currentLine;
}

inline static uword_t parseData() {
  uword_t data = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // for hex notation
    sscanf(buf.c_str(), "%i", &data);
  }
  else { // for decimal notation
    stringstream ss;
    ss << buf;
    ss >> data;
  }
  return data;
}

inline static uword_t parseField() {
  uword_t field = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // hex notation means absolute address
    sscanf(buf.c_str(), "%i", &field);
  }
  else { // symbol means an address that needs to be relocated later
    relatives.emplace(mem_size);

    // looking for array offset
    if (buf[buf.size() - 1] == ']') {
      string offset = buf.substr(buf.find("[") + 1, buf.size());
      buf = buf.substr(0, buf.find("["));
      offset = offset.substr(0, offset.find("]"));
      stringstream ss;
      ss << offset;
      ss >> field;
    }

    auto sym = symbols.find(buf);
    if (sym == symbols.end()) { // symbol not found. leave a reference
      references[buf].emplace(mem_size);
    }
    else { // symbol found. the field is the address of the symbol
      field = sym->second;
    }
  }
  return field;
}

int assembler32(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage mode: subleq-asm <assembly_file> <object_file>\n");
    return 0;
  }

  f.open(argv[1]);

  readToken(); // reading ".export"

  // reading export section
  for (readToken(); buf != ".data"; readToken()) {
    exported.insert(buf);
  }

  // reading data section
  for (readToken(); buf != ".text";) {
    symbols[buf.substr(0, buf.size() - 1)] = mem_size;
    readToken();
    if (buf == ".array") { // uninitialized array
      readToken();
      mem_size += parseData();
      readToken(); // next symbol
    }
    else if (buf == ".iarray") { // initialized array
      for (readToken(); currentTokenLine == lastTokenLine; readToken()) {
        mem[mem_size++] = parseData();
      }
    }
    else if (buf == ".ptr") { // pointer
      mem[mem_size] = parseField();
      mem_size++;
      readToken(); // next symbol
    }
    else { // initialized word
      mem[mem_size++] = parseData();
      readToken(); // next symbol
    }
  }

  // reading text section
  int field = 0;
  for (readToken(); buf.size();) {
    // field 2 omitted
    if (field == 2 && currentTokenLine != lastTokenLine) {
      relatives.emplace(mem_size);
      mem[mem_size] = mem_size + 1;
      mem_size++;
      field = (field + 1)%3;
    }
    // symbol found
    else if (buf[buf.size() - 1] == ':') {
      symbols[buf.substr(0, buf.size() - 1)] = mem_size;
      if (buf == "start:")
        exported.emplace("start");
      readToken();
    }
    // field 0, 1, or field 2 specified
    else {
      mem[mem_size] = parseField();
      mem_size++;
      field = (field + 1)%3;
      readToken();
    }
  }

  f.close();

  // resolve references
  for (auto map_it = references.begin(); map_it != references.end();) {
    // external symbols
    auto sym = symbols.find(map_it->first);
    if (sym == symbols.end()) {
      ++map_it;
      continue;
    }

    // resolve
    for (auto it = map_it->second.begin(); it != map_it->second.end(); ++it) {
      mem[*it] += sym->second;
    }

    references.erase(map_it++);
  }

  f.open(argv[2], fstream::out | fstream::binary);

  {
    uword_t tmp;

    // write number of exported symbols
    tmp = exported.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write exported symbols
    for (auto& exp : exported) {
      // string
      f.write(exp.c_str(), exp.size() + 1);

      // address
      tmp = symbols[exp];
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write number of symbols of pending references
    tmp = references.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write symbols of pending references
    for (auto& sym : references) {
      // string
      f.write(sym.first.c_str(), sym.first.size() + 1);

      // write number of references to current symbol
      tmp = sym.second.size();
      f.write((const char*)&tmp, sizeof(uword_t));

      // write references to current symbol
      for (auto ref : sym.second) {
        tmp = ref;
        f.write((const char*)&tmp, sizeof(uword_t));
      }
    }

    // write number of relative addresses
    tmp = relatives.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write relative addresses
    for (auto addr : relatives) {
      tmp = addr;
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write assembled code size
    f.write((const char*)&mem_size, sizeof(uword_t));

    // write assembled code
    f.write((const char*)mem, sizeof(uword_t)*mem_size);
  }

  f.close();

  delete[] mem;

  return 0;
}
<commit_msg>Now the array offset is a plus sign<commit_after>/*
 * assembler32.cpp
 *
 *  Created on: Jul 23, 2014
 *      Author: Pimenta
 */

#include <cstdint>
#include <cstdio>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

static fstream f;
static string buf;
static set<string> exported;
static map<string, uword_t> symbols;
static map<string, set<uword_t>> references;
static set<uword_t> relatives;
static uword_t mem_size = 0;
static uword_t* mem = new uword_t[MEM_WORDS];
static int currentLine = 1, lastTokenLine = 1, currentTokenLine = 1;

inline static void readToken() {
  buf = "";
  lastTokenLine = currentTokenLine;

  for (char c = f.get(); f.good(); c = f.get()) {
    if (c == '/') { // comment found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
      // ignoring comment
      for (c = f.get(); c != '\r' && c != '\n' && f.good(); c = f.get());
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      currentLine++;
    }
    else if (c == '\r' || c == '\n') { // line break found
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      if (buf.size()) { // token was read
        currentTokenLine = currentLine++;
        return;
      }
      currentLine++;
    }
    else if (c == ' ' || c == '\t') { // white space found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
    }
    else { // concatenating the character read
      buf += c;
    }
  }

  currentTokenLine = currentLine;
}

inline static uword_t parseData() {
  uword_t data = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // for hex notation
    sscanf(buf.c_str(), "%i", &data);
  }
  else { // for decimal notation
    stringstream ss;
    ss << buf;
    ss >> data;
  }
  return data;
}

inline static uword_t parseField() {
  uword_t field = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // hex notation means absolute address
    sscanf(buf.c_str(), "%i", &field);
  }
  else { // symbol means an address that needs to be relocated later
    relatives.emplace(mem_size);

    // looking for array offset
    if (buf.find("+") != buf.npos) {
      string offset = buf.substr(buf.find("+") + 1, buf.size());
      buf = buf.substr(0, buf.find("+"));
      stringstream ss;
      ss << offset;
      ss >> field;
    }

    auto sym = symbols.find(buf);
    if (sym == symbols.end()) { // symbol not found. leave a reference
      references[buf].emplace(mem_size);
    }
    else { // symbol found. the field is the address of the symbol
      field = sym->second;
    }
  }
  return field;
}

int assembler32(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage mode: subleq-asm <assembly_file> <object_file>\n");
    return 0;
  }

  f.open(argv[1]);

  readToken(); // reading ".export"

  // reading export section
  for (readToken(); buf != ".data"; readToken()) {
    exported.insert(buf);
  }

  // reading data section
  for (readToken(); buf != ".text";) {
    symbols[buf.substr(0, buf.size() - 1)] = mem_size;
    readToken();
    if (buf == ".array") { // uninitialized array
      readToken();
      mem_size += parseData();
      readToken(); // next symbol
    }
    else if (buf == ".iarray") { // initialized array
      for (readToken(); currentTokenLine == lastTokenLine; readToken()) {
        mem[mem_size++] = parseData();
      }
    }
    else if (buf == ".ptr") { // pointer
      mem[mem_size] = parseField();
      mem_size++;
      readToken(); // next symbol
    }
    else { // initialized word
      mem[mem_size++] = parseData();
      readToken(); // next symbol
    }
  }

  // reading text section
  int field = 0;
  for (readToken(); buf.size();) {
    // field 2 omitted
    if (field == 2 && currentTokenLine != lastTokenLine) {
      relatives.emplace(mem_size);
      mem[mem_size] = mem_size + 1;
      mem_size++;
      field = (field + 1)%3;
    }
    // symbol found
    else if (buf[buf.size() - 1] == ':') {
      symbols[buf.substr(0, buf.size() - 1)] = mem_size;
      if (buf == "start:")
        exported.emplace("start");
      readToken();
    }
    // field 0, 1, or field 2 specified
    else {
      mem[mem_size] = parseField();
      mem_size++;
      field = (field + 1)%3;
      readToken();
    }
  }

  f.close();

  // resolve references
  for (auto map_it = references.begin(); map_it != references.end();) {
    // external symbols
    auto sym = symbols.find(map_it->first);
    if (sym == symbols.end()) {
      ++map_it;
      continue;
    }

    // resolve
    for (auto it = map_it->second.begin(); it != map_it->second.end(); ++it) {
      mem[*it] += sym->second;
    }

    references.erase(map_it++);
  }

  f.open(argv[2], fstream::out | fstream::binary);

  {
    uword_t tmp;

    // write number of exported symbols
    tmp = exported.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write exported symbols
    for (auto& exp : exported) {
      // string
      f.write(exp.c_str(), exp.size() + 1);

      // address
      tmp = symbols[exp];
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write number of symbols of pending references
    tmp = references.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write symbols of pending references
    for (auto& sym : references) {
      // string
      f.write(sym.first.c_str(), sym.first.size() + 1);

      // write number of references to current symbol
      tmp = sym.second.size();
      f.write((const char*)&tmp, sizeof(uword_t));

      // write references to current symbol
      for (auto ref : sym.second) {
        tmp = ref;
        f.write((const char*)&tmp, sizeof(uword_t));
      }
    }

    // write number of relative addresses
    tmp = relatives.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write relative addresses
    for (auto addr : relatives) {
      tmp = addr;
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write assembled code size
    f.write((const char*)&mem_size, sizeof(uword_t));

    // write assembled code
    f.write((const char*)mem, sizeof(uword_t)*mem_size);
  }

  f.close();

  delete[] mem;

  return 0;
}
<|endoftext|>


<commit_before>#ifndef FIRSTPERSONCONTROL_HPP_INCLUDED
#define FIRSTPERSONCONTROL_HPP_INCLUDED

#include "spatialcontrol.hpp"

namespace gst
{
    // The responsibility of this class is to imitate the behavior of
    // first-person camera control.
    class FirstPersonControl : public SpatialControl {
    public:
        FirstPersonControl();
        void update(float dt, Input const & input, Spatial & spatial) override;

        float rotation_speed; // also known as the mouse sensitivity
        float movement_speed;
    private:
        void rotate(float dt, Input const & input, Spatial & spatial);
        void move(float dt, Input const & input, Spatial & spatial);

        float yaw_angle;
        float pitch_angle;
    };
}

#endif
<commit_msg>add more to first person control documentation<commit_after>#ifndef FIRSTPERSONCONTROL_HPP_INCLUDED
#define FIRSTPERSONCONTROL_HPP_INCLUDED

#include "spatialcontrol.hpp"

namespace gst
{
    // The responsibility of this class is to imitate the behavior of
    // first-person camera control.
    //
    // The rotation is limited by only allowing pitch between -90 and 90
    // degrees, but yaw has no limits. The movement is limited by projecting
    // the forward vector to the XY-plane.
    class FirstPersonControl : public SpatialControl {
    public:
        FirstPersonControl();
        void update(float dt, Input const & input, Spatial & spatial) override;

        float rotation_speed; // also known as the mouse sensitivity
        float movement_speed;
    private:
        void rotate(float dt, Input const & input, Spatial & spatial);
        void move(float dt, Input const & input, Spatial & spatial);

        float yaw_angle;
        float pitch_angle;
    };
}

#endif
<|endoftext|>


<commit_before>#include <sequence/Parser.hpp>
#include <cstdio>
#include <cstdlib>

namespace sequence {

inline static void print(const Item& item) {
	const auto pFilename = item.filename.c_str();
	switch (item.getType()) {
	case Item::SINGLE:
		printf("%s\n", pFilename);
		break;
	case Item::INVALID:
		printf("Invalid\n");
		break;
	case Item::INDICED:
		printf("%s (%lu) %d\n", pFilename, item.indices.size(), item.padding);
		break;
	case Item::PACKED:
		if (item.step == 1)
			printf("%s [%d:%d] #%d\n", pFilename, item.start, item.end, item.padding);
		else
			printf("%s [%d:%d]/%d #%d\n", pFilename, item.start, item.end, item.step, item.padding);
		break;
	}
}

} // namespace sequence

static void printHelp() {
	printf("USAGE [OPTIONS] [FOLDER]\n");
	printf("--help,-h            Print help and exit\n");
	printf("--merge-padding,-m   Merge sequence with different padding\n");
	printf("--recursive,-r       Parse folder recursively\n");
	printf("--pack,-p            Drop indices and replace with one or several contiguous chunks\n");
	printf("--bake-singleton,-b  Replace Items with only one index by it's corresponding filename\n");
	printf("--sort,-s            Print folder and files lexicographically sorted\n");
	printf("--keep=              Strategy to handle ambiguous locations\n");
	printf("       none          flattens the set\n");
	printf("       first         keep first number\n");
	printf("       last          keep last number\n");
	printf("       max-variance  keep number with highest variance (default)\n");
	printf("                     backups to 'none' if same variance\n");
}

#include <list>

int main(int argc, char **argv) {
	using namespace std;
	using namespace sequence;

	bool recursive = false;
	Configuration configuration;
	configuration.getPivotIndex = RETAIN_HIGHEST_VARIANCE;

	string folder = ".";
	for (int i = 1; i < argc; ++i) {
		string arg = argv[i];
		if (arg == "--help" || arg == "-h") {
			printHelp();
			return 0;
		} else if (arg == "--merge-padding" || arg == "-m")
			configuration.mergePadding = true;
		else if (arg == "--pack" || arg == "-p")
			configuration.pack = true;
		else if (arg == "--recursive" || arg == "-r")
			recursive = true;
		else if (arg == "--bake-singleton" || arg == "-b")
			configuration.bakeSingleton = true;
		else if (arg == "--sort" || arg == "-s")
			configuration.sort = true;
		else if (arg == "--keep=none")
			configuration.getPivotIndex = RETAIN_NONE;
		else if (arg == "--keep=first")
			configuration.getPivotIndex = RETAIN_FIRST_LOCATION;
		else if (arg == "--keep=last")
			configuration.getPivotIndex = RETAIN_LAST_LOCATION;
		else if (arg == "--keep=max-variance")
			configuration.getPivotIndex = RETAIN_HIGHEST_VARIANCE;
		else if (arg[0] == '-') {
			printf("Unknown option : %s\n", arg.c_str());
			return EXIT_FAILURE;
		} else
			folder = arg;
	}

	list<Item> folders;
	folders.emplace_back(folder);

	while (!folders.empty()) {
		const auto &current = folders.front().filename;

		auto result = parseDir(configuration, current.c_str());

		printf("\n\n* %s\n", result.name.c_str());
		for (const Item &item : result.directories) {
			print(item);
			const string& filename = item.filename;
			if (recursive && !filename.empty() && filename != "." && filename != "..") {
				const bool lastCurrentCharIsSlash = current.back() == '/';
				if (lastCurrentCharIsSlash)
					folders.emplace_back(current + filename);
				else
					folders.emplace_back(current + '/' + filename);
			}
		}
		printf("\n");
		for (const Item &item : result.files)
			print(item);

		folders.pop_front();
	}

	return EXIT_SUCCESS;
}
<commit_msg>fixing printf issue on MinGW<commit_after>#include <sequence/Parser.hpp>
#include <cstdio>
#include <cstdlib>

namespace sequence {

inline static void print(const Item& item) {
	const auto pFilename = item.filename.c_str();
	switch (item.getType()) {
	case Item::SINGLE:
		printf("%s\n", pFilename);
		break;
	case Item::INVALID:
		printf("Invalid\n");
		break;
	case Item::INDICED:
		printf("%s (%lu) %d\n", pFilename, (unsigned long)item.indices.size(), item.padding);
		break;
	case Item::PACKED:
		if (item.step == 1)
			printf("%s [%d:%d] #%d\n", pFilename, item.start, item.end, item.padding);
		else
			printf("%s [%d:%d]/%d #%d\n", pFilename, item.start, item.end, item.step, item.padding);
		break;
	}
}

} // namespace sequence

static void printHelp() {
	printf("USAGE [OPTIONS] [FOLDER]\n");
	printf("--help,-h            Print help and exit\n");
	printf("--merge-padding,-m   Merge sequence with different padding\n");
	printf("--recursive,-r       Parse folder recursively\n");
	printf("--pack,-p            Drop indices and replace with one or several contiguous chunks\n");
	printf("--bake-singleton,-b  Replace Items with only one index by it's corresponding filename\n");
	printf("--sort,-s            Print folder and files lexicographically sorted\n");
	printf("--keep=              Strategy to handle ambiguous locations\n");
	printf("       none          flattens the set\n");
	printf("       first         keep first number\n");
	printf("       last          keep last number\n");
	printf("       max-variance  keep number with highest variance (default)\n");
	printf("                     backups to 'none' if same variance\n");
}

#include <list>

int main(int argc, char **argv) {
	using namespace std;
	using namespace sequence;

	bool recursive = false;
	Configuration configuration;
	configuration.getPivotIndex = RETAIN_HIGHEST_VARIANCE;

	string folder = ".";
	for (int i = 1; i < argc; ++i) {
		string arg = argv[i];
		if (arg == "--help" || arg == "-h") {
			printHelp();
			return 0;
		} else if (arg == "--merge-padding" || arg == "-m")
			configuration.mergePadding = true;
		else if (arg == "--pack" || arg == "-p")
			configuration.pack = true;
		else if (arg == "--recursive" || arg == "-r")
			recursive = true;
		else if (arg == "--bake-singleton" || arg == "-b")
			configuration.bakeSingleton = true;
		else if (arg == "--sort" || arg == "-s")
			configuration.sort = true;
		else if (arg == "--keep=none")
			configuration.getPivotIndex = RETAIN_NONE;
		else if (arg == "--keep=first")
			configuration.getPivotIndex = RETAIN_FIRST_LOCATION;
		else if (arg == "--keep=last")
			configuration.getPivotIndex = RETAIN_LAST_LOCATION;
		else if (arg == "--keep=max-variance")
			configuration.getPivotIndex = RETAIN_HIGHEST_VARIANCE;
		else if (arg[0] == '-') {
			printf("Unknown option : %s\n", arg.c_str());
			return EXIT_FAILURE;
		} else
			folder = arg;
	}

	list<Item> folders;
	folders.emplace_back(folder);

	while (!folders.empty()) {
		const auto &current = folders.front().filename;

		auto result = parseDir(configuration, current.c_str());

		printf("\n\n* %s\n", result.name.c_str());
		for (const Item &item : result.directories) {
			print(item);
			const string& filename = item.filename;
			if (recursive && !filename.empty() && filename != "." && filename != "..") {
				const bool lastCurrentCharIsSlash = current.back() == '/';
				if (lastCurrentCharIsSlash)
					folders.emplace_back(current + filename);
				else
					folders.emplace_back(current + '/' + filename);
			}
		}
		printf("\n");
		for (const Item &item : result.files)
			print(item);

		folders.pop_front();
	}

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrRenderTarget.h"

#include "GrContext.h"
#include "GrGpu.h"
#include "GrStencilBuffer.h"

SK_DEFINE_INST_COUNT(GrRenderTarget)

bool GrRenderTarget::readPixels(int left, int top, int width, int height,
                                GrPixelConfig config,
                                void* buffer,
                                size_t rowBytes,
                                uint32_t pixelOpsFlags) {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (NULL == context) {
        return false;
    }
    return context->readRenderTargetPixels(this,
                                           left, top, width, height,
                                           config, buffer, rowBytes,
                                           pixelOpsFlags);
}

void GrRenderTarget::writePixels(int left, int top, int width, int height,
                                 GrPixelConfig config,
                                 const void* buffer,
                                 size_t rowBytes,
                                 uint32_t pixelOpsFlags) {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (NULL == context) {
        return;
    }
    context->writeRenderTargetPixels(this,
                                     left, top, width, height,
                                     config, buffer, rowBytes,
                                     pixelOpsFlags);
}

void GrRenderTarget::resolve() {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (NULL == context) {
        return;
    }
    context->resolveRenderTarget(this);
}

size_t GrRenderTarget::sizeInBytes() const {
    int colorBits;
    if (kUnknown_GrPixelConfig == fDesc.fConfig) {
        colorBits = 32; // don't know, make a guess
    } else {
        colorBits = GrBytesPerPixel(fDesc.fConfig);
    }
    uint64_t size = fDesc.fWidth;
    size *= fDesc.fHeight;
    size *= colorBits;
    size *= GrMax(1, fDesc.fSampleCnt);
    return (size_t)(size / 8);
}

void GrRenderTarget::flagAsNeedingResolve(const GrIRect* rect) {
    if (kCanResolve_ResolveType == getResolveType()) {
        if (NULL != rect) {
            fResolveRect.join(*rect);
            if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
                fResolveRect.setEmpty();
            }
        } else {
            fResolveRect.setLTRB(0, 0, this->width(), this->height());
        }
    }
}

void GrRenderTarget::overrideResolveRect(const GrIRect rect) {
    fResolveRect = rect;
    if (fResolveRect.isEmpty()) {
        fResolveRect.setLargestInverted();
    } else {
        if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
            fResolveRect.setLargestInverted();
        }
    }
}

void GrRenderTarget::setStencilBuffer(GrStencilBuffer* stencilBuffer) {
    if (NULL != fStencilBuffer) {
        fStencilBuffer->unref();

        GrContext* context = this->getContext();
        if (NULL != context) {
            context->purgeCache();
        }

        if (NULL != context) {
            context->purgeCache();
        }
    }

    fStencilBuffer = stencilBuffer;

    if (NULL != fStencilBuffer) {
        fStencilBuffer->ref();
    }
}

void GrRenderTarget::onRelease() {
    this->setStencilBuffer(NULL);

    INHERITED::onRelease();
}

void GrRenderTarget::onAbandon() {
    this->setStencilBuffer(NULL);

    INHERITED::onAbandon();
}
<commit_msg>Protect against unref/ref of stencil buffer.<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrRenderTarget.h"

#include "GrContext.h"
#include "GrGpu.h"
#include "GrStencilBuffer.h"

SK_DEFINE_INST_COUNT(GrRenderTarget)

bool GrRenderTarget::readPixels(int left, int top, int width, int height,
                                GrPixelConfig config,
                                void* buffer,
                                size_t rowBytes,
                                uint32_t pixelOpsFlags) {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (NULL == context) {
        return false;
    }
    return context->readRenderTargetPixels(this,
                                           left, top, width, height,
                                           config, buffer, rowBytes,
                                           pixelOpsFlags);
}

void GrRenderTarget::writePixels(int left, int top, int width, int height,
                                 GrPixelConfig config,
                                 const void* buffer,
                                 size_t rowBytes,
                                 uint32_t pixelOpsFlags) {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (NULL == context) {
        return;
    }
    context->writeRenderTargetPixels(this,
                                     left, top, width, height,
                                     config, buffer, rowBytes,
                                     pixelOpsFlags);
}

void GrRenderTarget::resolve() {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (NULL == context) {
        return;
    }
    context->resolveRenderTarget(this);
}

size_t GrRenderTarget::sizeInBytes() const {
    int colorBits;
    if (kUnknown_GrPixelConfig == fDesc.fConfig) {
        colorBits = 32; // don't know, make a guess
    } else {
        colorBits = GrBytesPerPixel(fDesc.fConfig);
    }
    uint64_t size = fDesc.fWidth;
    size *= fDesc.fHeight;
    size *= colorBits;
    size *= GrMax(1, fDesc.fSampleCnt);
    return (size_t)(size / 8);
}

void GrRenderTarget::flagAsNeedingResolve(const GrIRect* rect) {
    if (kCanResolve_ResolveType == getResolveType()) {
        if (NULL != rect) {
            fResolveRect.join(*rect);
            if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
                fResolveRect.setEmpty();
            }
        } else {
            fResolveRect.setLTRB(0, 0, this->width(), this->height());
        }
    }
}

void GrRenderTarget::overrideResolveRect(const GrIRect rect) {
    fResolveRect = rect;
    if (fResolveRect.isEmpty()) {
        fResolveRect.setLargestInverted();
    } else {
        if (!fResolveRect.intersect(0, 0, this->width(), this->height())) {
            fResolveRect.setLargestInverted();
        }
    }
}

void GrRenderTarget::setStencilBuffer(GrStencilBuffer* stencilBuffer) {
    if (stencilBuffer == fStencilBuffer) {
        return;
    }

    if (NULL != fStencilBuffer) {
        fStencilBuffer->unref();

        GrContext* context = this->getContext();
        if (NULL != context) {
            context->purgeCache();
        }

        if (NULL != context) {
            context->purgeCache();
        }
    }

    fStencilBuffer = stencilBuffer;

    if (NULL != fStencilBuffer) {
        fStencilBuffer->ref();
    }
}

void GrRenderTarget::onRelease() {
    this->setStencilBuffer(NULL);

    INHERITED::onRelease();
}

void GrRenderTarget::onAbandon() {
    this->setStencilBuffer(NULL);

    INHERITED::onAbandon();
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <limits>

#include <Api/KttException.h>
#include <Kernel/KernelParameterGroup.h>
#include <Output/TimeConfiguration/TimeConfiguration.h>
#include <TuningRunner/ConfigurationData.h>
#include <Utility/ErrorHandling/Assert.h>
#include <Utility/Logger/Logger.h>
#include <Utility/StlHelpers.h>
#include <Utility/Timer/Timer.h>

namespace ktt
{

ConfigurationData::ConfigurationData(Searcher& searcher, const Kernel& kernel) :
    m_BestConfiguration({KernelConfiguration(), InvalidDuration}),
    m_Searcher(searcher),
    m_Kernel(kernel),
    m_ExploredConfigurations(0)
{
    InitializeConfigurations();
}

ConfigurationData::~ConfigurationData()
{
    m_Searcher.Reset();
}

bool ConfigurationData::CalculateNextConfiguration(const KernelResult& previousResult)
{
    ++m_ExploredConfigurations;
    UpdateBestConfiguration(previousResult);

    if (!IsProcessed())
    {
        m_Searcher.CalculateNextConfiguration(previousResult);
        return true;
    }

    return false;
}

KernelConfiguration ConfigurationData::GetConfigurationForIndex(const uint64_t index) const
{
    if (index >= GetTotalConfigurationsCount())
    {
        throw KttException("Invalid configuration index");
    }

    const ConfigurationTree* localTree = nullptr;
    uint64_t localIndex = index;

    for (const auto& tree : m_Trees)
    {
        const uint64_t localCount = tree->GetConfigurationsCount();

        if (localCount <= localIndex)
        {
            localIndex -= localCount;
            continue;
        }

        localTree = tree.get();
        break;
    }

    auto result = localTree->GetConfiguration(localIndex);
    result.Merge(m_BestConfiguration.first);
    return result;
}

uint64_t ConfigurationData::GetTotalConfigurationsCount() const
{
    uint64_t result = 0;

    for (const auto& tree : m_Trees)
    {
        result += tree->GetConfigurationsCount();
    }

    return result;
}

uint64_t ConfigurationData::GetExploredConfigurationsCount() const
{
    return static_cast<uint64_t>(m_ExploredConfigurations);
}

bool ConfigurationData::IsProcessed() const
{
    return GetExploredConfigurationsCount() >= GetTotalConfigurationsCount();
}

KernelConfiguration ConfigurationData::GetCurrentConfiguration() const
{
    if (!m_Searcher.IsInitialized() || IsProcessed())
    {
        return KernelConfiguration();
    }

    return m_Searcher.GetCurrentConfiguration();
}

KernelConfiguration ConfigurationData::GetBestConfiguration() const
{
    if (m_BestConfiguration.second != InvalidDuration)
    {
        return m_BestConfiguration.first;
    }

    return GetCurrentConfiguration();
}

void ConfigurationData::InitializeConfigurations()
{
    const auto groups = m_Kernel.GenerateParameterGroups();
    Logger::LogInfo("Generating configurations for kernel " + m_Kernel.GetName());

    Timer timer;
    timer.Start();

    for (const auto& group : groups)
    {
        auto tree = std::make_unique<ConfigurationTree>();
        tree->Build(group);
        m_Trees.push_back(std::move(tree));
    }

    timer.Stop();

    const auto& time = TimeConfiguration::GetInstance();
    const uint64_t elapsedTime = time.ConvertFromNanoseconds(timer.GetElapsedTime());
    Logger::LogInfo("Configurations were generated in " + std::to_string(elapsedTime) + time.GetUnitTag());

    KernelConfiguration initialBest;

    for (const auto& tree : m_Trees)
    {
        initialBest.Merge(tree->GetConfiguration(0));
    }

    m_BestConfiguration = {initialBest, InvalidDuration};
    m_Searcher.Initialize(*this);
}

void ConfigurationData::UpdateBestConfiguration(const KernelResult& previousResult)
{
    const auto& configuration = previousResult.GetConfiguration();
    const Nanoseconds duration = previousResult.GetTotalDuration();

    if (duration < m_BestConfiguration.second)
    {
        m_BestConfiguration.first = configuration;
        m_BestConfiguration.second = duration;
    }
}

void ConfigurationData::ComputeConfigurations(const KernelParameterGroup& group, const size_t currentIndex,
    std::vector<ParameterPair>& pairs, std::vector<KernelConfiguration>& finalResult) const
{
    if (currentIndex >= group.GetParameters().size())
    {
        // All parameters are now included in the configuration
        if (IsConfigurationValid(pairs))
        {
            finalResult.emplace_back(pairs);
        }

        return;
    }

    const KernelParameter& parameter = *group.GetParameters()[currentIndex];

    for (const auto& pair : parameter.GeneratePairs())
    {
        // Recursively build tree of configurations for each parameter value
        std::vector<ParameterPair> newPairs = pairs;
        newPairs.push_back(pair);

        if (!IsConfigurationValid(newPairs))
        {
            continue;
        }

        ComputeConfigurations(group, currentIndex + 1, newPairs, finalResult);
    }
}

bool ConfigurationData::IsConfigurationValid(const std::vector<ParameterPair>& pairs) const
{
    for (const auto& constraint : m_Kernel.GetConstraints())
    {
        if (!constraint.HasAllParameters(pairs))
        {
            continue;
        }

        if (!constraint.IsFulfilled(pairs))
        {
            return false;
        }
    }

    return true;
}

} // namespace ktt
<commit_msg>* Configuration trees for different parameter groups are now built in parallel<commit_after>#include <algorithm>
#include <future>
#include <limits>

#include <Api/KttException.h>
#include <Kernel/KernelParameterGroup.h>
#include <Output/TimeConfiguration/TimeConfiguration.h>
#include <TuningRunner/ConfigurationData.h>
#include <Utility/ErrorHandling/Assert.h>
#include <Utility/Logger/Logger.h>
#include <Utility/StlHelpers.h>
#include <Utility/Timer/Timer.h>

namespace ktt
{

ConfigurationData::ConfigurationData(Searcher& searcher, const Kernel& kernel) :
    m_BestConfiguration({KernelConfiguration(), InvalidDuration}),
    m_Searcher(searcher),
    m_Kernel(kernel),
    m_ExploredConfigurations(0)
{
    InitializeConfigurations();
}

ConfigurationData::~ConfigurationData()
{
    m_Searcher.Reset();
}

bool ConfigurationData::CalculateNextConfiguration(const KernelResult& previousResult)
{
    ++m_ExploredConfigurations;
    UpdateBestConfiguration(previousResult);

    if (!IsProcessed())
    {
        m_Searcher.CalculateNextConfiguration(previousResult);
        return true;
    }

    return false;
}

KernelConfiguration ConfigurationData::GetConfigurationForIndex(const uint64_t index) const
{
    if (index >= GetTotalConfigurationsCount())
    {
        throw KttException("Invalid configuration index");
    }

    const ConfigurationTree* localTree = nullptr;
    uint64_t localIndex = index;

    for (const auto& tree : m_Trees)
    {
        const uint64_t localCount = tree->GetConfigurationsCount();

        if (localCount <= localIndex)
        {
            localIndex -= localCount;
            continue;
        }

        localTree = tree.get();
        break;
    }

    auto result = localTree->GetConfiguration(localIndex);
    result.Merge(m_BestConfiguration.first);
    return result;
}

uint64_t ConfigurationData::GetTotalConfigurationsCount() const
{
    uint64_t result = 0;

    for (const auto& tree : m_Trees)
    {
        result += tree->GetConfigurationsCount();
    }

    return result;
}

uint64_t ConfigurationData::GetExploredConfigurationsCount() const
{
    return static_cast<uint64_t>(m_ExploredConfigurations);
}

bool ConfigurationData::IsProcessed() const
{
    return GetExploredConfigurationsCount() >= GetTotalConfigurationsCount();
}

KernelConfiguration ConfigurationData::GetCurrentConfiguration() const
{
    if (!m_Searcher.IsInitialized() || IsProcessed())
    {
        return KernelConfiguration();
    }

    return m_Searcher.GetCurrentConfiguration();
}

KernelConfiguration ConfigurationData::GetBestConfiguration() const
{
    if (m_BestConfiguration.second != InvalidDuration)
    {
        return m_BestConfiguration.first;
    }

    return GetCurrentConfiguration();
}

void ConfigurationData::InitializeConfigurations()
{
    const auto groups = m_Kernel.GenerateParameterGroups();
    Logger::LogInfo("Generating configurations for kernel " + m_Kernel.GetName());

    Timer timer;
    timer.Start();

    // Thread pool library would be useful here
    std::vector<std::future<void>> futures;

    for (size_t i = 0; i < groups.size(); ++i)
    {
        auto newTree = std::make_unique<ConfigurationTree>();
        m_Trees.push_back(std::move(newTree));

        auto& tree = *m_Trees[i].get();
        auto& group = groups[i];

        futures.push_back(std::async([&tree, &group]()
        {
            tree.Build(group);
        }));
    }

    for (auto& future : futures)
    {
        future.wait();
    }

    timer.Stop();

    const auto& time = TimeConfiguration::GetInstance();
    const uint64_t elapsedTime = time.ConvertFromNanoseconds(timer.GetElapsedTime());
    Logger::LogInfo("Configurations were generated in " + std::to_string(elapsedTime) + time.GetUnitTag());

    KernelConfiguration initialBest;

    for (const auto& tree : m_Trees)
    {
        initialBest.Merge(tree->GetConfiguration(0));
    }

    m_BestConfiguration = {initialBest, InvalidDuration};
    m_Searcher.Initialize(*this);
}

void ConfigurationData::UpdateBestConfiguration(const KernelResult& previousResult)
{
    const auto& configuration = previousResult.GetConfiguration();
    const Nanoseconds duration = previousResult.GetTotalDuration();

    if (duration < m_BestConfiguration.second)
    {
        m_BestConfiguration.first = configuration;
        m_BestConfiguration.second = duration;
    }
}

void ConfigurationData::ComputeConfigurations(const KernelParameterGroup& group, const size_t currentIndex,
    std::vector<ParameterPair>& pairs, std::vector<KernelConfiguration>& finalResult) const
{
    if (currentIndex >= group.GetParameters().size())
    {
        // All parameters are now included in the configuration
        if (IsConfigurationValid(pairs))
        {
            finalResult.emplace_back(pairs);
        }

        return;
    }

    const KernelParameter& parameter = *group.GetParameters()[currentIndex];

    for (const auto& pair : parameter.GeneratePairs())
    {
        // Recursively build tree of configurations for each parameter value
        std::vector<ParameterPair> newPairs = pairs;
        newPairs.push_back(pair);

        if (!IsConfigurationValid(newPairs))
        {
            continue;
        }

        ComputeConfigurations(group, currentIndex + 1, newPairs, finalResult);
    }
}

bool ConfigurationData::IsConfigurationValid(const std::vector<ParameterPair>& pairs) const
{
    for (const auto& constraint : m_Kernel.GetConstraints())
    {
        if (!constraint.HasAllParameters(pairs))
        {
            continue;
        }

        if (!constraint.IsFulfilled(pairs))
        {
            return false;
        }
    }

    return true;
}

} // namespace ktt
<|endoftext|>


<commit_before>//============================================================================
// Name        : RotatingCubeWithLightingAndShadow.cpp
// Author      : Duarte Peixinho
// Version     :
// Copyright   : ;)
// Description : Game Example
//============================================================================

#include "RotatingCubeWithLightingAndShadow.h"

using namespace p3d;

RotatingCubeWithLightingAndShadow::RotatingCubeWithLightingAndShadow() : ClassName(1024, 768, "Pyros3D - Rotating Cube With Lighting And Shadow", WindowType::Close | WindowType::Resize)
{

}

void RotatingCubeWithLightingAndShadow::OnResize(const uint32 width, const uint32 height)
{
	// Execute Parent Resize Function
	ClassName::OnResize(width, height);

	// Resize
	Renderer->Resize(width, height);
	projection.Perspective(70.f, (f32)width / (f32)height, 1.f, 200.f);
}

void RotatingCubeWithLightingAndShadow::Init()
{
	// Initialization

	// Initialize Scene
	Scene = new SceneGraph();

	// Initialize Renderer
	Renderer = new ForwardRenderer(Width, Height);

	// Projection
	projection.Perspective(70.f, (f32)Width / (f32)Height, 1.f, 2000.f);

	// Create Camera
	Camera = new GameObject();
	Camera->SetPosition(Vec3(0, 10, 100));

	// Material
	Diffuse = new GenericShaderMaterial(ShaderUsage::Color | ShaderUsage::SpecularColor | ShaderUsage::Diffuse | ShaderUsage::SpotShadow | ShaderUsage::DirectionalShadow);
	Diffuse->SetColor(Vec4(1, 0, 0, 1));
	Diffuse->SetPCFTexelSize(0.0001f);
	Diffuse->SetSpecular(Vec4(1,1,1,1));

	// Add a Directional Light
	Light = new GameObject();
	dLight = new DirectionalLight(Vec4(1, 1, 1, 1), Vec3(-1, -1, -1));
	// Enable Shadow Casting
	dLight->EnableCastShadows(2048, 2048, projection, 0.1, 300.0, 1);
	dLight->SetShadowBias(5.f, 3.f);
	Light->Add(dLight);

	Light2 = new GameObject();
	pLight = new SpotLight(Vec4(1, 1, 1, 1), 300, Vec3(0, -1, 0), 45, 30);
	//pLight = new PointLight(Vec4(1, 1, 1, 1), 300);
	pLight->EnableCastShadows(256, 256);
	pLight->SetShadowBias(1.f, 3.f);

	Light2->Add(pLight);
	Scene->Add(Light2);
	Light2->SetPosition(Vec3(0, 20, 0));

	// Add Light to Scene
	Scene->Add(Light);

	// Create Floor Material
	FloorMaterial = new GenericShaderMaterial(ShaderUsage::Color | ShaderUsage::Diffuse | ShaderUsage::SpotShadow | ShaderUsage::DirectionalShadow);
	FloorMaterial->SetColor(Vec4(1, 1, 1, 1));
	FloorMaterial->SetPCFTexelCascadesSize(0.0001f);

	// Create Floor
	Floor = new GameObject();
	floorMesh = new Cube(200, 15, 200);
	Ceiling = new GameObject();

	// Create Floor Rendering Component
	rFloor = new RenderingComponent(floorMesh, FloorMaterial);
	rCeiling = new RenderingComponent(floorMesh, FloorMaterial);

	// Add Rendering Component To GameObject
	Floor->Add(rFloor);
	Ceiling->Add(rCeiling);
	Ceiling->SetScale(Vec3(0.5, 0.5, 0.5));

	// Add Floor to Scene
	Scene->Add(Floor);
	Scene->Add(Ceiling);

	// Rotate Floor

	// Translate Floor
	Floor->SetPosition(Vec3(0, -30, -20));
	Ceiling->SetPosition(Vec3(0, 30, -20));

	// Create Game Object
	CubeObject = new GameObject();
	cubeMesh = new Cube(10, 10, 10);
	rCube = new RenderingComponent(cubeMesh, Diffuse);
	CubeObject->Add(rCube);

	// Add Camera to Scene
	Scene->Add(Camera);
	// Add GameObject to Scene
	Scene->Add(CubeObject);

	SetMousePosition((uint32)Width / 2, (uint32)Height / 2);
	mouseCenter = Vec2((uint32)Width / 2, (uint32)Height / 2);
	mouseLastPosition = mouseCenter;
	counterX = counterY = 0;

	// Input
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::W, this, &RotatingCubeWithLightingAndShadow::MoveFrontPress);
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::S, this, &RotatingCubeWithLightingAndShadow::MoveBackPress);
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::A, this, &RotatingCubeWithLightingAndShadow::StrafeLeftPress);
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::D, this, &RotatingCubeWithLightingAndShadow::StrafeRightPress);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::W, this, &RotatingCubeWithLightingAndShadow::MoveFrontRelease);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::S, this, &RotatingCubeWithLightingAndShadow::MoveBackRelease);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::A, this, &RotatingCubeWithLightingAndShadow::StrafeLeftRelease);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::D, this, &RotatingCubeWithLightingAndShadow::StrafeRightRelease);
	InputManager::AddEvent(Event::Type::OnMove, Event::Input::Mouse::Move, this, &RotatingCubeWithLightingAndShadow::LookTo);

	_strafeLeft = _strafeRight = _moveBack = _moveFront = 0;
	HideMouse();

}

void RotatingCubeWithLightingAndShadow::Update()
{
	// Update - Game Loop

	// Update Scene
	Scene->Update(GetTime());

	// Game Logic Here
	CubeObject->SetRotation(Vec3(0, GetTime(), 0));

	// Render Scene
	Renderer->RenderScene(projection, Camera, Scene);

	Vec3 finalPosition;
	Vec3 direction = Camera->GetDirection();
	float dt = GetTimeInterval();
	float speed = dt * 20.f;
	if (_moveFront)
	{
		finalPosition -= direction*speed;
	}
	if (_moveBack)
	{
		finalPosition += direction*speed;
	}
	if (_strafeLeft)
	{
		finalPosition += direction.cross(Vec3(0, 1, 0))*speed;
	}
	if (_strafeRight)
	{
		finalPosition -= direction.cross(Vec3(0, 1, 0))*speed;
	}

	Camera->SetPosition(Camera->GetPosition() + finalPosition);
}

void RotatingCubeWithLightingAndShadow::Shutdown()
{
	// All your Shutdown Code Here

	// Remove GameObjects From Scene
	Scene->Remove(CubeObject);
	Scene->Remove(Camera);
	Scene->Remove(Light);
	Scene->Remove(Floor);

	CubeObject->Remove(rCube);
	Light->Remove(dLight);
	Floor->Remove(rFloor);

	// Delete
	delete rCube;
	delete CubeObject;
	delete rFloor;
	delete Floor;
	delete cubeMesh;
	delete floorMesh;
	delete dLight;
	delete Light;
	delete Diffuse;
	delete FloorMaterial;
	delete Camera;
	delete Renderer;
	delete Scene;
}

RotatingCubeWithLightingAndShadow::~RotatingCubeWithLightingAndShadow() {}

void RotatingCubeWithLightingAndShadow::MoveFrontPress(Event::Input::Info e)
{
	_moveFront = true;
}
void RotatingCubeWithLightingAndShadow::MoveBackPress(Event::Input::Info e)
{
	_moveBack = true;
}
void RotatingCubeWithLightingAndShadow::StrafeLeftPress(Event::Input::Info e)
{
	_strafeLeft = true;
}
void RotatingCubeWithLightingAndShadow::StrafeRightPress(Event::Input::Info e)
{
	_strafeRight = true;
}
void RotatingCubeWithLightingAndShadow::MoveFrontRelease(Event::Input::Info e)
{
	_moveFront = false;
}
void RotatingCubeWithLightingAndShadow::MoveBackRelease(Event::Input::Info e)
{
	_moveBack = false;
}
void RotatingCubeWithLightingAndShadow::StrafeLeftRelease(Event::Input::Info e)
{
	_strafeLeft = false;
}
void RotatingCubeWithLightingAndShadow::StrafeRightRelease(Event::Input::Info e)
{
	_strafeRight = false;
}
void RotatingCubeWithLightingAndShadow::LookTo(Event::Input::Info e)
{
	if (mouseCenter != GetMousePosition())
	{
		mousePosition = InputManager::GetMousePosition();
		Vec2 mouseDelta = (mousePosition - mouseLastPosition);
		if (mouseDelta.x != 0 || mouseDelta.y != 0)
		{
			counterX -= mouseDelta.x / 10.f;
			counterY -= mouseDelta.y / 10.f;
			if (counterY<-90.f) counterY = -90.f;
			if (counterY>90.f) counterY = 90.f;
			Quaternion qX, qY;
			qX.AxisToQuaternion(Vec3(1.f, 0.f, 0.f), DEGTORAD(counterY));
			qY.AxisToQuaternion(Vec3(0.f, 1.f, 0.f), DEGTORAD(counterX));
			//                Matrix rotX, rotY;
			//                rotX.RotationX(DEGTORAD(counterY));
			//                rotY.RotationY(DEGTORAD(counterX));
			Camera->SetRotation((qY*qX).GetEulerFromQuaternion());
			SetMousePosition((int)(mouseCenter.x), (int)(mouseCenter.y));
			mouseLastPosition = mouseCenter;
		}
	}
}<commit_msg>Removed unused line<commit_after>//============================================================================
// Name        : RotatingCubeWithLightingAndShadow.cpp
// Author      : Duarte Peixinho
// Version     :
// Copyright   : ;)
// Description : Game Example
//============================================================================

#include "RotatingCubeWithLightingAndShadow.h"

using namespace p3d;

RotatingCubeWithLightingAndShadow::RotatingCubeWithLightingAndShadow() : ClassName(1024, 768, "Pyros3D - Rotating Cube With Lighting And Shadow", WindowType::Close | WindowType::Resize)
{

}

void RotatingCubeWithLightingAndShadow::OnResize(const uint32 width, const uint32 height)
{
	// Execute Parent Resize Function
	ClassName::OnResize(width, height);

	// Resize
	Renderer->Resize(width, height);
	projection.Perspective(70.f, (f32)width / (f32)height, 1.f, 200.f);

}

void RotatingCubeWithLightingAndShadow::Init()
{
	// Initialization

	// Initialize Scene
	Scene = new SceneGraph();

	// Initialize Renderer
	Renderer = new ForwardRenderer(Width, Height);

	// Projection
	projection.Perspective(70.f, (f32)Width / (f32)Height, 1.f, 2000.f);

	// Create Camera
	Camera = new GameObject();
	Camera->SetPosition(Vec3(0, 10, 100));

	// Material
	Diffuse = new GenericShaderMaterial(ShaderUsage::Color | ShaderUsage::SpecularColor | ShaderUsage::Diffuse | ShaderUsage::SpotShadow | ShaderUsage::DirectionalShadow);
	Diffuse->SetColor(Vec4(1, 0, 0, 1));
	Diffuse->SetPCFTexelSize(0.0001f);
	Diffuse->SetSpecular(Vec4(1,1,1,1));

	// Add a Directional Light
	Light = new GameObject();
	dLight = new DirectionalLight(Vec4(1, 1, 1, 1), Vec3(-1, -1, -1));
	// Enable Shadow Casting
	dLight->EnableCastShadows(2048, 2048, projection, 0.1, 300.0, 1);
	dLight->SetShadowBias(5.f, 3.f);
	Light->Add(dLight);

	Light2 = new GameObject();
	pLight = new SpotLight(Vec4(1, 1, 1, 1), 300, Vec3(0, -1, 0), 45, 30);
	//pLight = new PointLight(Vec4(1, 1, 1, 1), 300);
	pLight->EnableCastShadows(256, 256);
	pLight->SetShadowBias(1.f, 3.f);

	Light2->Add(pLight);
	Scene->Add(Light2);
	Light2->SetPosition(Vec3(0, 20, 0));

	// Add Light to Scene
	Scene->Add(Light);

	// Create Floor Material
	FloorMaterial = new GenericShaderMaterial(ShaderUsage::Color | ShaderUsage::Diffuse | ShaderUsage::SpotShadow | ShaderUsage::DirectionalShadow);
	FloorMaterial->SetColor(Vec4(1, 1, 1, 1));
	FloorMaterial->SetPCFTexelCascadesSize(0.0001f);

	// Create Floor
	Floor = new GameObject();
	floorMesh = new Cube(200, 15, 200);
	Ceiling = new GameObject();

	// Create Floor Rendering Component
	rFloor = new RenderingComponent(floorMesh, FloorMaterial);
	rCeiling = new RenderingComponent(floorMesh, FloorMaterial);

	// Add Rendering Component To GameObject
	Floor->Add(rFloor);
	Ceiling->Add(rCeiling);
	Ceiling->SetScale(Vec3(0.5, 0.5, 0.5));

	// Add Floor to Scene
	Scene->Add(Floor);
	Scene->Add(Ceiling);

	// Rotate Floor

	// Translate Floor
	Floor->SetPosition(Vec3(0, -30, -20));
	Ceiling->SetPosition(Vec3(0, 30, -20));

	// Create Game Object
	CubeObject = new GameObject();
	cubeMesh = new Cube(10, 10, 10);
	rCube = new RenderingComponent(cubeMesh, Diffuse);
	CubeObject->Add(rCube);

	// Add Camera to Scene
	Scene->Add(Camera);
	// Add GameObject to Scene
	Scene->Add(CubeObject);

	SetMousePosition((uint32)Width / 2, (uint32)Height / 2);
	mouseCenter = Vec2((uint32)Width / 2, (uint32)Height / 2);
	mouseLastPosition = mouseCenter;
	counterX = counterY = 0;

	// Input
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::W, this, &RotatingCubeWithLightingAndShadow::MoveFrontPress);
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::S, this, &RotatingCubeWithLightingAndShadow::MoveBackPress);
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::A, this, &RotatingCubeWithLightingAndShadow::StrafeLeftPress);
	InputManager::AddEvent(Event::Type::OnPress, Event::Input::Keyboard::D, this, &RotatingCubeWithLightingAndShadow::StrafeRightPress);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::W, this, &RotatingCubeWithLightingAndShadow::MoveFrontRelease);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::S, this, &RotatingCubeWithLightingAndShadow::MoveBackRelease);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::A, this, &RotatingCubeWithLightingAndShadow::StrafeLeftRelease);
	InputManager::AddEvent(Event::Type::OnRelease, Event::Input::Keyboard::D, this, &RotatingCubeWithLightingAndShadow::StrafeRightRelease);
	InputManager::AddEvent(Event::Type::OnMove, Event::Input::Mouse::Move, this, &RotatingCubeWithLightingAndShadow::LookTo);

	_strafeLeft = _strafeRight = _moveBack = _moveFront = 0;
	HideMouse();

}

void RotatingCubeWithLightingAndShadow::Update()
{
	// Update - Game Loop

	// Update Scene
	Scene->Update(GetTime());

	// Game Logic Here
	CubeObject->SetRotation(Vec3(0, GetTime(), 0));

	// Render Scene
	Renderer->RenderScene(projection, Camera, Scene);

	Vec3 finalPosition;
	Vec3 direction = Camera->GetDirection();
	float dt = GetTimeInterval();
	float speed = dt * 20.f;
	if (_moveFront)
	{
		finalPosition -= direction*speed;
	}
	if (_moveBack)
	{
		finalPosition += direction*speed;
	}
	if (_strafeLeft)
	{
		finalPosition += direction.cross(Vec3(0, 1, 0))*speed;
	}
	if (_strafeRight)
	{
		finalPosition -= direction.cross(Vec3(0, 1, 0))*speed;
	}

	Camera->SetPosition(Camera->GetPosition() + finalPosition);
}

void RotatingCubeWithLightingAndShadow::Shutdown()
{
	// All your Shutdown Code Here

	// Remove GameObjects From Scene
	Scene->Remove(CubeObject);
	Scene->Remove(Camera);
	Scene->Remove(Light);
	Scene->Remove(Floor);

	CubeObject->Remove(rCube);
	Light->Remove(dLight);
	Floor->Remove(rFloor);

	// Delete
	delete rCube;
	delete CubeObject;
	delete rFloor;
	delete Floor;
	delete cubeMesh;
	delete floorMesh;
	delete dLight;
	delete Light;
	delete Diffuse;
	delete FloorMaterial;
	delete Camera;
	delete Renderer;
	delete Scene;
}

RotatingCubeWithLightingAndShadow::~RotatingCubeWithLightingAndShadow() {}

void RotatingCubeWithLightingAndShadow::MoveFrontPress(Event::Input::Info e)
{
	_moveFront = true;
}
void RotatingCubeWithLightingAndShadow::MoveBackPress(Event::Input::Info e)
{
	_moveBack = true;
}
void RotatingCubeWithLightingAndShadow::StrafeLeftPress(Event::Input::Info e)
{
	_strafeLeft = true;
}
void RotatingCubeWithLightingAndShadow::StrafeRightPress(Event::Input::Info e)
{
	_strafeRight = true;
}
void RotatingCubeWithLightingAndShadow::MoveFrontRelease(Event::Input::Info e)
{
	_moveFront = false;
}
void RotatingCubeWithLightingAndShadow::MoveBackRelease(Event::Input::Info e)
{
	_moveBack = false;
}
void RotatingCubeWithLightingAndShadow::StrafeLeftRelease(Event::Input::Info e)
{
	_strafeLeft = false;
}
void RotatingCubeWithLightingAndShadow::StrafeRightRelease(Event::Input::Info e)
{
	_strafeRight = false;
}
void RotatingCubeWithLightingAndShadow::LookTo(Event::Input::Info e)
{
	if (mouseCenter != GetMousePosition())
	{
		mousePosition = InputManager::GetMousePosition();
		Vec2 mouseDelta = (mousePosition - mouseLastPosition);
		if (mouseDelta.x != 0 || mouseDelta.y != 0)
		{
			counterX -= mouseDelta.x / 10.f;
			counterY -= mouseDelta.y / 10.f;
			if (counterY<-90.f) counterY = -90.f;
			if (counterY>90.f) counterY = 90.f;
			Quaternion qX, qY;
			qX.AxisToQuaternion(Vec3(1.f, 0.f, 0.f), DEGTORAD(counterY));
			qY.AxisToQuaternion(Vec3(0.f, 1.f, 0.f), DEGTORAD(counterX));
			//                Matrix rotX, rotY;
			//                rotX.RotationX(DEGTORAD(counterY));
			//                rotY.RotationY(DEGTORAD(counterX));
			Camera->SetRotation((qY*qX).GetEulerFromQuaternion());
			SetMousePosition((int)(mouseCenter.x), (int)(mouseCenter.y));
			mouseLastPosition = mouseCenter;
		}
	}
}<|endoftext|>


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

#include "minidump/minidump_misc_info_writer.h"

#include <limits>

#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "minidump/minidump_writer_util.h"
#include "package.h"
#include "snapshot/process_snapshot.h"
#include "snapshot/system_snapshot.h"
#include "util/file/file_writer.h"
#include "util/numeric/in_range_cast.h"
#include "util/numeric/safe_assignment.h"

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

namespace crashpad {
namespace {

uint32_t TimevalToRoundedSeconds(const timeval& tv) {
  uint32_t seconds =
      InRangeCast<uint32_t>(tv.tv_sec, std::numeric_limits<uint32_t>::max());
  const int kMicrosecondsPerSecond = static_cast<int>(1E6);
  if (tv.tv_usec >= kMicrosecondsPerSecond / 2 &&
      seconds != std::numeric_limits<uint32_t>::max()) {
    ++seconds;
  }
  return seconds;
}

// For MINIDUMP_MISC_INFO_4::BuildString. dbghelp only places OS version
// information here, but if a machine description is also available, this is the
// only reasonable place in a minidump file to put it.
std::string BuildString(const SystemSnapshot* system_snapshot) {
  std::string os_version_full = system_snapshot->OSVersionFull();
  std::string machine_description = system_snapshot->MachineDescription();
  if (!os_version_full.empty()) {
    if (!machine_description.empty()) {
      return base::StringPrintf(
          "%s; %s", os_version_full.c_str(), machine_description.c_str());
    }
    return os_version_full;
  }
  return machine_description;
}

#if defined(OS_MACOSX)
// Converts the value of the MAC_OS_VERSION_MIN_REQUIRED or
// MAC_OS_X_VERSION_MAX_ALLOWED macro from <AvailabilityMacros.h> to a number
// identifying the minor Mac OS X version that it represents. For example, with
// an argument of MAC_OS_X_VERSION_10_6, this function will return 6.
int AvailabilityVersionToMacOSXMinorVersion(int availability) {
  // Through MAC_OS_X_VERSION_10_9, the minor version is the tens digit.
  if (availability >= 1000 && availability <= 1099) {
    return (availability / 10) % 10;
  }

  // After MAC_OS_X_VERSION_10_9, the older format was insufficient to represent
  // versions. Since then, the minor version is the thousands and hundreds
  // digits.
  if (availability >= 100000 && availability <= 109999) {
    return (availability / 100) % 100;
  }

  return 0;
}
#endif

}  // namespace

namespace internal {

// For MINIDUMP_MISC_INFO_4::DbgBldStr. dbghelp produces strings like
// “dbghelp.i386,6.3.9600.16520” and “dbghelp.amd64,6.3.9600.16520”. Mimic that
// format, and add the OS that wrote the minidump along with any relevant
// platform-specific data describing the compilation environment.
std::string MinidumpMiscInfoDebugBuildString() {
  // Caution: the minidump file format only has room for 39 UTF-16 code units
  // plus a UTF-16 NUL terminator. Don’t let strings get longer than this, or
  // they will be truncated and a message will be logged.
#if defined(OS_MACOSX)
  const char kOS[] = "mac";
#elif defined(OS_LINUX)
  const char kOS[] = "linux";
#elif defined(OS_WIN)
  const char kOS[] = "win";
#else
#error define kOS for this operating system
#endif

#if defined(ARCH_CPU_X86)
  const char kCPU[] = "i386";
#elif defined(ARCH_CPU_X86_64)
  const char kCPU[] = "amd64";
#else
#error define kCPU for this CPU
#endif

  std::string debug_build_string = base::StringPrintf("%s.%s,%s,%s",
                                                      PACKAGE_TARNAME,
                                                      kCPU,
                                                      PACKAGE_VERSION,
                                                      kOS);

#if defined(OS_MACOSX)
  debug_build_string += base::StringPrintf(
      ",%d,%d",
      AvailabilityVersionToMacOSXMinorVersion(MAC_OS_X_VERSION_MIN_REQUIRED),
      AvailabilityVersionToMacOSXMinorVersion(MAC_OS_X_VERSION_MAX_ALLOWED));
#endif

  return debug_build_string;
}

}  // namespace internal

MinidumpMiscInfoWriter::MinidumpMiscInfoWriter()
    : MinidumpStreamWriter(), misc_info_() {
}

MinidumpMiscInfoWriter::~MinidumpMiscInfoWriter() {
}

void MinidumpMiscInfoWriter::InitializeFromSnapshot(
    const ProcessSnapshot* process_snapshot) {
  DCHECK_EQ(state(), kStateMutable);
  DCHECK_EQ(misc_info_.Flags1, 0u);

  SetProcessID(InRangeCast<uint32_t>(process_snapshot->ProcessID(), 0));

  const SystemSnapshot* system_snapshot = process_snapshot->System();

  uint64_t current_hz;
  uint64_t max_hz;
  system_snapshot->CPUFrequency(&current_hz, &max_hz);
  const uint32_t kHzPerMHz = static_cast<const uint32_t>(1E6);
  SetProcessorPowerInfo(
      InRangeCast<uint32_t>(current_hz / kHzPerMHz,
                            std::numeric_limits<uint32_t>::max()),
      InRangeCast<uint32_t>(max_hz / kHzPerMHz,
                            std::numeric_limits<uint32_t>::max()),
      0,
      0,
      0);

  timeval start_time;
  process_snapshot->ProcessStartTime(&start_time);

  timeval user_time;
  timeval system_time;
  process_snapshot->ProcessCPUTimes(&user_time, &system_time);

  // Round the resource usage fields to the nearest second, because the minidump
  // format only has one-second resolution. The start_time field is truncated
  // instead of rounded so that the process uptime is reflected more accurately
  // when the start time is compared to the snapshot time in the
  // MINIDUMP_HEADER, which is also truncated, not rounded.
  uint32_t user_seconds = TimevalToRoundedSeconds(user_time);
  uint32_t system_seconds = TimevalToRoundedSeconds(system_time);

  SetProcessTimes(start_time.tv_sec, user_seconds, system_seconds);

  // This determines the system’s time zone, which may be different than the
  // process’ notion of the time zone.
  SystemSnapshot::DaylightSavingTimeStatus dst_status;
  int standard_offset_seconds;
  int daylight_offset_seconds;
  std::string standard_name;
  std::string daylight_name;
  system_snapshot->TimeZone(&dst_status,
                            &standard_offset_seconds,
                            &daylight_offset_seconds,
                            &standard_name,
                            &daylight_name);

  // standard_offset_seconds is seconds east of UTC, but the minidump file wants
  // minutes west of UTC. daylight_offset_seconds is also seconds east of UTC,
  // but the minidump file wants minutes west of the standard offset. The empty
  // ({}) arguments are for the transition times in and out of daylight saving
  // time. These are not determined because no API exists to do so, and the
  // transition times may vary from year to year.
  SetTimeZone(dst_status,
              standard_offset_seconds / -60,
              standard_name,
              {},
              0,
              daylight_name,
              {},
              (standard_offset_seconds - daylight_offset_seconds) / 60);

  SetBuildString(BuildString(system_snapshot),
                 internal::MinidumpMiscInfoDebugBuildString());
}

void MinidumpMiscInfoWriter::SetProcessID(uint32_t process_id) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessId = process_id;
  misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESS_ID;
}

void MinidumpMiscInfoWriter::SetProcessTimes(time_t process_create_time,
                                             uint32_t process_user_time,
                                             uint32_t process_kernel_time) {
  DCHECK_EQ(state(), kStateMutable);

  internal::MinidumpWriterUtil::AssignTimeT(&misc_info_.ProcessCreateTime,
                                            process_create_time);

  misc_info_.ProcessUserTime = process_user_time;
  misc_info_.ProcessKernelTime = process_kernel_time;
  misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESS_TIMES;
}

void MinidumpMiscInfoWriter::SetProcessorPowerInfo(
    uint32_t processor_max_mhz,
    uint32_t processor_current_mhz,
    uint32_t processor_mhz_limit,
    uint32_t processor_max_idle_state,
    uint32_t processor_current_idle_state) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessorMaxMhz = processor_max_mhz;
  misc_info_.ProcessorCurrentMhz = processor_current_mhz;
  misc_info_.ProcessorMhzLimit = processor_mhz_limit;
  misc_info_.ProcessorMaxIdleState = processor_max_idle_state;
  misc_info_.ProcessorCurrentIdleState = processor_current_idle_state;
  misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESSOR_POWER_INFO;
}

void MinidumpMiscInfoWriter::SetProcessIntegrityLevel(
    uint32_t process_integrity_level) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessIntegrityLevel = process_integrity_level;
  misc_info_.Flags1 |= MINIDUMP_MISC3_PROCESS_INTEGRITY;
}

void MinidumpMiscInfoWriter::SetProcessExecuteFlags(
    uint32_t process_execute_flags) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessExecuteFlags = process_execute_flags;
  misc_info_.Flags1 |= MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS;
}

void MinidumpMiscInfoWriter::SetProtectedProcess(uint32_t protected_process) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProtectedProcess = protected_process;
  misc_info_.Flags1 |= MINIDUMP_MISC3_PROTECTED_PROCESS;
}

void MinidumpMiscInfoWriter::SetTimeZone(uint32_t time_zone_id,
                                         int32_t bias,
                                         const std::string& standard_name,
                                         const SYSTEMTIME& standard_date,
                                         int32_t standard_bias,
                                         const std::string& daylight_name,
                                         const SYSTEMTIME& daylight_date,
                                         int32_t daylight_bias) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.TimeZoneId = time_zone_id;
  misc_info_.TimeZone.Bias = bias;

  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.TimeZone.StandardName,
      arraysize(misc_info_.TimeZone.StandardName),
      standard_name);

  misc_info_.TimeZone.StandardDate = standard_date;
  misc_info_.TimeZone.StandardBias = standard_bias;

  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.TimeZone.DaylightName,
      arraysize(misc_info_.TimeZone.DaylightName),
      daylight_name);

  misc_info_.TimeZone.DaylightDate = daylight_date;
  misc_info_.TimeZone.DaylightBias = daylight_bias;

  misc_info_.Flags1 |= MINIDUMP_MISC3_TIMEZONE;
}

void MinidumpMiscInfoWriter::SetBuildString(
    const std::string& build_string,
    const std::string& debug_build_string) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.Flags1 |= MINIDUMP_MISC4_BUILDSTRING;

  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.BuildString, arraysize(misc_info_.BuildString), build_string);
  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.DbgBldStr,
      arraysize(misc_info_.DbgBldStr),
      debug_build_string);
}

bool MinidumpMiscInfoWriter::Freeze() {
  DCHECK_EQ(state(), kStateMutable);

  if (!MinidumpStreamWriter::Freeze()) {
    return false;
  }

  size_t size = CalculateSizeOfObjectFromFlags();
  if (!AssignIfInRange(&misc_info_.SizeOfInfo, size)) {
    LOG(ERROR) << "size " << size << " out of range";
    return false;
  }

  return true;
}

size_t MinidumpMiscInfoWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);

  return CalculateSizeOfObjectFromFlags();
}

bool MinidumpMiscInfoWriter::WriteObject(FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

  return file_writer->Write(&misc_info_, CalculateSizeOfObjectFromFlags());
}

MinidumpStreamType MinidumpMiscInfoWriter::StreamType() const {
  return kMinidumpStreamTypeMiscInfo;
}

size_t MinidumpMiscInfoWriter::CalculateSizeOfObjectFromFlags() const {
  DCHECK_GE(state(), kStateFrozen);

  if (misc_info_.Flags1 & MINIDUMP_MISC4_BUILDSTRING) {
    return sizeof(MINIDUMP_MISC_INFO_4);
  }
  if (misc_info_.Flags1 &
      (MINIDUMP_MISC3_PROCESS_INTEGRITY | MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS |
       MINIDUMP_MISC3_TIMEZONE | MINIDUMP_MISC3_PROTECTED_PROCESS)) {
    return sizeof(MINIDUMP_MISC_INFO_3);
  }
  if (misc_info_.Flags1 & MINIDUMP_MISC1_PROCESSOR_POWER_INFO) {
    return sizeof(MINIDUMP_MISC_INFO_2);
  }
  return sizeof(MINIDUMP_MISC_INFO);
}

}  // namespace crashpad
<commit_msg>Port the minidump library to Android and ARM<commit_after>// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "minidump/minidump_misc_info_writer.h"

#include <limits>

#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "minidump/minidump_writer_util.h"
#include "package.h"
#include "snapshot/process_snapshot.h"
#include "snapshot/system_snapshot.h"
#include "util/file/file_writer.h"
#include "util/numeric/in_range_cast.h"
#include "util/numeric/safe_assignment.h"

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#elif defined(OS_ANDROID)
#include <android/api-level.h>
#endif

namespace crashpad {
namespace {

uint32_t TimevalToRoundedSeconds(const timeval& tv) {
  uint32_t seconds =
      InRangeCast<uint32_t>(tv.tv_sec, std::numeric_limits<uint32_t>::max());
  const int kMicrosecondsPerSecond = static_cast<int>(1E6);
  if (tv.tv_usec >= kMicrosecondsPerSecond / 2 &&
      seconds != std::numeric_limits<uint32_t>::max()) {
    ++seconds;
  }
  return seconds;
}

// For MINIDUMP_MISC_INFO_4::BuildString. dbghelp only places OS version
// information here, but if a machine description is also available, this is the
// only reasonable place in a minidump file to put it.
std::string BuildString(const SystemSnapshot* system_snapshot) {
  std::string os_version_full = system_snapshot->OSVersionFull();
  std::string machine_description = system_snapshot->MachineDescription();
  if (!os_version_full.empty()) {
    if (!machine_description.empty()) {
      return base::StringPrintf(
          "%s; %s", os_version_full.c_str(), machine_description.c_str());
    }
    return os_version_full;
  }
  return machine_description;
}

#if defined(OS_MACOSX)
// Converts the value of the MAC_OS_VERSION_MIN_REQUIRED or
// MAC_OS_X_VERSION_MAX_ALLOWED macro from <AvailabilityMacros.h> to a number
// identifying the minor Mac OS X version that it represents. For example, with
// an argument of MAC_OS_X_VERSION_10_6, this function will return 6.
int AvailabilityVersionToMacOSXMinorVersion(int availability) {
  // Through MAC_OS_X_VERSION_10_9, the minor version is the tens digit.
  if (availability >= 1000 && availability <= 1099) {
    return (availability / 10) % 10;
  }

  // After MAC_OS_X_VERSION_10_9, the older format was insufficient to represent
  // versions. Since then, the minor version is the thousands and hundreds
  // digits.
  if (availability >= 100000 && availability <= 109999) {
    return (availability / 100) % 100;
  }

  return 0;
}
#endif

}  // namespace

namespace internal {

// For MINIDUMP_MISC_INFO_4::DbgBldStr. dbghelp produces strings like
// “dbghelp.i386,6.3.9600.16520” and “dbghelp.amd64,6.3.9600.16520”. Mimic that
// format, and add the OS that wrote the minidump along with any relevant
// platform-specific data describing the compilation environment.
std::string MinidumpMiscInfoDebugBuildString() {
  // Caution: the minidump file format only has room for 39 UTF-16 code units
  // plus a UTF-16 NUL terminator. Don’t let strings get longer than this, or
  // they will be truncated and a message will be logged.
#if defined(OS_MACOSX)
  const char kOS[] = "mac";
#elif defined(OS_ANDROID)
  const char kOS[] = "android";
#elif defined(OS_LINUX)
  const char kOS[] = "linux";
#elif defined(OS_WIN)
  const char kOS[] = "win";
#else
#error define kOS for this operating system
#endif

#if defined(ARCH_CPU_X86)
  const char kCPU[] = "i386";
#elif defined(ARCH_CPU_X86_64)
  const char kCPU[] = "amd64";
#elif defined(ARCH_CPU_ARM)
  const char kCPU[] = "arm";
#elif defined(ARCH_CPU_ARM64)
  const char kCPU[] = "arm64";
#else
#error define kCPU for this CPU
#endif

  std::string debug_build_string = base::StringPrintf("%s.%s,%s,%s",
                                                      PACKAGE_TARNAME,
                                                      kCPU,
                                                      PACKAGE_VERSION,
                                                      kOS);

#if defined(OS_MACOSX)
  debug_build_string += base::StringPrintf(
      ",%d,%d",
      AvailabilityVersionToMacOSXMinorVersion(MAC_OS_X_VERSION_MIN_REQUIRED),
      AvailabilityVersionToMacOSXMinorVersion(MAC_OS_X_VERSION_MAX_ALLOWED));
#elif defined(OS_ANDROID)
  debug_build_string += base::StringPrintf(",%d", __ANDROID_API__);
#endif

  return debug_build_string;
}

}  // namespace internal

MinidumpMiscInfoWriter::MinidumpMiscInfoWriter()
    : MinidumpStreamWriter(), misc_info_() {
}

MinidumpMiscInfoWriter::~MinidumpMiscInfoWriter() {
}

void MinidumpMiscInfoWriter::InitializeFromSnapshot(
    const ProcessSnapshot* process_snapshot) {
  DCHECK_EQ(state(), kStateMutable);
  DCHECK_EQ(misc_info_.Flags1, 0u);

  SetProcessID(InRangeCast<uint32_t>(process_snapshot->ProcessID(), 0));

  const SystemSnapshot* system_snapshot = process_snapshot->System();

  uint64_t current_hz;
  uint64_t max_hz;
  system_snapshot->CPUFrequency(&current_hz, &max_hz);
  const uint32_t kHzPerMHz = static_cast<const uint32_t>(1E6);
  SetProcessorPowerInfo(
      InRangeCast<uint32_t>(current_hz / kHzPerMHz,
                            std::numeric_limits<uint32_t>::max()),
      InRangeCast<uint32_t>(max_hz / kHzPerMHz,
                            std::numeric_limits<uint32_t>::max()),
      0,
      0,
      0);

  timeval start_time;
  process_snapshot->ProcessStartTime(&start_time);

  timeval user_time;
  timeval system_time;
  process_snapshot->ProcessCPUTimes(&user_time, &system_time);

  // Round the resource usage fields to the nearest second, because the minidump
  // format only has one-second resolution. The start_time field is truncated
  // instead of rounded so that the process uptime is reflected more accurately
  // when the start time is compared to the snapshot time in the
  // MINIDUMP_HEADER, which is also truncated, not rounded.
  uint32_t user_seconds = TimevalToRoundedSeconds(user_time);
  uint32_t system_seconds = TimevalToRoundedSeconds(system_time);

  SetProcessTimes(start_time.tv_sec, user_seconds, system_seconds);

  // This determines the system’s time zone, which may be different than the
  // process’ notion of the time zone.
  SystemSnapshot::DaylightSavingTimeStatus dst_status;
  int standard_offset_seconds;
  int daylight_offset_seconds;
  std::string standard_name;
  std::string daylight_name;
  system_snapshot->TimeZone(&dst_status,
                            &standard_offset_seconds,
                            &daylight_offset_seconds,
                            &standard_name,
                            &daylight_name);

  // standard_offset_seconds is seconds east of UTC, but the minidump file wants
  // minutes west of UTC. daylight_offset_seconds is also seconds east of UTC,
  // but the minidump file wants minutes west of the standard offset. The empty
  // ({}) arguments are for the transition times in and out of daylight saving
  // time. These are not determined because no API exists to do so, and the
  // transition times may vary from year to year.
  SetTimeZone(dst_status,
              standard_offset_seconds / -60,
              standard_name,
              {},
              0,
              daylight_name,
              {},
              (standard_offset_seconds - daylight_offset_seconds) / 60);

  SetBuildString(BuildString(system_snapshot),
                 internal::MinidumpMiscInfoDebugBuildString());
}

void MinidumpMiscInfoWriter::SetProcessID(uint32_t process_id) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessId = process_id;
  misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESS_ID;
}

void MinidumpMiscInfoWriter::SetProcessTimes(time_t process_create_time,
                                             uint32_t process_user_time,
                                             uint32_t process_kernel_time) {
  DCHECK_EQ(state(), kStateMutable);

  internal::MinidumpWriterUtil::AssignTimeT(&misc_info_.ProcessCreateTime,
                                            process_create_time);

  misc_info_.ProcessUserTime = process_user_time;
  misc_info_.ProcessKernelTime = process_kernel_time;
  misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESS_TIMES;
}

void MinidumpMiscInfoWriter::SetProcessorPowerInfo(
    uint32_t processor_max_mhz,
    uint32_t processor_current_mhz,
    uint32_t processor_mhz_limit,
    uint32_t processor_max_idle_state,
    uint32_t processor_current_idle_state) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessorMaxMhz = processor_max_mhz;
  misc_info_.ProcessorCurrentMhz = processor_current_mhz;
  misc_info_.ProcessorMhzLimit = processor_mhz_limit;
  misc_info_.ProcessorMaxIdleState = processor_max_idle_state;
  misc_info_.ProcessorCurrentIdleState = processor_current_idle_state;
  misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESSOR_POWER_INFO;
}

void MinidumpMiscInfoWriter::SetProcessIntegrityLevel(
    uint32_t process_integrity_level) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessIntegrityLevel = process_integrity_level;
  misc_info_.Flags1 |= MINIDUMP_MISC3_PROCESS_INTEGRITY;
}

void MinidumpMiscInfoWriter::SetProcessExecuteFlags(
    uint32_t process_execute_flags) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProcessExecuteFlags = process_execute_flags;
  misc_info_.Flags1 |= MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS;
}

void MinidumpMiscInfoWriter::SetProtectedProcess(uint32_t protected_process) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.ProtectedProcess = protected_process;
  misc_info_.Flags1 |= MINIDUMP_MISC3_PROTECTED_PROCESS;
}

void MinidumpMiscInfoWriter::SetTimeZone(uint32_t time_zone_id,
                                         int32_t bias,
                                         const std::string& standard_name,
                                         const SYSTEMTIME& standard_date,
                                         int32_t standard_bias,
                                         const std::string& daylight_name,
                                         const SYSTEMTIME& daylight_date,
                                         int32_t daylight_bias) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.TimeZoneId = time_zone_id;
  misc_info_.TimeZone.Bias = bias;

  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.TimeZone.StandardName,
      arraysize(misc_info_.TimeZone.StandardName),
      standard_name);

  misc_info_.TimeZone.StandardDate = standard_date;
  misc_info_.TimeZone.StandardBias = standard_bias;

  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.TimeZone.DaylightName,
      arraysize(misc_info_.TimeZone.DaylightName),
      daylight_name);

  misc_info_.TimeZone.DaylightDate = daylight_date;
  misc_info_.TimeZone.DaylightBias = daylight_bias;

  misc_info_.Flags1 |= MINIDUMP_MISC3_TIMEZONE;
}

void MinidumpMiscInfoWriter::SetBuildString(
    const std::string& build_string,
    const std::string& debug_build_string) {
  DCHECK_EQ(state(), kStateMutable);

  misc_info_.Flags1 |= MINIDUMP_MISC4_BUILDSTRING;

  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.BuildString, arraysize(misc_info_.BuildString), build_string);
  internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
      misc_info_.DbgBldStr,
      arraysize(misc_info_.DbgBldStr),
      debug_build_string);
}

bool MinidumpMiscInfoWriter::Freeze() {
  DCHECK_EQ(state(), kStateMutable);

  if (!MinidumpStreamWriter::Freeze()) {
    return false;
  }

  size_t size = CalculateSizeOfObjectFromFlags();
  if (!AssignIfInRange(&misc_info_.SizeOfInfo, size)) {
    LOG(ERROR) << "size " << size << " out of range";
    return false;
  }

  return true;
}

size_t MinidumpMiscInfoWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);

  return CalculateSizeOfObjectFromFlags();
}

bool MinidumpMiscInfoWriter::WriteObject(FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

  return file_writer->Write(&misc_info_, CalculateSizeOfObjectFromFlags());
}

MinidumpStreamType MinidumpMiscInfoWriter::StreamType() const {
  return kMinidumpStreamTypeMiscInfo;
}

size_t MinidumpMiscInfoWriter::CalculateSizeOfObjectFromFlags() const {
  DCHECK_GE(state(), kStateFrozen);

  if (misc_info_.Flags1 & MINIDUMP_MISC4_BUILDSTRING) {
    return sizeof(MINIDUMP_MISC_INFO_4);
  }
  if (misc_info_.Flags1 &
      (MINIDUMP_MISC3_PROCESS_INTEGRITY | MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS |
       MINIDUMP_MISC3_TIMEZONE | MINIDUMP_MISC3_PROTECTED_PROCESS)) {
    return sizeof(MINIDUMP_MISC_INFO_3);
  }
  if (misc_info_.Flags1 & MINIDUMP_MISC1_PROCESSOR_POWER_INFO) {
    return sizeof(MINIDUMP_MISC_INFO_2);
  }
  return sizeof(MINIDUMP_MISC_INFO);
}

}  // namespace crashpad
<|endoftext|>