<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_constant_expression.cpp
 * Evaluate and process constant valued expressions
 *
 * In GLSL, constant valued expressions are used in several places.  These
 * must be processed and evaluated very early in the compilation process.
 *
 *    * Sizes of arrays
 *    * Initializers for uniforms
 *    * Initializers for \c const variables
 */

#define NULL 0
#include "ir.h"
#include "ir_visitor.h"
#include "glsl_types.h"

/**
 * Visitor class for evaluating constant expressions
 */
class ir_constant_visitor : public ir_visitor {
public:
   ir_constant_visitor()
      : value(NULL)
   {
      /* empty */
   }

   virtual ~ir_constant_visitor()
   {
      /* empty */
   }

   /**
    * \name Visit methods
    *
    * As typical for the visitor pattern, there must be one \c visit method for
    * each concrete subclass of \c ir_instruction.  Virtual base classes within
    * the hierarchy should not have \c visit methods.
    */
   /*@{*/
   virtual void visit(ir_variable *);
   virtual void visit(ir_label *);
   virtual void visit(ir_function_signature *);
   virtual void visit(ir_function *);
   virtual void visit(ir_expression *);
   virtual void visit(ir_swizzle *);
   virtual void visit(ir_dereference *);
   virtual void visit(ir_assignment *);
   virtual void visit(ir_constant *);
   virtual void visit(ir_call *);
   virtual void visit(ir_return *);
   virtual void visit(ir_if *);
   /*@}*/

   /**
    * Value of the constant expression.
    *
    * \note
    * This field will be \c NULL if the expression is not constant valued.
    */
   /* FINIHSME: This cannot hold values for constant arrays or structures. */
   ir_constant *value;
};

ir_constant *
ir_instruction::constant_expression_value()
{
   ir_constant_visitor visitor;

   this->accept(& visitor);
   return visitor.value;
}

void
ir_constant_visitor::visit(ir_variable *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_label *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_function_signature *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_function *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_expression *ir)
{
   value = NULL;
   ir_constant *op[2];
   unsigned int operand, c;
   unsigned u[16];
   int i[16];
   float f[16];
   bool b[16];
   const glsl_type *type = NULL;

   for (operand = 0; operand < ir->get_num_operands(); operand++) {
      op[operand] = ir->operands[operand]->constant_expression_value();
      if (!op[operand])
	 return;
   }

   switch (ir->operation) {
   case ir_unop_logic_not:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = !op[0]->value.b[c];
      break;
   case ir_binop_add:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] + op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] + op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] + op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_sub:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] - op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] - op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] - op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_mul:
      if (ir->operands[0]->type == ir->operands[1]->type &&
	  !ir->operands[0]->type->is_matrix()) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] * op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] * op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] * op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_div:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] / op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] / op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] / op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_logic_and:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = op[0]->value.b[c] && op[1]->value.b[c];
      break;
   case ir_binop_logic_xor:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
      break;
   case ir_binop_logic_or:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = op[0]->value.b[c] || op[1]->value.b[c];
      break;

   case ir_binop_less:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] < op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] < op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] < op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;
   case ir_binop_greater:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] > op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] > op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] > op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;
   case ir_binop_lequal:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;
   case ir_binop_gequal:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;

   case ir_binop_equal:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = glsl_type::bool_type;
	 b[0] = true;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       b[0] = b[0] && op[0]->value.u[c] == op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       b[0] = b[0] && op[0]->value.i[c] == op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       b[0] = b[0] && op[0]->value.f[c] == op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_nequal:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = glsl_type::bool_type;
	 b[0] = false;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       b[0] = b[0] || op[0]->value.u[c] != op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       b[0] = b[0] || op[0]->value.i[c] != op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       b[0] = b[0] || op[0]->value.f[c] != op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;

   default:
      break;
   }

   if (type) {
      switch (type->base_type) {
      case GLSL_TYPE_UINT:
	 value = new ir_constant(type, u);
	 break;
      case GLSL_TYPE_INT:
	 value = new ir_constant(type, i);
	 break;
      case GLSL_TYPE_FLOAT:
	 value = new ir_constant(type, f);
	 break;
      case GLSL_TYPE_BOOL:
	 value = new ir_constant(type, b);
	 break;
      }
   }
}

void
ir_constant_visitor::visit(ir_swizzle *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_dereference *ir)
{
   value = NULL;

   if (ir->mode == ir_dereference::ir_reference_variable) {
      ir_variable *var = ir->var->as_variable();
      if (var && var->constant_value) {
	 value = new ir_constant(ir->type, &var->constant_value->value);
      }
   }
   /* FINISHME: Other dereference modes. */
}

void
ir_constant_visitor::visit(ir_assignment *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_constant *ir)
{
   value = ir;
}

void
ir_constant_visitor::visit(ir_call *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_return *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_if *ir)
{
   (void) ir;
   value = NULL;
}
<commit_msg>Add float/int conversion to ir_constant_expression.cpp.<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_constant_expression.cpp
 * Evaluate and process constant valued expressions
 *
 * In GLSL, constant valued expressions are used in several places.  These
 * must be processed and evaluated very early in the compilation process.
 *
 *    * Sizes of arrays
 *    * Initializers for uniforms
 *    * Initializers for \c const variables
 */

#define NULL 0
#include "ir.h"
#include "ir_visitor.h"
#include "glsl_types.h"

/**
 * Visitor class for evaluating constant expressions
 */
class ir_constant_visitor : public ir_visitor {
public:
   ir_constant_visitor()
      : value(NULL)
   {
      /* empty */
   }

   virtual ~ir_constant_visitor()
   {
      /* empty */
   }

   /**
    * \name Visit methods
    *
    * As typical for the visitor pattern, there must be one \c visit method for
    * each concrete subclass of \c ir_instruction.  Virtual base classes within
    * the hierarchy should not have \c visit methods.
    */
   /*@{*/
   virtual void visit(ir_variable *);
   virtual void visit(ir_label *);
   virtual void visit(ir_function_signature *);
   virtual void visit(ir_function *);
   virtual void visit(ir_expression *);
   virtual void visit(ir_swizzle *);
   virtual void visit(ir_dereference *);
   virtual void visit(ir_assignment *);
   virtual void visit(ir_constant *);
   virtual void visit(ir_call *);
   virtual void visit(ir_return *);
   virtual void visit(ir_if *);
   /*@}*/

   /**
    * Value of the constant expression.
    *
    * \note
    * This field will be \c NULL if the expression is not constant valued.
    */
   /* FINIHSME: This cannot hold values for constant arrays or structures. */
   ir_constant *value;
};

ir_constant *
ir_instruction::constant_expression_value()
{
   ir_constant_visitor visitor;

   this->accept(& visitor);
   return visitor.value;
}

