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

#include "ir/load-utils.h"
#include "ir/utils.h"
#include "support/hash.h"

namespace wasm {

namespace ExpressionManipulator {

Expression*
flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
  struct Copier : public OverriddenVisitor<Copier, Expression*> {
    Module& wasm;
    CustomCopier custom;

    Builder builder;

    Copier(Module& wasm, CustomCopier custom)
      : wasm(wasm), custom(custom), builder(wasm) {}

    Expression* copy(Expression* curr) {
      if (!curr) {
        return nullptr;
      }
      auto* ret = custom(curr);
      if (ret) {
        return ret;
      }
      return OverriddenVisitor<Copier, Expression*>::visit(curr);
    }

    Expression* visitBlock(Block* curr) {
      ExpressionList list(wasm.allocator);
      for (Index i = 0; i < curr->list.size(); i++) {
        list.push_back(copy(curr->list[i]));
      }
      return builder.makeBlock(curr->name, list, curr->type);
    }
    Expression* visitIf(If* curr) {
      return builder.makeIf(copy(curr->condition),
                            copy(curr->ifTrue),
                            copy(curr->ifFalse),
                            curr->type);
    }
    Expression* visitLoop(Loop* curr) {
      return builder.makeLoop(curr->name, copy(curr->body));
    }
    Expression* visitBreak(Break* curr) {
      return builder.makeBreak(
        curr->name, copy(curr->value), copy(curr->condition));
    }
    Expression* visitSwitch(Switch* curr) {
      return builder.makeSwitch(curr->targets,
                                curr->default_,
                                copy(curr->condition),
                                copy(curr->value));
    }
    Expression* visitCall(Call* curr) {
      auto* ret =
        builder.makeCall(curr->target, {}, curr->type, curr->isReturn);
      for (Index i = 0; i < curr->operands.size(); i++) {
        ret->operands.push_back(copy(curr->operands[i]));
      }
      return ret;
    }
    Expression* visitCallIndirect(CallIndirect* curr) {
      auto* ret = builder.makeCallIndirect(
        curr->fullType, copy(curr->target), {}, curr->type, curr->isReturn);
      for (Index i = 0; i < curr->operands.size(); i++) {
        ret->operands.push_back(copy(curr->operands[i]));
      }
      return ret;
    }
    Expression* visitLocalGet(LocalGet* curr) {
      return builder.makeLocalGet(curr->index, curr->type);
    }
    Expression* visitLocalSet(LocalSet* curr) {
      if (curr->isTee()) {
        return builder.makeLocalTee(curr->index, copy(curr->value));
      } else {
        return builder.makeLocalSet(curr->index, copy(curr->value));
      }
    }
    Expression* visitGlobalGet(GlobalGet* curr) {
      return builder.makeGlobalGet(curr->name, curr->type);
    }
    Expression* visitGlobalSet(GlobalSet* curr) {
      return builder.makeGlobalSet(curr->name, copy(curr->value));
    }
    Expression* visitLoad(Load* curr) {
      if (curr->isAtomic) {
        return builder.makeAtomicLoad(
          curr->bytes, curr->offset, copy(curr->ptr), curr->type);
      }
      return builder.makeLoad(curr->bytes,
                              LoadUtils::isSignRelevant(curr) ? curr->signed_
                                                              : false,
                              curr->offset,
                              curr->align,
                              copy(curr->ptr),
                              curr->type);
    }
    Expression* visitStore(Store* curr) {
      if (curr->isAtomic) {
        return builder.makeAtomicStore(curr->bytes,
                                       curr->offset,
                                       copy(curr->ptr),
                                       copy(curr->value),
                                       curr->valueType);
      }
      return builder.makeStore(curr->bytes,
                               curr->offset,
                               curr->align,
                               copy(curr->ptr),
                               copy(curr->value),
                               curr->valueType);
    }
    Expression* visitAtomicRMW(AtomicRMW* curr) {
      return builder.makeAtomicRMW(curr->op,
                                   curr->bytes,
                                   curr->offset,
                                   copy(curr->ptr),
                                   copy(curr->value),
                                   curr->type);
    }
    Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
      return builder.makeAtomicCmpxchg(curr->bytes,
                                       curr->offset,
                                       copy(curr->ptr),
                                       copy(curr->expected),
                                       copy(curr->replacement),
                                       curr->type);
    }
    Expression* visitAtomicWait(AtomicWait* curr) {
      return builder.makeAtomicWait(copy(curr->ptr),
                                    copy(curr->expected),
                                    copy(curr->timeout),
                                    curr->expectedType,
                                    curr->offset);
    }
    Expression* visitAtomicNotify(AtomicNotify* curr) {
      return builder.makeAtomicNotify(
        copy(curr->ptr), copy(curr->notifyCount), curr->offset);
    }
    Expression* visitSIMDExtract(SIMDExtract* curr) {
      return builder.makeSIMDExtract(curr->op, copy(curr->vec), curr->index);
    }
    Expression* visitSIMDReplace(SIMDReplace* curr) {
      return builder.makeSIMDReplace(
        curr->op, copy(curr->vec), curr->index, copy(curr->value));
    }
    Expression* visitSIMDShuffle(SIMDShuffle* curr) {
      return builder.makeSIMDShuffle(
        copy(curr->left), copy(curr->right), curr->mask);
    }
    Expression* visitSIMDBitselect(SIMDBitselect* curr) {
      return builder.makeSIMDBitselect(
        copy(curr->left), copy(curr->right), copy(curr->cond));
    }
    Expression* visitSIMDShift(SIMDShift* curr) {
      return builder.makeSIMDShift(
        curr->op, copy(curr->vec), copy(curr->shift));
    }
    Expression* visitConst(Const* curr) {
      return builder.makeConst(curr->value);
    }
    Expression* visitMemoryInit(MemoryInit* curr) {
      return builder.makeMemoryInit(
        curr->segment, copy(curr->dest), copy(curr->offset), copy(curr->size));
    }
    Expression* visitDataDrop(DataDrop* curr) {
      return builder.makeDataDrop(curr->segment);
    }
    Expression* visitMemoryCopy(MemoryCopy* curr) {
      return builder.makeMemoryCopy(
        copy(curr->dest), copy(curr->source), copy(curr->size));
    }
    Expression* visitMemoryFill(MemoryFill* curr) {
      return builder.makeMemoryFill(
        copy(curr->dest), copy(curr->value), copy(curr->size));
    }
    Expression* visitUnary(Unary* curr) {
      return builder.makeUnary(curr->op, copy(curr->value));
    }
    Expression* visitBinary(Binary* curr) {
      return builder.makeBinary(curr->op, copy(curr->left), copy(curr->right));
    }
    Expression* visitSelect(Select* curr) {
      return builder.makeSelect(
        copy(curr->condition), copy(curr->ifTrue), copy(curr->ifFalse));
    }
    Expression* visitDrop(Drop* curr) {
      return builder.makeDrop(copy(curr->value));
    }
    Expression* visitReturn(Return* curr) {
      return builder.makeReturn(copy(curr->value));
    }
    Expression* visitHost(Host* curr) {
      std::vector<Expression*> operands;
      for (Index i = 0; i < curr->operands.size(); i++) {
        operands.push_back(copy(curr->operands[i]));
      }
      auto* ret =
        builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
      return ret;
    }
    Expression* visitNop(Nop* curr) { return builder.makeNop(); }
    Expression* visitUnreachable(Unreachable* curr) {
      return builder.makeUnreachable();
    }
    Expression* visitPush(Push* curr) { return builder.makePush(curr->value); }
    Expression* visitPop(Pop* curr) { return builder.makePop(curr->type); }
  };

  Copier copier(wasm, custom);
  return copier.copy(original);
}

