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

/**
 * \file ir_mat_op_to_vec.cpp
 *
 * Breaks matrix operation expressions down to a series of vector operations.
 *
 * Generally this is how we have to codegen matrix operations for a
 * GPU, so this gives us the chance to constant fold operations on a
 * column or row.
 */

#include "ir.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"

class ir_mat_op_to_vec_visitor : public ir_hierarchical_visitor {
public:
   ir_mat_op_to_vec_visitor()
   {
      this->made_progress = false;
   }

   ir_visitor_status visit_leave(ir_assignment *);

   ir_rvalue *get_column(ir_variable *var, int i);

   bool made_progress;
};

static bool
mat_op_to_vec_predicate(ir_instruction *ir)
{
   ir_expression *expr = ir->as_expression();
   unsigned int i;

   if (!expr)
      return false;

   for (i = 0; i < expr->get_num_operands(); i++) {
      if (expr->operands[i]->type->is_matrix())
	 return true;
   }

   return false;
}

bool
do_mat_op_to_vec(exec_list *instructions)
{
   ir_mat_op_to_vec_visitor v;

   /* Pull out any matrix expression to a separate assignment to a
    * temp.  This will make our handling of the breakdown to
    * operations on the matrix's vector components much easier.
    */
   do_expression_flattening(instructions, mat_op_to_vec_predicate);

   visit_list_elements(&v, instructions);

   return v.made_progress;
}

ir_rvalue *
ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int i)
{
   ir_dereference *deref;

   if (!var->type->is_matrix()) {
      deref = new(base_ir) ir_dereference_variable(var);
   } else {
      deref = new(base_ir) ir_dereference_variable(var);
      deref = new(base_ir) ir_dereference_array(deref,
						new(base_ir) ir_constant(i));
   }

   return deref;
}

ir_visitor_status
ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)
{
   ir_expression *expr = assign->rhs->as_expression();
   bool found_matrix = false;
   unsigned int i, matrix_columns = 1;
   ir_variable *op_var[2];

   if (!expr)
      return visit_continue;

   for (i = 0; i < expr->get_num_operands(); i++) {
      if (expr->operands[i]->type->is_matrix()) {
	 found_matrix = true;
	 matrix_columns = expr->operands[i]->type->matrix_columns;
	 break;
      }
   }
   if (!found_matrix)
      return visit_continue;

   /* FINISHME: see below */
   if (expr->operation == ir_binop_mul)
      return visit_continue;

   ir_dereference_variable *lhs_deref = assign->lhs->as_dereference_variable();
   assert(lhs_deref);

   ir_variable *result_var = lhs_deref->var;

   /* Store the expression operands in temps so we can use them
    * multiple times.
    */
   for (i = 0; i < expr->get_num_operands(); i++) {
      ir_assignment *assign;

      op_var[i] = new(base_ir) ir_variable(expr->operands[i]->type,
					   "mat_op_to_vec");
      base_ir->insert_before(op_var[i]);

      lhs_deref = new(base_ir) ir_dereference_variable(op_var[i]);
      assign = new(base_ir) ir_assignment(lhs_deref,
					  expr->operands[i],
					  NULL);
      base_ir->insert_before(assign);
   }

   /* OK, time to break down this matrix operation. */
   switch (expr->operation) {
   case ir_binop_add:
   case ir_binop_sub:
   case ir_binop_div:
   case ir_binop_mod:
      /* For most operations, the matrix version is just going
       * column-wise through and applying the operation to each column
       * if available.
       */
      for (i = 0; i < matrix_columns; i++) {
	 ir_rvalue *op0 = get_column(op_var[0], i);
	 ir_rvalue *op1 = get_column(op_var[1], i);
	 ir_rvalue *result = get_column(result_var, i);
	 ir_expression *column_expr;
	 ir_assignment *column_assign;

	 column_expr = new(base_ir) ir_expression(expr->operation,
						  result->type,
						  op0,
						  op1);

	 column_assign = new(base_ir) ir_assignment(result,
						    column_expr,
						    NULL);
	 base_ir->insert_before(column_assign);
      }
      break;
   case ir_binop_mul:
      /* FINISHME */
      return visit_continue;
      break;
   default:
      printf("FINISHME: Handle matrix operation for %s\n", expr->operator_string());
      abort();
   }
   assign->remove();
   this->made_progress = true;

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

/**
 * \file ir_mat_op_to_vec.cpp
 *
 * Breaks matrix operation expressions down to a series of vector operations.
 *
 * Generally this is how we have to codegen matrix operations for a
 * GPU, so this gives us the chance to constant fold operations on a
 * column or row.
 */

#include "ir.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"

class ir_mat_op_to_vec_visitor : public ir_hierarchical_visitor {
public:
   ir_mat_op_to_vec_visitor()
   {
      this->made_progress = false;
   }

   ir_visitor_status visit_leave(ir_assignment *);

   ir_rvalue *get_column(ir_variable *var, int col);
   ir_rvalue *get_element(ir_variable *var, int col, int row);

   void do_mul_mat_mat(ir_variable *result_var,
		       ir_variable *a_var, ir_variable *b_var);
   void do_mul_mat_vec(ir_variable *result_var,
		       ir_variable *a_var, ir_variable *b_var);
   void do_mul_vec_mat(ir_variable *result_var,
		       ir_variable *a_var, ir_variable *b_var);
   void do_mul_mat_scalar(ir_variable *result_var,
			  ir_variable *a_var, ir_variable *b_var);

   bool made_progress;
};

static bool
mat_op_to_vec_predicate(ir_instruction *ir)
{
   ir_expression *expr = ir->as_expression();
   unsigned int i;

   if (!expr)
      return false;

   for (i = 0; i < expr->get_num_operands(); i++) {
      if (expr->operands[i]->type->is_matrix())
	 return true;
   }

   return false;
}

bool
do_mat_op_to_vec(exec_list *instructions)
{
   ir_mat_op_to_vec_visitor v;

   /* Pull out any matrix expression to a separate assignment to a
    * temp.  This will make our handling of the breakdown to
    * operations on the matrix's vector components much easier.
    */
   do_expression_flattening(instructions, mat_op_to_vec_predicate);

   visit_list_elements(&v, instructions);

   return v.made_progress;
}

ir_rvalue *
ir_mat_op_to_vec_visitor::get_element(ir_variable *var, int col, int row)
{
   ir_dereference *deref;

   deref = new(base_ir) ir_dereference_variable(var);

   if (var->type->is_matrix()) {
      deref = new(base_ir) ir_dereference_array(var,
						new(base_ir) ir_constant(col));
   } else {
      assert(col == 0);
   }

   return new(base_ir) ir_swizzle(deref, row, 0, 0, 0, 1);
}

ir_rvalue *
ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int row)
{
   ir_dereference *deref;

   if (!var->type->is_matrix()) {
      deref = new(base_ir) ir_dereference_variable(var);
   } else {
      deref = new(base_ir) ir_dereference_variable(var);
      deref = new(base_ir) ir_dereference_array(deref,
						new(base_ir) ir_constant(row));
   }

   return deref;
}

void
ir_mat_op_to_vec_visitor::do_mul_mat_mat(ir_variable *result_var,
					 ir_variable *a_var,
					 ir_variable *b_var)
{
   int b_col, i;
   ir_assignment *assign;
   ir_expression *expr;

   for (b_col = 0; b_col < b_var->type->matrix_columns; b_col++) {
      ir_rvalue *a = get_column(a_var, 0);
      ir_rvalue *b = get_element(b_var, b_col, 0);

      /* first column */
      expr = new(base_ir) ir_expression(ir_binop_mul,
					a->type,
					a,
					b);

      /* following columns */
      for (i = 1; i < a_var->type->matrix_columns; i++) {
	 ir_expression *mul_expr;

	 a = get_column(a_var, i);
	 b = get_element(b_var, b_col, i);

	 mul_expr = new(base_ir) ir_expression(ir_binop_mul,
					       a->type,
					       a,
					       b);
	 expr = new(base_ir) ir_expression(ir_binop_add,
					   a->type,
					   expr,
					   mul_expr);
      }

      ir_rvalue *result = get_column(result_var, b_col);
      assign = new(base_ir) ir_assignment(result,
					  expr,
					  NULL);
      base_ir->insert_before(assign);
   }
}

void
ir_mat_op_to_vec_visitor::do_mul_mat_vec(ir_variable *result_var,
					 ir_variable *a_var,
					 ir_variable *b_var)
{
   int i;
   ir_rvalue *a = get_column(a_var, 0);
   ir_rvalue *b = get_element(b_var, 0, 0);
   ir_assignment *assign;
   ir_expression *expr;

   /* first column */
   expr = new(base_ir) ir_expression(ir_binop_mul,
				     result_var->type,
				     a,
				     b);

   /* following columns */
   for (i = 1; i < a_var->type->matrix_columns; i++) {
      ir_expression *mul_expr;

      a = get_column(a_var, i);
      b = get_element(b_var, 0, i);

      mul_expr = new(base_ir) ir_expression(ir_binop_mul,
					    result_var->type,
					    a,
					    b);
      expr = new(base_ir) ir_expression(ir_binop_add,
					result_var->type,
					expr,
					mul_expr);
   }

   ir_rvalue *result = new(base_ir) ir_dereference_variable(result_var);
   assign = new(base_ir) ir_assignment(result,
				       expr,
				       NULL);
   base_ir->insert_before(assign);
}

void
ir_mat_op_to_vec_visitor::do_mul_vec_mat(ir_variable *result_var,
					 ir_variable *a_var,
					 ir_variable *b_var)
{
   int i;

   for (i = 0; i < b_var->type->matrix_columns; i++) {
      ir_rvalue *a = new(base_ir) ir_dereference_variable(a_var);
      ir_rvalue *b = get_column(b_var, i);
      ir_rvalue *result;
      ir_expression *column_expr;
      ir_assignment *column_assign;

      result = new(base_ir) ir_dereference_variable(result_var);
      result = new(base_ir) ir_swizzle(result, i, 0, 0, 0, 1);

      column_expr = new(base_ir) ir_expression(ir_binop_dot,
					       result->type,
					       a,
					       b);

      column_assign = new(base_ir) ir_assignment(result,
						 column_expr,
						 NULL);
      base_ir->insert_before(column_assign);
   }
}

void
ir_mat_op_to_vec_visitor::do_mul_mat_scalar(ir_variable *result_var,
					    ir_variable *a_var,
					    ir_variable *b_var)
{
   int i;

   for (i = 0; i < a_var->type->matrix_columns; i++) {
      ir_rvalue *a = get_column(a_var, i);
      ir_rvalue *b = new(base_ir) ir_dereference_variable(b_var);
      ir_rvalue *result = get_column(result_var, i);
      ir_expression *column_expr;
      ir_assignment *column_assign;

      column_expr = new(base_ir) ir_expression(ir_binop_mul,
					       result->type,
					       a,
					       b);

      column_assign = new(base_ir) ir_assignment(result,
						 column_expr,
						 NULL);
      base_ir->insert_before(column_assign);
   }
}