void
ir_constant_visitor::visit(ir_variable *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_label *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_function_signature *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_function *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_expression *ir)
{
   value = NULL;
   ir_constant *op[2];
   unsigned int operand, c;
   unsigned u[16];
   int i[16];
   float f[16];
   bool b[16];
   const glsl_type *type = NULL;

   for (operand = 0; operand < ir->get_num_operands(); operand++) {
      op[operand] = ir->operands[operand]->constant_expression_value();
      if (!op[operand])
	 return;
   }

   switch (ir->operation) {
   case ir_unop_logic_not:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = !op[0]->value.b[c];
      break;

   case ir_unop_f2i:
      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
      type = ir->type;
      for (c = 0; c < ir->operands[0]->type->components(); c++) {
	 i[c] = op[0]->value.f[c];
      }
      break;
   case ir_unop_i2f:
      assert(op[0]->type->base_type == GLSL_TYPE_UINT ||
	     op[0]->type->base_type == GLSL_TYPE_INT);
      type = ir->type;
      for (c = 0; c < ir->operands[0]->type->components(); c++) {
	 if (op[0]->type->base_type == GLSL_TYPE_INT)
	    f[c] = op[0]->value.i[c];
	 else
	    f[c] = op[0]->value.u[c];
      }
      break;

   case ir_binop_add:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] + op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] + op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] + op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_sub:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] - op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] - op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] - op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_mul:
      if (ir->operands[0]->type == ir->operands[1]->type &&
	  !ir->operands[0]->type->is_matrix()) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] * op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] * op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] * op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_div:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = ir->operands[0]->type;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       u[c] = op[0]->value.u[c] / op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       i[c] = op[0]->value.i[c] / op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       f[c] = op[0]->value.f[c] / op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_logic_and:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = op[0]->value.b[c] && op[1]->value.b[c];
      break;
   case ir_binop_logic_xor:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
      break;
   case ir_binop_logic_or:
      type = ir->operands[0]->type;
      assert(type->base_type == GLSL_TYPE_BOOL);
      for (c = 0; c < ir->operands[0]->type->components(); c++)
	 b[c] = op[0]->value.b[c] || op[1]->value.b[c];
      break;

   case ir_binop_less:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] < op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] < op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] < op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;
   case ir_binop_greater:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] > op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] > op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] > op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;
   case ir_binop_lequal:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;
   case ir_binop_gequal:
      type = glsl_type::bool_type;
      switch (ir->operands[0]->type->base_type) {
      case GLSL_TYPE_UINT:
	 b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
	 break;
      case GLSL_TYPE_INT:
	 b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
	 break;
      case GLSL_TYPE_FLOAT:
	 b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
	 break;
      default:
	 assert(0);
      }
      break;

   case ir_binop_equal:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = glsl_type::bool_type;
	 b[0] = true;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       b[0] = b[0] && op[0]->value.u[c] == op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       b[0] = b[0] && op[0]->value.i[c] == op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       b[0] = b[0] && op[0]->value.f[c] == op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;
   case ir_binop_nequal:
      if (ir->operands[0]->type == ir->operands[1]->type) {
	 type = glsl_type::bool_type;
	 b[0] = false;
	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
	    switch (ir->operands[0]->type->base_type) {
	    case GLSL_TYPE_UINT:
	       b[0] = b[0] || op[0]->value.u[c] != op[1]->value.u[c];
	       break;
	    case GLSL_TYPE_INT:
	       b[0] = b[0] || op[0]->value.i[c] != op[1]->value.i[c];
	       break;
	    case GLSL_TYPE_FLOAT:
	       b[0] = b[0] || op[0]->value.f[c] != op[1]->value.f[c];
	       break;
	    default:
	       assert(0);
	    }
	 }
      }
      break;

   default:
      break;
   }

   if (type) {
      switch (type->base_type) {
      case GLSL_TYPE_UINT:
	 value = new ir_constant(type, u);
	 break;
      case GLSL_TYPE_INT:
	 value = new ir_constant(type, i);
	 break;
      case GLSL_TYPE_FLOAT:
	 value = new ir_constant(type, f);
	 break;
      case GLSL_TYPE_BOOL:
	 value = new ir_constant(type, b);
	 break;
      }
   }
}

void
ir_constant_visitor::visit(ir_swizzle *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_dereference *ir)
{
   value = NULL;

   if (ir->mode == ir_dereference::ir_reference_variable) {
      ir_variable *var = ir->var->as_variable();
      if (var && var->constant_value) {
	 value = new ir_constant(ir->type, &var->constant_value->value);
      }
   }
   /* FINISHME: Other dereference modes. */
}

void
ir_constant_visitor::visit(ir_assignment *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_constant *ir)
{
   value = ir;
}

void
ir_constant_visitor::visit(ir_call *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_return *ir)
{
   (void) ir;
   value = NULL;
}

void
ir_constant_visitor::visit(ir_if *ir)
{
   (void) ir;
   value = NULL;
}
<|endoftext|>


<commit_before>/*  -*- mode: C++; c-file-style: "gnu" -*-
 *
 *  This file is part of KMail, the KDE mail client.
 *
 *  Copyright (c) 2002-2003 Carsten Pfeiffer <pfeiffer@kde.org>
 *  Copyright (c) 2003      Zack Rusin <zack@kde.org>
 *
 *  KMail is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License, version 2, as
 *  published by the Free Software Foundation.
 *
 *  KMail is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of this program with any edition of
 *  the Qt library by Trolltech AS, Norway (or with modified versions
 *  of Qt that use the same license as Qt), and distribute linked
 *  combinations including the two.  You must obey the GNU General
 *  Public License in all respects for all of the code used other than
 *  Qt.  If you modify this file, you may extend this exception to
 *  your version of the file, but you are not obligated to do so.  If
 *  you do not wish to do so, delete this exception statement from
 *  your version.
 */
#include "mailsourceviewer.h"
#include <QApplication>
#include <QIcon>
#include <kwindowsystem.h>

#include <QRegExp>
#include <QShortcut>
#include <kiconloader.h>

namespace KMail {

void MailSourceHighlighter::highlightBlock ( const QString & text ) {
  QRegExp regexp( "^([\\w-]+:\\s)" );
  if( regexp.indexIn( text ) != -1 ) {
    QFont font = document()->defaultFont ();
    font.setBold( true );
    setFormat( 0, regexp.matchedLength(), font );
  }
}

MailSourceViewer::MailSourceViewer( QWidget *parent )
  : KTextBrowser( parent ), mSourceHighLighter( 0 )
{
  setAttribute( Qt::WA_DeleteOnClose );
  setLineWrapMode( QTextEdit::NoWrap );
  setTextInteractionFlags( Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard );

  // combining the shortcuts in one qkeysequence() did not work...
  QShortcut* shortcut = new QShortcut( this );
  shortcut->setKey( Qt::Key_Escape );
  connect( shortcut, SIGNAL( activated() ), SLOT( close() ) );

  shortcut = new QShortcut( this );
  shortcut->setKey( Qt::Key_W+Qt::CTRL );
  connect( shortcut, SIGNAL( activated() ), SLOT( close() ) );
  KWindowSystem::setIcons( winId(),
                  qApp->windowIcon().pixmap( IconSize( KIconLoader::Desktop ),
                  IconSize( KIconLoader::Desktop ) ),
                  qApp->windowIcon().pixmap( IconSize( KIconLoader::Small ),
                  IconSize( KIconLoader::Small ) ) );
  mSourceHighLighter = new MailSourceHighlighter( this );
}

MailSourceViewer::~MailSourceViewer()
{
  delete mSourceHighLighter; mSourceHighLighter = 0;
}

}
<commit_msg>BUG: 88271 BUG: 152707<commit_after>/*  -*- mode: C++; c-file-style: "gnu" -*-
 *
 *  This file is part of KMail, the KDE mail client.
 *
 *  Copyright (c) 2002-2003 Carsten Pfeiffer <pfeiffer@kde.org>
 *  Copyright (c) 2003      Zack Rusin <zack@kde.org>
 *
 *  KMail is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License, version 2, as
 *  published by the Free Software Foundation.
 *
 *  KMail is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of this program with any edition of
 *  the Qt library by Trolltech AS, Norway (or with modified versions
 *  of Qt that use the same license as Qt), and distribute linked
 *  combinations including the two.  You must obey the GNU General
 *  Public License in all respects for all of the code used other than
 *  Qt.  If you modify this file, you may extend this exception to
 *  your version of the file, but you are not obligated to do so.  If
 *  you do not wish to do so, delete this exception statement from
 *  your version.
 */
#include "mailsourceviewer.h"
#include <QApplication>
#include <QIcon>
#include <kwindowsystem.h>

#include <QRegExp>
#include <QShortcut>
#include <kiconloader.h>

namespace KMail {

void MailSourceHighlighter::highlightBlock ( const QString & text ) {
  // all visible ascii except space and :
  const QRegExp regexp( "^([\\x21-9;-\\x7E]+:\\s)" );
  const int headersState = -1; // Also the initial State
  const int bodyState = 0;

  // keep the previous state
  setCurrentBlockState( previousBlockState() );
  // If a header is found
  if( regexp.indexIn( text ) != -1 )
  {
    // Content- header starts a new mime part, and therefore new headers
    // If a Content-* header is found, change State to headers until a blank line is found.
    if ( text.startsWith( "Content-" ) )
    {
      setCurrentBlockState( headersState );
    }
    // highligth it if in headers state
    if( ( currentBlockState() == headersState ) )
    {
      QFont font = document()->defaultFont ();
      font.setBold( true );
      setFormat( 0, regexp.matchedLength(), font );
    }
  }
  // Change to body state
  else if (text.isEmpty())
  {
    setCurrentBlockState( bodyState );
  }
}

MailSourceViewer::MailSourceViewer( QWidget *parent )
  : KTextBrowser( parent ), mSourceHighLighter( 0 )
{
  setAttribute( Qt::WA_DeleteOnClose );
  setLineWrapMode( QTextEdit::NoWrap );
  setTextInteractionFlags( Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard );

  // combining the shortcuts in one qkeysequence() did not work...
  QShortcut* shortcut = new QShortcut( this );
  shortcut->setKey( Qt::Key_Escape );
  connect( shortcut, SIGNAL( activated() ), SLOT( close() ) );

  shortcut = new QShortcut( this );
  shortcut->setKey( Qt::Key_W+Qt::CTRL );
  connect( shortcut, SIGNAL( activated() ), SLOT( close() ) );
  KWindowSystem::setIcons( winId(),
                  qApp->windowIcon().pixmap( IconSize( KIconLoader::Desktop ),
                  IconSize( KIconLoader::Desktop ) ),
                  qApp->windowIcon().pixmap( IconSize( KIconLoader::Small ),
                  IconSize( KIconLoader::Small ) ) );
  mSourceHighLighter = new MailSourceHighlighter( this );
}

MailSourceViewer::~MailSourceViewer()
{
  delete mSourceHighLighter; mSourceHighLighter = 0;
}

}
<|endoftext|>