// Splice an item into the middle of a block's list
void spliceIntoBlock(Block* block, Index index, Expression* add) {
  auto& list = block->list;
  if (index == list.size()) {
    list.push_back(add); // simple append
  } else {
    // we need to make room
    list.push_back(nullptr);
    for (Index i = list.size() - 1; i > index; i--) {
      list[i] = list[i - 1];
    }
    list[index] = add;
  }
  block->finalize(block->type);
}

} // namespace ExpressionManipulator

} // namespace wasm
<commit_msg>Add missing copy in Copier::visitPush (#2295)<commit_after>/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ir/load-utils.h"
#include "ir/utils.h"
#include "support/hash.h"

namespace wasm {

namespace ExpressionManipulator {

Expression*
flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
  struct Copier : public OverriddenVisitor<Copier, Expression*> {
    Module& wasm;
    CustomCopier custom;

    Builder builder;

    Copier(Module& wasm, CustomCopier custom)
      : wasm(wasm), custom(custom), builder(wasm) {}

    Expression* copy(Expression* curr) {
      if (!curr) {
        return nullptr;
      }
      auto* ret = custom(curr);
      if (ret) {
        return ret;
      }
      return OverriddenVisitor<Copier, Expression*>::visit(curr);
    }

    Expression* visitBlock(Block* curr) {
      ExpressionList list(wasm.allocator);
      for (Index i = 0; i < curr->list.size(); i++) {
        list.push_back(copy(curr->list[i]));
      }
      return builder.makeBlock(curr->name, list, curr->type);
    }
    Expression* visitIf(If* curr) {
      return builder.makeIf(copy(curr->condition),
                            copy(curr->ifTrue),
                            copy(curr->ifFalse),
                            curr->type);
    }
    Expression* visitLoop(Loop* curr) {
      return builder.makeLoop(curr->name, copy(curr->body));
    }
    Expression* visitBreak(Break* curr) {
      return builder.makeBreak(
        curr->name, copy(curr->value), copy(curr->condition));
    }
    Expression* visitSwitch(Switch* curr) {
      return builder.makeSwitch(curr->targets,
                                curr->default_,
                                copy(curr->condition),
                                copy(curr->value));
    }
    Expression* visitCall(Call* curr) {
      auto* ret =
        builder.makeCall(curr->target, {}, curr->type, curr->isReturn);
      for (Index i = 0; i < curr->operands.size(); i++) {
        ret->operands.push_back(copy(curr->operands[i]));
      }
      return ret;
    }
    Expression* visitCallIndirect(CallIndirect* curr) {
      auto* ret = builder.makeCallIndirect(
        curr->fullType, copy(curr->target), {}, curr->type, curr->isReturn);
      for (Index i = 0; i < curr->operands.size(); i++) {
        ret->operands.push_back(copy(curr->operands[i]));
      }
      return ret;
    }
    Expression* visitLocalGet(LocalGet* curr) {
      return builder.makeLocalGet(curr->index, curr->type);
    }
    Expression* visitLocalSet(LocalSet* curr) {
      if (curr->isTee()) {
        return builder.makeLocalTee(curr->index, copy(curr->value));
      } else {
        return builder.makeLocalSet(curr->index, copy(curr->value));
      }
    }
    Expression* visitGlobalGet(GlobalGet* curr) {
      return builder.makeGlobalGet(curr->name, curr->type);
    }
    Expression* visitGlobalSet(GlobalSet* curr) {
      return builder.makeGlobalSet(curr->name, copy(curr->value));
    }
    Expression* visitLoad(Load* curr) {
      if (curr->isAtomic) {
        return builder.makeAtomicLoad(
          curr->bytes, curr->offset, copy(curr->ptr), curr->type);
      }
      return builder.makeLoad(curr->bytes,
                              LoadUtils::isSignRelevant(curr) ? curr->signed_
                                                              : false,
                              curr->offset,
                              curr->align,
                              copy(curr->ptr),
                              curr->type);
    }
    Expression* visitStore(Store* curr) {
      if (curr->isAtomic) {
        return builder.makeAtomicStore(curr->bytes,
                                       curr->offset,
                                       copy(curr->ptr),
                                       copy(curr->value),
                                       curr->valueType);
      }
      return builder.makeStore(curr->bytes,
                               curr->offset,
                               curr->align,
                               copy(curr->ptr),
                               copy(curr->value),
                               curr->valueType);
    }
    Expression* visitAtomicRMW(AtomicRMW* curr) {
      return builder.makeAtomicRMW(curr->op,
                                   curr->bytes,
                                   curr->offset,
                                   copy(curr->ptr),
                                   copy(curr->value),
                                   curr->type);
    }
    Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
      return builder.makeAtomicCmpxchg(curr->bytes,
                                       curr->offset,
                                       copy(curr->ptr),
                                       copy(curr->expected),
                                       copy(curr->replacement),
                                       curr->type);
    }
    Expression* visitAtomicWait(AtomicWait* curr) {
      return builder.makeAtomicWait(copy(curr->ptr),
                                    copy(curr->expected),
                                    copy(curr->timeout),
                                    curr->expectedType,
                                    curr->offset);
    }
    Expression* visitAtomicNotify(AtomicNotify* curr) {
      return builder.makeAtomicNotify(
        copy(curr->ptr), copy(curr->notifyCount), curr->offset);
    }
    Expression* visitSIMDExtract(SIMDExtract* curr) {
      return builder.makeSIMDExtract(curr->op, copy(curr->vec), curr->index);
    }
    Expression* visitSIMDReplace(SIMDReplace* curr) {
      return builder.makeSIMDReplace(
        curr->op, copy(curr->vec), curr->index, copy(curr->value));
    }
    Expression* visitSIMDShuffle(SIMDShuffle* curr) {
      return builder.makeSIMDShuffle(
        copy(curr->left), copy(curr->right), curr->mask);
    }
    Expression* visitSIMDBitselect(SIMDBitselect* curr) {
      return builder.makeSIMDBitselect(
        copy(curr->left), copy(curr->right), copy(curr->cond));
    }
    Expression* visitSIMDShift(SIMDShift* curr) {
      return builder.makeSIMDShift(
        curr->op, copy(curr->vec), copy(curr->shift));
    }
    Expression* visitConst(Const* curr) {
      return builder.makeConst(curr->value);
    }
    Expression* visitMemoryInit(MemoryInit* curr) {
      return builder.makeMemoryInit(
        curr->segment, copy(curr->dest), copy(curr->offset), copy(curr->size));
    }
    Expression* visitDataDrop(DataDrop* curr) {
      return builder.makeDataDrop(curr->segment);
    }
    Expression* visitMemoryCopy(MemoryCopy* curr) {
      return builder.makeMemoryCopy(
        copy(curr->dest), copy(curr->source), copy(curr->size));
    }
    Expression* visitMemoryFill(MemoryFill* curr) {
      return builder.makeMemoryFill(
        copy(curr->dest), copy(curr->value), copy(curr->size));
    }
    Expression* visitUnary(Unary* curr) {
      return builder.makeUnary(curr->op, copy(curr->value));
    }
    Expression* visitBinary(Binary* curr) {
      return builder.makeBinary(curr->op, copy(curr->left), copy(curr->right));
    }
    Expression* visitSelect(Select* curr) {
      return builder.makeSelect(
        copy(curr->condition), copy(curr->ifTrue), copy(curr->ifFalse));
    }
    Expression* visitDrop(Drop* curr) {
      return builder.makeDrop(copy(curr->value));
    }
    Expression* visitReturn(Return* curr) {
      return builder.makeReturn(copy(curr->value));
    }
    Expression* visitHost(Host* curr) {
      std::vector<Expression*> operands;
      for (Index i = 0; i < curr->operands.size(); i++) {
        operands.push_back(copy(curr->operands[i]));
      }
      auto* ret =
        builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
      return ret;
    }
    Expression* visitNop(Nop* curr) { return builder.makeNop(); }
    Expression* visitUnreachable(Unreachable* curr) {
      return builder.makeUnreachable();
    }
    Expression* visitPush(Push* curr) {
      return builder.makePush(copy(curr->value));
    }
    Expression* visitPop(Pop* curr) { return builder.makePop(curr->type); }
  };

  Copier copier(wasm, custom);
  return copier.copy(original);
}

// Splice an item into the middle of a block's list
void spliceIntoBlock(Block* block, Index index, Expression* add) {
  auto& list = block->list;
  if (index == list.size()) {
    list.push_back(add); // simple append
  } else {
    // we need to make room
    list.push_back(nullptr);
    for (Index i = list.size() - 1; i > index; i--) {
      list[i] = list[i - 1];
    }
    list[index] = add;
  }
  block->finalize(block->type);
}

} // namespace ExpressionManipulator

} // namespace wasm
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Implementation of object for charges in sensor
 * @copyright MIT License
 */

#ifndef ALLPIX_SENSOR_CHARGE_H
#define ALLPIX_SENSOR_CHARGE_H

#include <Math/Point3D.h>

#include "Object.hpp"

namespace allpix {
    /**
     * @ingroup Objects
     * @brief Base object for charge deposits and propagated charges in the sensor
     */
    class SensorCharge : public Object {
    public:
        /**
         * @brief Construct a set of charges in a sensor
         * @param local_position Local position of the set of charges in the sensor
         * @param global_position Global position of the set of charges in the sensor
         * @param charge Total charge at position
         * @param event_time Total time after event start
         */
        SensorCharge(ROOT::Math::XYZPoint local_position,
                     ROOT::Math::XYZPoint global_position,
                     unsigned int charge,
                     double event_time);

        /**
         * @brief Get local position of the set of charges in the sensor
         * @return Local position of charges
         */
        ROOT::Math::XYZPoint getLocalPosition() const;

        /**
         * @brief Get the global position of the set of charges in the sensor
         */
        ROOT::Math::XYZPoint getGlobalPosition() const;

        /**
         * @brief Get total amount of charges stored
         * @return Total charge stored
         */
        unsigned int getCharge() const;
        /**
         * @brief Get time after start of event
         * @return Time from start event
         */
        double getEventTime() const;

        /**
         * @brief ROOT class definition
         */
        ClassDef(SensorCharge, 2);
        /**
         * @brief Default constructor for ROOT I/O
         */
        SensorCharge() = default;

    private:
        ROOT::Math::XYZPoint local_position_;
        ROOT::Math::XYZPoint global_position_;

        unsigned int charge_{};
        double event_time_{};
    };
} // namespace allpix

#endif /* ALLPIX_SENSOR_CHARGE_H */
<commit_msg>Objects/SensorCharge: add CarrierType enum to distinguish between e/h<commit_after>/**
 * @file
 * @brief Implementation of object for charges in sensor
 * @copyright MIT License
 */

#ifndef ALLPIX_SENSOR_CHARGE_H
#define ALLPIX_SENSOR_CHARGE_H

#include <Math/Point3D.h>

#include "Object.hpp"

namespace allpix {
    /**
     * @ingroup Objects
     * @brief Flags to distinguish between eletron and hole charge carriers
     */
    enum class CarrierType : int8_t { ELECTRON = -1, HOLE = 1 };

    /**
     * @ingroup Objects
     * @brief Base object for charge deposits and propagated charges in the sensor
     */
    class SensorCharge : public Object {
    public:
        /**
         * @brief Construct a set of charges in a sensor
         * @param local_position Local position of the set of charges in the sensor
         * @param global_position Global position of the set of charges in the sensor
         * @param charge Total charge at position
         * @param event_time Total time after event start
         */
        SensorCharge(ROOT::Math::XYZPoint local_position,
                     ROOT::Math::XYZPoint global_position,
                     unsigned int charge,
                     double event_time);

        /**
         * @brief Get local position of the set of charges in the sensor
         * @return Local position of charges
         */
        ROOT::Math::XYZPoint getLocalPosition() const;

        /**
         * @brief Get the global position of the set of charges in the sensor
         */
        ROOT::Math::XYZPoint getGlobalPosition() const;

        /**
         * @brief Get total amount of charges stored
         * @return Total charge stored
         */
        unsigned int getCharge() const;
        /**
         * @brief Get time after start of event
         * @return Time from start event
         */
        double getEventTime() const;

        /**
         * @brief ROOT class definition
         */
        ClassDef(SensorCharge, 2);
        /**
         * @brief Default constructor for ROOT I/O
         */
        SensorCharge() = default;

    private:
        ROOT::Math::XYZPoint local_position_;
        ROOT::Math::XYZPoint global_position_;

        CarrierType type_{};
        unsigned int charge_{};
        double event_time_{};
    };
} // namespace allpix

#endif /* ALLPIX_SENSOR_CHARGE_H */
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_INTRUSIVE_TASK_QUEUE_HPP
#define CAF_INTRUSIVE_TASK_QUEUE_HPP

#include <utility>

#include "caf/intrusive/forward_iterator.hpp"

namespace caf {
namespace intrusive {

/// A singly-linked FIFO queue for storing tasks of varying size. This queue is
/// used as a base type for concrete task abstractions such as `drr_queue` and
/// therefore has no dequeue functions.
template <class Policy>
class task_queue {
public:
  // -- member types ----------------------------------------------------------

  using policy_type = Policy;

  using value_type = typename policy_type::mapped_type;

  using node_type = typename value_type::node_type;

  using node_pointer = node_type*;

  using pointer = value_type*;

  using const_pointer = const value_type*;

  using reference = value_type&;

  using const_reference = const value_type&;

  using deleter_type = typename policy_type::deleter_type;

  using unique_pointer = typename policy_type::unique_pointer;

  using task_size_type = typename policy_type::task_size_type;

  using iterator = forward_iterator<value_type>;

  // -- constructors, destructors, and assignment operators -------------------

  task_queue(policy_type p) : old_last_(nullptr), policy_(std::move(p)) {
    init();
  }

  task_queue(task_queue&& other) : task_queue(other.policy()) {
    if (other.empty()) {
      init();
    } else {
      head_.next = other.head_.next;
      tail_.next = other.tail_.next;
      tail_.next->next = &tail_;
      total_task_size_ = other.total_task_size_;
      other.init();
    }
  }

  task_queue& operator=(task_queue&& other) {
    deinit();
    if (other.empty()) {
      init();
    } else {
      head_.next = other.head_.next;
      tail_.next = other.tail_.next;
      tail_.next->next = &tail_;
      total_task_size_ = other.total_task_size_;
      other.init();
    }
    return *this;
  }

  virtual ~task_queue() {
    deinit();
  }

  // -- observers -------------------------------------------------------------

  /// Returns the policy object.
  const policy_type& policy() const noexcept {
    return policy_;
  }

  /// Returns the accumulated size of all stored tasks.
  task_size_type total_task_size() const noexcept {
    return total_task_size_;
  }

  /// Returns whether the queue has no elements.
  bool empty() const noexcept {
    return total_task_size() == 0;
  }

  /// Peeks at the first element in the queue. Returns `nullptr` if the queue is
  /// empty.
  pointer peek() noexcept {
    auto ptr = head_.next;
    return ptr != &tail_ ? promote(ptr) : nullptr;
  }

  // -- modifiers -------------------------------------------------------------

  /// Removes all elements from the queue.
  void clear() {
    deinit();
    init();
  }

  /// Appends `ptr` to the queue.
  /// @pre `ptr != nullptr`
  bool push_back(pointer ptr) noexcept {
    CAF_ASSERT(ptr != nullptr);
    tail_.next->next = ptr;
    tail_.next = ptr;
    ptr->next = &tail_;
    inc_total_task_size(*ptr);
    return true;
  }