ir_visitor_status
ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)
{
   ir_expression *expr = assign->rhs->as_expression();
   bool found_matrix = false;
   unsigned int i, matrix_columns = 1;
   ir_variable *op_var[2];

   if (!expr)
      return visit_continue;

   for (i = 0; i < expr->get_num_operands(); i++) {
      if (expr->operands[i]->type->is_matrix()) {
	 found_matrix = true;
	 matrix_columns = expr->operands[i]->type->matrix_columns;
	 break;
      }
   }
   if (!found_matrix)
      return visit_continue;

   ir_dereference_variable *lhs_deref = assign->lhs->as_dereference_variable();
   assert(lhs_deref);

   ir_variable *result_var = lhs_deref->var;

   /* Store the expression operands in temps so we can use them
    * multiple times.
    */
   for (i = 0; i < expr->get_num_operands(); i++) {
      ir_assignment *assign;

      op_var[i] = new(base_ir) ir_variable(expr->operands[i]->type,
					   "mat_op_to_vec");
      base_ir->insert_before(op_var[i]);

      lhs_deref = new(base_ir) ir_dereference_variable(op_var[i]);
      assign = new(base_ir) ir_assignment(lhs_deref,
					  expr->operands[i],
					  NULL);
      base_ir->insert_before(assign);
   }

   /* OK, time to break down this matrix operation. */
   switch (expr->operation) {
   case ir_binop_add:
   case ir_binop_sub:
   case ir_binop_div:
   case ir_binop_mod:
      /* For most operations, the matrix version is just going
       * column-wise through and applying the operation to each column
       * if available.
       */
      for (i = 0; i < matrix_columns; i++) {
	 ir_rvalue *op0 = get_column(op_var[0], i);
	 ir_rvalue *op1 = get_column(op_var[1], i);
	 ir_rvalue *result = get_column(result_var, i);
	 ir_expression *column_expr;
	 ir_assignment *column_assign;

	 column_expr = new(base_ir) ir_expression(expr->operation,
						  result->type,
						  op0,
						  op1);

	 column_assign = new(base_ir) ir_assignment(result,
						    column_expr,
						    NULL);
	 base_ir->insert_before(column_assign);
      }
      break;
   case ir_binop_mul:
      if (op_var[0]->type->is_matrix()) {
	 if (op_var[1]->type->is_matrix()) {
	    do_mul_mat_mat(result_var, op_var[0], op_var[1]);
	 } else if (op_var[1]->type->is_vector()) {
	    do_mul_mat_vec(result_var, op_var[0], op_var[1]);
	 } else {
	    assert(op_var[1]->type->is_scalar());
	    do_mul_mat_scalar(result_var, op_var[0], op_var[1]);
	 }
      } else {
	 assert(op_var[1]->type->is_matrix());
	 if (op_var[0]->type->is_vector()) {
	    do_mul_vec_mat(result_var, op_var[0], op_var[1]);
	 } else {
	    assert(op_var[0]->type->is_scalar());
	    do_mul_mat_scalar(result_var, op_var[1], op_var[0]);
	 }
      }
      break;
   default:
      printf("FINISHME: Handle matrix operation for %s\n", expr->operator_string());
      abort();
   }
   assign->remove();
   this->made_progress = true;

   return visit_continue;
}
<|endoftext|>


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

#include "gpu-compute/hsail_code.hh"

#include "arch/gpu_types.hh"
#include "arch/hsail/Brig.h"
#include "arch/hsail/operand.hh"
#include "config/the_gpu_isa.hh"
#include "debug/BRIG.hh"
#include "debug/HSAILObject.hh"
#include "gpu-compute/brig_object.hh"
#include "gpu-compute/gpu_static_inst.hh"
#include "gpu-compute/kernel_cfg.hh"

using namespace Brig;

int getBrigDataTypeBytes(BrigType16_t t);

HsailCode::HsailCode(const std::string &name_str)
    : HsaCode(name_str), private_size(-1), readonly_size(-1)
{
}

void
HsailCode::init(const BrigDirectiveExecutable *code_dir, const BrigObject *obj,
                StorageMap *objStorageMap)
{
    storageMap = objStorageMap;

    // set pointer so that decoding process can find this kernel context when
    // needed
    obj->currentCode = this;

    if (code_dir->base.kind != BRIG_KIND_DIRECTIVE_FUNCTION &&
        code_dir->base.kind != BRIG_KIND_DIRECTIVE_KERNEL) {
        fatal("unexpected directive kind %d inside kernel/function init\n",
              code_dir->base.kind);
    }

    DPRINTF(HSAILObject, "Initializing code, first code block entry is: %d\n",
            code_dir->firstCodeBlockEntry);

    // clear these static vars so we can properly track the max index
    // for this kernel
    SRegOperand::maxRegIdx = 0;
    DRegOperand::maxRegIdx = 0;
    CRegOperand::maxRegIdx = 0;
    setPrivateSize(0);

    const BrigBase *entryPtr = brigNext((BrigBase*)code_dir);
    const BrigBase *endPtr =
        obj->getCodeSectionEntry(code_dir->nextModuleEntry);

    // the instruction's byte address (relative to the base addr
    // of the code section)
    int inst_addr = 0;
    // the index that points to the instruction in the instruction
    // array
    int inst_idx = 0;
    std::vector<GPUStaticInst*> instructions;
    int funcarg_size_scope = 0;

    // walk through instructions in code section and directives in
    // directive section in parallel, processing directives that apply
    // when we reach the relevant code point.
    while (entryPtr < endPtr) {
        switch (entryPtr->kind) {
          case BRIG_KIND_DIRECTIVE_VARIABLE:
           {
                const BrigDirectiveVariable *sym =
                    (const BrigDirectiveVariable*)entryPtr;

                DPRINTF(HSAILObject,"Initializing code, directive is "
                        "kind_variable, symbol is: %s\n",
                        obj->getString(sym->name));

                StorageElement *se = storageMap->addSymbol(sym, obj);

                if (sym->segment == BRIG_SEGMENT_PRIVATE) {
                    setPrivateSize(se->size);
                } else { // spill
                    funcarg_size_scope += se->size;
                }
            }
            break;

          case BRIG_KIND_DIRECTIVE_LABEL:
            {
                const BrigDirectiveLabel *lbl =
                    (const BrigDirectiveLabel*)entryPtr;

                DPRINTF(HSAILObject,"Initializing code, directive is "
                        "kind_label, label is: %s \n",
                        obj->getString(lbl->name));

                labelMap.addLabel(lbl, inst_addr, obj);
            }
            break;

          case BRIG_KIND_DIRECTIVE_PRAGMA:
            {
                DPRINTF(HSAILObject, "Initializing code, directive "
                        "is kind_pragma\n");
            }
            break;

          case BRIG_KIND_DIRECTIVE_COMMENT:
            {
                DPRINTF(HSAILObject, "Initializing code, directive is "
                        "kind_comment\n");
            }
            break;

          case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
            {
                DPRINTF(HSAILObject, "Initializing code, directive is "
                        "kind_arg_block_start\n");

                storageMap->resetOffset(BRIG_SEGMENT_ARG);
                funcarg_size_scope = 0;
            }
            break;

          case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
            {
                DPRINTF(HSAILObject, "Initializing code, directive is "
                        "kind_arg_block_end\n");

                funcarg_size = funcarg_size < funcarg_size_scope ?
                                              funcarg_size_scope : funcarg_size;
            }
            break;

          case BRIG_KIND_DIRECTIVE_END:
            DPRINTF(HSAILObject, "Initializing code, dircetive is "
                    "kind_end\n");

            break;

          default:
            if (entryPtr->kind >= BRIG_KIND_INST_BEGIN &&
                entryPtr->kind <= BRIG_KIND_INST_END) {

                BrigInstBase *instPtr = (BrigInstBase*)entryPtr;
                TheGpuISA::MachInst machInst = { instPtr, obj };
                GPUStaticInst *iptr = decoder.decode(machInst);

                if (iptr) {
                    DPRINTF(HSAILObject, "Initializing code, processing inst "
                            "byte addr #%d idx %d: OPCODE=%d\n", inst_addr,
                            inst_idx, instPtr->opcode);

                    TheGpuISA::RawMachInst raw_inst = decoder.saveInst(iptr);
                    iptr->instNum(inst_idx);
                    iptr->instAddr(inst_addr);
                    _insts.push_back(raw_inst);
                    instructions.push_back(iptr);
                }
                inst_addr += sizeof(TheGpuISA::RawMachInst);
                ++inst_idx;
            } else if (entryPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
                       entryPtr->kind < BRIG_KIND_OPERAND_END) {
                warn("unexpected operand entry in code segment\n");
            } else {
                // there are surely some more cases we will need to handle,
                // but we'll deal with them as we find them.
                fatal("unexpected directive kind %d inside kernel scope\n",
                      entryPtr->kind);
            }
        }

        entryPtr = brigNext(entryPtr);
    }

    // compute Control Flow Graph for current kernel
    ControlFlowInfo::assignImmediatePostDominators(instructions);

    max_sreg = SRegOperand::maxRegIdx;
    max_dreg = DRegOperand::maxRegIdx;
    max_creg = CRegOperand::maxRegIdx;

    obj->currentCode = nullptr;
}

HsailCode::HsailCode(const std::string &name_str,
                     const BrigDirectiveExecutable *code_dir,
                     const BrigObject *obj, StorageMap *objStorageMap)
    : HsaCode(name_str), private_size(-1), readonly_size(-1)
{
    init(code_dir, obj, objStorageMap);
}

void
LabelMap::addLabel(const Brig::BrigDirectiveLabel *lblDir, int inst_index,
                   const BrigObject *obj)
{
    std::string lbl_name = obj->getString(lblDir->name);
    Label &lbl = map[lbl_name];

    if (lbl.defined()) {
        fatal("Attempt to redefine existing label %s\n", lbl_name);
    }

    lbl.define(lbl_name, inst_index);
    DPRINTF(HSAILObject, "label %s = %d\n", lbl_name, inst_index);
}

Label*
LabelMap::refLabel(const Brig::BrigDirectiveLabel *lblDir,
                   const BrigObject *obj)
{
    std::string name = obj->getString(lblDir->name);
    Label &lbl = map[name];
    lbl.checkName(name);

    return &lbl;
}

int
getBrigDataTypeBytes(BrigType16_t t)
{
    switch (t) {
      case BRIG_TYPE_S8:
      case BRIG_TYPE_U8:
      case BRIG_TYPE_B8:
        return 1;

      case BRIG_TYPE_S16:
      case BRIG_TYPE_U16:
      case BRIG_TYPE_B16:
      case BRIG_TYPE_F16:
        return 2;

      case BRIG_TYPE_S32:
      case BRIG_TYPE_U32:
      case BRIG_TYPE_B32:
      case BRIG_TYPE_F32:
        return 4;

      case BRIG_TYPE_S64:
      case BRIG_TYPE_U64:
      case BRIG_TYPE_B64:
      case BRIG_TYPE_F64:
        return 8;

      case BRIG_TYPE_B1:

      default:
        fatal("unhandled symbol data type %d", t);
        return 0;
    }
}

StorageElement*
StorageSpace::addSymbol(const BrigDirectiveVariable *sym,
                        const BrigObject *obj)
{
    const char *sym_name = obj->getString(sym->name);
    uint64_t size = 0;
    uint64_t offset = 0;

    if (sym->type & BRIG_TYPE_ARRAY) {
        size = getBrigDataTypeBytes(sym->type & ~BRIG_TYPE_ARRAY);
        size *= (((uint64_t)sym->dim.hi) << 32 | (uint64_t)sym->dim.lo);

        offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type &
                         ~BRIG_TYPE_ARRAY));
    } else {
        size = getBrigDataTypeBytes(sym->type);
        offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type));
    }

    nextOffset = offset + size;

    DPRINTF(HSAILObject, "Adding SYMBOL %s size %d offset %#x, init: %d\n",
            sym_name, size, offset, sym->init);

    StorageElement* se = new StorageElement(sym_name, offset, size, sym);
    elements.push_back(se);
    elements_by_addr.insert(AddrRange(offset, offset + size - 1), se);
    elements_by_brigptr[sym] = se;

    return se;
}

StorageElement*
StorageSpace::findSymbol(std::string name)
{
    for (auto it : elements) {
        if (it->name == name) {
            return it;
        }
    }

    return nullptr;
}

StorageElement*
StorageSpace::findSymbol(uint64_t addr)
{
    assert(elements_by_addr.size() > 0);

    auto se = elements_by_addr.find(addr);

    if (se == elements_by_addr.end()) {
        return nullptr;
    } else {
        return se->second;
    }
}

StorageElement*
StorageSpace::findSymbol(const BrigDirectiveVariable *brigptr)
{
    assert(elements_by_brigptr.size() > 0);

    auto se = elements_by_brigptr.find(brigptr);

    if (se == elements_by_brigptr.end()) {
        return nullptr;
    } else {
        return se->second;
    }
}

StorageMap::StorageMap(StorageMap *outerScope)
    : outerScopeMap(outerScope)
{
    for (int i = 0; i < NumSegments; ++i)
        space[i] = new StorageSpace((BrigSegment)i);
}