<commit_before>/***************************************************************************
 *  The Kernel-Machine Library                                             *
 *  Copyright (C) 2004, 2005 by Rutger W. ter Borg                         *
 *                                                                         *
 *  This program is free software; you can redistribute it and/or          *
 *  modify it under the terms of the GNU General Public License            *
 *  as published by the Free Software Foundation; either version 2         *
 *  of the License, or (at your option) any later version.                 *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program; if not, write to the Free Software            *
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307  *
 ***************************************************************************/

#ifndef ONLINE_DETERMINATE_HPP
#define ONLINE_DETERMINATE_HPP

#include <boost/call_traits.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <kml/determinate.hpp>

namespace kml {

template< typename Input,typename Output,template<typename,int> class Kernel >
class online_determinate: public determinate<Input,Output,Kernel> {
public:
    typedef Kernel<Input,0> kernel_type;
    typedef typename kernel_result<kernel_type>::type result_type;
    typedef determinate<Input,Output,Kernel> base_type;
    typedef Input input_type;
    typedef Output output_type;

    // constructor
    online_determinate( typename boost::call_traits<kernel_type>::param_type k ):
    base_type::determinate(k)	{}

    // works for any Single Pass Range
    template<typename InputRange, typename OutputRange>
    void learn( InputRange const &input, OutputRange const &output ) {
        typename boost::range_const_iterator<InputRange>::type input_iter( boost::const_begin(input) );
        typename boost::range_const_iterator<OutputRange>::type output_iter( boost::const_begin(output) );
        for( ; input_iter != boost::const_end(input); ++input_iter, ++output_iter )
            push_back( *input_iter, *output_iter );
    }

    // pure virtual
    virtual void push_back( input_type const &input, output_type const &output ) = 0;

};

}

#endif

<commit_msg>Fixed a bug in online_determinate<commit_after>/***************************************************************************
 *  The Kernel-Machine Library                                             *
 *  Copyright (C) 2004, 2005 by Rutger W. ter Borg                         *
 *                                                                         *
 *  This program is free software; you can redistribute it and/or          *
 *  modify it under the terms of the GNU General Public License            *
 *  as published by the Free Software Foundation; either version 2         *
 *  of the License, or (at your option) any later version.                 *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program; if not, write to the Free Software            *
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307  *
 ***************************************************************************/

#ifndef ONLINE_DETERMINATE_HPP
#define ONLINE_DETERMINATE_HPP

#include <boost/call_traits.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <kml/determinate.hpp>

namespace kml {

template< typename Input,typename Output,template<typename,int> class Kernel >
class online_determinate: public determinate<Input,Output,Kernel> {
public:
    typedef Kernel<Input,0> kernel_type;
    typedef typename kernel_result<kernel_type>::type result_type;
    typedef determinate<Input,Output,Kernel> base_type;
    typedef Input input_type;
    typedef Output output_type;

    // constructor
    online_determinate( typename boost::call_traits<kernel_type>::param_type k ):
    base_type(k) {}

    // works for any Single Pass Range
    template<typename InputRange, typename OutputRange>
    void learn( InputRange const &input, OutputRange const &output ) {
        typename boost::range_const_iterator<InputRange>::type input_iter( boost::const_begin(input) );
        typename boost::range_const_iterator<OutputRange>::type output_iter( boost::const_begin(output) );
        for( ; input_iter != boost::const_end(input); ++input_iter, ++output_iter )
            push_back( *input_iter, *output_iter );
    }

    // pure virtual
    virtual void push_back( input_type const &input, output_type const &output ) = 0;

};

}

#endif

<|endoftext|>


<commit_before>/* KPilot
**
** Copyright (C) 2001 by Dan Pilone
** Copyright (C) 2001,2002,2003,2004 by Adriaan de Groot
**
** This is the main program for kpilotTest, which shows a SyncLog and
** exercises the KPilotDeviceLink class. It's intended to test if the
** Palm hardware and the KPilot software are functioning correctly to
** some extent.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org.
*/
static const char *test_id =
	"$Id$";

#include "options.h"

#include <stdlib.h>
#include <time.h>
#include <iostream>

#include <qpushbutton.h>
#include <qhbox.h>
#include <qtimer.h>

#include <kapplication.h>
#include <klocale.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <kservice.h>
#include <kservicetype.h>
#include <kuserprofile.h>

#include <pi-version.h>

#include "logWidget.h"
#include "kpilotConfig.h"
#include "syncStack.h"
#include "hotSync.h"
#include "interactiveSync.h"

static KCmdLineOptions kpilotoptions[] = {
	{"p",0,0},
	{"port <device>",
		I18N_NOOP("Path to Pilot device node"),
		"/dev/pilot"},
	{"l",0,0},
	{"list", I18N_NOOP("List DBs (default)"), 0},
	{"b",0,0},
	{"backup", I18N_NOOP("Backup instead of list DBs"), 0},
	{"r",0,0},
	{"restore", I18N_NOOP("Restore Pilot from backup"), 0},
	{"L",0,0},
	{ "conduit-list", I18N_NOOP("List available conduits"), 0},
	{"E",0,0},
	{ "conduit-exec <filename>",
		I18N_NOOP("Run conduit from desktop file <filename>"),
		0 },
	{ "T",0,0},
	{ "notest",
		I18N_NOOP("*Really* run the conduit, not in test mode."),
		0 } ,
	{ "F",0,0},
	{ "local",
		I18N_NOOP("Run the conduit in file-test mode."),
		0 } ,
	{ "HHtoPC",
		I18N_NOOP("Copy Pilot to Desktop."),
		0 } ,
	{ "PCtoHH",
		I18N_NOOP("Copy Desktop to Pilot."),
		0 } ,
	{ "test-timeout",
		I18N_NOOP("Run conduit specially designed to timeout."),
		0 } ,
	{ "test-usercheck",
		I18N_NOOP("Run conduit just for user check."),
		0 } ,
	{ "dump-calendar",
		I18N_NOOP("Dump calendar to stdout."),
		0 } ,
#ifdef DEBUG
	{"debug <level>", I18N_NOOP("Set debugging level"), "0"},
#endif
	KCmdLineLastOption
};

static LogWidget *logWidget = 0L;
static QPushButton *resetButton = 0L;

/**
*** Conduits - sync actions - for testing specific scenarios.
**/

class TimeoutAction : public SyncAction
{
public:
	TimeoutAction(KPilotDeviceLink *p) ;
protected:
	virtual bool exec();
} ;

TimeoutAction::TimeoutAction(KPilotDeviceLink *p) :
	SyncAction(p)
{
	FUNCTIONSETUP;
}

bool TimeoutAction::exec()
{
	FUNCTIONSETUP;

	for (int i = 0; i<3; i++)
	{
		logMessage( CSL1("Hup two %1").arg(i) );
		fHandle->tickle();
		qApp->processEvents();
		sleep(1);
	}

	logMessage( CSL1("Now sleeping 65") );
	qApp->processEvents();
	sleep(65);
	return delayDone();
}

void createLogWidget()
{
	LogWidget *w = new LogWidget(0L);

	w->resize(300, 300);
	w->show();
	w->setShowTime(true);
	kapp->setMainWidget(w);
	logWidget = w;

	resetButton = new QPushButton(i18n("Reset"),w->buttonBox());
}

static KPilotDeviceLink *deviceLink = 0L;

void createLink()
{
	FUNCTIONSETUP;

	deviceLink = new KPilotDeviceLink(0, "deviceLink");

	QObject::connect(deviceLink, SIGNAL(logError(const QString &)),
		logWidget, SLOT(addError(const QString &)));
	QObject::connect(deviceLink, SIGNAL(logMessage(const QString &)),
		logWidget, SLOT(addMessage(const QString &)));
	QObject::connect(deviceLink,SIGNAL(logProgress(const QString &,int)),
		logWidget, SLOT(addProgress(const QString &,int)));

}

static ActionQueue *syncStack = 0L;