  /// Appends `ptr` to the queue.
  /// @pre `ptr != nullptr`
  bool push_back(unique_pointer ptr) noexcept {
    return push_back(ptr.release());
  }

  /// Creates a new element from `xs...` and appends it.
  template <class... Ts>
  bool emplace_back(Ts&&... xs) {
    return push_back(new value_type(std::forward<Ts>(xs)...));
  }

  /// @private
  void inc_total_task_size(task_size_type x) noexcept {
    total_task_size_ += x;
  }

  /// @private
  void inc_total_task_size(const value_type& x) noexcept {
    inc_total_task_size(policy_.task_size(x));
  }

  /// Returns an iterator to the dummy before the first element.
  iterator before_begin() noexcept {
    return &head_;
  }

  /// Returns an iterator to the dummy before the first element.
  iterator begin() noexcept {
    return head_.next;
  }

  /// Returns a pointer to the dummy past the last element.
  iterator end() noexcept {
    return &tail_;
  }

  /// Returns a pointer to the first element.
  pointer front() noexcept {
    return promote(head_.next);
  }

  /// Returns a pointer to the last element.
  pointer back() noexcept {
    return promote(tail_.next);
  }

  /// Transfers all element from `other` to the front of this queue.
  template <class Container>
  void prepend(Container& other) {
    if (other.empty())
      return;
    if (empty()) {
      *this = std::move(other);
      return;
    }
    other.back()->next = head_.next;
    head_.next = other.front();
    total_task_size_ += other.total_task_size();
    other.init();
  }

  /// Transfers all element from `other` to the back of this queue.
  template <class Container>
  void append(Container& other) {
    if (other.empty())
      return;
    if (empty()) {
      *this = std::move(other);
      return;
    }
    back()->next = other.front();
    other.back()->next = &tail_;
    tail_.next = other.back();
    total_task_size_ += other.total_task_size();
    other.init();
  }

  /// Allows to insert a LIFO-ordered sequence at the end of the queue by
  /// calling this member function multiple times. Converts the order to FIFO
  /// on the fly.
  /// @warning leaves the queue in an invalid state until calling
  ///          `stop_lifo_append`.
  /// @private
  void lifo_append(node_pointer ptr) {
    if (old_last_ == nullptr) {
      old_last_ = back();
      push_back(promote(ptr));
    } else {
      ptr->next = new_head_;
      inc_total_task_size(*promote(ptr));
    }
    new_head_ = ptr;
  }

  /// Restores a consistent state of the queue after calling `lifo_append`.
  /// @private
  void stop_lifo_append() {
    if (old_last_ != nullptr) {
      CAF_ASSERT(new_head_ != nullptr);
      old_last_->next = new_head_;
      old_last_ = nullptr;
    }
  }

  // -- construction and destruction helper -----------------------------------

  /// Restores a consistent, empty state.
  /// @private
  void init() noexcept {
    head_.next = &tail_;
    tail_.next = &head_;
    total_task_size_ = 0;
  }

  /// Deletes all elements.
  /// @warning leaves the queue in an invalid state until calling `init` again.
  /// @private
  void deinit() noexcept {
    for (auto i = head_.next; i != &tail_;) {
      auto ptr = i;
      i = i->next;
      deleter_type d;
      d(promote(ptr));
    }
  }

protected:
  // -- member variables ------------------------------------------------------

  /// node element pointing to the first element.
  node_type head_;

  /// node element pointing past the last element.
  node_type tail_;

  /// Stores the total size of all items in the queue.
  task_size_type total_task_size_ = 0;

  /// Used for LIFO -> FIFO insertion.
  node_pointer old_last_;

  /// Used for LIFO -> FIFO insertion.
  node_pointer new_head_;

  /// Manipulates instances of T.
  policy_type policy_;
};

} // namespace intrusive
} // namespace caf

#endif // CAF_INTRUSIVE_TASK_QUEUE_HPP
<commit_msg>Add missing policy getter to task_queue<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_INTRUSIVE_TASK_QUEUE_HPP
#define CAF_INTRUSIVE_TASK_QUEUE_HPP

#include <utility>

#include "caf/intrusive/forward_iterator.hpp"

namespace caf {
namespace intrusive {

/// A singly-linked FIFO queue for storing tasks of varying size. This queue is
/// used as a base type for concrete task abstractions such as `drr_queue` and
/// therefore has no dequeue functions.
template <class Policy>
class task_queue {
public:
  // -- member types ----------------------------------------------------------

  using policy_type = Policy;

  using value_type = typename policy_type::mapped_type;

  using node_type = typename value_type::node_type;

  using node_pointer = node_type*;

  using pointer = value_type*;

  using const_pointer = const value_type*;

  using reference = value_type&;

  using const_reference = const value_type&;

  using deleter_type = typename policy_type::deleter_type;

  using unique_pointer = typename policy_type::unique_pointer;

  using task_size_type = typename policy_type::task_size_type;

  using iterator = forward_iterator<value_type>;

  // -- constructors, destructors, and assignment operators -------------------

  task_queue(policy_type p) : old_last_(nullptr), policy_(std::move(p)) {
    init();
  }

  task_queue(task_queue&& other) : task_queue(other.policy()) {
    if (other.empty()) {
      init();
    } else {
      head_.next = other.head_.next;
      tail_.next = other.tail_.next;
      tail_.next->next = &tail_;
      total_task_size_ = other.total_task_size_;
      other.init();
    }
  }

  task_queue& operator=(task_queue&& other) {
    deinit();
    if (other.empty()) {
      init();
    } else {
      head_.next = other.head_.next;
      tail_.next = other.tail_.next;
      tail_.next->next = &tail_;
      total_task_size_ = other.total_task_size_;
      other.init();
    }
    return *this;
  }

  virtual ~task_queue() {
    deinit();
  }

  // -- observers -------------------------------------------------------------

  /// Returns the policy object.
  policy_type& policy() noexcept {
    return policy_;
  }

  /// Returns the policy object.
  const policy_type& policy() const noexcept {
    return policy_;
  }

  /// Returns the accumulated size of all stored tasks.
  task_size_type total_task_size() const noexcept {
    return total_task_size_;
  }

  /// Returns whether the queue has no elements.
  bool empty() const noexcept {
    return total_task_size() == 0;
  }

  /// Peeks at the first element in the queue. Returns `nullptr` if the queue is
  /// empty.
  pointer peek() noexcept {
    auto ptr = head_.next;
    return ptr != &tail_ ? promote(ptr) : nullptr;
  }

  // -- modifiers -------------------------------------------------------------

  /// Removes all elements from the queue.
  void clear() {
    deinit();
    init();
  }

  /// Appends `ptr` to the queue.
  /// @pre `ptr != nullptr`
  bool push_back(pointer ptr) noexcept {
    CAF_ASSERT(ptr != nullptr);
    tail_.next->next = ptr;
    tail_.next = ptr;
    ptr->next = &tail_;
    inc_total_task_size(*ptr);
    return true;
  }

  /// Appends `ptr` to the queue.
  /// @pre `ptr != nullptr`
  bool push_back(unique_pointer ptr) noexcept {
    return push_back(ptr.release());
  }

  /// Creates a new element from `xs...` and appends it.
  template <class... Ts>
  bool emplace_back(Ts&&... xs) {
    return push_back(new value_type(std::forward<Ts>(xs)...));
  }

  /// @private
  void inc_total_task_size(task_size_type x) noexcept {
    total_task_size_ += x;
  }

  /// @private
  void inc_total_task_size(const value_type& x) noexcept {
    inc_total_task_size(policy_.task_size(x));
  }

  /// Returns an iterator to the dummy before the first element.
  iterator before_begin() noexcept {
    return &head_;
  }

  /// Returns an iterator to the dummy before the first element.
  iterator begin() noexcept {
    return head_.next;
  }

  /// Returns a pointer to the dummy past the last element.
  iterator end() noexcept {
    return &tail_;
  }

  /// Returns a pointer to the first element.
  pointer front() noexcept {
    return promote(head_.next);
  }

  /// Returns a pointer to the last element.
  pointer back() noexcept {
    return promote(tail_.next);
  }

  /// Transfers all element from `other` to the front of this queue.
  template <class Container>
  void prepend(Container& other) {
    if (other.empty())
      return;
    if (empty()) {
      *this = std::move(other);
      return;
    }
    other.back()->next = head_.next;
    head_.next = other.front();
    total_task_size_ += other.total_task_size();
    other.init();
  }

  /// Transfers all element from `other` to the back of this queue.
  template <class Container>
  void append(Container& other) {
    if (other.empty())
      return;
    if (empty()) {
      *this = std::move(other);
      return;
    }
    back()->next = other.front();
    other.back()->next = &tail_;
    tail_.next = other.back();
    total_task_size_ += other.total_task_size();
    other.init();
  }

  /// Allows to insert a LIFO-ordered sequence at the end of the queue by
  /// calling this member function multiple times. Converts the order to FIFO
  /// on the fly.
  /// @warning leaves the queue in an invalid state until calling
  ///          `stop_lifo_append`.
  /// @private
  void lifo_append(node_pointer ptr) {
    if (old_last_ == nullptr) {
      old_last_ = back();
      push_back(promote(ptr));
    } else {
      ptr->next = new_head_;
      inc_total_task_size(*promote(ptr));
    }
    new_head_ = ptr;
  }

  /// Restores a consistent state of the queue after calling `lifo_append`.
  /// @private
  void stop_lifo_append() {
    if (old_last_ != nullptr) {
      CAF_ASSERT(new_head_ != nullptr);
      old_last_->next = new_head_;
      old_last_ = nullptr;
    }
  }

  // -- construction and destruction helper -----------------------------------

  /// Restores a consistent, empty state.
  /// @private
  void init() noexcept {
    head_.next = &tail_;
    tail_.next = &head_;
    total_task_size_ = 0;
  }

  /// Deletes all elements.
  /// @warning leaves the queue in an invalid state until calling `init` again.
  /// @private
  void deinit() noexcept {
    for (auto i = head_.next; i != &tail_;) {
      auto ptr = i;
      i = i->next;
      deleter_type d;
      d(promote(ptr));
    }
  }

protected:
  // -- member variables ------------------------------------------------------

  /// node element pointing to the first element.
  node_type head_;

  /// node element pointing past the last element.
  node_type tail_;

  /// Stores the total size of all items in the queue.
  task_size_type total_task_size_ = 0;

  /// Used for LIFO -> FIFO insertion.
  node_pointer old_last_;

  /// Used for LIFO -> FIFO insertion.
  node_pointer new_head_;

  /// Manipulates instances of T.
  policy_type policy_;
};

} // namespace intrusive
} // namespace caf

#endif // CAF_INTRUSIVE_TASK_QUEUE_HPP
<|endoftext|>