StorageElement*
StorageMap::addSymbol(const BrigDirectiveVariable *sym, const BrigObject *obj)
{
    BrigSegment8_t segment = sym->segment;

    assert(segment >= Brig::BRIG_SEGMENT_FLAT);
    assert(segment < NumSegments);

    return space[segment]->addSymbol(sym, obj);
}

int
StorageMap::getSize(Brig::BrigSegment segment)
{
    assert(segment > Brig::BRIG_SEGMENT_GLOBAL);
    assert(segment < NumSegments);

    if (segment != Brig::BRIG_SEGMENT_GROUP &&
        segment != Brig::BRIG_SEGMENT_READONLY) {
        return space[segment]->getSize();
    } else {
        int ret = space[segment]->getSize();

        if (outerScopeMap) {
            ret += outerScopeMap->getSize(segment);
        }

        return ret;
    }
}

void
StorageMap::resetOffset(Brig::BrigSegment segment)
{
    space[segment]->resetOffset();
}

StorageElement*
StorageMap::findSymbol(BrigSegment segment, std::string name)
{
    StorageElement *se = space[segment]->findSymbol(name);

    if (se)
        return se;

    if (outerScopeMap)
        return outerScopeMap->findSymbol(segment, name);

    return nullptr;
}

StorageElement*
StorageMap::findSymbol(Brig::BrigSegment segment, uint64_t addr)
{
    StorageSpace *sp = space[segment];

    if (!sp) {
        // there is no memory in segment?
        return nullptr;
    }

    StorageElement *se = sp->findSymbol(addr);

    if (se)
        return se;

    if (outerScopeMap)
        return outerScopeMap->findSymbol(segment, addr);

    return nullptr;

}

StorageElement*
StorageMap::findSymbol(Brig::BrigSegment segment,
                       const BrigDirectiveVariable *brigptr)
{
    StorageSpace *sp = space[segment];

    if (!sp) {
        // there is no memory in segment?
        return nullptr;
    }

    StorageElement *se = sp->findSymbol(brigptr);

    if (se)
        return se;

    if (outerScopeMap)
        return outerScopeMap->findSymbol(segment, brigptr);

    return nullptr;

}
<commit_msg>hsail-x86: fix addr_range_map error<commit_after>/*
 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * For use for simulation and test purposes only
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Steve Reinhardt
 */

#include "gpu-compute/hsail_code.hh"

#include "arch/gpu_types.hh"
#include "arch/hsail/Brig.h"
#include "arch/hsail/operand.hh"
#include "config/the_gpu_isa.hh"
#include "debug/BRIG.hh"
#include "debug/HSAILObject.hh"
#include "gpu-compute/brig_object.hh"
#include "gpu-compute/gpu_static_inst.hh"
#include "gpu-compute/kernel_cfg.hh"

using namespace Brig;

int getBrigDataTypeBytes(BrigType16_t t);

HsailCode::HsailCode(const std::string &name_str)
    : HsaCode(name_str), private_size(-1), readonly_size(-1)
{
}

void
HsailCode::init(const BrigDirectiveExecutable *code_dir, const BrigObject *obj,
                StorageMap *objStorageMap)
{
    storageMap = objStorageMap;

    // set pointer so that decoding process can find this kernel context when
    // needed
    obj->currentCode = this;

    if (code_dir->base.kind != BRIG_KIND_DIRECTIVE_FUNCTION &&
        code_dir->base.kind != BRIG_KIND_DIRECTIVE_KERNEL) {
        fatal("unexpected directive kind %d inside kernel/function init\n",
              code_dir->base.kind);
    }

    DPRINTF(HSAILObject, "Initializing code, first code block entry is: %d\n",
            code_dir->firstCodeBlockEntry);

    // clear these static vars so we can properly track the max index
    // for this kernel
    SRegOperand::maxRegIdx = 0;
    DRegOperand::maxRegIdx = 0;
    CRegOperand::maxRegIdx = 0;
    setPrivateSize(0);

    const BrigBase *entryPtr = brigNext((BrigBase*)code_dir);
    const BrigBase *endPtr =
        obj->getCodeSectionEntry(code_dir->nextModuleEntry);

    // the instruction's byte address (relative to the base addr
    // of the code section)
    int inst_addr = 0;
    // the index that points to the instruction in the instruction
    // array
    int inst_idx = 0;
    std::vector<GPUStaticInst*> instructions;
    int funcarg_size_scope = 0;

    // walk through instructions in code section and directives in
    // directive section in parallel, processing directives that apply
    // when we reach the relevant code point.
    while (entryPtr < endPtr) {
        switch (entryPtr->kind) {
          case BRIG_KIND_DIRECTIVE_VARIABLE:
           {
                const BrigDirectiveVariable *sym =
                    (const BrigDirectiveVariable*)entryPtr;

                DPRINTF(HSAILObject,"Initializing code, directive is "
                        "kind_variable, symbol is: %s\n",
                        obj->getString(sym->name));

                StorageElement *se = storageMap->addSymbol(sym, obj);

                if (sym->segment == BRIG_SEGMENT_PRIVATE) {
                    setPrivateSize(se->size);
                } else { // spill
                    funcarg_size_scope += se->size;
                }
            }
            break;

          case BRIG_KIND_DIRECTIVE_LABEL:
            {
                const BrigDirectiveLabel *lbl =
                    (const BrigDirectiveLabel*)entryPtr;

                DPRINTF(HSAILObject,"Initializing code, directive is "
                        "kind_label, label is: %s \n",
                        obj->getString(lbl->name));

                labelMap.addLabel(lbl, inst_addr, obj);
            }
            break;

          case BRIG_KIND_DIRECTIVE_PRAGMA:
            {
                DPRINTF(HSAILObject, "Initializing code, directive "
                        "is kind_pragma\n");
            }
            break;

          case BRIG_KIND_DIRECTIVE_COMMENT:
            {
                DPRINTF(HSAILObject, "Initializing code, directive is "
                        "kind_comment\n");
            }
            break;

          case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
            {
                DPRINTF(HSAILObject, "Initializing code, directive is "
                        "kind_arg_block_start\n");

                storageMap->resetOffset(BRIG_SEGMENT_ARG);
                funcarg_size_scope = 0;
            }
            break;

          case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
            {
                DPRINTF(HSAILObject, "Initializing code, directive is "
                        "kind_arg_block_end\n");

                funcarg_size = funcarg_size < funcarg_size_scope ?
                                              funcarg_size_scope : funcarg_size;
            }
            break;

          case BRIG_KIND_DIRECTIVE_END:
            DPRINTF(HSAILObject, "Initializing code, dircetive is "
                    "kind_end\n");

            break;

          default:
            if (entryPtr->kind >= BRIG_KIND_INST_BEGIN &&
                entryPtr->kind <= BRIG_KIND_INST_END) {

                BrigInstBase *instPtr = (BrigInstBase*)entryPtr;
                TheGpuISA::MachInst machInst = { instPtr, obj };
                GPUStaticInst *iptr = decoder.decode(machInst);

                if (iptr) {
                    DPRINTF(HSAILObject, "Initializing code, processing inst "
                            "byte addr #%d idx %d: OPCODE=%d\n", inst_addr,
                            inst_idx, instPtr->opcode);

                    TheGpuISA::RawMachInst raw_inst = decoder.saveInst(iptr);
                    iptr->instNum(inst_idx);
                    iptr->instAddr(inst_addr);
                    _insts.push_back(raw_inst);
                    instructions.push_back(iptr);
                }
                inst_addr += sizeof(TheGpuISA::RawMachInst);
                ++inst_idx;
            } else if (entryPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
                       entryPtr->kind < BRIG_KIND_OPERAND_END) {
                warn("unexpected operand entry in code segment\n");
            } else {
                // there are surely some more cases we will need to handle,
                // but we'll deal with them as we find them.
                fatal("unexpected directive kind %d inside kernel scope\n",
                      entryPtr->kind);
            }
        }

        entryPtr = brigNext(entryPtr);
    }

    // compute Control Flow Graph for current kernel
    ControlFlowInfo::assignImmediatePostDominators(instructions);

    max_sreg = SRegOperand::maxRegIdx;
    max_dreg = DRegOperand::maxRegIdx;
    max_creg = CRegOperand::maxRegIdx;

    obj->currentCode = nullptr;
}

HsailCode::HsailCode(const std::string &name_str,
                     const BrigDirectiveExecutable *code_dir,
                     const BrigObject *obj, StorageMap *objStorageMap)
    : HsaCode(name_str), private_size(-1), readonly_size(-1)
{
    init(code_dir, obj, objStorageMap);
}

void
LabelMap::addLabel(const Brig::BrigDirectiveLabel *lblDir, int inst_index,
                   const BrigObject *obj)
{
    std::string lbl_name = obj->getString(lblDir->name);
    Label &lbl = map[lbl_name];

    if (lbl.defined()) {
        fatal("Attempt to redefine existing label %s\n", lbl_name);
    }

    lbl.define(lbl_name, inst_index);
    DPRINTF(HSAILObject, "label %s = %d\n", lbl_name, inst_index);
}

Label*
LabelMap::refLabel(const Brig::BrigDirectiveLabel *lblDir,
                   const BrigObject *obj)
{
    std::string name = obj->getString(lblDir->name);
    Label &lbl = map[name];
    lbl.checkName(name);

    return &lbl;
}

int
getBrigDataTypeBytes(BrigType16_t t)
{
    switch (t) {
      case BRIG_TYPE_S8:
      case BRIG_TYPE_U8:
      case BRIG_TYPE_B8:
        return 1;

      case BRIG_TYPE_S16:
      case BRIG_TYPE_U16:
      case BRIG_TYPE_B16:
      case BRIG_TYPE_F16:
        return 2;

      case BRIG_TYPE_S32:
      case BRIG_TYPE_U32:
      case BRIG_TYPE_B32:
      case BRIG_TYPE_F32:
        return 4;

      case BRIG_TYPE_S64:
      case BRIG_TYPE_U64:
      case BRIG_TYPE_B64:
      case BRIG_TYPE_F64:
        return 8;

      case BRIG_TYPE_B1:

      default:
        fatal("unhandled symbol data type %d", t);
        return 0;
    }
}

StorageElement*
StorageSpace::addSymbol(const BrigDirectiveVariable *sym,
                        const BrigObject *obj)
{
    const char *sym_name = obj->getString(sym->name);
    uint64_t size = 0;
    uint64_t offset = 0;

    if (sym->type & BRIG_TYPE_ARRAY) {
        size = getBrigDataTypeBytes(sym->type & ~BRIG_TYPE_ARRAY);
        size *= (((uint64_t)sym->dim.hi) << 32 | (uint64_t)sym->dim.lo);

        offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type &
                         ~BRIG_TYPE_ARRAY));
    } else {
        size = getBrigDataTypeBytes(sym->type);
        offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type));
    }

    nextOffset = offset + size;

    DPRINTF(HSAILObject, "Adding SYMBOL %s size %d offset %#x, init: %d\n",
            sym_name, size, offset, sym->init);

    StorageElement* se = new StorageElement(sym_name, offset, size, sym);
    elements.push_back(se);
    elements_by_addr.insert(AddrRange(offset, offset + size - 1), se);
    elements_by_brigptr[sym] = se;

    return se;
}

StorageElement*
StorageSpace::findSymbol(std::string name)
{
    for (auto it : elements) {
        if (it->name == name) {
            return it;
        }
    }

    return nullptr;
}

StorageElement*
StorageSpace::findSymbol(uint64_t addr)
{
    assert(elements_by_addr.size() > 0);

    auto se = elements_by_addr.contains(addr);

    if (se == elements_by_addr.end()) {
        return nullptr;
    } else {
        return se->second;
    }
}

StorageElement*
StorageSpace::findSymbol(const BrigDirectiveVariable *brigptr)
{
    assert(elements_by_brigptr.size() > 0);

    auto se = elements_by_brigptr.find(brigptr);

    if (se == elements_by_brigptr.end()) {
        return nullptr;
    } else {
        return se->second;
    }
}

StorageMap::StorageMap(StorageMap *outerScope)
    : outerScopeMap(outerScope)
{
    for (int i = 0; i < NumSegments; ++i)
        space[i] = new StorageSpace((BrigSegment)i);
}