void connectStack()
{
	FUNCTIONSETUP;

	QObject::connect(syncStack, SIGNAL(logError(const QString &)),
		logWidget, SLOT(addError(const QString &)));
	QObject::connect(syncStack, SIGNAL(logMessage(const QString &)),
		logWidget, SLOT(addMessage(const QString &)));
	QObject::connect(syncStack,SIGNAL(logProgress(const QString &,int)),
		logWidget, SLOT(addProgress(const QString &,int)));

	QObject::connect(deviceLink, SIGNAL(deviceReady(KPilotDeviceLink*)), syncStack, SLOT(execConduit()));

	QObject::connect(syncStack, SIGNAL(syncDone(SyncAction *)),
		logWidget, SLOT(syncDone()));
	QObject::connect(syncStack, SIGNAL(syncDone(SyncAction *)),
		deviceLink, SLOT(close()));

	QObject::connect(resetButton,SIGNAL(clicked()),deviceLink,SLOT(reset()));
}

void createConnection(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	QString devicePath = p->getOption("port");

	if (devicePath.isEmpty())
	{
		devicePath = "/dev/pilot";
	}

	deviceLink->reset(devicePath);
}

int syncTest(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	createLogWidget();
	createLink();

	syncStack = new ActionQueue(deviceLink);

	if (p->isSet("backup"))
	{
		syncStack->queueInit();
		syncStack->addAction(new BackupAction(deviceLink,true));
	}
	else if (p->isSet("restore"))
	{
		syncStack->queueInit(0);
		syncStack->addAction(new RestoreAction(deviceLink));
	}
	else if (p->isSet("test-timeout"))
	{
		syncStack->queueInit();
		syncStack->addAction( new TimeoutAction(deviceLink) );
		syncStack->addAction( new TimeoutAction(deviceLink) );
	}
	else
	{
		syncStack->queueInit(p->isSet("test-usercheck") /* whether to run usercheck */);
		syncStack->addAction(new TestLink(deviceLink));
	}
	syncStack->queueCleanup();

	connectStack();
	createConnection(p);
	return kapp->exec();
}

int execConduit(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	// get --exec-conduit value
	QString s = p->getOption("conduit-exec");
	if (s.isEmpty()) return 1;
	QStringList l;
	l.append(s);

	createLogWidget();
	createLink();

	SyncAction::SyncMode::Mode syncMode = SyncAction::SyncMode::eHotSync;
	if (p->isSet("HHtoPC")) syncMode = SyncAction::SyncMode::eCopyHHToPC;
	if (p->isSet("PCtoHH")) syncMode = SyncAction::SyncMode::eCopyPCToHH;

	SyncAction::SyncMode mode(syncMode,p->isSet("test"),p->isSet("local"));
	syncStack = new ActionQueue(deviceLink);
	syncStack->queueInit();
	syncStack->queueConduits(l,mode,false);
	syncStack->queueCleanup();

	connectStack();
	createConnection(p);

	return kapp->exec();
}

int listConduits(KCmdLineArgs *)
{
	FUNCTIONSETUP;

	KServiceTypeProfile::OfferList offers =
		KServiceTypeProfile::offers(CSL1("KPilotConduit"));

	// Now actually fill the two list boxes, just make
	// sure that nothing gets listed in both.
	//
	//
	QValueListIterator < KServiceOffer > availList(offers.begin());
	while (availList != offers.end())
	{
		KSharedPtr < KService > o = (*availList).service();

		std::cout << o->desktopEntryName().latin1() << std::endl;
		std::cout << "\t" << o->name().latin1()  << std::endl;
		if (!o->library().isEmpty())
		{
			std::cout << "\tIn "
				<< o->library().latin1()
				<< std::endl;
		}

		++availList;
	}

	return 0;
}

int main(int argc, char **argv)
{
	FUNCTIONSETUP;
	KAboutData about("kpilotTest",
		I18N_NOOP("KPilotTest"),
		KPILOT_VERSION,
		"KPilot Tester",
		KAboutData::License_GPL, "(C) 2001-2004, Adriaan de Groot");
	about.addAuthor("Adriaan de Groot",
		I18N_NOOP("KPilot Maintainer"),
		"groot@kde.org", "http://www.cs.kun.nl/~adridg/kpilot/");

	KCmdLineArgs::init(argc, argv, &about);
	KCmdLineArgs::addCmdLineOptions(kpilotoptions, "kpilottest");
	KApplication::addCmdLineOptions();

	KCmdLineArgs *p = KCmdLineArgs::parsedArgs();

	KApplication a;
#ifdef DEBUG
	KPilotConfig::getDebugLevel(p);
#endif

	if ( p->isSet("backup") ||
		p->isSet("restore") ||
		p->isSet("list") ||
		p->isSet("test-timeout") ||
		p->isSet("test-usercheck") )
	{
		return syncTest(p);
	}

	if (p->isSet("conduit-list"))
	{
		return listConduits(p);
	}

	if (p->isSet("conduit-exec"))
	{
		return execConduit(p);
	}

	// The default is supposed to be "list"
	return syncTest(p);
	/* NOTREACHED */
	(void) test_id;
}

<commit_msg>Start supporting --local again. You can mix --local with --exec-conduit and it won't crash immediately.<commit_after>/* KPilot
**
** Copyright (C) 2001 by Dan Pilone
** Copyright (C) 2001,2002,2003,2004 by Adriaan de Groot
**
** This is the main program for kpilotTest, which shows a SyncLog and
** exercises the KPilotDeviceLink class. It's intended to test if the
** Palm hardware and the KPilot software are functioning correctly to
** some extent.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
** MA 02110-1301, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org.
*/
static const char *test_id =
	"$Id$";

#include "options.h"

#include <stdlib.h>
#include <time.h>
#include <iostream>

#include <qpushbutton.h>
#include <qhbox.h>
#include <qtimer.h>

#include <kapplication.h>
#include <klocale.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <kservice.h>
#include <kservicetype.h>
#include <kuserprofile.h>

#include <pi-version.h>

#include "logWidget.h"
#include "kpilotConfig.h"
#include "syncStack.h"
#include "hotSync.h"
#include "interactiveSync.h"

static KCmdLineOptions kpilotoptions[] = {
	{"p",0,0},
	{"port <device>",
		I18N_NOOP("Path to Pilot device node"),
		"/dev/pilot"},
	{"l",0,0},
	{"list", I18N_NOOP("List DBs (default)"), 0},
	{"b",0,0},
	{"backup", I18N_NOOP("Backup instead of list DBs"), 0},
	{"r",0,0},
	{"restore", I18N_NOOP("Restore Pilot from backup"), 0},
	{"L",0,0},
	{ "conduit-list", I18N_NOOP("List available conduits"), 0},
	{"E",0,0},
	{ "conduit-exec <filename>",
		I18N_NOOP("Run conduit from desktop file <filename>"),
		0 },
	{ "T",0,0},
	{ "notest",
		I18N_NOOP("*Really* run the conduit, not in test mode."),
		0 } ,
	{ "F",0,0},
	{ "local",
		I18N_NOOP("Run the conduit in file-test mode."),
		0 } ,
	{ "HHtoPC",
		I18N_NOOP("Copy Pilot to Desktop."),
		0 } ,
	{ "PCtoHH",
		I18N_NOOP("Copy Desktop to Pilot."),
		0 } ,
	{ "test-timeout",
		I18N_NOOP("Run conduit specially designed to timeout."),
		0 } ,
	{ "test-usercheck",
		I18N_NOOP("Run conduit just for user check."),
		0 } ,
	{ "dump-calendar",
		I18N_NOOP("Dump calendar to stdout."),
		0 } ,
#ifdef DEBUG
	{"debug <level>", I18N_NOOP("Set debugging level"), "0"},
#endif
	KCmdLineLastOption
};

static LogWidget *logWidget = 0L;
static QPushButton *resetButton = 0L;

/**
*** Conduits - sync actions - for testing specific scenarios.
**/

class TimeoutAction : public SyncAction
{
public:
	TimeoutAction(KPilotDeviceLink *p) ;
protected:
	virtual bool exec();
} ;

TimeoutAction::TimeoutAction(KPilotDeviceLink *p) :
	SyncAction(p)
{
	FUNCTIONSETUP;
}

bool TimeoutAction::exec()
{
	FUNCTIONSETUP;

	for (int i = 0; i<3; i++)
	{
		logMessage( CSL1("Hup two %1").arg(i) );
		fHandle->tickle();
		qApp->processEvents();
		sleep(1);
	}

	logMessage( CSL1("Now sleeping 65") );
	qApp->processEvents();
	sleep(65);
	return delayDone();
}