<commit_before>AliAnalysisTaskMinijet* AddTaskMinijet(Int_t runNumber, TString format="esd",Bool_t useMC = kFALSE, TString kGridDataSet="LHC10e")
{

  //starting with periode LHC10e, there are also events triggered with High Mult trigger
  //add stand alone task in case these events are availale
  Bool_t IsHighMult= (!kGridDataSet.CompareTo("LHC10e") || !kGridDataSet.CompareTo("LHC10f"));
  //extent with new periods (LHC10g,h,...)

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) mgr = new AliAnalysisManager("Analysis train");

  // Set cuts (used for ESDs)
  //===========================================================================
  AliESDtrackCuts* esdTrackCutsITSTPC=0x0;
  if(!format.CompareTo("esd")){
    esdTrackCutsITSTPC = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010(kTRUE);
  }

  // Configure tasks
  //===========================================================================

  //first task for min bias events
  AliAnalysisTaskMinijet *task = new AliAnalysisTaskMinijet("AliAnalysisTaskMinijet Min bias");
  task->UseMC(useMC);
  task->SetRadiusCut(0.7);
  task->SetTriggerPtCut(0.7);
  task->SetAssociatePtCut(0.4);
  task->SetEventAxis(1); //1=random track
  task->SetDebugLevel(0);
  task->SetMaxVertexZ(10.);
  if(!format.CompareTo("esd")){
    task->SetCuts(esdTrackCutsITSTPC);
    task->SetMode(0);//0=reading ESDs
    task->SelectCollisionCandidates(AliVEvent::kMB);//MB
  }

  //second task for high multipliciy events
  AliAnalysisTaskMinijet *taskHM =0x0;
  if(IsHighMult && !format.CompareTo("esd")){
    taskHM  = new AliAnalysisTaskMinijet("AliAnalysisTaskMinijet HighMult");
    taskHM->UseMC(useMC);
    taskHM->SetRadiusCut(0.7);
    taskHM->SetTriggerPtCut(0.7);
    taskHM->SetAssociatePtCut(0.4);
    taskHM->SetEventAxis(1); //1=random track
    taskHM->SetDebugLevel(0);
    taskHM->SetMaxVertexZ(10.);
    taskHM->SetCuts(esdTrackCutsITSTPC);
    taskHM->SetMode(0);//0=reading ESDs
    taskHM->SelectCollisionCandidates(AliVEvent::kHighMult);//high mult triggered event
  }

  if (!format.CompareTo("aod")){
    task->SetMode(1);// 1 = reading AODs
  }

  //create output containers
  //===========================================================================
  AliAnalysisDataContainer *output1  = 0x0;
  AliAnalysisDataContainer *outputHM = 0x0;

  if(runNumber>0){
    output1  =  mgr->CreateContainer("MiniJets",TList::Class(),
				  AliAnalysisManager::kOutputContainer, Form("run%d.root",runNumber));
    outputHM =  mgr->CreateContainer("MiniJets_HighMult",TList::Class(),
				  AliAnalysisManager::kOutputContainer, Form("run%d.root",runNumber));
   }

   else{
     output1  = mgr->CreateContainer("MiniJets",TList::Class(),
				 AliAnalysisManager::kOutputContainer,
				 Form("%s:PWG4_MiniJets",AliAnalysisManager::GetCommonFileName()));
     outputHM = mgr->CreateContainer("MiniJets_HighMult",TList::Class(),
				     AliAnalysisManager::kOutputContainer,
				     Form("%s:PWG4_MiniJets",AliAnalysisManager::GetCommonFileName()));

   }

  //===========================================================================
  // add first task to the manager

  mgr->AddTask(task);

  //connect input and output
  mgr->ConnectInput(task, 0,  mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, output1);

  //===========================================================================
  //do same for high mult task if necassary
  if(!format.CompareTo("esd") && IsHighMult){

    // add task to the manager
    mgr->AddTask(taskHM);

    //connect input and output
    mgr->ConnectInput (taskHM, 0,  mgr->GetCommonInputContainer());
    mgr->ConnectOutput(taskHM, 1, outputHM);
  }

  return task;

}

<commit_msg>fix: generate DataContainer highmult data only it is needed<commit_after>AliAnalysisTaskMinijet* AddTaskMinijet(Int_t runNumber, TString format="esd",Bool_t useMC = kFALSE, TString kGridDataSet="LHC10e")
{

  //starting with periode LHC10e, there are also events triggered with High Mult trigger
  //add stand alone task in case these events are availale
  Bool_t IsHighMult= (!kGridDataSet.CompareTo("LHC10e") || !kGridDataSet.CompareTo("LHC10f"));
  //extent with new periods (LHC10g,h,...)

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) mgr = new AliAnalysisManager("Analysis train");

  // Set cuts (used for ESDs)
  //===========================================================================
  AliESDtrackCuts* esdTrackCutsITSTPC=0x0;
  if(!format.CompareTo("esd")){
    esdTrackCutsITSTPC = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010(kTRUE);
  }

  // Configure tasks
  //===========================================================================

  //first task for min bias events
  AliAnalysisTaskMinijet *task = new AliAnalysisTaskMinijet("AliAnalysisTaskMinijet Min bias");
  task->UseMC(useMC);
  task->SetRadiusCut(0.7);
  task->SetTriggerPtCut(0.7);
  task->SetAssociatePtCut(0.4);
  task->SetEventAxis(1); //1=random track
  task->SetDebugLevel(0);
  task->SetMaxVertexZ(10.);
  if(!format.CompareTo("esd")){
    task->SetCuts(esdTrackCutsITSTPC);
    task->SetMode(0);//0=reading ESDs
    task->SelectCollisionCandidates(AliVEvent::kMB);//MB
  }

  //second task for high multipliciy events
  AliAnalysisTaskMinijet *taskHM =0x0;
  if(IsHighMult && !format.CompareTo("esd")){
    taskHM  = new AliAnalysisTaskMinijet("AliAnalysisTaskMinijet HighMult");
    taskHM->UseMC(useMC);
    taskHM->SetRadiusCut(0.7);
    taskHM->SetTriggerPtCut(0.7);
    taskHM->SetAssociatePtCut(0.4);
    taskHM->SetEventAxis(1); //1=random track
    taskHM->SetDebugLevel(0);
    taskHM->SetMaxVertexZ(10.);
    taskHM->SetCuts(esdTrackCutsITSTPC);
    taskHM->SetMode(0);//0=reading ESDs
    taskHM->SelectCollisionCandidates(AliVEvent::kHighMult);//high mult triggered event
  }

  if (!format.CompareTo("aod")){
    task->SetMode(1);// 1 = reading AODs
  }

  //create output containers
  //===========================================================================
  AliAnalysisDataContainer *output1  = 0x0;
  AliAnalysisDataContainer *outputHM = 0x0;

  if(runNumber>0){
    output1  =  mgr->CreateContainer("MiniJets",TList::Class(),
				  AliAnalysisManager::kOutputContainer, Form("run%d.root",runNumber));
    if(!format.CompareTo("esd") && IsHighMult){
      outputHM =  mgr->CreateContainer("MiniJets_HighMult",TList::Class(),
				       AliAnalysisManager::kOutputContainer, Form("run%d.root",runNumber));
    }
   }

   else{
     output1  = mgr->CreateContainer("MiniJets",TList::Class(),
				 AliAnalysisManager::kOutputContainer,
				 Form("%s:PWG4_MiniJets",AliAnalysisManager::GetCommonFileName()));
     if(!format.CompareTo("esd") && IsHighMult){
       outputHM = mgr->CreateContainer("MiniJets_HighMult",TList::Class(),
				       AliAnalysisManager::kOutputContainer,
				       Form("%s:PWG4_MiniJets",AliAnalysisManager::GetCommonFileName()));
     }

   }

  //===========================================================================
  // add first task to the manager

  mgr->AddTask(task);

  //connect input and output
  mgr->ConnectInput(task, 0,  mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, output1);

  //===========================================================================
  //do same for high mult task if necassary
  if(!format.CompareTo("esd") && IsHighMult){

    // add task to the manager
    mgr->AddTask(taskHM);

    //connect input and output
    mgr->ConnectInput (taskHM, 0,  mgr->GetCommonInputContainer());
    mgr->ConnectOutput(taskHM, 1, outputHM);
  }

  return task;

}

<|endoftext|>


<commit_before>
#include "Math_basics.h"

namespace P_RVD
{
	namespace Math
	{
		Vector3d computeCenter(const Vector3d p1, const Vector3d p2, const Vector3d p3)
		{
			return Vector3d((p1.x + p2.x + p3.x) / 3,
				(p1.y + p2.y + p3.y) / 3,
				(p1.z + p2.z + p3.z) / 3);
		}

		float computeDistance(const Vector3d p1, const Vector3d p2)
		{
			return (p1.x - p2.x) * (p1.x - p2.x)
				+ (p1.y - p2.y) * (p1.y - p2.y)
				+ (p1.z - p2.z) * (p1.z - p2.z);
		}
	}
}<commit_msg>add computeTriangleArea<commit_after>
#include "Math_basics.h"

namespace P_RVD
{
	namespace Math
	{
		Vector3d computeCenter(const Vector3d p1, const Vector3d p2, const Vector3d p3)
		{
			return Vector3d((p1.x + p2.x + p3.x) / 3,
				(p1.y + p2.y + p3.y) / 3,
				(p1.z + p2.z + p3.z) / 3);
		}

		double computeDistance(const Vector3d p1, const Vector3d p2)
		{
			return (p1.x - p2.x) * (p1.x - p2.x)
				+ (p1.y - p2.y) * (p1.y - p2.y)
				+ (p1.z - p2.z) * (p1.z - p2.z);
		}

		double computeTriangleArea(const Vector3d p1, const Vector3d p2, const Vector3d p3)
		{
			double a = computeDistance(p1, p2);
			double b = computeDistance(p2, p3);
			double c = computeDistance(p1, p3);

			//Heron's Formula to compute the area of the triangle
			double p = (a + b + c) / 2;
			double tmp = geo_max(a, b);
			if (p > geo_max(tmp, c))
				return sqrt(p * (p - a) * (p - b) * (p - c));
			else
				fprintf(stderr, "the three point cannot construct a triangle!");
			return 0.0;
		}
	}
}<|endoftext|>


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

#ifndef STRINGUTIL_HH
#define STRINGUTIL_HH

#include <algorithm>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

namespace fsqueeze {

/**
 * Parse a string.
 * @The string to be parsed.
 */
template <typename T>
T parseString(std::string const &str)
{
	std::istringstream iss(str);
	T val;
	iss >> val;

	if (!iss)
		throw std::invalid_argument("Error parsing option argument: " +
str);

	return val;
}

/**
 * Split a string on whitespace.
 * @str The string to be split.
 */
std::vector<std::string> stringSplit(std::string str)
{
	std::istringstream iss(str);
	std::vector<std::string> strParts;
	copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
		back_inserter(strParts));

	return strParts;
}

}

#endif // STRINGUTIL_HH<commit_msg>parseString: correct error message.<commit_after>/*
 * Copyright (c) 2009 Daniël de Kok
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA
 */

#ifndef STRINGUTIL_HH
#define STRINGUTIL_HH

#include <algorithm>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

namespace fsqueeze {

/**
 * Parse a string.
 * @The string to be parsed.
 */
template <typename T>
T parseString(std::string const &str)
{
	std::istringstream iss(str);
	T val;
	iss >> val;

	if (!iss)
		throw std::invalid_argument("Error parsing: " +
str);

	return val;
}

/**
 * Split a string on whitespace.
 * @str The string to be split.
 */
std::vector<std::string> stringSplit(std::string str)
{
	std::istringstream iss(str);
	std::vector<std::string> strParts;
	copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
		back_inserter(strParts));

	return strParts;
}

}

#endif // STRINGUTIL_HH<|endoftext|>


<commit_before>#include "Vector2.h"

#include <ostream>

#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif

#ifndef EQ_THRESHOLD
#define EQ_THRESHOLD 0.00001
#endif

std::ostream& operator<<(std::ostream& os, const Vector2& v)
{
	os << "(" << v.x << ", " << v.y << ")";
	return os;
}

Vector2::Vector2() :
	x(0.0),
	y(0.0)
{

}

Vector2::Vector2(double angle) :
	x(cos(angle * M_PI / 180)),
	y(sin(angle * M_PI / 180))
{

}

Vector2::Vector2(double _x, double _y) :
	x(_x),
	y(_y)
{

}