StorageElement*
StorageMap::addSymbol(const BrigDirectiveVariable *sym, const BrigObject *obj)
{
    BrigSegment8_t segment = sym->segment;

    assert(segment >= Brig::BRIG_SEGMENT_FLAT);
    assert(segment < NumSegments);

    return space[segment]->addSymbol(sym, obj);
}

int
StorageMap::getSize(Brig::BrigSegment segment)
{
    assert(segment > Brig::BRIG_SEGMENT_GLOBAL);
    assert(segment < NumSegments);

    if (segment != Brig::BRIG_SEGMENT_GROUP &&
        segment != Brig::BRIG_SEGMENT_READONLY) {
        return space[segment]->getSize();
    } else {
        int ret = space[segment]->getSize();

        if (outerScopeMap) {
            ret += outerScopeMap->getSize(segment);
        }

        return ret;
    }
}

void
StorageMap::resetOffset(Brig::BrigSegment segment)
{
    space[segment]->resetOffset();
}

StorageElement*
StorageMap::findSymbol(BrigSegment segment, std::string name)
{
    StorageElement *se = space[segment]->findSymbol(name);

    if (se)
        return se;

    if (outerScopeMap)
        return outerScopeMap->findSymbol(segment, name);

    return nullptr;
}

StorageElement*
StorageMap::findSymbol(Brig::BrigSegment segment, uint64_t addr)
{
    StorageSpace *sp = space[segment];

    if (!sp) {
        // there is no memory in segment?
        return nullptr;
    }

    StorageElement *se = sp->findSymbol(addr);

    if (se)
        return se;

    if (outerScopeMap)
        return outerScopeMap->findSymbol(segment, addr);

    return nullptr;

}

StorageElement*
StorageMap::findSymbol(Brig::BrigSegment segment,
                       const BrigDirectiveVariable *brigptr)
{
    StorageSpace *sp = space[segment];

    if (!sp) {
        // there is no memory in segment?
        return nullptr;
    }

    StorageElement *se = sp->findSymbol(brigptr);

    if (se)
        return se;

    if (outerScopeMap)
        return outerScopeMap->findSymbol(segment, brigptr);

    return nullptr;

}
<|endoftext|>


<commit_before>/* Please refer to license.txt */

#include "window.hpp"

#include "../2d/2d.hpp"

#include <iostream>

#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/GLRenderer.h>

namespace GEngine
{

namespace mgfx
{

Window::Window()
{
	parent_d2d = nullptr;

	width = nullptr;
	height = nullptr;
	delete_width = false;
	delete_height = false;

	fullscreen = false;

	windowname = "";

	window2d = nullptr;
	event = nullptr;

	closed = true;
	can_close = true;

	focus = true;
}

Window::~Window()
{
	if (width) //If the width exists.
	{
		if (delete_width) //If it should be deleted.
		{
			delete width; //Delete it.
			width = nullptr; //Reset it.
		}
		else
		{
			width = nullptr; //Don't delete it, simply reset it.
		}
	}

	if (height) //If the height exists.
	{
		if (delete_height) //Delete it.
		{
			delete height; //Delete it.
			height = nullptr; //Reset it.
		}
		else
		{
			height = nullptr; //Don't delete it, only reset it.
		}
	}

	if (window2d) //If the 2d window exists.
	{
		window2d->close(); //Close the window.
		delete window2d; //Delete the window.
		window2d = nullptr; //Reset it.
	}

	if (event) //If the event exists.
	{
		delete event; //Delete it.
		event = nullptr; //Set to null.
	}
}

bool Window::create(int _width, int _height, bool _fullscreen, std::string _windowname, bool use_opengl)
{
	if (width) //Delete the width if it exists.
	{
		delete width;
	}
	width = new int; //Allocate memory for the width.
	delete_width = true; //The width is to be deleted.
	*width = _width; //Store the width.

	if (height) //Delete the height if it exists.
	{
		delete height;
	}
	height = new int; //Allocate memory for the height.
	delete_height = true; //The height is to be deleted.
	*height = _height; //Store the height.

	fullscreen = _fullscreen; //Store the fullscreen state.

	windowname = _windowname; //Store the window name.

	//TODO: Point the width and the height to the SFML window's width and height? Don't know if that's possible.
	window2d = new sf::RenderWindow; //Create a new (2d) window.

	if(fullscreen) //If it is to be fullscreen, do it.
	{
		window2d->create(sf::VideoMode(*width, *height), _windowname, sf::Style::Fullscreen); //Make the window fullscreen.
	}
	else
	{
		window2d->create(sf::VideoMode(*width, *height), _windowname, sf::Style::Default); //Nope, just a normal window.
	}

	closed = false; //Not closed.

	if (event) //If it already exists.
	{
		delete event; //Delete it.
	}
	event = new sf::Event; //Allocate memory for it.

	//TODO: Error checking?

	return true; //Success.
}

void Window::update()
{
	events.clear(); //Reset all events.

	if (!closed && window2d && event) //If the window is open, the window exists, and event exists.
	{
		while (window2d->pollEvent(*event)) //Poll events. //TODO: Give access to these events to the game.
		{
			if (event->type == sf::Event::Closed && can_close) //Check if the event is a window close.
			{
				window2d->close(); //Close the window.
				closed = true; //Update that it's closed.
			}
			else if (event->type == sf::Event::Resized && !closed && window2d) //Window resized. //TODO: Make a can_resize check.
			{
				window2d->setView(sf::View(sf::FloatRect(0, 0, event->size.width, event->size.height)));
				//CEGUI::Sizef size(event->size.width, event->size.height);
				//CEGUI::System::getSingleton().notifyDisplaySizeChanged(size); //Notify CEGUI of the changed size.
				//CEGUI::System::getSingleton().notifyDisplaySizeChanged(CEGUI::Sizef(event->size.width, event->size.height)); //Notify CEGUI of the changed size. //TODO: Notify the GUI context involved.
				if (parent_d2d && parent_d2d->cegui_renderer)
				{
					parent_d2d->cegui_renderer->setDisplaySize(CEGUI::Size<float>(event->size.width, event->size.height));
				}

				std::cout << "\n[GEngine::mgfx::Window::update()] Resized window.\n";
			}
			else if (event->type == sf::Event::LostFocus)
			{
				focus = false; //Lost focus.
			}
			else if (event->type == sf::Event::GainedFocus)
			{
				focus = true; //Gained focus.
			}
			else
			{
				events.push_back(*event); //Save the event for later processing.
			}
		}
	}
}
void Window::draw()
{
	if (!closed && window2d) //If the window was not closed.
	{
		window2d->display(); //Display the window.
		window2d->clear();
	}
}

int Window::getWidth()
{
	if (!window2d)
	{
		std::cout << "\nNo 2d window, fool.\n";
		return -1;
	}

	if (!width || !delete_width) //If width does not exist or if it should not be deleted (meaning it's pointing to some other int).
	{
		width = new int; //Allocate it.
		delete_width = true; //It will be deleted.
	}

	sf::Vector2u vector = window2d->getSize(); //Get the size.

	*width = vector.x; //Set/update the width.

	return *width; //Return the width.
}

int Window::getHeight()
{
	if (!window2d)
	{
		std::cout << "\nNo, seriously, there is no 2d window! Why don't you understand?\n";
		return -1;
	}

	if (!height || !delete_height) //If height does not exist or if it should not be deleted (meaning it's pointing to some other int).
	{
		height = new int; //Allocate it.
		delete_height = true; //It will be deleted.
	}

	sf::Vector2u vector = window2d->getSize(); //Get the size of the window.

	*height = vector.y; //Set/update the height.

	return *height; //Return the height.
}

int Window::getX()
{
	return window2d->getPosition().x;
	//return (using_opengl) ? /*3d*/window3d->getPosition().x /*window*/ : /*2d*/ window2d->getPosition().x /*window*/;
}

int Window::getY()
{
	return window2d->getPosition().y;
	//return (using_opengl) ? /*3d*/window3d->getPosition().y /*window*/ : /*2d*/ window2d->getPosition().y /*window*/;
}

void Window::drawSprite(mgfx::d2d::Sprite &sprite)
{
	if (!window2d)
	{
		std::cout << "\nAnd just what are you trying to achieve with a window that does not exist?\n";
		return;
	}

	window2d->draw(*sprite.sprite); //Draw the sprite.
}

void Window::renderText(std::string text, int _x, int _y, int font_size, sf::Font &font)
{
	sf::Text _text(text, font);
	_text.setCharacterSize(font_size);
	_text.setPosition(_x, _y);

	if (!window2d)
	{
		std::cout << "\nAnd just what are you trying to achieve with a 2D window that does not exist?\n";
		return;
	}
	window2d->pushGLStates();
	window2d->draw(_text);
	window2d->popGLStates();
}

void Window::setFramerateLimit(int fps)
{
	//Set the frames per second rate for the window.
	if (!window2d)
	{
		std::cout << "I can't set the framerate limit -- window2d doesn't exist!\n"; //Error.
		return; //Abort this function.
	}

	window2d->setFramerateLimit(fps);
}

void Window::showMouseCursor(bool show)
{
	//Set the frames per second rate for the window.
	if (!window2d)
	{
		std::cout << "I can't show or hide the mouse cursor -- window2d doesn't exist!\n"; //Error.
		return; //Abort this function.
	}

	window2d->setMouseCursorVisible(show);
}

void Window::setActive()
{
	window2d->setActive(true);
}

void Window::getMousePosition(int *x, int *y)
{
	if (window2d)
	{
		if (x)
			*x = sf::Mouse::getPosition(*window2d).x;
		if (y)
			*y = sf::Mouse::getPosition(*window2d).y;
	}
}

} //namespace mgfx

} //namespace GEngine.
<commit_msg> * Uh, forgot to commit this forever ago.<commit_after>/* Please refer to license.txt */

#include "window.hpp"

#include "../2d/2d.hpp"

#include <iostream>

#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/GLRenderer.h>