void createLogWidget()
{
	LogWidget *w = new LogWidget(0L);

	w->resize(300, 300);
	w->show();
	w->setShowTime(true);
	kapp->setMainWidget(w);
	logWidget = w;

	resetButton = new QPushButton(i18n("Reset"),w->buttonBox());
}

static KPilotDeviceLink *deviceLink = 0L;

void createLink()
{
	FUNCTIONSETUP;

	deviceLink = new KPilotDeviceLink(0, "deviceLink");

	QObject::connect(deviceLink, SIGNAL(logError(const QString &)),
		logWidget, SLOT(addError(const QString &)));
	QObject::connect(deviceLink, SIGNAL(logMessage(const QString &)),
		logWidget, SLOT(addMessage(const QString &)));
	QObject::connect(deviceLink,SIGNAL(logProgress(const QString &,int)),
		logWidget, SLOT(addProgress(const QString &,int)));

}

static ActionQueue *syncStack = 0L;

void connectStack()
{
	FUNCTIONSETUP;

	QObject::connect(syncStack, SIGNAL(logError(const QString &)),
		logWidget, SLOT(addError(const QString &)));
	QObject::connect(syncStack, SIGNAL(logMessage(const QString &)),
		logWidget, SLOT(addMessage(const QString &)));
	QObject::connect(syncStack,SIGNAL(logProgress(const QString &,int)),
		logWidget, SLOT(addProgress(const QString &,int)));
	QObject::connect(syncStack, SIGNAL(syncDone(SyncAction *)),
		logWidget, SLOT(syncDone()));

	if (deviceLink)
	{
		QObject::connect(syncStack, SIGNAL(syncDone(SyncAction *)),
			deviceLink, SLOT(close()));
		QObject::connect(deviceLink, SIGNAL(deviceReady(KPilotDeviceLink*)), syncStack, SLOT(execConduit()));
		QObject::connect(resetButton,SIGNAL(clicked()),deviceLink,SLOT(reset()));
	}
}

void createConnection(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	QString devicePath = p->getOption("port");

	if (devicePath.isEmpty())
	{
		devicePath = "/dev/pilot";
	}

	deviceLink->reset(devicePath);
}

int syncTest(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	createLogWidget();
	createLink();

	syncStack = new ActionQueue(deviceLink);

	if (p->isSet("backup"))
	{
		syncStack->queueInit();
		syncStack->addAction(new BackupAction(deviceLink,true));
	}
	else if (p->isSet("restore"))
	{
		syncStack->queueInit(0);
		syncStack->addAction(new RestoreAction(deviceLink));
	}
	else if (p->isSet("test-timeout"))
	{
		syncStack->queueInit();
		syncStack->addAction( new TimeoutAction(deviceLink) );
		syncStack->addAction( new TimeoutAction(deviceLink) );
	}
	else
	{
		syncStack->queueInit(p->isSet("test-usercheck") /* whether to run usercheck */);
		syncStack->addAction(new TestLink(deviceLink));
	}
	syncStack->queueCleanup();

	connectStack();
	createConnection(p);
	return kapp->exec();
}

int execConduit(KCmdLineArgs *p)
{
	FUNCTIONSETUP;

	// get --exec-conduit value
	QString s = p->getOption("conduit-exec");
	if (s.isEmpty()) return 1;
	QStringList l;
	l.append(s);

	createLogWidget();

	SyncAction::SyncMode::Mode syncMode = SyncAction::SyncMode::eHotSync;
	if (p->isSet("HHtoPC")) syncMode = SyncAction::SyncMode::eCopyHHToPC;
	if (p->isSet("PCtoHH")) syncMode = SyncAction::SyncMode::eCopyPCToHH;
	SyncAction::SyncMode mode(syncMode,p->isSet("test"),p->isSet("local"));

	if (!p->isSet("local"))
	{
		createLink();

		syncStack = new ActionQueue(deviceLink);
		syncStack->queueInit();
		syncStack->queueConduits(l,mode,false);
		syncStack->queueCleanup();
		connectStack();
		createConnection(p);
	}
	else
	{
		syncStack = new ActionQueue( 0L );
		syncStack->queueInit();
		syncStack->queueConduits(l,mode,false);
		syncStack->queueCleanup();
		connectStack();
		QTimer::singleShot(100,syncStack,SLOT(execConduit()));
	}

	return kapp->exec();
}

int listConduits(KCmdLineArgs *)
{
	FUNCTIONSETUP;

	KServiceTypeProfile::OfferList offers =
		KServiceTypeProfile::offers(CSL1("KPilotConduit"));

	// Now actually fill the two list boxes, just make
	// sure that nothing gets listed in both.
	//
	//
	QValueListIterator < KServiceOffer > availList(offers.begin());
	while (availList != offers.end())
	{
		KSharedPtr < KService > o = (*availList).service();

		std::cout << o->desktopEntryName().latin1() << std::endl;
		std::cout << "\t" << o->name().latin1()  << std::endl;
		if (!o->library().isEmpty())
		{
			std::cout << "\tIn "
				<< o->library().latin1()
				<< std::endl;
		}

		++availList;
	}

	return 0;
}

int main(int argc, char **argv)
{
	FUNCTIONSETUP;
	KAboutData about("kpilotTest",
		I18N_NOOP("KPilotTest"),
		KPILOT_VERSION,
		"KPilot Tester",
		KAboutData::License_GPL, "(C) 2001-2004, Adriaan de Groot");
	about.addAuthor("Adriaan de Groot",
		I18N_NOOP("KPilot Maintainer"),
		"groot@kde.org", "http://www.cs.kun.nl/~adridg/kpilot/");

	KCmdLineArgs::init(argc, argv, &about);
	KCmdLineArgs::addCmdLineOptions(kpilotoptions, "kpilottest");
	KApplication::addCmdLineOptions();

	KCmdLineArgs *p = KCmdLineArgs::parsedArgs();

	KApplication a;
#ifdef DEBUG
	KPilotConfig::getDebugLevel(p);
#endif

	if ( p->isSet("backup") ||
		p->isSet("restore") ||
		p->isSet("list") ||
		p->isSet("test-timeout") ||
		p->isSet("test-usercheck") )
	{
		return syncTest(p);
	}

	if (p->isSet("conduit-list"))
	{
		return listConduits(p);
	}

	if (p->isSet("conduit-exec"))
	{
		return execConduit(p);
	}

	// The default is supposed to be "list"
	return syncTest(p);
	/* NOTREACHED */
	(void) test_id;
}

<|endoftext|>


<commit_before>//==-- llvm/Support/ThreadPool.cpp - A ThreadPool implementation -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a crude C++11 based thread pool.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/ThreadPool.h"

#include "llvm/Config/llvm-config.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#if LLVM_ENABLE_THREADS

// Default to std::thread::hardware_concurrency
ThreadPool::ThreadPool() : ThreadPool(std::thread::hardware_concurrency()) {}

ThreadPool::ThreadPool(unsigned ThreadCount)
    : ActiveThreads(0), EnableFlag(true) {
  // Create ThreadCount threads that will loop forever, wait on QueueCondition
  // for tasks to be queued or the Pool to be destroyed.
  Threads.reserve(ThreadCount);
  for (unsigned ThreadID = 0; ThreadID < ThreadCount; ++ThreadID) {
    Threads.emplace_back([&] {
      while (true) {
        PackagedTaskTy Task;
        {
          std::unique_lock<std::mutex> LockGuard(QueueLock);
          // Wait for tasks to be pushed in the queue
          QueueCondition.wait(LockGuard,
                              [&] { return !EnableFlag || !Tasks.empty(); });
          // Exit condition
          if (!EnableFlag && Tasks.empty())
            return;
          // Yeah, we have a task, grab it and release the lock on the queue

          // We first need to signal that we are active before popping the queue
          // in order for wait() to properly detect that even if the queue is
          // empty, there is still a task in flight.
          {
            ++ActiveThreads;
            std::unique_lock<std::mutex> LockGuard(CompletionLock);
          }
          Task = std::move(Tasks.front());
          Tasks.pop();
        }
        // Run the task we just grabbed
#ifndef _MSC_VER
        Task();
#else
        Task(/* unused */ false);
#endif

        {
          // Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait()
          std::unique_lock<std::mutex> LockGuard(CompletionLock);
          --ActiveThreads;
        }

        // Notify task completion, in case someone waits on ThreadPool::wait()
        CompletionCondition.notify_all();
      }
    });
  }
}