Vector2::Vector2(const Vector2& v1, const Vector2& v2) :
	x(v2.x - v1.x),
	y(v2.y - v1.y)
{

}

Vector2::~Vector2()
{

}

Vector2::Vector2(const Vector2& v) :
	x(v.x),
	y(v.y)
{

}

Vector2::Vector2(Vector2&& v) :
	x(v.x),
	y(v.y)
{

}

Vector2& Vector2::operator=(const Vector2& v)
{
	if (&v == this)
	{
		return *this;
	}

	x = v.x;
	y = v.y;

	return *this;
}

Vector2& Vector2::operator=(Vector2&& v)
{
	if (&v == this)
	{
		return *this;
	}

	x = v.x;
	y = v.y;

	return *this;
}

Vector2& Vector2::operator+=(const Vector2& v)
{
	x += v.x;
	y += v.y;

	return *this;
}

Vector2& Vector2::operator+=(const double f)
{
	x += f;
	y += f;

	return *this;
}

Vector2& Vector2::operator-=(const Vector2& v)
{
	x -= v.x;
	y -= v.y;

	return *this;
}

Vector2& Vector2::operator-=(const double f)
{
	x -= f;
	y -= f;

	return *this;
}

Vector2& Vector2::operator*=(const double f)
{
	x *= f;
	y *= f;

	return *this;
}

Vector2& Vector2::operator/=(const double f)
{
	x /= f;
	y /= f;

	return *this;
}

bool Vector2::operator==(const Vector2& v) const
{
	double diffX = abs(x - v.x);
	double diffY = abs(y - v.y);

	return diffX < EQ_THRESHOLD && diffY < EQ_THRESHOLD;
}

bool Vector2::operator!=(const Vector2& v) const
{
	return !(*this == v);
}

void Vector2::Normalize()
{
	double mod = Length();

	if (mod > 0)
	{
		x /= mod;
		y /= mod;
	}
}

void Vector2::Reflect(const Vector2& v)
{
	*this += 2.0 * DotProduct(v) * Vector2(v.x * -1, v.y * -1);
}

void Vector2::Reverse()
{
	x *= -1;
	y *= -1;
}

void Vector2::Truncate(double maxLength)
{
	if (Length() > maxLength)
	{
		Normalize();
		*this *= maxLength;
	}
}

void Vector2::RotateByDegree(double degree)
{
	RotateByRadian(degree * M_PI / 180);
}

void Vector2::RotateByRadian(double radian)
{
	double newX = x * cos(radian) - y * sin(radian);
	double newY = x * sin(radian) + y * cos(radian);

	x = newX;
	y = newY;
}

double Vector2::DotProduct(const Vector2& v) const
{
	return x * v.x + y * v.y;
}

double Vector2::CrossProduct(const Vector2& v) const
{
	return x * v.y - v.x * y;
}

double Vector2::Length() const
{
	return sqrt(x * x + y * y);
}

double Vector2::LengthSqrt() const
{
	return x * x + y * y;
}

double Vector2::Distance(const Vector2& v) const
{
	Vector2 dist(*this, v);
	return dist.Length();
}

double Vector2::DistanceSqrt(const Vector2& v) const
{
	Vector2 dist(*this, v);
	return dist.LengthSqrt();
}

double Vector2::GetAngleByDegree() const
{
	return GetAngleByRadian() * 180 / M_PI;
}

double Vector2::GetAngleByDegree(const Vector2& v) const
{
	return GetAngleByRadian(v) * 180 / M_PI;
}

double Vector2::GetAngleByRadian() const
{
	if (IsZero())
	{
		return 0;
	}

	return atan2(y, x);
}

double Vector2::GetAngleByRadian(const Vector2& v) const
{
	if (IsZero() || v.IsZero())
	{
		return 0;
	}

	double angle = atan2(v.y - y, v.x - x);
	return angle;
}

bool Vector2::Sign(const Vector2& v) const
{
	return x * v.y > v.x * y;
}

bool Vector2::IsZero() const
{
	return x == 0 && y == 0;
}

Vector2 operator+(const Vector2& lhs, const Vector2& rhs)
{
	Vector2 aux(lhs);
	aux += rhs;

	return aux;
}

Vector2 operator-(const Vector2& lhs, const Vector2& rhs)
{
	Vector2 aux(lhs);
	aux -= rhs;

	return aux;
}

Vector2 operator*(const double fac, const Vector2& rhs)
{
	Vector2 aux(rhs);
	aux *= fac;

	return aux;
}
Vector2 operator*(const Vector2& lhs, const double fac)
{
	Vector2 aux(lhs);
	aux *= fac;

	return aux;
}

Vector2 operator/(const Vector2& lhs, const double fac)
{
	Vector2 aux(lhs);
	aux /= fac;

	return aux;
}

Vector2 Normalize(const Vector2& v) {
	Vector2 aux(v);
	aux.Normalize();

	return aux;
}

Vector2 Reflect(const Vector2& v1, const Vector2& v2) {
	Vector2 aux(v1);
	aux.Reflect(v2);

	return aux;
}

Vector2 Reverse(const Vector2& v) {
	Vector2 aux(v);
	aux.Reverse();

	return aux;
}

Vector2 Truncate(const Vector2& v, double maxLength) {
	Vector2 aux(v);
	aux.Truncate(maxLength);

	return aux;
}

Vector2 RotateByDegree(const Vector2& v, double degree) {
	Vector2 aux(v);
	aux.RotateByDegree(degree);

	return aux;
}

Vector2 RotateByRadian(const Vector2& v, double radian) {
	Vector2 aux(v);
	aux.RotateByRadian(radian);

	return aux;
}

double Distance(const Vector2& v1, const Vector2& v2) {
	Vector2 aux(v1, v2);

	return aux.Length();
}<commit_msg>Modify macro to const variable<commit_after>#include "Vector2.h"

#include <ostream>

const double M_PI = 3.14159265358979323846264338327;
const double EQ_THRESHOLD = 0.00001;

std::ostream& operator<<(std::ostream& os, const Vector2& v)
{
	os << "(" << v.x << ", " << v.y << ")";
	return os;
}

Vector2::Vector2() :
	x(0.0),
	y(0.0)
{

}

Vector2::Vector2(double angle) :
	x(cos(angle * M_PI / 180)),
	y(sin(angle * M_PI / 180))
{

}

Vector2::Vector2(double _x, double _y) :
	x(_x),
	y(_y)
{

}

Vector2::Vector2(const Vector2& v1, const Vector2& v2) :
	x(v2.x - v1.x),
	y(v2.y - v1.y)
{

}

Vector2::~Vector2()
{

}

Vector2::Vector2(const Vector2& v) :
	x(v.x),
	y(v.y)
{

}

Vector2::Vector2(Vector2&& v) :
	x(v.x),
	y(v.y)
{

}

Vector2& Vector2::operator=(const Vector2& v)
{
	if (&v == this)
	{
		return *this;
	}

	x = v.x;
	y = v.y;

	return *this;
}

Vector2& Vector2::operator=(Vector2&& v)
{
	if (&v == this)
	{
		return *this;
	}

	x = v.x;
	y = v.y;

	return *this;
}

Vector2& Vector2::operator+=(const Vector2& v)
{
	x += v.x;
	y += v.y;

	return *this;
}

Vector2& Vector2::operator+=(const double f)
{
	x += f;
	y += f;

	return *this;
}

Vector2& Vector2::operator-=(const Vector2& v)
{
	x -= v.x;
	y -= v.y;

	return *this;
}

Vector2& Vector2::operator-=(const double f)
{
	x -= f;
	y -= f;

	return *this;
}

Vector2& Vector2::operator*=(const double f)
{
	x *= f;
	y *= f;

	return *this;
}

Vector2& Vector2::operator/=(const double f)
{
	x /= f;
	y /= f;

	return *this;
}

bool Vector2::operator==(const Vector2& v) const
{
	double diffX = abs(x - v.x);
	double diffY = abs(y - v.y);

	return diffX < EQ_THRESHOLD && diffY < EQ_THRESHOLD;
}

bool Vector2::operator!=(const Vector2& v) const
{
	return !(*this == v);
}

void Vector2::Normalize()
{
	double mod = Length();

	if (mod > 0)
	{
		x /= mod;
		y /= mod;
	}
}

void Vector2::Reflect(const Vector2& v)
{
	*this += 2.0 * DotProduct(v) * Vector2(v.x * -1, v.y * -1);
}

void Vector2::Reverse()
{
	x *= -1;
	y *= -1;
}

void Vector2::Truncate(double maxLength)
{
	if (Length() > maxLength)
	{
		Normalize();
		*this *= maxLength;
	}
}

void Vector2::RotateByDegree(double degree)
{
	RotateByRadian(degree * M_PI / 180);
}

void Vector2::RotateByRadian(double radian)
{
	double newX = x * cos(radian) - y * sin(radian);
	double newY = x * sin(radian) + y * cos(radian);

	x = newX;
	y = newY;
}

double Vector2::DotProduct(const Vector2& v) const
{
	return x * v.x + y * v.y;
}

double Vector2::CrossProduct(const Vector2& v) const
{
	return x * v.y - v.x * y;
}

double Vector2::Length() const
{
	return sqrt(x * x + y * y);
}

double Vector2::LengthSqrt() const
{
	return x * x + y * y;
}

double Vector2::Distance(const Vector2& v) const
{
	Vector2 dist(*this, v);
	return dist.Length();
}

double Vector2::DistanceSqrt(const Vector2& v) const
{
	Vector2 dist(*this, v);
	return dist.LengthSqrt();
}

double Vector2::GetAngleByDegree() const
{
	return GetAngleByRadian() * 180 / M_PI;
}

double Vector2::GetAngleByDegree(const Vector2& v) const
{
	return GetAngleByRadian(v) * 180 / M_PI;
}

double Vector2::GetAngleByRadian() const
{
	if (IsZero())
	{
		return 0;
	}

	return atan2(y, x);
}

double Vector2::GetAngleByRadian(const Vector2& v) const
{
	if (IsZero() || v.IsZero())
	{
		return 0;
	}

	double angle = atan2(v.y - y, v.x - x);
	return angle;
}

bool Vector2::Sign(const Vector2& v) const
{
	return x * v.y > v.x * y;
}

bool Vector2::IsZero() const
{
	return x == 0 && y == 0;
}

Vector2 operator+(const Vector2& lhs, const Vector2& rhs)
{
	Vector2 aux(lhs);
	aux += rhs;

	return aux;
}

Vector2 operator-(const Vector2& lhs, const Vector2& rhs)
{
	Vector2 aux(lhs);
	aux -= rhs;

	return aux;
}

Vector2 operator*(const double fac, const Vector2& rhs)
{
	Vector2 aux(rhs);
	aux *= fac;

	return aux;
}
Vector2 operator*(const Vector2& lhs, const double fac)
{
	Vector2 aux(lhs);
	aux *= fac;

	return aux;
}

Vector2 operator/(const Vector2& lhs, const double fac)
{
	Vector2 aux(lhs);
	aux /= fac;

	return aux;
}

Vector2 Normalize(const Vector2& v) {
	Vector2 aux(v);
	aux.Normalize();

	return aux;
}

Vector2 Reflect(const Vector2& v1, const Vector2& v2) {
	Vector2 aux(v1);
	aux.Reflect(v2);

	return aux;
}

Vector2 Reverse(const Vector2& v) {
	Vector2 aux(v);
	aux.Reverse();

	return aux;
}

Vector2 Truncate(const Vector2& v, double maxLength) {
	Vector2 aux(v);
	aux.Truncate(maxLength);

	return aux;
}