namespace GEngine
{

namespace mgfx
{

Window::Window()
{
	parent_d2d = nullptr;

	width = nullptr;
	height = nullptr;
	delete_width = false;
	delete_height = false;

	fullscreen = false;

	windowname = "";

	window2d = nullptr;
	event = nullptr;

	closed = true;
	can_close = true;

	focus = true;
}

Window::~Window()
{
	if (width) //If the width exists.
	{
		if (delete_width) //If it should be deleted.
		{
			delete width; //Delete it.
			width = nullptr; //Reset it.
		}
		else
		{
			width = nullptr; //Don't delete it, simply reset it.
		}
	}

	if (height) //If the height exists.
	{
		if (delete_height) //Delete it.
		{
			delete height; //Delete it.
			height = nullptr; //Reset it.
		}
		else
		{
			height = nullptr; //Don't delete it, only reset it.
		}
	}

	if (window2d) //If the 2d window exists.
	{
		window2d->close(); //Close the window.
		delete window2d; //Delete the window.
		window2d = nullptr; //Reset it.
	}

	if (event) //If the event exists.
	{
		delete event; //Delete it.
		event = nullptr; //Set to null.
	}
}

bool Window::create(int _width, int _height, bool _fullscreen, std::string _windowname, bool use_opengl)
{
	if (width) //Delete the width if it exists.
	{
		delete width;
	}
	width = new int; //Allocate memory for the width.
	delete_width = true; //The width is to be deleted.
	*width = _width; //Store the width.

	if (height) //Delete the height if it exists.
	{
		delete height;
	}
	height = new int; //Allocate memory for the height.
	delete_height = true; //The height is to be deleted.
	*height = _height; //Store the height.

	fullscreen = _fullscreen; //Store the fullscreen state.

	windowname = _windowname; //Store the window name.

	//TODO: Point the width and the height to the SFML window's width and height? Don't know if that's possible.
	window2d = new sf::RenderWindow; //Create a new (2d) window.

	if(fullscreen) //If it is to be fullscreen, do it.
	{
		window2d->create(sf::VideoMode(*width, *height), _windowname, sf::Style::Fullscreen); //Make the window fullscreen.
	}
	else
	{
		window2d->create(sf::VideoMode(*width, *height), _windowname, sf::Style::Default); //Nope, just a normal window.
	}

	closed = false; //Not closed.

	if (event) //If it already exists.
	{
		delete event; //Delete it.
	}
	event = new sf::Event; //Allocate memory for it.

	//TODO: Error checking?

	return true; //Success.
}

void Window::update()
{
	events.clear(); //Reset all events.

	if (!closed && window2d && event) //If the window is open, the window exists, and event exists.
	{
		while (window2d->pollEvent(*event)) //Poll events. //TODO: Give access to these events to the game.
		{
			if (event->type == sf::Event::Closed && can_close) //Check if the event is a window close.
			{
				window2d->close(); //Close the window.
				closed = true; //Update that it's closed.
			}
			else if (event->type == sf::Event::Resized && !closed && window2d) //Window resized. //TODO: Make a can_resize check.
			{
				window2d->setView(sf::View(sf::FloatRect(0, 0, event->size.width, event->size.height)));
				//CEGUI::Sizef size(event->size.width, event->size.height);
				//CEGUI::System::getSingleton().notifyDisplaySizeChanged(size); //Notify CEGUI of the changed size.
				//CEGUI::System::getSingleton().notifyDisplaySizeChanged(CEGUI::Sizef(event->size.width, event->size.height)); //Notify CEGUI of the changed size. //TODO: Notify the GUI context involved.
				if (parent_d2d && parent_d2d->cegui_renderer)
				{
					parent_d2d->cegui_renderer->setDisplaySize(CEGUI::Size<float>(event->size.width, event->size.height));
				}

				//TODO: Maybe I need to do a bunch of OpenGL calls?
				//TODO: At any rate, check out SFML's forums and wiki to see why it's not working properly. Maybe OpenGL mode needs special stuff.

				std::cout << "\n[GEngine::mgfx::Window::update()] Resized window.\n";
			}
			else if (event->type == sf::Event::LostFocus)
			{
				focus = false; //Lost focus.
			}
			else if (event->type == sf::Event::GainedFocus)
			{
				focus = true; //Gained focus.
			}
			else
			{
				events.push_back(*event); //Save the event for later processing.
			}
		}
	}
}
void Window::draw()
{
	if (!closed && window2d) //If the window was not closed.
	{
		window2d->display(); //Display the window.
		window2d->clear();
	}
}

int Window::getWidth()
{
	if (!window2d)
	{
		std::cout << "\nNo 2d window, fool.\n";
		return -1;
	}

	if (!width || !delete_width) //If width does not exist or if it should not be deleted (meaning it's pointing to some other int).
	{
		width = new int; //Allocate it.
		delete_width = true; //It will be deleted.
	}

	sf::Vector2u vector = window2d->getSize(); //Get the size.

	*width = vector.x; //Set/update the width.

	return *width; //Return the width.
}

int Window::getHeight()
{
	if (!window2d)
	{
		std::cout << "\nNo, seriously, there is no 2d window! Why don't you understand?\n";
		return -1;
	}

	if (!height || !delete_height) //If height does not exist or if it should not be deleted (meaning it's pointing to some other int).
	{
		height = new int; //Allocate it.
		delete_height = true; //It will be deleted.
	}

	sf::Vector2u vector = window2d->getSize(); //Get the size of the window.

	*height = vector.y; //Set/update the height.

	return *height; //Return the height.
}

int Window::getX()
{
	return window2d->getPosition().x;
	//return (using_opengl) ? /*3d*/window3d->getPosition().x /*window*/ : /*2d*/ window2d->getPosition().x /*window*/;
}

int Window::getY()
{
	return window2d->getPosition().y;
	//return (using_opengl) ? /*3d*/window3d->getPosition().y /*window*/ : /*2d*/ window2d->getPosition().y /*window*/;
}

void Window::drawSprite(mgfx::d2d::Sprite &sprite)
{
	if (!window2d)
	{
		std::cout << "\nAnd just what are you trying to achieve with a window that does not exist?\n";
		return;
	}

	window2d->draw(*sprite.sprite); //Draw the sprite.
}

void Window::renderText(std::string text, int _x, int _y, int font_size, sf::Font &font)
{
	sf::Text _text(text, font);
	_text.setCharacterSize(font_size);
	_text.setPosition(_x, _y);

	if (!window2d)
	{
		std::cout << "\nAnd just what are you trying to achieve with a 2D window that does not exist?\n";
		return;
	}
	window2d->pushGLStates();
	window2d->draw(_text);
	window2d->popGLStates();
}

void Window::setFramerateLimit(int fps)
{
	//Set the frames per second rate for the window.
	if (!window2d)
	{
		std::cout << "I can't set the framerate limit -- window2d doesn't exist!\n"; //Error.
		return; //Abort this function.
	}

	window2d->setFramerateLimit(fps);
}

void Window::showMouseCursor(bool show)
{
	//Set the frames per second rate for the window.
	if (!window2d)
	{
		std::cout << "I can't show or hide the mouse cursor -- window2d doesn't exist!\n"; //Error.
		return; //Abort this function.
	}

	window2d->setMouseCursorVisible(show);
}

void Window::setActive()
{
	window2d->setActive(true);
}

void Window::getMousePosition(int *x, int *y)
{
	if (window2d)
	{
		if (x)
			*x = sf::Mouse::getPosition(*window2d).x;
		if (y)
			*y = sf::Mouse::getPosition(*window2d).y;
	}
}

} //namespace mgfx

} //namespace GEngine.
<|endoftext|>


<commit_before>#include "graphics/textureAtlas.h"
#include "graphics/opengl.h"
#include "textureManager.h"
#include <algorithm>

namespace sp {

AtlasTexture::AtlasTexture(glm::ivec2 size)
{
    texture_size = size;
    available_areas.push_back({{0, 0}, {size.x, size.y}});
    gl_handle = 0;
    smooth = textureManager.isDefaultSmoothFiltering();
}

AtlasTexture::~AtlasTexture()
{
    if (gl_handle)
        glDeleteTextures(1, &gl_handle);
}

void AtlasTexture::bind()
{
    if (gl_handle == 0)
    {
        glGenTextures(1, &gl_handle);
        glBindTexture(GL_TEXTURE_2D, gl_handle);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_size.x, texture_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
        //Put 1 white pixel in the {1,1} corner, which we can use to draw solid things.
        glm::u8vec4 white{255,255,255,255};
        glTexSubImage2D(GL_TEXTURE_2D, 0, texture_size.x - 1, texture_size.y - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &white);
    }
    else
    {
        glBindTexture(GL_TEXTURE_2D, gl_handle);
    }

    if (!add_list.empty())
    {
        for(auto& add_item : add_list)
            glTexSubImage2D(GL_TEXTURE_2D, 0, add_item.position.x, add_item.position.y, add_item.image.getSize().x, add_item.image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, add_item.image.getPtr());

        add_list.clear();
    }
}

bool AtlasTexture::canAdd(const Image& image, int margin)
{
    glm::ivec2 size = image.getSize() + glm::ivec2(margin * 2, margin * 2);
    for(int n=int(available_areas.size()) - 1; n >= 0; n--)
    {
        if (available_areas[n].size.x >= size.x && available_areas[n].size.y >= size.y)
            return true;
    }
    return false;
}

Rect AtlasTexture::add(Image&& image, int margin)
{
    glm::ivec2 size = image.getSize() + glm::ivec2(margin * 2, margin * 2);
    for(int n=int(available_areas.size()) - 1; n >= 0; n--)
    {
        if (available_areas[n].size.x >= size.x && available_areas[n].size.y >= size.y)
        {
            //Suitable area found, grab it, cut it, and put it in a stew.
            RectInt full_area = available_areas[n];
            available_areas.erase(available_areas.begin() + n);

            if (full_area.size.x <= full_area.size.y)
            {
                //Split horizontal
                addArea({{full_area.position.x + size.x, full_area.position.y}, {full_area.size.x - size.x, size.y}});
                addArea({{full_area.position.x, full_area.position.y + size.y}, {full_area.size.x, full_area.size.y - size.y}});
            }
            else
            {
                //Split vertical
                addArea({{full_area.position.x + size.x, full_area.position.y}, {full_area.size.x - size.x, full_area.size.y}});
                addArea({{full_area.position.x, full_area.position.y + size.y}, {size.x, full_area.size.y - size.y}});
            }

            if (image.getSize().x > 0 && image.getSize().y > 0)
            {
                add_list.emplace_back();
                add_list.back().image = std::move(image);
                add_list.back().position.x = full_area.position.x + margin;
                add_list.back().position.y = full_area.position.y + margin;
            }

            return Rect(
                float(full_area.position.x + margin) / float(texture_size.x), float(full_area.position.y + margin) / float(texture_size.y),
                float(size.x - margin * 2) / float(texture_size.x), float(size.y - margin * 2) / float(texture_size.y));
        }
    }
    return Rect(0, 0, -1, -1);
}

float AtlasTexture::usageRate()
{
    int all_texture_volume = texture_size.x * texture_size.y;
    int unused_texture_volume = 0;
    for(auto& area : available_areas)
        unused_texture_volume += area.size.x * area.size.y;
    return float(all_texture_volume - unused_texture_volume) / float(all_texture_volume);
}

void AtlasTexture::addArea(RectInt area)
{
    //Ignore really slim areas, they are never really used and use up a lot of room in the available_areas otherwise.
    if (area.size.x < 4 || area.size.y < 4)
        return;
    int area_volume = area.size.x * area.size.y;
    auto it = std::lower_bound(available_areas.begin(), available_areas.end(), area_volume, [](const RectInt& r, int volume) -> bool
    {
        return r.size.x * r.size.y > volume;
    });
    available_areas.insert(it, area);
}

}//namespace sp
<commit_msg>Initialize atlas textures with default transparent black instead of undefined data. (which is white on some GPUs)<commit_after>#include "graphics/textureAtlas.h"
#include "graphics/opengl.h"
#include "textureManager.h"
#include <algorithm>

namespace sp {

AtlasTexture::AtlasTexture(glm::ivec2 size)
{
    texture_size = size;
    available_areas.push_back({{0, 0}, {size.x, size.y}});
    gl_handle = 0;
    smooth = textureManager.isDefaultSmoothFiltering();
}

AtlasTexture::~AtlasTexture()
{
    if (gl_handle)
        glDeleteTextures(1, &gl_handle);
}

void AtlasTexture::bind()
{
    if (gl_handle == 0)
    {
        glGenTextures(1, &gl_handle);
        glBindTexture(GL_TEXTURE_2D, gl_handle);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST);

        std::vector<glm::u8vec4> initial_data;
        initial_data.resize(texture_size.x * texture_size.y, {0, 0, 0, 0});
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_size.x, texture_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, initial_data.data());
        //Put 1 white pixel in the {1,1} corner, which we can use to draw solid things.
        glm::u8vec4 white{255,255,255,255};
        glTexSubImage2D(GL_TEXTURE_2D, 0, texture_size.x - 1, texture_size.y - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &white);
    }
    else
    {
        glBindTexture(GL_TEXTURE_2D, gl_handle);
    }

    if (!add_list.empty())
    {
        for(auto& add_item : add_list)
            glTexSubImage2D(GL_TEXTURE_2D, 0, add_item.position.x, add_item.position.y, add_item.image.getSize().x, add_item.image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, add_item.image.getPtr());

        add_list.clear();
    }
}

bool AtlasTexture::canAdd(const Image& image, int margin)
{
    glm::ivec2 size = image.getSize() + glm::ivec2(margin * 2, margin * 2);
    for(int n=int(available_areas.size()) - 1; n >= 0; n--)
    {
        if (available_areas[n].size.x >= size.x && available_areas[n].size.y >= size.y)
            return true;
    }
    return false;
}