void ThreadPool::wait() {
  // Wait for all threads to complete and the queue to be empty
  std::unique_lock<std::mutex> LockGuard(CompletionLock);
  // The order of the checks for ActiveThreads and Tasks.empty() matters because
  // any active threads might be modifying the Tasks queue, and this would be a
  // race.
  CompletionCondition.wait(LockGuard,
                           [&] { return !ActiveThreads && Tasks.empty(); });
}

std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
  /// Wrap the Task in a packaged_task to return a future object.
  PackagedTaskTy PackagedTask(std::move(Task));
  auto Future = PackagedTask.get_future();
  {
    // Lock the queue and push the new task
    std::unique_lock<std::mutex> LockGuard(QueueLock);

    // Don't allow enqueueing after disabling the pool
    assert(EnableFlag && "Queuing a thread during ThreadPool destruction");

    Tasks.push(std::move(PackagedTask));
  }
  QueueCondition.notify_one();
  return Future.share();
}

// The destructor joins all threads, waiting for completion.
ThreadPool::~ThreadPool() {
  {
    std::unique_lock<std::mutex> LockGuard(QueueLock);
    EnableFlag = false;
  }
  QueueCondition.notify_all();
  for (auto &Worker : Threads)
    Worker.join();
}

#else // LLVM_ENABLE_THREADS Disabled

ThreadPool::ThreadPool() : ThreadPool(0) {}

// No threads are launched, issue a warning if ThreadCount is not 0
ThreadPool::ThreadPool(unsigned ThreadCount)
    : ActiveThreads(0) {
  if (ThreadCount) {
    errs() << "Warning: request a ThreadPool with " << ThreadCount
           << " threads, but LLVM_ENABLE_THREADS has been turned off\n";
  }
}

void ThreadPool::wait() {
  // Sequential implementation running the tasks
  while (!Tasks.empty()) {
    auto Task = std::move(Tasks.front());
    Tasks.pop();
#ifndef _MSC_VER
        Task();
#else
        Task(/* unused */ false);
#endif
  }
}

std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
#ifndef _MSC_VER
  // Get a Future with launch::deferred execution using std::async
  auto Future = std::async(std::launch::deferred, std::move(Task)).share();
  // Wrap the future so that both ThreadPool::wait() can operate and the
  // returned future can be sync'ed on.
  PackagedTaskTy PackagedTask([Future]() { Future.get(); });
#else
  auto Future = std::async(std::launch::deferred, std::move(Task), false).share();
  PackagedTaskTy PackagedTask([Future](bool) -> bool { Future.get(); return false; });
#endif
  Tasks.push(std::move(PackagedTask));
  return Future;
}

ThreadPool::~ThreadPool() {
  wait();
}

#endif
<commit_msg>Add whitespace to check commit access<commit_after>//==-- llvm/Support/ThreadPool.cpp - A ThreadPool implementation -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a crude C++11 based thread pool.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/ThreadPool.h"

#include "llvm/Config/llvm-config.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#if LLVM_ENABLE_THREADS

// Default to std::thread::hardware_concurrency
ThreadPool::ThreadPool() : ThreadPool(std::thread::hardware_concurrency()) {}

ThreadPool::ThreadPool(unsigned ThreadCount)
    : ActiveThreads(0), EnableFlag(true) {
  // Create ThreadCount threads that will loop forever, wait on QueueCondition
  // for tasks to be queued or the Pool to be destroyed.
  Threads.reserve(ThreadCount);
  for (unsigned ThreadID = 0; ThreadID < ThreadCount; ++ThreadID) {
    Threads.emplace_back([&] {
      while (true) {
        PackagedTaskTy Task;
        {
          std::unique_lock<std::mutex> LockGuard(QueueLock);
          // Wait for tasks to be pushed in the queue
          QueueCondition.wait(LockGuard,
                              [&] { return !EnableFlag || !Tasks.empty(); });
          // Exit condition
          if (!EnableFlag && Tasks.empty())
            return;
          // Yeah, we have a task, grab it and release the lock on the queue

          // We first need to signal that we are active before popping the queue
          // in order for wait() to properly detect that even if the queue is
          // empty, there is still a task in flight.
          {
            ++ActiveThreads;
            std::unique_lock<std::mutex> LockGuard(CompletionLock);
          }
          Task = std::move(Tasks.front());
          Tasks.pop();
        }
        // Run the task we just grabbed
#ifndef _MSC_VER
        Task();
#else
        Task(/* unused */ false);
#endif

        {
          // Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait()
          std::unique_lock<std::mutex> LockGuard(CompletionLock);
          --ActiveThreads;
        }

        // Notify task completion, in case someone waits on ThreadPool::wait()
        CompletionCondition.notify_all();
      }
    });
  }
}

void ThreadPool::wait() {
  // Wait for all threads to complete and the queue to be empty
  std::unique_lock<std::mutex> LockGuard(CompletionLock);
  // The order of the checks for ActiveThreads and Tasks.empty() matters because
  // any active threads might be modifying the Tasks queue, and this would be a
  // race.
  CompletionCondition.wait(LockGuard,
                           [&] { return !ActiveThreads && Tasks.empty(); });
}

std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
  /// Wrap the Task in a packaged_task to return a future object.
  PackagedTaskTy PackagedTask(std::move(Task));
  auto Future = PackagedTask.get_future();
  {
    // Lock the queue and push the new task
    std::unique_lock<std::mutex> LockGuard(QueueLock);

    // Don't allow enqueueing after disabling the pool
    assert(EnableFlag && "Queuing a thread during ThreadPool destruction");

    Tasks.push(std::move(PackagedTask));
  }
  QueueCondition.notify_one();
  return Future.share();
}

// The destructor joins all threads, waiting for completion.
ThreadPool::~ThreadPool() {
  {
    std::unique_lock<std::mutex> LockGuard(QueueLock);
    EnableFlag = false;
  }
  QueueCondition.notify_all();
  for (auto &Worker : Threads)
    Worker.join();
}

#else // LLVM_ENABLE_THREADS Disabled

ThreadPool::ThreadPool() : ThreadPool(0) {}

// No threads are launched, issue a warning if ThreadCount is not 0
ThreadPool::ThreadPool(unsigned ThreadCount)
    : ActiveThreads(0) {
  if (ThreadCount) {
    errs() << "Warning: request a ThreadPool with " << ThreadCount
           << " threads, but LLVM_ENABLE_THREADS has been turned off\n";
  }
}

void ThreadPool::wait() {
  // Sequential implementation running the tasks
  while (!Tasks.empty()) {
    auto Task = std::move(Tasks.front());
    Tasks.pop();
#ifndef _MSC_VER
        Task();
#else
        Task(/* unused */ false);
#endif
  }
}

std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
#ifndef _MSC_VER
  // Get a Future with launch::deferred execution using std::async
  auto Future = std::async(std::launch::deferred, std::move(Task)).share();
  // Wrap the future so that both ThreadPool::wait() can operate and the
  // returned future can be sync'ed on.
  PackagedTaskTy PackagedTask([Future]() { Future.get(); });
#else
  auto Future = std::async(std::launch::deferred, std::move(Task), false).share();
  PackagedTaskTy PackagedTask([Future](bool) -> bool { Future.get(); return false; });
#endif
  Tasks.push(std::move(PackagedTask));
  return Future;
}

ThreadPool::~ThreadPool() {
  wait();
}

#endif
<|endoftext|>


<commit_before>/*
  This is an example file shipped by 'Aleph - A Library for Exploring
  Persistent Homology'.

  This example demonstrates how to create random persistence diagrams
  that may be used to compare topological algorithms with each other,
  such as persistence indicator functions and Wasserstein distances.

  Demonstrated classes:

    - aleph::distances::Euclidean
    - aleph::geometry::BruteForce
    - aleph::PersistenceDiagram

  Demonstrated functions:

    - aleph::calculatePersistenceDiagrams
    - aleph::geometry::buildVietorisRipsComplex
    - aleph::geometry::makeSphere
    - aleph::geometry::makeTorus
    - aleph::geometry::sphereSampling
    - aleph::geometry::torusRejectionSampling

  Original author: Bastian Rieck
*/

#include <aleph/geometry/BruteForce.hh>
#include <aleph/geometry/SphereSampling.hh>
#include <aleph/geometry/TorusSampling.hh>
#include <aleph/geometry/VietorisRipsComplex.hh>

#include <aleph/geometry/distances/Euclidean.hh>

#include <aleph/persistenceDiagrams/PersistenceDiagram.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <limits>
#include <random>
#include <sstream>
#include <vector>

#include <cmath>

#include <getopt.h>