Vector2 RotateByDegree(const Vector2& v, double degree) {
	Vector2 aux(v);
	aux.RotateByDegree(degree);

	return aux;
}

Vector2 RotateByRadian(const Vector2& v, double radian) {
	Vector2 aux(v);
	aux.RotateByRadian(radian);

	return aux;
}

double Distance(const Vector2& v1, const Vector2& v2) {
	Vector2 aux(v1, v2);

	return aux.Length();
}<|endoftext|>


<commit_before>#include "Halide.h"

using namespace Halide;

int main(int argc, char **argv) {

    int W = 6400;
    int H = 4800;
    Buffer<uint16_t> input(W, H);

    for (int y = 0; y < input.height(); y++) {
        for (int x = 0; x < input.width(); x++) {
            input(x, y) = rand() & 0xfff;
        }
    }

    Var x("x"), y("y");

    int num_stencils = 15;

    std::vector<Func> stencils;
    for(int i = 0; i < num_stencils; i ++) {
        Func s("stencil_" + std::to_string(i));
        stencils.push_back(s);
    }

    stencils[0](x, y) = (input(x, y) + input(x+1, y) + input(x+2, y))/3;
    for (int i = 1; i < num_stencils; i++) {
        stencils[i](x, y) = (stencils[i-1](x, y) + stencils[i-1](x, y+1) +
                             stencils[i-1](x, y+2))/3;
    }

    // Provide estimates on the pipeline output
    stencils[num_stencils - 1].estimate(x, 0, 6200).estimate(y, 0, 4600);

    // Auto-schedule the pipeline
    Target target = get_target_from_environment();
    Pipeline p(stencils[num_stencils - 1]);

    p.auto_schedule(target);

    // Inspect the schedule
    stencils[num_stencils - 1].print_loop_nest();

    // Run the schedule
    Buffer<uint16_t> out = p.realize(6204, 4604);

    printf("Success!\n");
    return 0;
}
<commit_msg>Add print schedule in cost function test<commit_after>#include "Halide.h"

using namespace Halide;

int main(int argc, char **argv) {

    int W = 6400;
    int H = 4800;
    Buffer<uint16_t> input(W, H);

    for (int y = 0; y < input.height(); y++) {
        for (int x = 0; x < input.width(); x++) {
            input(x, y) = rand() & 0xfff;
        }
    }

    Var x("x"), y("y");

    int num_stencils = 15;

    std::vector<Func> stencils;
    for(int i = 0; i < num_stencils; i ++) {
        Func s("stencil_" + std::to_string(i));
        stencils.push_back(s);
    }

    stencils[0](x, y) = (input(x, y) + input(x+1, y) + input(x+2, y))/3;
    for (int i = 1; i < num_stencils; i++) {
        stencils[i](x, y) = (stencils[i-1](x, y) + stencils[i-1](x, y+1) +
                             stencils[i-1](x, y+2))/3;
    }

    // Provide estimates on the pipeline output
    stencils[num_stencils - 1].estimate(x, 0, 6200).estimate(y, 0, 4600);

    // Auto-schedule the pipeline
    Target target = get_target_from_environment();
    Pipeline p(stencils[num_stencils - 1]);

    std::cout << "\n\n******************************************\nSCHEDULE:\n"
              << "******************************************\n"
              << p.auto_schedule(target)
              << "\n******************************************\n\n";

    // Inspect the schedule
    stencils[num_stencils - 1].print_loop_nest();

    // Run the schedule
    Buffer<uint16_t> out = p.realize(6204, 4604);

    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2009 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapProcState_opts_SSE2.h"
#include "SkBitmapProcState_opts_SSSE3.h"
#include "SkBlitMask.h"
#include "SkBlitRow.h"
#include "SkBlitRect_opts_SSE2.h"
#include "SkBlitRow_opts_SSE2.h"
#include "SkUtils_opts_SSE2.h"
#include "SkUtils.h"

/* This file must *not* be compiled with -msse or -msse2, otherwise
   gcc may generate sse2 even for scalar ops (and thus give an invalid
   instruction on Pentium3 on the code below).  Only files named *_SSE2.cpp
   in this directory should be compiled with -msse2. */

#ifdef _MSC_VER
static inline void getcpuid(int info_type, int info[4]) {
    __asm {
        mov    eax, [info_type]
        cpuid
        mov    edi, [info]
        mov    [edi], eax
        mov    [edi+4], ebx
        mov    [edi+8], ecx
        mov    [edi+12], edx
    }
}
#else
#if defined(__x86_64__)
static inline void getcpuid(int info_type, int info[4]) {
    asm volatile (
        "cpuid \n\t"
        : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3])
        : "a"(info_type)
    );
}
#else
static inline void getcpuid(int info_type, int info[4]) {
    // We save and restore ebx, so this code can be compatible with -fPIC
    asm volatile (
        "pushl %%ebx      \n\t"
        "cpuid            \n\t"
        "movl %%ebx, %1   \n\t"
        "popl %%ebx       \n\t"
        : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
        : "a"(info_type)
    );
}
#endif
#endif

#if defined(__x86_64__) || defined(_WIN64)
/* All x86_64 machines have SSE2, so don't even bother checking. */
static inline bool hasSSE2() {
    return true;
}
#else

static inline bool hasSSE2() {
    int cpu_info[4] = { 0 };
    getcpuid(1, cpu_info);
    return (cpu_info[3] & (1<<26)) != 0;
}
#endif

static inline bool hasSSSE3() {
    int cpu_info[4] = { 0 };
    getcpuid(1, cpu_info);
    return (cpu_info[2] & 0x200) != 0;
}

static bool cachedHasSSE2() {
    static bool gHasSSE2 = hasSSE2();
    return gHasSSE2;
}

static bool cachedHasSSSE3() {
    static bool gHasSSSE3 = hasSSSE3();
    return gHasSSSE3;
}

void SkBitmapProcState::platformProcs() {
    if (cachedHasSSSE3()) {
#if !defined(SK_BUILD_FOR_ANDROID)
        // Disable SSSE3 optimization for Android x86
        if (fSampleProc32 == S32_opaque_D32_filter_DX) {
            fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
        } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
            fSampleProc32 = S32_alpha_D32_filter_DX_SSSE3;
        }

        if (fSampleProc32 == S32_opaque_D32_filter_DXDY) {
            fSampleProc32 = S32_opaque_D32_filter_DXDY_SSSE3;
        } else if (fSampleProc32 == S32_alpha_D32_filter_DXDY) {
            fSampleProc32 = S32_alpha_D32_filter_DXDY_SSSE3;
        }
#endif
    } else if (cachedHasSSE2()) {
        if (fSampleProc32 == S32_opaque_D32_filter_DX) {
            fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
        } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
            fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
        }
    }

    if (cachedHasSSSE3() || cachedHasSSE2()) {
        if (fMatrixProc == ClampX_ClampY_filter_scale) {
            fMatrixProc = ClampX_ClampY_filter_scale_SSE2;
        } else if (fMatrixProc == ClampX_ClampY_nofilter_scale) {
            fMatrixProc = ClampX_ClampY_nofilter_scale_SSE2;
        }

        if (fMatrixProc == ClampX_ClampY_filter_affine) {
            fMatrixProc = ClampX_ClampY_filter_affine_SSE2;
        } else if (fMatrixProc == ClampX_ClampY_nofilter_affine) {
            fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
        }
    }
}

static SkBlitRow::Proc32 platform_32_procs[] = {
    NULL,                               // S32_Opaque,
    S32_Blend_BlitRow32_SSE2,           // S32_Blend,
    S32A_Opaque_BlitRow32_SSE2,         // S32A_Opaque
    S32A_Blend_BlitRow32_SSE2,          // S32A_Blend,
};

SkBlitRow::Proc SkBlitRow::PlatformProcs4444(unsigned flags) {
    return NULL;
}

SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
    return NULL;
}

SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
    if (cachedHasSSE2()) {
        return Color32_SSE2;
    } else {
        return NULL;
    }
}

SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
    if (cachedHasSSE2()) {
        return platform_32_procs[flags];
    } else {
        return NULL;
    }
}

SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
                                                     SkMask::Format maskFormat,
                                                     SkColor color) {
    if (SkMask::kA8_Format != maskFormat) {
        return NULL;
    }

    ColorProc proc = NULL;
    if (cachedHasSSE2()) {
        switch (dstConfig) {
            case SkBitmap::kARGB_8888_Config:
                // The SSE2 version is not (yet) faster for black, so we check
                // for that.
                if (SK_ColorBLACK != color) {
                    proc = SkARGB32_A8_BlitMask_SSE2;
                }
                break;
            default:
                break;
        }
    }
    return proc;
}

SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
    if (cachedHasSSE2()) {
        if (isOpaque) {
            return SkBlitLCD16OpaqueRow_SSE2;
        } else {
            return SkBlitLCD16Row_SSE2;
        }
    } else {
        return NULL;
    }

}
SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
                                                 SkMask::Format maskFormat,
                                                 RowFlags flags) {
    return NULL;
}

SkMemset16Proc SkMemset16GetPlatformProc() {
    if (cachedHasSSE2()) {
        return sk_memset16_SSE2;
    } else {
        return NULL;
    }
}

SkMemset32Proc SkMemset32GetPlatformProc() {
    if (cachedHasSSE2()) {
        return sk_memset32_SSE2;
    } else {
        return NULL;
    }
}

SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
    if (cachedHasSSE2()) {
        return ColorRect32_SSE2;
    } else {
        return NULL;
    }
}

<commit_msg>Use intrinsics instead of inline assembly for detecting CPU ID & SSE2/3 support on 64-bit builds in MS Visual Studio 2010. Original code provided by jianliang79.<commit_after>/*
 * Copyright 2009 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapProcState_opts_SSE2.h"
#include "SkBitmapProcState_opts_SSSE3.h"
#include "SkBlitMask.h"
#include "SkBlitRow.h"
#include "SkBlitRect_opts_SSE2.h"
#include "SkBlitRow_opts_SSE2.h"
#include "SkUtils_opts_SSE2.h"
#include "SkUtils.h"

#if defined(_MSC_VER) && defined(_WIN64)
#include <intrin.h>
#endif

/* This file must *not* be compiled with -msse or -msse2, otherwise
   gcc may generate sse2 even for scalar ops (and thus give an invalid
   instruction on Pentium3 on the code below).  Only files named *_SSE2.cpp
   in this directory should be compiled with -msse2. */

#ifdef _MSC_VER
static inline void getcpuid(int info_type, int info[4]) {
#if defined(_WIN64)
    __cpuid(info, info_type);
#else
    __asm {
        mov    eax, [info_type]
        cpuid
        mov    edi, [info]
        mov    [edi], eax
        mov    [edi+4], ebx
        mov    [edi+8], ecx
        mov    [edi+12], edx
    }
#endif
}
#else
#if defined(__x86_64__)
static inline void getcpuid(int info_type, int info[4]) {
    asm volatile (
        "cpuid \n\t"
        : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3])
        : "a"(info_type)
    );
}
#else
static inline void getcpuid(int info_type, int info[4]) {
    // We save and restore ebx, so this code can be compatible with -fPIC
    asm volatile (
        "pushl %%ebx      \n\t"
        "cpuid            \n\t"
        "movl %%ebx, %1   \n\t"
        "popl %%ebx       \n\t"
        : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
        : "a"(info_type)
    );
}
#endif
#endif

#if defined(__x86_64__) || defined(_WIN64)
/* All x86_64 machines have SSE2, so don't even bother checking. */
static inline bool hasSSE2() {
    return true;
}
#else