Rect AtlasTexture::add(Image&& image, int margin)
{
    glm::ivec2 size = image.getSize() + glm::ivec2(margin * 2, margin * 2);
    for(int n=int(available_areas.size()) - 1; n >= 0; n--)
    {
        if (available_areas[n].size.x >= size.x && available_areas[n].size.y >= size.y)
        {
            //Suitable area found, grab it, cut it, and put it in a stew.
            RectInt full_area = available_areas[n];
            available_areas.erase(available_areas.begin() + n);

            if (full_area.size.x <= full_area.size.y)
            {
                //Split horizontal
                addArea({{full_area.position.x + size.x, full_area.position.y}, {full_area.size.x - size.x, size.y}});
                addArea({{full_area.position.x, full_area.position.y + size.y}, {full_area.size.x, full_area.size.y - size.y}});
            }
            else
            {
                //Split vertical
                addArea({{full_area.position.x + size.x, full_area.position.y}, {full_area.size.x - size.x, full_area.size.y}});
                addArea({{full_area.position.x, full_area.position.y + size.y}, {size.x, full_area.size.y - size.y}});
            }

            if (image.getSize().x > 0 && image.getSize().y > 0)
            {
                add_list.emplace_back();
                add_list.back().image = std::move(image);
                add_list.back().position.x = full_area.position.x + margin;
                add_list.back().position.y = full_area.position.y + margin;
            }

            return Rect(
                float(full_area.position.x + margin) / float(texture_size.x), float(full_area.position.y + margin) / float(texture_size.y),
                float(size.x - margin * 2) / float(texture_size.x), float(size.y - margin * 2) / float(texture_size.y));
        }
    }
    return Rect(0, 0, -1, -1);
}

float AtlasTexture::usageRate()
{
    int all_texture_volume = texture_size.x * texture_size.y;
    int unused_texture_volume = 0;
    for(auto& area : available_areas)
        unused_texture_volume += area.size.x * area.size.y;
    return float(all_texture_volume - unused_texture_volume) / float(all_texture_volume);
}

void AtlasTexture::addArea(RectInt area)
{
    //Ignore really slim areas, they are never really used and use up a lot of room in the available_areas otherwise.
    if (area.size.x < 4 || area.size.y < 4)
        return;
    int area_volume = area.size.x * area.size.y;
    auto it = std::lower_bound(available_areas.begin(), available_areas.end(), area_volume, [](const RectInt& r, int volume) -> bool
    {
        return r.size.x * r.size.y > volume;
    });
    available_areas.insert(it, area);
}

}//namespace sp
<|endoftext|>


<commit_before>#include "packagemanagerplugin.h"
#include "dbsettings.h"

PackageManagerPlugin::PackageManagerPlugin(QObject *parent) :
	QObject(parent)
{}

void PackageManagerPlugin::initialize()
{

}

bool PackageManagerPlugin::startGuiInstall(const QStringList &packages)
{
	Q_UNUSED(packages);
	return false;
}

bool PackageManagerPlugin::startGuiUninstall(const QStringList &packages)
{
	Q_UNUSED(packages);
	return false;
}

QSettings *PackageManagerPlugin::createSyncedSettings(QObject *parent) const
{
	auto settings = DbSettings::create(parent);
	settings->beginGroup(QStringLiteral("plugins/%1")
						 .arg(QString::fromUtf8(metaObject()->className())));
	return settings;
}

QSettings *PackageManagerPlugin::createLocalSettings(QObject *parent) const
{
	auto settings = new QSettings(parent);
	settings->beginGroup(QStringLiteral("plugins/%1")
						 .arg(QString::fromUtf8(metaObject()->className())));
	return settings;
}

void PackageManagerPlugin::settingsChanged() {}

QVariant PackageManagerPlugin::settingsValue(QSettings *settings, const QString &key) const
{
	if(!settings->contains(key)) {
		foreach(auto info, listSettings()) {
			if(info.settingsKeys == key)
				return info.defaultValue;
		}
		return QVariant();
	} else
		return settings->value(key);
}

PackageManagerPlugin::SettingsInfo::SettingsInfo(QString displayName, QString description, QString settingsKeys, int type, QVariant defaultValue, QByteArray widgetClassName) :
	displayName(displayName),
	description(description),
	settingsKeys(settingsKeys),
	type(type),
	defaultValue(defaultValue),
	widgetClassName(widgetClassName)
{

}
<commit_msg>combobocConfig<commit_after>#include "packagemanagerplugin.h"
#include "dbsettings.h"
#include "comboboxconfig.h"

PackageManagerPlugin::PackageManagerPlugin(QObject *parent) :
	QObject(parent)
{}

void PackageManagerPlugin::initialize()
{

}

bool PackageManagerPlugin::startGuiInstall(const QStringList &packages)
{
	Q_UNUSED(packages);
	return false;
}

bool PackageManagerPlugin::startGuiUninstall(const QStringList &packages)
{
	Q_UNUSED(packages);
	return false;
}

QSettings *PackageManagerPlugin::createSyncedSettings(QObject *parent) const
{
	auto settings = DbSettings::create(parent);
	settings->beginGroup(QStringLiteral("plugins/%1")
						 .arg(QString::fromUtf8(metaObject()->className())));
	return settings;
}

QSettings *PackageManagerPlugin::createLocalSettings(QObject *parent) const
{
	auto settings = new QSettings(parent);
	settings->beginGroup(QStringLiteral("plugins/%1")
						 .arg(QString::fromUtf8(metaObject()->className())));
	return settings;
}

void PackageManagerPlugin::settingsChanged() {}

QVariant PackageManagerPlugin::settingsValue(QSettings *settings, const QString &key) const
{
	if(!settings->contains(key)) {
		foreach(auto info, listSettings()) {
			if(info.settingsKeys == key){
				if(qMetaTypeId<ComboboxConfig>() == info.defaultValue.userType())
					return info.defaultValue.value<ComboboxConfig>().defaultValue;
				else
					return info.defaultValue;
			}
		}
		return QVariant();
	} else
		return settings->value(key);
}