// We first have to specify the data type of the persistence diagram,
// i.e. the type that is used by its individual points.
using DataType           = double;
using Distance           = aleph::geometry::distances::Euclidean<DataType>;
using PointCloud         = aleph::containers::PointCloud<DataType>;
using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;

/**
  Auxiliary function for creating a random persistence diagram. Points
  are drawn from a uniform distribution on [0,1]. The function ensures
  that all points are situated _above_ the diagonal.
*/

PersistenceDiagram createRandomPersistenceDiagram( unsigned n )
{
  std::random_device rd;
  std::default_random_engine rng( rd() );
  std::uniform_real_distribution<DataType> distribution( DataType(0), DataType( std::nextafter( DataType(1), std::numeric_limits<DataType>::max() ) ) );

  PersistenceDiagram D;

  for( unsigned i = 0; i < n; i++ )
  {
    auto x = distribution( rng );
    auto y = distribution( rng );

    if( x > y )
      std::swap( x,y );

    D.add( x,y );
  }

  return D;
}

/**
  Auxiliary function for creating random persistence diagrams based on
  random samples from a box with a given length.

  Note that this function automatically handles Vietoris--Rips
  expansion.
*/

std::vector<PersistenceDiagram> createRandomBoxPersistenceDiagrams( DataType r, unsigned n, unsigned d = 3 )
{
  std::random_device rd;
  std::default_random_engine rng( rd() );
  std::uniform_real_distribution<DataType> distribution( DataType(0), DataType( std::nextafter( DataType(r), std::numeric_limits<DataType>::max() ) ) );

  PointCloud pointCloud( n, 3 );

  for( unsigned i = 0; i < n; i++ )
  {
    auto x = distribution( rng );
    auto y = distribution( rng );
    auto z = distribution( rng );

    std::vector<DataType> p = {x,y,z};
    pointCloud.set( i, p.begin(), p.end() );
  }

  aleph::geometry::BruteForce<PointCloud, Distance> bruteForceWrapper( pointCloud );

  auto K
    = aleph::geometry::buildVietorisRipsComplex( bruteForceWrapper, 0.7 * r, d );

  auto diagrams
    = aleph::calculatePersistenceDiagrams( K );

  for( auto&& diagram : diagrams )
    diagram.removeDiagonal();

  return diagrams;
}

/**
  Auxiliary function for creating a random persistence diagram based on
  random samples from a torus. The torus is described by two radii, one
  for the outer part, the other for the inner part.

  Due to the sampling technique used, the specified number is merely an
  upper bound for the number of points that are to be sampled. Moreover
  the function will automatically handle Vietoris--Rips expansion.
*/

PersistenceDiagram createRandomTorusPersistenceDiagram( DataType R, DataType r, unsigned n )
{
  auto pointCloud = aleph::geometry::makeTorus(
    aleph::geometry::torusRejectionSampling( R, r, n ),
    R, r
  );

  aleph::geometry::BruteForce<PointCloud, Distance> bruteForceWrapper( pointCloud );

  auto K
    = aleph::geometry::buildVietorisRipsComplex( bruteForceWrapper, 0.5 * R, 2 );

  auto diagrams
    = aleph::calculatePersistenceDiagrams( K );

  diagrams.at(1).removeDiagonal();

  // We are only interested in the one-dimensional persistent homology
  // of the samples.
  return diagrams.at(1);
}

/**
  Auxiliary function for creating a random persistence diagram based on
  random samples from a sphere with a given radius.

  Note that this function automatically handles Vietoris--Rips
  expansion.
*/

PersistenceDiagram createRandomSpherePersistenceDiagram( DataType r, unsigned n )
{
  auto pointCloud = aleph::geometry::makeSphere(
    aleph::geometry::sphereSampling<DataType>( n ),
    r
  );

  aleph::geometry::BruteForce<PointCloud, Distance> bruteForceWrapper( pointCloud );

  auto K
    = aleph::geometry::buildVietorisRipsComplex( bruteForceWrapper, r, 2 );

  auto diagrams
    = aleph::calculatePersistenceDiagrams( K );

  diagrams.at(1).removeDiagonal();

  // We are only interested in the one-dimensional persistent homology
  // of the samples.
  return diagrams.at(1);
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] = {
      { "m"     , required_argument, nullptr, 'm' },
      { "n"     , required_argument, nullptr, 'n' },
      { "R"     , required_argument, nullptr, 'R' },
      { "r"     , required_argument, nullptr, 'r' },
      { "d"     , required_argument, nullptr, 'd' },
      { "box"   , no_argument      , nullptr, 'b' },
      { "sphere", no_argument      , nullptr, 's' },
      { "torus" , no_argument      , nullptr, 't' },
      { "output", no_argument      , nullptr, 'o' },
      { nullptr , 0                , nullptr,  0  }
  };

  unsigned d            = 3; // default dimension to use for expansion
  unsigned m            = 50;
  unsigned n            = 50;
  DataType R            = DataType(0.50);
  DataType r            = DataType(0.25);

  bool sampleFromBox    = false;
  bool sampleFromSphere = false;
  bool sampleFromTorus  = false;

  bool output           = false;

  int option = 0;
  while( ( option = getopt_long( argc, argv, "d:m:n:R:r:bsto", commandLineOptions, nullptr ) ) != -1 )
  {
    switch( option )
    {
    case 'd':
      d = static_cast<unsigned>( std::stoul(optarg) );
      break;
    case 'm':
      m = static_cast<unsigned>( std::stoul(optarg) );
      break;
    case 'n':
      n = static_cast<unsigned>( std::stoul(optarg) );
      break;
    case 'R':
      R = static_cast<DataType>( std::stod(optarg) );
      break;
    case 'r':
      r = static_cast<DataType>( std::stod(optarg) );
      break;
    case 'b':
      sampleFromBox    = true;
      sampleFromSphere = false;
      sampleFromTorus  = false;
      break;
    case 's':
      sampleFromBox    = false;
      sampleFromSphere = true;
      sampleFromTorus  = false;
      break;
    case 't':
      sampleFromBox    = false;
      sampleFromSphere = false;
      sampleFromTorus  = true;
      break;
    case 'o':
      output = true;
      break;
    default:
      break;
    }
  }

  std::cerr << "* Sampling " << n << " persistence diagrams\n";
  if( sampleFromBox )
    std::cerr << "* Sampling " << m << " points from a box with a=" << r << "\n";
  else if( sampleFromSphere )
    std::cerr << "* Sampling " << m << " points from a sphere with r=" << r << "\n";
  else if( sampleFromTorus )
    std::cerr << "* Sampling " << m << " points from a torus with R=" << R << " and r=" << r << "\n";
  else
    std::cerr << "* Generating " << m << " random points per diagram\n";

  for( unsigned i = 0; i < n; i++ )
  {
    std::vector<PersistenceDiagram> pds;
    PersistenceDiagram pd;

    if( sampleFromBox )
      pds = createRandomBoxPersistenceDiagrams(r, m, d);
    else if( sampleFromSphere )
      pd = createRandomSpherePersistenceDiagram(r, m);
    else if( sampleFromTorus )
      pd = createRandomTorusPersistenceDiagram(R, r, m);
    else
      pd = createRandomPersistenceDiagram(m);

    if( output )
    {
      if( !pds.empty() )
      {
        for( auto&& pd : pds )
        {
          std::stringstream stream;
          stream << "/tmp/";
          stream << std::setw( static_cast<int>( std::floor( std::log10(n)+1 ) ) ) << std::setfill( '0' ) << i << "_d" << pd.dimension();
          stream << ".txt";

          std::ofstream out( stream.str() );
          out << pd << "\n";
        }
      }
      else
      {
        std::stringstream stream;
        stream << "/tmp/";
        stream << std::setw( static_cast<int>( std::floor( std::log10(n)+1 ) ) ) << std::setfill( '0' ) << i;
        stream << ".txt";

        std::ofstream out( stream.str() );
        out << pd << "\n";
      }
    }
  }
}
<commit_msg>Removed obsolete line<commit_after>/*
  This is an example file shipped by 'Aleph - A Library for Exploring
  Persistent Homology'.

  This example demonstrates how to create random persistence diagrams
  that may be used to compare topological algorithms with each other,
  such as persistence indicator functions and Wasserstein distances.

  Demonstrated classes:

    - aleph::distances::Euclidean
    - aleph::geometry::BruteForce
    - aleph::PersistenceDiagram

  Demonstrated functions:

    - aleph::calculatePersistenceDiagrams
    - aleph::geometry::buildVietorisRipsComplex
    - aleph::geometry::makeSphere
    - aleph::geometry::makeTorus
    - aleph::geometry::sphereSampling
    - aleph::geometry::torusRejectionSampling

  Original author: Bastian Rieck
*/