static inline bool hasSSE2() {
    int cpu_info[4] = { 0 };
    getcpuid(1, cpu_info);
    return (cpu_info[3] & (1<<26)) != 0;
}
#endif

static inline bool hasSSSE3() {
    int cpu_info[4] = { 0 };
    getcpuid(1, cpu_info);
    return (cpu_info[2] & 0x200) != 0;
}

static bool cachedHasSSE2() {
    static bool gHasSSE2 = hasSSE2();
    return gHasSSE2;
}

static bool cachedHasSSSE3() {
    static bool gHasSSSE3 = hasSSSE3();
    return gHasSSSE3;
}

void SkBitmapProcState::platformProcs() {
    if (cachedHasSSSE3()) {
#if !defined(SK_BUILD_FOR_ANDROID)
        // Disable SSSE3 optimization for Android x86
        if (fSampleProc32 == S32_opaque_D32_filter_DX) {
            fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
        } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
            fSampleProc32 = S32_alpha_D32_filter_DX_SSSE3;
        }

        if (fSampleProc32 == S32_opaque_D32_filter_DXDY) {
            fSampleProc32 = S32_opaque_D32_filter_DXDY_SSSE3;
        } else if (fSampleProc32 == S32_alpha_D32_filter_DXDY) {
            fSampleProc32 = S32_alpha_D32_filter_DXDY_SSSE3;
        }
#endif
    } else if (cachedHasSSE2()) {
        if (fSampleProc32 == S32_opaque_D32_filter_DX) {
            fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
        } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
            fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
        }
    }

    if (cachedHasSSSE3() || cachedHasSSE2()) {
        if (fMatrixProc == ClampX_ClampY_filter_scale) {
            fMatrixProc = ClampX_ClampY_filter_scale_SSE2;
        } else if (fMatrixProc == ClampX_ClampY_nofilter_scale) {
            fMatrixProc = ClampX_ClampY_nofilter_scale_SSE2;
        }

        if (fMatrixProc == ClampX_ClampY_filter_affine) {
            fMatrixProc = ClampX_ClampY_filter_affine_SSE2;
        } else if (fMatrixProc == ClampX_ClampY_nofilter_affine) {
            fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
        }
    }
}

static SkBlitRow::Proc32 platform_32_procs[] = {
    NULL,                               // S32_Opaque,
    S32_Blend_BlitRow32_SSE2,           // S32_Blend,
    S32A_Opaque_BlitRow32_SSE2,         // S32A_Opaque
    S32A_Blend_BlitRow32_SSE2,          // S32A_Blend,
};

SkBlitRow::Proc SkBlitRow::PlatformProcs4444(unsigned flags) {
    return NULL;
}

SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
    return NULL;
}

SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
    if (cachedHasSSE2()) {
        return Color32_SSE2;
    } else {
        return NULL;
    }
}

SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
    if (cachedHasSSE2()) {
        return platform_32_procs[flags];
    } else {
        return NULL;
    }
}

SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
                                                     SkMask::Format maskFormat,
                                                     SkColor color) {
    if (SkMask::kA8_Format != maskFormat) {
        return NULL;
    }

    ColorProc proc = NULL;
    if (cachedHasSSE2()) {
        switch (dstConfig) {
            case SkBitmap::kARGB_8888_Config:
                // The SSE2 version is not (yet) faster for black, so we check
                // for that.
                if (SK_ColorBLACK != color) {
                    proc = SkARGB32_A8_BlitMask_SSE2;
                }
                break;
            default:
                break;
        }
    }
    return proc;
}

SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
    if (cachedHasSSE2()) {
        if (isOpaque) {
            return SkBlitLCD16OpaqueRow_SSE2;
        } else {
            return SkBlitLCD16Row_SSE2;
        }
    } else {
        return NULL;
    }

}
SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
                                                 SkMask::Format maskFormat,
                                                 RowFlags flags) {
    return NULL;
}

SkMemset16Proc SkMemset16GetPlatformProc() {
    if (cachedHasSSE2()) {
        return sk_memset16_SSE2;
    } else {
        return NULL;
    }
}

SkMemset32Proc SkMemset32GetPlatformProc() {
    if (cachedHasSSE2()) {
        return sk_memset32_SSE2;
    } else {
        return NULL;
    }
}

SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
    if (cachedHasSSE2()) {
        return ColorRect32_SSE2;
    } else {
        return NULL;
    }
}

<|endoftext|>


<commit_before>/*-------------Anderson.cpp---------------------------------------------------//
*
*              Anderson.cpp -- Diffusion Monte Carlo for Schroedy
*
* Purpose: Implement the quantum Monte Carlo (diffusion) by Anderson:
*             http://www.huy-nguyen.com/wp-content/uploads/QMC-papers/Anderson-JChemPhys-1975.pdf
*          For H3+, with 3 protons and 2 electrons
*
*    Note: This algorithm may be improved by later work
*          A "psip" is an imaginary configuration of electrons in space.
*          Requires c++11 for random and Eigen for matrix
*          Protons assume to be at origin
*          A lot of this algorithm is more easily understood here:
*              http://www.thphys.uni-heidelberg.de/~wetzel/qmc2006/KOSZ96.pdf
*
*-----------------------------------------------------------------------------*/

#include <algorithm>
#include <array>
#include <cassert>
#include <vector>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <omp.h>
#include <random>

constexpr size_t DOF = 6;
constexpr size_t MAX_SIZE = 2000;
constexpr size_t INITIAL_SIZE = 1000;
constexpr double TIMESTEP = 0.001;
constexpr double RADIUS = 1.8;

using coord = std::array<double, DOF>;

struct particle {
    coord coords;
    int id;
    int m_n;
    double potential;

    // This is the constructor used for the initial state creation
    particle(int id, const coord& coords)
      : coords(coords), id(id),  m_n(-1), potential(0.0) {}

    // Used in branching to create a replica of an other particle.
    // Sets m_n to 1 so even if this was to be processed, it will
    // be ignored as per the algorithm described in the Kosztin paper
    particle(int id, const particle& p)
      : coords(p.coords), id(id),  m_n(1), potential(p.potential) {}
};

struct h3plus {
    std::vector<particle> particles;
    double v_ref, dt, energy;
    int global_id;

    // This wouldn't be strictly necessary,
    // but pre-allocating should speed up the program a bit
    h3plus(size_t reserved_size) {
        particles.reserve(reserved_size);
    }
};

// Populate a distribution of particles for QMC
h3plus generate_initial(size_t initial_size, double dt);

// Calculates energy of a configuration and stores it as the particle potential
void find_weights(h3plus& state);

// Random walk
void random_walk(h3plus& state);

// Branching scheme
void branch(h3plus& state);

// Random walking of matrix of position created in populate
void diffuse(h3plus& state, std::ostream& output);

void print_visualization_data(std::ostream& output, const h3plus& state);