PackageManagerPlugin::SettingsInfo::SettingsInfo(QString displayName, QString description, QString settingsKeys, int type, QVariant defaultValue, QByteArray widgetClassName) :
	displayName(displayName),
	description(description),
	settingsKeys(settingsKeys),
	type(type),
	defaultValue(defaultValue),
	widgetClassName(widgetClassName)
{

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008 James Molloy, JÃ¶rg PfÃ¤hler, Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <Log.h>
#include <Debugger.h>
#include <processor/PageFaultHandler.h>
#include <process/Scheduler.h>
#include <panic.h>
#include <processor/PhysicalMemoryManager.h>

PageFaultHandler PageFaultHandler::m_Instance;

#define PAGE_FAULT_EXCEPTION  0x0E
#define PFE_PAGE_PRESENT      0x01
#define PFE_ATTEMPTED_WRITE   0x02
#define PFE_USER_MODE         0x04
#define PFE_RESERVED_BIT      0x08
#define PFE_INSTRUCTION_FETCH 0x10

bool PageFaultHandler::initialise()
{
  InterruptManager &IntManager = InterruptManager::instance();

  return(IntManager.registerInterruptHandler(PAGE_FAULT_EXCEPTION, this));
}

void PageFaultHandler::interrupt(size_t interruptNumber, InterruptState &state)
{
  uint32_t cr2, code;
  asm volatile("mov %%cr2, %%eax" : "=a" (cr2));
  code = state.m_Errorcode;

  uintptr_t page = cr2 & ~(PhysicalMemoryManager::instance().getPageSize()-1);

  // Check for copy-on-write.
  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
  if (va.isMapped(reinterpret_cast<void*>(page)))
  {
    physical_uintptr_t phys;
    size_t flags;
    va.getMapping(reinterpret_cast<void*>(page), phys, flags);
    if (flags & VirtualAddressSpace::CopyOnWrite)
    {
#if 0
      static uint8_t buffer[PhysicalMemoryManager::instance().getPageSize()];
      memcpy(buffer, reinterpret_cast<uint8_t*>(page), PhysicalMemoryManager::instance().getPageSize());

      // Now that we've saved the page content, we can make a new physical page and map it.
      physical_uintptr_t p = PhysicalMemoryManager::instance().allocatePage();
      if (!p)
      {
        FATAL("PageFaultHandler: Out of memory!");
        return;
      }
      va.unmap(reinterpret_cast<void*>(page));
      if (!va.map(p, reinterpret_cast<void*>(page), VirtualAddressSpace::Write))
      {
        FATAL("PageFaultHandler: map() failed.");
        return;
      }
      memcpy(reinterpret_cast<uint8_t*>(page), buffer, PhysicalMemoryManager::instance().getPageSize());
      return;
#endif
    }
  }

  if (cr2 < 0xc0000000)
  {
      // Check our handler list.
      for (List<MemoryTrapHandler*>::Iterator it = m_Handlers.begin();
           it != m_Handlers.end();
           it++)
      {
          if ((*it)->trap(cr2, code & PFE_ATTEMPTED_WRITE))
          {
              return;
          }
      }
  }

  //  Get PFE location and error code
  static LargeStaticString sError;
  sError.clear();
  sError.append("Page Fault Exception at 0x");
  sError.append(cr2, 16, 8, '0');
  sError.append(", error code 0x");
  sError.append(code, 16, 8, '0');
  sError.append(", EIP 0x");
  sError.append(state.getInstructionPointer(), 16, 8, '0');

  //  Extract error code information
  static LargeStaticString sCode;
  sCode.clear();
  sCode.append("Details: PID=");
  sCode.append(Processor::information().getCurrentThread()->getParent()->getId());
  sCode.append(" ");

  if(!(code & PFE_PAGE_PRESENT)) sCode.append("NOT ");
  sCode.append("PRESENT | ");

  if(code & PFE_ATTEMPTED_WRITE)
    sCode.append("WRITE | ");
  else
    sCode.append("READ | ");

  if(code & PFE_USER_MODE) sCode.append("USER "); else sCode.append("KERNEL ");
  sCode.append("MODE | ");

  if(code & PFE_RESERVED_BIT) sCode.append("RESERVED BIT SET | ");
  if(code & PFE_INSTRUCTION_FETCH) sCode.append("FETCH |");

  // Ensure the log spinlock isn't going to die on us...
//  Log::instance().m_Lock.release();

  ERROR_NOLOCK(static_cast<const char*>(sError));
  ERROR_NOLOCK(static_cast<const char*>(sCode));

  //static LargeStaticString eCode;
  #ifdef DEBUGGER
    uintptr_t physAddr = 0, flags = 0;
    if(va.isMapped(reinterpret_cast<void*>(state.getInstructionPointer())))
        va.getMapping(reinterpret_cast<void*>(state.getInstructionPointer()), physAddr, flags);

    // Page faults in usermode are usually useless to debug in the debugger (some exceptions exist)
    if(!(code & PFE_USER_MODE))
        Debugger::instance().start(state, sError);
  #endif

  Scheduler &scheduler = Scheduler::instance();
  if(UNLIKELY(scheduler.getNumProcesses() == 0))
  {
    //  We are in the early stages of the boot process (no processes started)
    panic(sError);
  }
  else
  {
    //  Unrecoverable PFE in a process - Kill the process and yield
    //Processor::information().getCurrentThread()->getParent()->kill();
    Thread *pThread = Processor::information().getCurrentThread();
    Process *pProcess = pThread->getParent();
    Subsystem *pSubsystem = pProcess->getSubsystem();
    if(pSubsystem)
        pSubsystem->threadException(pThread, Subsystem::PageFault, state);
    else
        pProcess->kill();

    //  kill member function also calls yield(), so shouldn't get here.
    for(;;) ;
  }

  //  Currently, no code paths return from a PFE.
}

PageFaultHandler::PageFaultHandler() :
    m_Handlers()
{
}
<commit_msg>Replaced a hardcoded constant in the x86 PageFaultHandler with a defined constant.<commit_after>/*
 * Copyright (c) 2008 James Molloy, JÃ¶rg PfÃ¤hler, Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <Log.h>
#include <Debugger.h>
#include <processor/PageFaultHandler.h>
#include <process/Scheduler.h>
#include <panic.h>
#include <processor/PhysicalMemoryManager.h>
#include "VirtualAddressSpace.h"

PageFaultHandler PageFaultHandler::m_Instance;

#define PAGE_FAULT_EXCEPTION  0x0E
#define PFE_PAGE_PRESENT      0x01
#define PFE_ATTEMPTED_WRITE   0x02
#define PFE_USER_MODE         0x04
#define PFE_RESERVED_BIT      0x08
#define PFE_INSTRUCTION_FETCH 0x10

bool PageFaultHandler::initialise()
{
  InterruptManager &IntManager = InterruptManager::instance();

  return(IntManager.registerInterruptHandler(PAGE_FAULT_EXCEPTION, this));
}

void PageFaultHandler::interrupt(size_t interruptNumber, InterruptState &state)
{
  uint32_t cr2, code;
  asm volatile("mov %%cr2, %%eax" : "=a" (cr2));
  code = state.m_Errorcode;

  uintptr_t page = cr2 & ~(PhysicalMemoryManager::instance().getPageSize()-1);

  // Check for copy-on-write.
  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
  if (va.isMapped(reinterpret_cast<void*>(page)))
  {
    physical_uintptr_t phys;
    size_t flags;
    va.getMapping(reinterpret_cast<void*>(page), phys, flags);
    if (flags & VirtualAddressSpace::CopyOnWrite)
    {
#if 0
      static uint8_t buffer[PhysicalMemoryManager::instance().getPageSize()];
      memcpy(buffer, reinterpret_cast<uint8_t*>(page), PhysicalMemoryManager::instance().getPageSize());

      // Now that we've saved the page content, we can make a new physical page and map it.
      physical_uintptr_t p = PhysicalMemoryManager::instance().allocatePage();
      if (!p)
      {
        FATAL("PageFaultHandler: Out of memory!");
        return;
      }
      va.unmap(reinterpret_cast<void*>(page));
      if (!va.map(p, reinterpret_cast<void*>(page), VirtualAddressSpace::Write))
      {
        FATAL("PageFaultHandler: map() failed.");
        return;
      }
      memcpy(reinterpret_cast<uint8_t*>(page), buffer, PhysicalMemoryManager::instance().getPageSize());
      return;
#endif
    }
  }

  if (cr2 < reinterpret_cast<uintptr_t>(KERNEL_SPACE_START))
  {
      // Check our handler list.
      for (List<MemoryTrapHandler*>::Iterator it = m_Handlers.begin();
           it != m_Handlers.end();
           it++)
      {
          if ((*it)->trap(cr2, code & PFE_ATTEMPTED_WRITE))
          {
              return;
          }
      }
  }

  //  Get PFE location and error code
  static LargeStaticString sError;
  sError.clear();
  sError.append("Page Fault Exception at 0x");
  sError.append(cr2, 16, 8, '0');
  sError.append(", error code 0x");
  sError.append(code, 16, 8, '0');
  sError.append(", EIP 0x");
  sError.append(state.getInstructionPointer(), 16, 8, '0');

  //  Extract error code information
  static LargeStaticString sCode;
  sCode.clear();
  sCode.append("Details: PID=");
  sCode.append(Processor::information().getCurrentThread()->getParent()->getId());
  sCode.append(" ");

  if(!(code & PFE_PAGE_PRESENT)) sCode.append("NOT ");
  sCode.append("PRESENT | ");

  if(code & PFE_ATTEMPTED_WRITE)
    sCode.append("WRITE | ");
  else
    sCode.append("READ | ");

  if(code & PFE_USER_MODE) sCode.append("USER "); else sCode.append("KERNEL ");
  sCode.append("MODE | ");

  if(code & PFE_RESERVED_BIT) sCode.append("RESERVED BIT SET | ");
  if(code & PFE_INSTRUCTION_FETCH) sCode.append("FETCH |");

  // Ensure the log spinlock isn't going to die on us...
//  Log::instance().m_Lock.release();

  ERROR_NOLOCK(static_cast<const char*>(sError));
  ERROR_NOLOCK(static_cast<const char*>(sCode));

  //static LargeStaticString eCode;
  #ifdef DEBUGGER
    uintptr_t physAddr = 0, flags = 0;
    if(va.isMapped(reinterpret_cast<void*>(state.getInstructionPointer())))
        va.getMapping(reinterpret_cast<void*>(state.getInstructionPointer()), physAddr, flags);

    // Page faults in usermode are usually useless to debug in the debugger (some exceptions exist)
    if(!(code & PFE_USER_MODE))
        Debugger::instance().start(state, sError);
  #endif

  Scheduler &scheduler = Scheduler::instance();
  if(UNLIKELY(scheduler.getNumProcesses() == 0))
  {
    //  We are in the early stages of the boot process (no processes started)
    panic(sError);
  }
  else
  {
    //  Unrecoverable PFE in a process - Kill the process and yield
    //Processor::information().getCurrentThread()->getParent()->kill();
    Thread *pThread = Processor::information().getCurrentThread();
    Process *pProcess = pThread->getParent();
    Subsystem *pSubsystem = pProcess->getSubsystem();
    if(pSubsystem)
        pSubsystem->threadException(pThread, Subsystem::PageFault, state);
    else
        pProcess->kill();

    //  kill member function also calls yield(), so shouldn't get here.
    for(;;) ;
  }

  //  Currently, no code paths return from a PFE.
}

PageFaultHandler::PageFaultHandler() :
    m_Handlers()
{
}
<|endoftext|>


<commit_before>/** @file gsFunctionExpr.hpp

    @brief Provides implementation of FunctionExpr class.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Mantzaflaris
*/

#pragma once

#include <gsCore/gsLinearAlgebra.h>

#include <exprtk.hpp>// External file

namespace gismo
{

template<typename T> class gsFunctionExprPrivate
{
public:
  T vars[6]; // const members can change this
  exprtk::symbol_table<T> symbol_table;
  exprtk::expression<T> expression;
  exprtk::expression<T> der_exp[6];
  bool der_flag[6];
  std::string  string;
  int dim;
};

template<typename T>
gsFunctionExpr<T>::gsFunctionExpr() : my(new gsFunctionExprPrivate<T>) {};

template<typename T>
gsFunctionExpr<T>::gsFunctionExpr(std::string expression_string) : my(new gsFunctionExprPrivate<T>)
{
    // Keep string data
    my->string = expression_string;
    my->string.erase(std::remove(my->string.begin(),my->string.end(),' '),my->string.end());
    stringReplace(my->string, "**", "^");
    init();
}

template<typename T>
gsFunctionExpr<T>::gsFunctionExpr(const gsFunctionExpr& other)
{
  my = new gsFunctionExprPrivate<T>;
  my->string = other.my->string;
  init();
}

template<typename T>
gsFunctionExpr<T>& gsFunctionExpr<T>::operator=(const gsFunctionExpr& other)
    {
      if (this != &other)
      {
        my->string = other.my->string;
        init();
      }
      return *this;
    }

template<typename T>
gsFunctionExpr<T>::~gsFunctionExpr()
	{
	    delete my;
	}

template<typename T>
void gsFunctionExpr<T>::init()
{

        my->symbol_table.clear();
        my->expression.release();

        // Identify symbol table
        my->symbol_table.add_variable("x",my->vars[0]);
        my->symbol_table.add_variable("y",my->vars[1]);
        my->symbol_table.add_variable("z",my->vars[2]);
        my->symbol_table.add_variable("w",my->vars[3]);
        my->symbol_table.add_variable("u",my->vars[4]);
        my->symbol_table.add_variable("v",my->vars[5]);
        //my->symbol_table.remove_variable("w",my->vars[3]);
        my->symbol_table.add_pi();
        //my->symbol_table.add_constant("C", 1);
        my->expression.register_symbol_table( my->symbol_table);

        exprtk::parser<T> parser;
        parser.cache_symbols() = true;
        bool success = parser.compile(my->string, my->expression);
        if ( ! success )
            std::cout<<"gsFunctionExpr error: " <<parser.error() <<std::endl;

        std::vector<std::string> varlist;
        parser.expression_symbols(varlist);
        varlist.erase(std::remove(varlist.begin(), varlist.end(), "pi"), varlist.end());
        my->dim = varlist.size();

        my->der_flag[0]=false;
        my->der_flag[1]=false;
        my->der_flag[2]=false;
        my->der_flag[3]=false;
        my->der_flag[4]=false;
        my->der_flag[5]=false;
}

template<typename T>
int gsFunctionExpr<T>::domainDim() const
{
   return my->dim;
}

template<typename T>
void gsFunctionExpr<T>::set_x (T const & v) const { my->vars[0]= v; }

template<typename T>
void gsFunctionExpr<T>::set_y (T const & v) const { my->vars[1]= v; }

template<typename T>
void gsFunctionExpr<T>::set_z (T const & v) const { my->vars[2]= v; }

template<typename T>
void gsFunctionExpr<T>::set_w (T const & v) const { my->vars[3]= v; }

template<typename T>
void gsFunctionExpr<T>::set_u (T const & v) const { my->vars[4]= v; }

template<typename T>
void gsFunctionExpr<T>::set_v (T const & v) const { my->vars[5]= v; }

template<typename T>
void gsFunctionExpr<T>::set_x_der (std::string expression_string)
{
    my->der_exp[0].register_symbol_table(my->symbol_table);
    exprtk::parser<T> parser;
    bool success = parser.compile(expression_string, my->der_exp[0] );
    if ( ! success )
	std::cout<<"gsFunctionExpr set_x_der(.) error: " <<parser.error() <<std::endl;
    else
	my->der_flag[0]=true;
} ;

template<typename T>
void gsFunctionExpr<T>::set_y_der (std::string expression_string)
{
    my->der_exp[1].register_symbol_table(my->symbol_table);
    exprtk::parser<T> parser;
    bool success = parser.compile(expression_string, my->der_exp[1] );
    if ( ! success )
	std::cout<<"gsFunctionExpr set_x_der(.) error: " <<parser.error() <<std::endl;
    else
	my->der_flag[1]=true;
} ;

template<typename T>
void gsFunctionExpr<T>::eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    GISMO_ASSERT ( u.rows() < 7 && u.rows() > 0, "Inconsistent point size." );

    result.resize(1, u.cols());
    for ( int i = 0; i<u.cols(); i++ )
    {
        for ( int j = 0; j<u.rows(); j++ )
        {
            my->vars[j] =u(j,i);
        }
        result(0,i) = my->expression.value();
    }
}
template<typename T>
void gsFunctionExpr<T>::eval_component_into(const gsMatrix<T>& u, const index_t comp, gsMatrix<T>& result) const
{
    GISMO_ASSERT (comp == 0, "Given component number is too high. Only one component");
    result.resize(1, u.cols());
    for ( int i = 0; i<u.cols(); i++ )
    {
        for ( int j = 0; j<u.rows(); j++ )
        {
            my->vars[j] =u(j,i);
        }
        result(0,i) = my->expression.value();
    }
}

template<typename T>
void gsFunctionExpr<T>::deriv_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    int n = u.rows();
    GISMO_ASSERT ( u.rows() < 7 && u.rows() > 0, "Inconsistent point size." );

    result.resize(1, n * u.cols());

    for( int i=0; i < u.cols(); ++i )
    {
        for ( int j = 0; j<n; j++ )
            my->vars[j] =u(j,i);
        for( int j=0; j< n; ++j )
            if ( my->der_flag[j] )
                result(n*i+j) = my->der_exp[j].value();
            else
                result(n*i+j) = exprtk::derivative<T>( my->expression, my->vars[j], 0.00001 ) ;
    }
}

template<typename T>
typename gsFunction<T>::uMatrixPtr
gsFunctionExpr<T>::hess(const gsMatrix<T>& u, unsigned coord) const
{
    GISMO_ENSURE(coord == 0, "Error, function is real");
    // one column only..
    int n = u.rows();
    GISMO_ASSERT ( u.rows() < 7 && u.rows() > 0, "Inconsistent point size." );

    gsMatrix<T> * res= new gsMatrix<T>(n,n) ;

    for ( int j = 0; j<n; j++ )
	my->vars[j] =u(j,0);
    for( int j=0; j< n; ++j )
    {
	(*res)(j,j) = exprtk::second_derivative<T>( my->expression, my->vars[j], 0.00001 ) ;
	for( int k=0; k<j; ++k )
	    (*res)(k,j) = (*res)(j,k) =
		exprtk::mixed_derivative<T>( my->expression, my->vars[k], my->vars[j], 0.00001 ) ;
    }
    return typename gsFunction<T>::uMatrixPtr(res);
} ;
template<typename T>
gsMatrix<T> * gsFunctionExpr<T>::mderiv(const gsMatrix<T>& u, const index_t &k, const index_t &j ) const
{
    gsMatrix<T> * res= new gsMatrix<T>(1,u.cols()) ;

    for( index_t i=0; i< res->cols(); ++i )
    {
      	for ( int t = 0; t<u.rows(); t++ )
	    my->vars[t] =u(t,i);
      	    (*res)(0,i) =
		exprtk::mixed_derivative<T>( my->expression, my->vars[k], my->vars[j], 0.00001 ) ;
    }
    return  res;
} ;