#include <aleph/geometry/BruteForce.hh>
#include <aleph/geometry/SphereSampling.hh>
#include <aleph/geometry/TorusSampling.hh>
#include <aleph/geometry/VietorisRipsComplex.hh>

#include <aleph/geometry/distances/Euclidean.hh>

#include <aleph/persistenceDiagrams/PersistenceDiagram.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <limits>
#include <random>
#include <sstream>
#include <vector>

#include <cmath>

#include <getopt.h>

// We first have to specify the data type of the persistence diagram,
// i.e. the type that is used by its individual points.
using DataType           = double;
using Distance           = aleph::geometry::distances::Euclidean<DataType>;
using PointCloud         = aleph::containers::PointCloud<DataType>;
using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;

/**
  Auxiliary function for creating a random persistence diagram. Points
  are drawn from a uniform distribution on [0,1]. The function ensures
  that all points are situated _above_ the diagonal.
*/

PersistenceDiagram createRandomPersistenceDiagram( unsigned n )
{
  std::random_device rd;
  std::default_random_engine rng( rd() );
  std::uniform_real_distribution<DataType> distribution( DataType(0), DataType( std::nextafter( DataType(1), std::numeric_limits<DataType>::max() ) ) );

  PersistenceDiagram D;

  for( unsigned i = 0; i < n; i++ )
  {
    auto x = distribution( rng );
    auto y = distribution( rng );

    if( x > y )
      std::swap( x,y );

    D.add( x,y );
  }

  return D;
}

/**
  Auxiliary function for creating random persistence diagrams based on
  random samples from a box with a given length.

  Note that this function automatically handles Vietoris--Rips
  expansion.
*/

std::vector<PersistenceDiagram> createRandomBoxPersistenceDiagrams( DataType r, unsigned n, unsigned d = 3 )
{
  std::random_device rd;
  std::default_random_engine rng( rd() );
  std::uniform_real_distribution<DataType> distribution( DataType(0), DataType( std::nextafter( DataType(r), std::numeric_limits<DataType>::max() ) ) );

  PointCloud pointCloud( n, 3 );

  for( unsigned i = 0; i < n; i++ )
  {
    auto x = distribution( rng );
    auto y = distribution( rng );
    auto z = distribution( rng );

    std::vector<DataType> p = {x,y,z};
    pointCloud.set( i, p.begin(), p.end() );
  }

  aleph::geometry::BruteForce<PointCloud, Distance> bruteForceWrapper( pointCloud );

  auto K
    = aleph::geometry::buildVietorisRipsComplex( bruteForceWrapper, 0.7 * r, d );

  auto diagrams
    = aleph::calculatePersistenceDiagrams( K );

  for( auto&& diagram : diagrams )
    diagram.removeDiagonal();

  return diagrams;
}

/**
  Auxiliary function for creating a random persistence diagram based on
  random samples from a torus. The torus is described by two radii, one
  for the outer part, the other for the inner part.

  Due to the sampling technique used, the specified number is merely an
  upper bound for the number of points that are to be sampled. Moreover
  the function will automatically handle Vietoris--Rips expansion.
*/

PersistenceDiagram createRandomTorusPersistenceDiagram( DataType R, DataType r, unsigned n )
{
  auto pointCloud = aleph::geometry::makeTorus(
    aleph::geometry::torusRejectionSampling( R, r, n ),
    R, r
  );

  aleph::geometry::BruteForce<PointCloud, Distance> bruteForceWrapper( pointCloud );

  auto K
    = aleph::geometry::buildVietorisRipsComplex( bruteForceWrapper, 0.5 * R, 2 );

  auto diagrams
    = aleph::calculatePersistenceDiagrams( K );

  diagrams.at(1).removeDiagonal();

  // We are only interested in the one-dimensional persistent homology
  // of the samples.
  return diagrams.at(1);
}

/**
  Auxiliary function for creating a random persistence diagram based on
  random samples from a sphere with a given radius.

  Note that this function automatically handles Vietoris--Rips
  expansion.
*/

PersistenceDiagram createRandomSpherePersistenceDiagram( DataType r, unsigned n )
{
  auto pointCloud = aleph::geometry::makeSphere(
    aleph::geometry::sphereSampling<DataType>( n ),
    r
  );

  aleph::geometry::BruteForce<PointCloud, Distance> bruteForceWrapper( pointCloud );

  auto K
    = aleph::geometry::buildVietorisRipsComplex( bruteForceWrapper, r, 2 );

  auto diagrams
    = aleph::calculatePersistenceDiagrams( K );

  diagrams.at(1).removeDiagonal();

  // We are only interested in the one-dimensional persistent homology
  // of the samples.
  return diagrams.at(1);
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] = {
      { "m"     , required_argument, nullptr, 'm' },
      { "n"     , required_argument, nullptr, 'n' },
      { "R"     , required_argument, nullptr, 'R' },
      { "r"     , required_argument, nullptr, 'r' },
      { "d"     , required_argument, nullptr, 'd' },
      { "box"   , no_argument      , nullptr, 'b' },
      { "sphere", no_argument      , nullptr, 's' },
      { "torus" , no_argument      , nullptr, 't' },
      { "output", no_argument      , nullptr, 'o' },
      { nullptr , 0                , nullptr,  0  }
  };

  unsigned d            = 3; // default dimension to use for expansion
  unsigned m            = 50;
  unsigned n            = 50;
  DataType R            = DataType(0.50);
  DataType r            = DataType(0.25);

  bool sampleFromBox    = false;
  bool sampleFromSphere = false;
  bool sampleFromTorus  = false;

  bool output           = false;

  int option = 0;
  while( ( option = getopt_long( argc, argv, "d:m:n:R:r:bsto", commandLineOptions, nullptr ) ) != -1 )
  {
    switch( option )
    {
    case 'd':
      d = static_cast<unsigned>( std::stoul(optarg) );
      break;
    case 'm':
      m = static_cast<unsigned>( std::stoul(optarg) );
      break;
    case 'n':
      n = static_cast<unsigned>( std::stoul(optarg) );
      break;
    case 'R':
      R = static_cast<DataType>( std::stod(optarg) );
      break;
    case 'r':
      r = static_cast<DataType>( std::stod(optarg) );
      break;
    case 'b':
      sampleFromBox    = true;
      sampleFromSphere = false;
      sampleFromTorus  = false;
      break;
    case 's':
      sampleFromBox    = false;
      sampleFromSphere = true;
      sampleFromTorus  = false;
      break;
    case 't':
      sampleFromBox    = false;
      sampleFromSphere = false;
      sampleFromTorus  = true;
      break;
    case 'o':
      output = true;
      break;
    default:
      break;
    }
  }

  std::cerr << "* Sampling " << n << " persistence diagrams\n";
  if( sampleFromBox )
    std::cerr << "* Sampling " << m << " points from a box with a=" << r << "\n";
  else if( sampleFromSphere )
    std::cerr << "* Sampling " << m << " points from a sphere with r=" << r << "\n";
  else if( sampleFromTorus )
    std::cerr << "* Sampling " << m << " points from a torus with R=" << R << " and r=" << r << "\n";
  else
    std::cerr << "* Generating " << m << " random points per diagram\n";

  for( unsigned i = 0; i < n; i++ )
  {
    std::vector<PersistenceDiagram> pds;
    PersistenceDiagram pd;

    if( sampleFromBox )
      pds = createRandomBoxPersistenceDiagrams(r, m, d);
    else if( sampleFromSphere )
      pd = createRandomSpherePersistenceDiagram(r, m);
    else if( sampleFromTorus )
      pd = createRandomTorusPersistenceDiagram(R, r, m);
    else
      pd = createRandomPersistenceDiagram(m);

    if( output )
    {
      if( !pds.empty() )
      {
        for( auto&& pd : pds )
        {
          std::stringstream stream;
          stream << "/tmp/";
          stream << std::setw( static_cast<int>( std::floor( std::log10(n)+1 ) ) ) << std::setfill( '0' ) << i << "_d" << pd.dimension();
          stream << ".txt";

          std::ofstream out( stream.str() );
          out << pd << "\n";
        }
      }
      else
      {
        std::stringstream stream;
        stream << "/tmp/";
        stream << std::setw( static_cast<int>( std::floor( std::log10(n)+1 ) ) ) << std::setfill( '0' ) << i;
        stream << ".txt";

        std::ofstream out( stream.str() );
        out << pd << "\n";
      }
    }
  }
}
<|endoftext|>