template <typename T>
double random_double(T distribution);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){
    std::ofstream output("out.dat", std::ostream::out);

    auto state = generate_initial(INITIAL_SIZE, TIMESTEP);
    //std::cout << state.v_ref << '\t' << state.particles.size() << '\n';

    diffuse(state, output);
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Populate a distribution of particles for QMC
// Unlike Anderson, we are initilizing each psip randomly from a distribution.
// This might screw things up, because
h3plus generate_initial(size_t initial_size, double dt) {
    h3plus state(MAX_SIZE);
    state.dt = dt;
    state.v_ref = 0;
    state.energy = 0;
    state.global_id = 0;

    // Random generation
    /*
    std::uniform_real_distribution<double> uniform(-1.0,1.0);
    for (size_t i = 0; i < initial_size; ++i){
        coord coords;
        for (auto& coord : coords) {
            coord = random_double(uniform);
        }
        state.particles.emplace_back(state.global_id++, std::move(coords));
    }
    */

    // Static generation
    for (size_t i = 0; i < initial_size; ++i) {
        coord coords = {RADIUS, RADIUS, RADIUS, -RADIUS, -RADIUS, -RADIUS};
        state.particles.emplace_back(state.global_id++, std::move(coords));
    }

    find_weights(state);
    return state;
}

// Calculates energy of a configuration and stores it into the final element of
// the MatrixPSIP
// Note: When calculating the potential, I am not sure whether we need to use
//       absolute value of distance or the distance, itself.
// Note: Inefficient. Can calculate energy on the fly with every generation of
//       psip. Think about it.
// Note: v_ref will be a dummy variable for now.
void find_weights(h3plus& state){
    // Note that this is specific to the Anderson paper
    // Finding the distance between electrons, then adding the distances
    // from the protons to the electrons.
    double potential_sum = 0.0;

    for (auto& particle : state.particles) {
        double dist = sqrt((particle.coords[0] - particle.coords[3]) *
                           (particle.coords[0] - particle.coords[3]) +
                           (particle.coords[1] - particle.coords[4]) *
                           (particle.coords[1] - particle.coords[4]) +
                           (particle.coords[2] - particle.coords[5]) *
                           (particle.coords[2] - particle.coords[5]));

        double potential = 1.0 / dist;
        for (const auto& coord : particle.coords) {
            potential -= 1.0 / std::abs(coord);
        }
        particle.potential = potential;
        potential_sum += potential;
    }

    size_t num_particles = state.particles.size();
    std::uniform_real_distribution<double> uniform(0.0, 1.0);

    // This needs type promotion to either double or int so it doesn't
    // underflow. Since it's going to be used as a double, might as well
    // do that directly.
    double particles_diff = static_cast<double>(num_particles) - INITIAL_SIZE;

    // defining the new reference potential
    state.energy = potential_sum / num_particles;
    state.v_ref = state.energy - particles_diff / (INITIAL_SIZE * state.dt);

    #pragma omp parallel for
    for (size_t i = 0; i < num_particles; ++i) {
        auto& particle = state.particles[i];
        double w = 1.0 - (particle.potential - state.v_ref) * state.dt;
        particle.m_n = std::min((int)(w + random_double(uniform)), 3);
    }
}

// 6D random walk
void random_walk(h3plus& state) {
    std::normal_distribution<double> gaussian(0.0, 1.0);
    size_t particles_size = state.particles.size();

    #pragma omp parallel for
    for (size_t i = 0; i < particles_size; ++i) {
        auto& particle = state.particles[i];
        for (auto& coord : particle.coords) {
            coord += sqrt(state.dt) * random_double(gaussian);
        }
    }
}

// Branching scheme
void branch(h3plus& state){
    find_weights(state);

    // I only cache this so I can fit the 80 character limit
    auto& particles = state.particles;

    // First, remove particles where M_n is zero, as per the Kosztin paper.
    // It's better to do it first to avoid unnecessary bookkeeping later
    auto remove = std::remove_if(std::begin(particles), std::end(particles),
                                 [](const particle& p) { return p.m_n == 0; });
    particles.erase(remove, std::end(particles));

    // Iterate over the current set of particles and add new ones as necessary.
    // The added particles will be skipped in the current iteration (which is
    // essentially the same behaviour as we had before)
    // We have to use direct indexes because of iterator invalidation.
    // Also note that current_size is cached outside of the loop, this is to
    // avoid unnecessary work
    size_t current_size = particles.size();
    for (size_t i = 0; i < current_size; ++i) {
        switch (particles[i].m_n) {
            case 2:
                particles.emplace_back(state.global_id++, particles[i]);
                break;
            case 3:
                particles.emplace_back(state.global_id++, particles[i]);
                particles.emplace_back(state.global_id++, particles[i]);
                break;
        }
    }

    // Just truncate if the vector would grow too large.
    // This should - theoratically - not happen
    if (particles.size() > MAX_SIZE) {
        particles.erase(std::begin(particles) + MAX_SIZE, std::end(particles));
    }
}

// Random walking of matrix of position created in populate
// Step 1: Move particles via 6D random walk
// Step 2: Destroy and create particles as need based on Anderson
// Step 3: check energy, end if needed.
void diffuse(h3plus& state, std::ostream& output){

    // For now, I am going to set a definite number of timesteps
    // This will be replaced by a while loop in the future.

    // double diff = 1.0;
    // while (diff > 0.01) {
    for (size_t t = 0; t < 10000; t++){
        double v_last = state.v_ref;

        random_walk(state);
        branch(state);
        // diff = sqrt((v_last - state.v_ref) * (v_last - state.v_ref));

        // Debug information for the current timestep
        std::cout << std::fixed
                  << state.v_ref << '\t'
                  << state.particles.size() << '\n';
        if (t % 1000 == 0) {
            print_visualization_data(output, state);
        }
    }
}

void print_visualization_data(std::ostream& output, const h3plus& state) {
    for (const auto& particle : state.particles) {
        for (const auto& coord : particle.coords) {
            output << std::fixed << coord << "\t";
        }
        output << particle.m_n << "\t";
        output << particle.id << "\n";
    }
    output << '\n' << '\n';
}

static inline std::mt19937& random_engine() {
    static std::random_device rd;
    // Use the Mersenne twister, the default random engine is not guaranteed
    // to be high quality. Use engine(rd()) if you want to test different cases
    static thread_local std::mt19937 engine; // engine(rd());
    return engine;
}

template <typename T>
double random_double(T distribution) {
    return distribution(random_engine());
}
<commit_msg>added in a better representation of the distances for our potential calculation.<commit_after>/*-------------Anderson.cpp---------------------------------------------------//
*
*              Anderson.cpp -- Diffusion Monte Carlo for Schroedy
*
* Purpose: Implement the quantum Monte Carlo (diffusion) by Anderson:
*             http://www.huy-nguyen.com/wp-content/uploads/QMC-papers/Anderson-JChemPhys-1975.pdf
*          For H3+, with 3 protons and 2 electrons
*
*    Note: This algorithm may be improved by later work
*          A "psip" is an imaginary configuration of electrons in space.
*          Requires c++11 for random and Eigen for matrix
*          Protons assume to be at origin
*          A lot of this algorithm is more easily understood here:
*              http://www.thphys.uni-heidelberg.de/~wetzel/qmc2006/KOSZ96.pdf
*
*-----------------------------------------------------------------------------*/

#include <algorithm>
#include <array>
#include <cassert>
#include <vector>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <omp.h>
#include <random>

constexpr size_t DOF = 6;
constexpr size_t MAX_SIZE = 2000;
constexpr size_t INITIAL_SIZE = 1000;
constexpr double TIMESTEP = 0.1;
constexpr double RADIUS = 1.8;

using coord = std::array<double, DOF>;

struct proton_pos{
    double pos[3][3] = {{0}};
};

struct particle {
    coord coords;
    int id;
    int m_n;
    double potential;

    // This is the constructor used for the initial state creation
    particle(int id, const coord& coords)
      : coords(coords), id(id),  m_n(-1), potential(0.0) {}

    // Used in branching to create a replica of an other particle.
    // Sets m_n to 1 so even if this was to be processed, it will
    // be ignored as per the algorithm described in the Kosztin paper
    particle(int id, const particle& p)
      : coords(p.coords), id(id),  m_n(1), potential(p.potential) {}

};

struct h3plus {
    std::vector<particle> particles;
    double v_ref, dt, energy;
    int global_id;

    // This wouldn't be strictly necessary,
    // but pre-allocating should speed up the program a bit
    h3plus(size_t reserved_size) {
        particles.reserve(reserved_size);
    }

    proton_pos proton;

};

// Populate a distribution of particles for QMC
h3plus generate_initial(size_t initial_size, double dt);

// Calculates energy of a configuration and stores it as the particle potential
void find_weights(h3plus& state);

// Random walk
void random_walk(h3plus& state);

// Branching scheme
void branch(h3plus& state);

// Random walking of matrix of position created in populate
void diffuse(h3plus& state, std::ostream& output);

void print_visualization_data(std::ostream& output, const h3plus& state);

template <typename T>
double random_double(T distribution);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){
    std::ofstream output("out.dat", std::ostream::out);

    auto state = generate_initial(INITIAL_SIZE, TIMESTEP);
    //std::cout << state.v_ref << '\t' << state.particles.size() << '\n';

    diffuse(state, output);
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Populate a distribution of particles for QMC
// Unlike Anderson, we are initilizing each psip randomly from a distribution.
// This might screw things up, because
h3plus generate_initial(size_t initial_size, double dt) {
    h3plus state(MAX_SIZE);
    state.dt = dt;
    state.v_ref = 0;
    state.energy = 0;
    state.global_id = 0;
    for (size_t i = 0; i < 3; i++){
        state.proton.pos[i][i] = 0.1;
    }

    // Random generation
    /*
    std::uniform_real_distribution<double> uniform(-1.0,1.0);
    for (size_t i = 0; i < initial_size; ++i){
        coord coords;
        for (auto& coord : coords) {
            coord = random_double(uniform);
        }
        state.particles.emplace_back(state.global_id++, std::move(coords));
    }
    */

    // Static generation
    for (size_t i = 0; i < initial_size; ++i) {
        coord coords = {RADIUS, RADIUS, RADIUS, -RADIUS, -RADIUS, -RADIUS};
        state.particles.emplace_back(state.global_id++, std::move(coords));
    }

    find_weights(state);
    return state;
}

// Calculates energy of a configuration and stores it into the final element of
// the MatrixPSIP
// Note: When calculating the potential, I am not sure whether we need to use
//       absolute value of distance or the distance, itself.
// Note: Inefficient. Can calculate energy on the fly with every generation of
//       psip. Think about it.
// Note: v_ref will be a dummy variable for now.
void find_weights(h3plus& state){
    // Note that this is specific to the Anderson paper
    // Finding the distance between electrons, then adding the distances
    // from the protons to the electrons.
    double potential_sum = 0.0, dist2;

    for (auto& particle : state.particles) {
        double dist1 = sqrt((particle.coords[0] - particle.coords[3]) *
                           (particle.coords[0] - particle.coords[3]) +
                           (particle.coords[1] - particle.coords[4]) *
                           (particle.coords[1] - particle.coords[4]) +
                           (particle.coords[2] - particle.coords[5]) *
                           (particle.coords[2] - particle.coords[5]));

        double potential = 1.0 / dist1;

        for (size_t i = 0; i < 3; i++){
            dist1 = sqrt((particle.coords[0] - state.proton.pos[i][0]) *
                         (particle.coords[0] - state.proton.pos[i][0]) +
                         (particle.coords[1] - state.proton.pos[i][1]) *
                         (particle.coords[1] - state.proton.pos[i][1]) +
                         (particle.coords[2] - state.proton.pos[i][2]) *
                         (particle.coords[2] - state.proton.pos[i][2]));

            dist2 = sqrt((particle.coords[3] - state.proton.pos[i][0]) *
                         (particle.coords[3] - state.proton.pos[i][0]) +
                         (particle.coords[4] - state.proton.pos[i][1]) *
                         (particle.coords[4] - state.proton.pos[i][1]) +
                         (particle.coords[5] - state.proton.pos[i][2]) *
                         (particle.coords[5] - state.proton.pos[i][2]));

            potential -= ((1/dist1) + (1/dist2));

        }
        /*
        for (const auto& coord : particle.coords) {

            potential -= 1.0 / std::abs(coord);
        }
        */
        particle.potential = potential;
        potential_sum += potential;
    }

    size_t num_particles = state.particles.size();
    std::uniform_real_distribution<double> uniform(0.0, 1.0);

    // This needs type promotion to either double or int so it doesn't
    // underflow. Since it's going to be used as a double, might as well
    // do that directly.
    double particles_diff = static_cast<double>(num_particles) - INITIAL_SIZE;

    // defining the new reference potential
    state.energy = potential_sum / num_particles;
    state.v_ref = state.energy - particles_diff / (INITIAL_SIZE * state.dt);

    #pragma omp parallel for
    for (size_t i = 0; i < num_particles; ++i) {
        auto& particle = state.particles[i];
        double w = 1.0 - (particle.potential - state.v_ref) * state.dt;
        particle.m_n = std::min((int)(w + random_double(uniform)), 3);
    }
}

// 6D random walk
void random_walk(h3plus& state) {
    std::normal_distribution<double> gaussian(0.0, 1.0);
    size_t particles_size = state.particles.size();

    #pragma omp parallel for
    for (size_t i = 0; i < particles_size; ++i) {
        auto& particle = state.particles[i];
        for (auto& coord : particle.coords) {
            coord += sqrt(state.dt) * random_double(gaussian);
        }
    }
}

// Branching scheme
void branch(h3plus& state){
    find_weights(state);

    // I only cache this so I can fit the 80 character limit
    auto& particles = state.particles;

    // First, remove particles where M_n is zero, as per the Kosztin paper.
    // It's better to do it first to avoid unnecessary bookkeeping later
    auto remove = std::remove_if(std::begin(particles), std::end(particles),
                                 [](const particle& p) { return p.m_n == 0; });
    particles.erase(remove, std::end(particles));

    // Iterate over the current set of particles and add new ones as necessary.
    // The added particles will be skipped in the current iteration (which is
    // essentially the same behaviour as we had before)
    // We have to use direct indexes because of iterator invalidation.
    // Also note that current_size is cached outside of the loop, this is to
    // avoid unnecessary work
    size_t current_size = particles.size();
    for (size_t i = 0; i < current_size; ++i) {
        switch (particles[i].m_n) {
            case 2:
                particles.emplace_back(state.global_id++, particles[i]);
                break;
            case 3:
                particles.emplace_back(state.global_id++, particles[i]);
                particles.emplace_back(state.global_id++, particles[i]);
                break;
        }
    }

    // Just truncate if the vector would grow too large.
    // This should - theoratically - not happen
    if (particles.size() > MAX_SIZE) {
        particles.erase(std::begin(particles) + MAX_SIZE, std::end(particles));
    }
}

// Random walking of matrix of position created in populate
// Step 1: Move particles via 6D random walk
// Step 2: Destroy and create particles as need based on Anderson
// Step 3: check energy, end if needed.
void diffuse(h3plus& state, std::ostream& output){

    // For now, I am going to set a definite number of timesteps
    // This will be replaced by a while loop in the future.

    // double diff = 1.0;
    // while (diff > 0.01) {
    for (size_t t = 0; t < 1000; t++){
        double v_last = state.v_ref;

        random_walk(state);
        branch(state);
        // diff = sqrt((v_last - state.v_ref) * (v_last - state.v_ref));

        // Debug information for the current timestep
        std::cout << std::fixed
                  << state.v_ref << '\t'
                  << state.particles.size() << '\n';
        if (t % 10 == 0) {
            print_visualization_data(output, state);
        }
    }
}

void print_visualization_data(std::ostream& output, const h3plus& state) {
    for (const auto& particle : state.particles) {
        for (const auto& coord : particle.coords) {
            output << std::fixed << coord << "\t";
        }
        output << particle.m_n << "\t";
        output << particle.id << "\n";
    }
    output << '\n' << '\n';
}

static inline std::mt19937& random_engine() {
    static std::random_device rd;
    // Use the Mersenne twister, the default random engine is not guaranteed
    // to be high quality. Use engine(rd()) if you want to test different cases
    static thread_local std::mt19937 engine; // engine(rd());
    return engine;
}

template <typename T>
double random_double(T distribution) {
    return distribution(random_engine());
}
<|endoftext|>