template<typename T>
gsMatrix<T> * gsFunctionExpr<T>::laplacian(const gsMatrix<T>& u) const
{
    gsMatrix<T> * res= new gsMatrix<T>(1,u.cols()) ;
    res->setZero();
    int n = u.rows();

    for( index_t i=0; i< res->cols(); ++i )
	for ( int j = 0; j<n; j++ )
	{
	    my->vars[j] =u(j,i);
	    (*res)(0,i) +=
		exprtk::second_derivative<T>( my->expression, my->vars[j], 0.00001 ) ;
	}
    return  res;
}

template<typename T>
T gsFunctionExpr<T>::value() const
{
return my->expression.value() ;
}

template<typename T>
std::ostream & gsFunctionExpr<T>::print(std::ostream &os) const
{ os << my->string ; return os; }

}; // namespace gismo
<commit_msg>update exprtk<commit_after>/** @file gsFunctionExpr.hpp

    @brief Provides implementation of FunctionExpr class.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Mantzaflaris
*/

#pragma once

#include <gsCore/gsLinearAlgebra.h>

#include <exprtk.hpp>// External file

namespace gismo
{

template<typename T> class gsFunctionExprPrivate
{
public:
    T vars[6];
    exprtk::symbol_table<T> symbol_table;
    exprtk::expression<T> expression;
    exprtk::expression<T> der_exp[6];
    bool der_flag[6];
    std::string  string;
    int dim;
};

/* / /AM: under construction
template<typename T> class gsSymbolListPrivate
{
public:
    exprtk::symbol_table<T> symbol_table;
    std::vector<T> vars  ;
    std::vector<T> params;
};

template<typename T>
gsSymbolList<T>::gsSymbolList() : my(new gsSymbolListPrivate<T>) {}

template<typename T>
gsSymbolList<T>::~gsSymbolList()
{
delete my;
}

template<typename T>
void gsSymbolList<T>::setDefault()
{
    my->symbol_table.clear();

    // Identify symbol table
    my->symbol_table.add_variable("x",my->vars[0]);
    my->symbol_table.add_variable("y",my->vars[1]);
    my->symbol_table.add_variable("z",my->vars[2]);
    my->symbol_table.add_variable("w",my->vars[3]);
    my->symbol_table.add_variable("u",my->vars[4]);
    my->symbol_table.add_variable("v",my->vars[5]);
    //my->symbol_table.remove_variable("w",my->vars[3]);
    my->symbol_table.add_pi();
    //my->symbol_table.add_constant("C", 1);
}

template<typename T>
bool gsSymbolList<T>::addConstant(const std::string & constant_name, const T& value)
{
return my->symbol_table.add_constant(constant_name, value);
}

template<typename T>
bool gsSymbolList<T>::addVariable(const std::string & variable_name)
{
    my->vars.push_back(0.0);
    return my->symbol_table.add_variable(variable_name, my->vars.back() );
}

template<typename T>
bool gsSymbolList<T>::addParameter(const std::string & variable_name)
{
    my->params.push_back(0.0);
    return my->symbol_table.add_variable(variable_name, my->params.back() );
}

template<typename T>
bool gsSymbolList<T>::hasSymbol(const std::string& symbol_name)
{
return true;
}
//*/

template<typename T>
gsFunctionExpr<T>::gsFunctionExpr() : my(new gsFunctionExprPrivate<T>) {}

template<typename T>
gsFunctionExpr<T>::gsFunctionExpr(std::string expression_string, int ddim)
: my(new gsFunctionExprPrivate<T>)
{
    // Keep string data
    my->string = expression_string;
    my->string.erase(std::remove(my->string.begin(),my->string.end(),' '),my->string.end());
    stringReplace(my->string, "**", "^");
    my->dim = ddim;
    init();
}

template<typename T>
gsFunctionExpr<T>::gsFunctionExpr(const gsFunctionExpr& other)
{
    my = new gsFunctionExprPrivate<T>;
    my->string = other.my->string;
    init();
}

template<typename T>
gsFunctionExpr<T>& gsFunctionExpr<T>::operator=(const gsFunctionExpr& other)
{
    if (this != &other)
    {
        my->string = other.my->string;
        init();
    }
    return *this;
}

template<typename T>
gsFunctionExpr<T>::~gsFunctionExpr()
{
    delete my;
}

// template<typename T>
// void gsFunctionExpr<T>::init(variables,constants)

template<typename T>
void gsFunctionExpr<T>::init()
{
    my->symbol_table.clear();
    my->expression.release();

    // Identify symbol table
    my->symbol_table.add_variable("x",my->vars[0]);
    my->symbol_table.add_variable("y",my->vars[1]);
    my->symbol_table.add_variable("z",my->vars[2]);
    my->symbol_table.add_variable("w",my->vars[3]);
    my->symbol_table.add_variable("u",my->vars[4]);
    my->symbol_table.add_variable("v",my->vars[5]);
    //my->symbol_table.remove_variable("w",my->vars[3]);
    my->symbol_table.add_pi();
    //my->symbol_table.add_constant("C", 1);
    my->expression.register_symbol_table(my->symbol_table);

    exprtk::parser<T> parser;
    //parser.cache_symbols() = true;
    bool success = parser.compile(my->string, my->expression);
    if ( ! success )
        std::cout<<"gsFunctionExpr error: " <<parser.error() <<std::endl;

/*
    AM: Changed in recent versions.
    std::vector<std::string> varlist;
    parser.expression_symbols(varlist);
    varlist.erase(std::remove(varlist.begin(), varlist.end(), "pi"), varlist.end());
    my->dim = varlist.size();
*/

    my->der_flag[0]=false;
    my->der_flag[1]=false;
    my->der_flag[2]=false;
    my->der_flag[3]=false;
    my->der_flag[4]=false;
    my->der_flag[5]=false;
}

template<typename T>
int gsFunctionExpr<T>::domainDim() const
{
    return my->dim;
}

template<typename T>
void gsFunctionExpr<T>::set_x (T const & v) const { my->vars[0]= v; }

template<typename T>
void gsFunctionExpr<T>::set_y (T const & v) const { my->vars[1]= v; }

template<typename T>
void gsFunctionExpr<T>::set_z (T const & v) const { my->vars[2]= v; }

template<typename T>
void gsFunctionExpr<T>::set_w (T const & v) const { my->vars[3]= v; }

template<typename T>
void gsFunctionExpr<T>::set_u (T const & v) const { my->vars[4]= v; }

template<typename T>
void gsFunctionExpr<T>::set_v (T const & v) const { my->vars[5]= v; }

template<typename T>
void gsFunctionExpr<T>::set_x_der (std::string expression_string)
{
    my->der_exp[0].register_symbol_table(my->symbol_table);
    exprtk::parser<T> parser;
    bool success = parser.compile(expression_string, my->der_exp[0] );
    if ( ! success )
        std::cout<<"gsFunctionExpr set_x_der(.) error: " <<parser.error() <<std::endl;
    else
        my->der_flag[0]=true;
}

template<typename T>
void gsFunctionExpr<T>::set_y_der (std::string expression_string)
{
    my->der_exp[1].register_symbol_table(my->symbol_table);
    exprtk::parser<T> parser;
    bool success = parser.compile(expression_string, my->der_exp[1] );
    if ( ! success )
        std::cout<<"gsFunctionExpr set_x_der(.) error: " <<parser.error() <<std::endl;
    else
        my->der_flag[1]=true;
}

template<typename T>
void gsFunctionExpr<T>::eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    GISMO_ASSERT ( u.rows() < 7 && u.rows() > 0, "Inconsistent point size." );

    result.resize(1, u.cols());
    for ( int i = 0; i<u.cols(); i++ )
    {
        for ( int j = 0; j<u.rows(); j++ )
        {
            my->vars[j] =u(j,i);
        }
        result(0,i) = my->expression.value();
    }
}

template<typename T>
void gsFunctionExpr<T>::eval_component_into(const gsMatrix<T>& u, const index_t comp, gsMatrix<T>& result) const
{
    GISMO_ASSERT (comp == 0, "Given component number is too high. Only one component");
    result.resize(1, u.cols());
    for ( int i = 0; i<u.cols(); i++ )
    {
        for ( int j = 0; j<u.rows(); j++ )
        {
            my->vars[j] =u(j,i);
        }
        result(0,i) = my->expression.value();
    }
}

template<typename T>
void gsFunctionExpr<T>::deriv_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
{
    int n = u.rows();
    GISMO_ASSERT ( u.rows() < 7 && u.rows() > 0, "Inconsistent point size." );

    result.resize(1, n * u.cols());

    for( int i=0; i < u.cols(); ++i )
    {
        for ( int j = 0; j<n; j++ )
            my->vars[j] =u(j,i);
        for( int j=0; j< n; ++j )
            if ( my->der_flag[j] )
                result(n*i+j) = my->der_exp[j].value();
            else
                result(n*i+j) = exprtk::derivative<T>( my->expression, my->vars[j], 0.00001 ) ;
    }
}

template<typename T>
typename gsFunction<T>::uMatrixPtr
gsFunctionExpr<T>::hess(const gsMatrix<T>& u, unsigned coord) const
{
    GISMO_ENSURE(coord == 0, "Error, function is real");
    // one column only..
    int n = u.rows();
    GISMO_ASSERT ( u.rows() < 7 && u.rows() > 0, "Inconsistent point size." );

    gsMatrix<T> * res= new gsMatrix<T>(n,n) ;

    for ( int j = 0; j<n; j++ )
        my->vars[j] =u(j,0);
    for( int j=0; j< n; ++j )
    {
        (*res)(j,j) = exprtk::second_derivative<T>( my->expression, my->vars[j], 0.00001 ) ;
        for( int k=0; k<j; ++k )
            (*res)(k,j) = (*res)(j,k) =
                exprtk::mixed_derivative<T>( my->expression, my->vars[k], my->vars[j], 0.00001 ) ;
    }
    return typename gsFunction<T>::uMatrixPtr(res);
} ;
template<typename T>
gsMatrix<T> * gsFunctionExpr<T>::mderiv(const gsMatrix<T>& u, const index_t &k, const index_t &j ) const
{
    gsMatrix<T> * res= new gsMatrix<T>(1,u.cols()) ;

    for( index_t i=0; i< res->cols(); ++i )
    {
      	for ( int t = 0; t<u.rows(); t++ )
            my->vars[t] =u(t,i);
        (*res)(0,i) =
            exprtk::mixed_derivative<T>( my->expression, my->vars[k], my->vars[j], 0.00001 ) ;
    }
    return  res;
} ;

template<typename T>
gsMatrix<T> * gsFunctionExpr<T>::laplacian(const gsMatrix<T>& u) const
{
    gsMatrix<T> * res= new gsMatrix<T>(1,u.cols()) ;
    res->setZero();
    int n = u.rows();

    for( index_t i=0; i< res->cols(); ++i )
        for ( int j = 0; j<n; j++ )
        {
            my->vars[j] =u(j,i);
            (*res)(0,i) +=
                exprtk::second_derivative<T>( my->expression, my->vars[j], 0.00001 ) ;
        }
    return  res;
}

template<typename T>
T gsFunctionExpr<T>::value() const
{
    return my->expression.value() ;
}

template<typename T>
std::ostream & gsFunctionExpr<T>::print(std::ostream &os) const
{ os << my->string ; return os; }

}; // namespace gismo
<|endoftext|>