<commit_before>#ifndef LIGHTGBM_IO_SPARSE_BIN_HPP_
#define LIGHTGBM_IO_SPARSE_BIN_HPP_

#include <LightGBM/utils/log.h>

#include <LightGBM/bin.h>
#include "ordered_sparse_bin.hpp"

#include <omp.h>

#include <cstring>
#include <cstdint>

#include <vector>

namespace LightGBM {

const size_t kNumFastIndex = 64;

template <typename VAL_T> class SparseBinIterator;

template <typename VAL_T>
class SparseBin:public Bin {
public:
  friend class SparseBinIterator<VAL_T>;

  explicit SparseBin(data_size_t num_data, int default_bin)
    : num_data_(num_data) {
    default_bin_ = static_cast<VAL_T>(default_bin);
    if (default_bin_ != 0) {
      Log::Info("Warning: sparse feature with negative values, treating negative values as zero");
    }
    #pragma omp parallel
    #pragma omp master
    {
      num_threads_ = omp_get_num_threads();
    }
    for (int i = 0; i < num_threads_; ++i) {
      push_buffers_.emplace_back();
    }
  }

  ~SparseBin() {
  }

  void Push(int tid, data_size_t idx, uint32_t value) override {
    // not store zero data
    if (value <= default_bin_) { return; }
    push_buffers_[tid].emplace_back(idx, static_cast<VAL_T>(value));
  }

  BinIterator* GetIterator(data_size_t start_idx) const override;

  void ConstructHistogram(data_size_t*, data_size_t , const score_t* ,
                 const score_t* , HistogramBinEntry*) const override {
    // Will use OrderedSparseBin->ConstructHistogram() instead
    Log::Info("Using OrderedSparseBin->ConstructHistogram() instead");
  }

  data_size_t Split(unsigned int threshold, data_size_t* data_indices, data_size_t num_data,
                         data_size_t* lte_indices, data_size_t* gt_indices) const override {
    const auto fast_pair = fast_index_[(data_indices[0]) >> fast_index_shift_];
    data_size_t j = fast_pair.first;
    data_size_t cur_pos = fast_pair.second;
    data_size_t lte_count = 0;
    data_size_t gt_count = 0;
    for (data_size_t i = 0; i < num_data; ++i) {
      const data_size_t idx = data_indices[i];
      while (cur_pos < idx && j < num_vals_) {
        ++j;
        cur_pos += delta_[j];
      }
      VAL_T bin = 0;
      if (cur_pos == idx && j < num_vals_) {
        bin = vals_[j];
      }
      if (bin > threshold) {
        gt_indices[gt_count++] = idx;
      } else {
        lte_indices[lte_count++] = idx;
      }
    }
    return lte_count;
  }

  data_size_t num_data() const override { return num_data_; }

  OrderedBin* CreateOrderedBin() const override {
    return new OrderedSparseBin<VAL_T>(delta_, vals_);
  }

  void FinishLoad() override {
    // get total non zero size
    size_t non_zero_size = 0;
    for (size_t i = 0; i < push_buffers_.size(); ++i) {
      non_zero_size += push_buffers_[i].size();
    }
    // merge
    non_zero_pair_.reserve(non_zero_size);
    for (size_t i = 0; i < push_buffers_.size(); ++i) {
      non_zero_pair_.insert(non_zero_pair_.end(), push_buffers_[i].begin(), push_buffers_[i].end());
      push_buffers_[i].clear();
      push_buffers_[i].shrink_to_fit();
    }
    push_buffers_.clear();
    push_buffers_.shrink_to_fit();
    // sort by data index
    std::sort(non_zero_pair_.begin(), non_zero_pair_.end(),
      [](const std::pair<data_size_t, VAL_T>& a, const std::pair<data_size_t, VAL_T>& b) {
      return a.first < b.first;
    });
    // load detla array
    LoadFromPair(non_zero_pair_);
    // free memory
    non_zero_pair_.clear();
    non_zero_pair_.shrink_to_fit();
  }

  void LoadFromPair(const std::vector<std::pair<data_size_t, VAL_T>>& non_zero_pair) {
    delta_.clear();
    vals_.clear();
    // transform to delta array
    const uint8_t kMaxDelta = 255;
    data_size_t last_idx = 0;
    for (size_t i = 0; i < non_zero_pair.size(); ++i) {
      const data_size_t cur_idx = non_zero_pair[i].first;
      const VAL_T bin = non_zero_pair[i].second;
      data_size_t cur_delta = cur_idx - last_idx;
      while (cur_delta > kMaxDelta) {
        delta_.push_back(255);
        vals_.push_back(0);
        cur_delta -= kMaxDelta;
      }
      delta_.push_back(static_cast<uint8_t>(cur_delta));
      vals_.push_back(bin);
      last_idx = cur_idx;
    }
    // avoid out of range
    delta_.push_back(0);
    num_vals_ = static_cast<data_size_t>(vals_.size());

    // reduce memory cost
    delta_.shrink_to_fit();
    vals_.shrink_to_fit();

    // generate fast index
    GetFastIndex();
  }

  void GetFastIndex() {
    fast_index_.clear();
    // get shift cnt
    data_size_t mod_size = (num_data_ + kNumFastIndex - 1) / kNumFastIndex;
    data_size_t pow2_mod_size = 1;
    fast_index_shift_ = 0;
    while (pow2_mod_size < mod_size) {
      pow2_mod_size <<= 1;
      ++fast_index_shift_;
    }
    // build fast index
    data_size_t next_i = 0;
    data_size_t cur_pos = 0;
    for (data_size_t i = 0; i < num_vals_; ++i) {
      cur_pos += delta_[i];
      while (next_i < cur_pos) {
        fast_index_.emplace_back(i, cur_pos);
        next_i += pow2_mod_size;
      }
    }
    // avoid out of range
    while (next_i < num_data_) {
      fast_index_.emplace_back(num_vals_ - 1, cur_pos);
      next_i += pow2_mod_size;
    }
    fast_index_.shrink_to_fit();
  }

  void SaveBinaryToFile(FILE* file) const override {
    fwrite(&num_vals_, sizeof(num_vals_), 1, file);
    fwrite(delta_.data(), sizeof(uint8_t), num_vals_ + 1, file);
    fwrite(vals_.data(), sizeof(VAL_T), num_vals_, file);
  }

  size_t SizesInByte() const override {
    return sizeof(num_vals_) + sizeof(uint8_t) * (num_vals_ + 1)
      + sizeof(VAL_T) * num_vals_;
  }

  void LoadFromMemory(const void* memory, const std::vector<data_size_t>& local_used_indices) override {
    const char* mem_ptr = reinterpret_cast<const char*>(memory);
    data_size_t tmp_num_vals = *(reinterpret_cast<const data_size_t*>(mem_ptr));
    mem_ptr += sizeof(tmp_num_vals);
    const uint8_t* tmp_delta = reinterpret_cast<const uint8_t*>(mem_ptr);
    mem_ptr += sizeof(uint8_t) * (tmp_num_vals + 1);
    const VAL_T* tmp_vals = reinterpret_cast<const VAL_T*>(mem_ptr);

    if (local_used_indices.size() <= 0) {
      delta_.clear();
      vals_.clear();
      num_vals_ = tmp_num_vals;
      for (data_size_t i = 0; i < num_vals_; ++i) {
        delta_.push_back(tmp_delta[i]);
        vals_.push_back(tmp_vals[i]);
      }
      delta_.push_back(0);
      // reduce memory cost
      delta_.shrink_to_fit();
      vals_.shrink_to_fit();

      // generate fast index
      GetFastIndex();

    } else {
      std::vector<std::pair<data_size_t, VAL_T>> tmp_pair;
      data_size_t cur_pos = tmp_delta[0];
      data_size_t j = 0;
      for (data_size_t i = 0; i < static_cast<data_size_t>(local_used_indices.size()); ++i) {
        const data_size_t idx = local_used_indices[i];
        while (cur_pos < idx && j < tmp_num_vals) {
          ++j;
          cur_pos += tmp_delta[j];
        }
        VAL_T bin = 0;
        if (cur_pos == idx && j < tmp_num_vals) {
          bin = tmp_vals[j];
        }
        if (bin > 0) {
          // new row index is i
          tmp_pair.emplace_back(i, bin);
        }
      }
      LoadFromPair(tmp_pair);
    }

  }

private:
  data_size_t num_data_;
  std::vector<std::pair<data_size_t, VAL_T>> non_zero_pair_;
  std::vector<uint8_t> delta_;
  std::vector<VAL_T> vals_;
  data_size_t num_vals_;
  int num_threads_;
  std::vector<std::vector<std::pair<data_size_t, VAL_T>>> push_buffers_;
  std::vector<std::pair<data_size_t, data_size_t>> fast_index_;
  data_size_t fast_index_shift_;
  VAL_T default_bin_;
};

template <typename VAL_T>
class SparseBinIterator: public BinIterator {
public:
  SparseBinIterator(const SparseBin<VAL_T>* bin_data, data_size_t start_idx)
    : bin_data_(bin_data) {
    const auto fast_pair = bin_data->fast_index_[start_idx >> bin_data->fast_index_shift_];
    i_delta_ = fast_pair.first;
    cur_pos_ = fast_pair.second;
  }
  uint32_t Get(data_size_t idx) override {
    while (cur_pos_ < idx && i_delta_ < bin_data_->num_vals_) {
      ++i_delta_;
      cur_pos_ += bin_data_->delta_[i_delta_];
    }
    if (idx == cur_pos_ && i_delta_ >= 0
      && i_delta_ < bin_data_->vals_.size()) {
      return bin_data_->vals_[i_delta_];
    } else { return 0; }
  }

private:
  const SparseBin<VAL_T>* bin_data_;
  data_size_t cur_pos_ = 0;
  data_size_t i_delta_ = 0;
};

template <typename VAL_T>
BinIterator* SparseBin<VAL_T>::GetIterator(data_size_t start_idx) const {
  return new SparseBinIterator<VAL_T>(this, start_idx);
}

}  // namespace LightGBM
#endif   // LightGBM_IO_SPARSE_BIN_HPP_
<commit_msg>fix bug when splitting sparse bin with passed num_data=0 (#68)<commit_after>#ifndef LIGHTGBM_IO_SPARSE_BIN_HPP_
#define LIGHTGBM_IO_SPARSE_BIN_HPP_

#include <LightGBM/utils/log.h>

#include <LightGBM/bin.h>
#include "ordered_sparse_bin.hpp"

#include <omp.h>

#include <cstring>
#include <cstdint>

#include <vector>

namespace LightGBM {

const size_t kNumFastIndex = 64;

template <typename VAL_T> class SparseBinIterator;

template <typename VAL_T>
class SparseBin:public Bin {
public:
  friend class SparseBinIterator<VAL_T>;

  explicit SparseBin(data_size_t num_data, int default_bin)
    : num_data_(num_data) {
    default_bin_ = static_cast<VAL_T>(default_bin);
    if (default_bin_ != 0) {
      Log::Info("Warning: sparse feature with negative values, treating negative values as zero");
    }
    #pragma omp parallel
    #pragma omp master
    {
      num_threads_ = omp_get_num_threads();
    }
    for (int i = 0; i < num_threads_; ++i) {
      push_buffers_.emplace_back();
    }
  }

  ~SparseBin() {
  }

  void Push(int tid, data_size_t idx, uint32_t value) override {
    // not store zero data
    if (value <= default_bin_) { return; }
    push_buffers_[tid].emplace_back(idx, static_cast<VAL_T>(value));
  }

  BinIterator* GetIterator(data_size_t start_idx) const override;

  void ConstructHistogram(data_size_t*, data_size_t , const score_t* ,
                 const score_t* , HistogramBinEntry*) const override {
    // Will use OrderedSparseBin->ConstructHistogram() instead
    Log::Info("Using OrderedSparseBin->ConstructHistogram() instead");
  }

  data_size_t Split(unsigned int threshold, data_size_t* data_indices, data_size_t num_data,
                         data_size_t* lte_indices, data_size_t* gt_indices) const override {
    // not need to split
    if (num_data <= 0) { return 0; }
    const auto fast_pair = fast_index_[(data_indices[0]) >> fast_index_shift_];
    data_size_t j = fast_pair.first;
    data_size_t cur_pos = fast_pair.second;
    data_size_t lte_count = 0;
    data_size_t gt_count = 0;
    for (data_size_t i = 0; i < num_data; ++i) {
      const data_size_t idx = data_indices[i];
      while (cur_pos < idx && j < num_vals_) {
        ++j;
        cur_pos += delta_[j];
      }
      VAL_T bin = 0;
      if (cur_pos == idx && j < num_vals_) {
        bin = vals_[j];
      }
      if (bin > threshold) {
        gt_indices[gt_count++] = idx;
      } else {
        lte_indices[lte_count++] = idx;
      }
    }
    return lte_count;
  }

  data_size_t num_data() const override { return num_data_; }

  OrderedBin* CreateOrderedBin() const override {
    return new OrderedSparseBin<VAL_T>(delta_, vals_);
  }

  void FinishLoad() override {
    // get total non zero size
    size_t non_zero_size = 0;
    for (size_t i = 0; i < push_buffers_.size(); ++i) {
      non_zero_size += push_buffers_[i].size();
    }
    // merge
    non_zero_pair_.reserve(non_zero_size);
    for (size_t i = 0; i < push_buffers_.size(); ++i) {
      non_zero_pair_.insert(non_zero_pair_.end(), push_buffers_[i].begin(), push_buffers_[i].end());
      push_buffers_[i].clear();
      push_buffers_[i].shrink_to_fit();
    }
    push_buffers_.clear();
    push_buffers_.shrink_to_fit();
    // sort by data index
    std::sort(non_zero_pair_.begin(), non_zero_pair_.end(),
      [](const std::pair<data_size_t, VAL_T>& a, const std::pair<data_size_t, VAL_T>& b) {
      return a.first < b.first;
    });
    // load detla array
    LoadFromPair(non_zero_pair_);
    // free memory
    non_zero_pair_.clear();
    non_zero_pair_.shrink_to_fit();
  }

  void LoadFromPair(const std::vector<std::pair<data_size_t, VAL_T>>& non_zero_pair) {
    delta_.clear();
    vals_.clear();
    // transform to delta array
    const uint8_t kMaxDelta = 255;
    data_size_t last_idx = 0;
    for (size_t i = 0; i < non_zero_pair.size(); ++i) {
      const data_size_t cur_idx = non_zero_pair[i].first;
      const VAL_T bin = non_zero_pair[i].second;
      data_size_t cur_delta = cur_idx - last_idx;
      while (cur_delta > kMaxDelta) {
        delta_.push_back(255);
        vals_.push_back(0);
        cur_delta -= kMaxDelta;
      }
      delta_.push_back(static_cast<uint8_t>(cur_delta));
      vals_.push_back(bin);
      last_idx = cur_idx;
    }
    // avoid out of range
    delta_.push_back(0);
    num_vals_ = static_cast<data_size_t>(vals_.size());

    // reduce memory cost
    delta_.shrink_to_fit();
    vals_.shrink_to_fit();

    // generate fast index
    GetFastIndex();
  }

  void GetFastIndex() {
    fast_index_.clear();
    // get shift cnt
    data_size_t mod_size = (num_data_ + kNumFastIndex - 1) / kNumFastIndex;
    data_size_t pow2_mod_size = 1;
    fast_index_shift_ = 0;
    while (pow2_mod_size < mod_size) {
      pow2_mod_size <<= 1;
      ++fast_index_shift_;
    }
    // build fast index
    data_size_t next_i = 0;
    data_size_t cur_pos = 0;
    for (data_size_t i = 0; i < num_vals_; ++i) {
      cur_pos += delta_[i];
      while (next_i < cur_pos) {
        fast_index_.emplace_back(i, cur_pos);
        next_i += pow2_mod_size;
      }
    }
    // avoid out of range
    while (next_i < num_data_) {
      fast_index_.emplace_back(num_vals_ - 1, cur_pos);
      next_i += pow2_mod_size;
    }
    fast_index_.shrink_to_fit();
  }

  void SaveBinaryToFile(FILE* file) const override {
    fwrite(&num_vals_, sizeof(num_vals_), 1, file);
    fwrite(delta_.data(), sizeof(uint8_t), num_vals_ + 1, file);
    fwrite(vals_.data(), sizeof(VAL_T), num_vals_, file);
  }

  size_t SizesInByte() const override {
    return sizeof(num_vals_) + sizeof(uint8_t) * (num_vals_ + 1)
      + sizeof(VAL_T) * num_vals_;
  }

  void LoadFromMemory(const void* memory, const std::vector<data_size_t>& local_used_indices) override {
    const char* mem_ptr = reinterpret_cast<const char*>(memory);
    data_size_t tmp_num_vals = *(reinterpret_cast<const data_size_t*>(mem_ptr));
    mem_ptr += sizeof(tmp_num_vals);
    const uint8_t* tmp_delta = reinterpret_cast<const uint8_t*>(mem_ptr);
    mem_ptr += sizeof(uint8_t) * (tmp_num_vals + 1);
    const VAL_T* tmp_vals = reinterpret_cast<const VAL_T*>(mem_ptr);

    if (local_used_indices.size() <= 0) {
      delta_.clear();
      vals_.clear();
      num_vals_ = tmp_num_vals;
      for (data_size_t i = 0; i < num_vals_; ++i) {
        delta_.push_back(tmp_delta[i]);
        vals_.push_back(tmp_vals[i]);
      }
      delta_.push_back(0);
      // reduce memory cost
      delta_.shrink_to_fit();
      vals_.shrink_to_fit();

      // generate fast index
      GetFastIndex();

    } else {
      std::vector<std::pair<data_size_t, VAL_T>> tmp_pair;
      data_size_t cur_pos = tmp_delta[0];
      data_size_t j = 0;
      for (data_size_t i = 0; i < static_cast<data_size_t>(local_used_indices.size()); ++i) {
        const data_size_t idx = local_used_indices[i];
        while (cur_pos < idx && j < tmp_num_vals) {
          ++j;
          cur_pos += tmp_delta[j];
        }
        VAL_T bin = 0;
        if (cur_pos == idx && j < tmp_num_vals) {
          bin = tmp_vals[j];
        }
        if (bin > 0) {
          // new row index is i
          tmp_pair.emplace_back(i, bin);
        }
      }
      LoadFromPair(tmp_pair);
    }

  }

private:
  data_size_t num_data_;
  std::vector<std::pair<data_size_t, VAL_T>> non_zero_pair_;
  std::vector<uint8_t> delta_;
  std::vector<VAL_T> vals_;
  data_size_t num_vals_;
  int num_threads_;
  std::vector<std::vector<std::pair<data_size_t, VAL_T>>> push_buffers_;
  std::vector<std::pair<data_size_t, data_size_t>> fast_index_;
  data_size_t fast_index_shift_;
  VAL_T default_bin_;
};

template <typename VAL_T>
class SparseBinIterator: public BinIterator {
public:
  SparseBinIterator(const SparseBin<VAL_T>* bin_data, data_size_t start_idx)
    : bin_data_(bin_data) {
    const auto fast_pair = bin_data->fast_index_[start_idx >> bin_data->fast_index_shift_];
    i_delta_ = fast_pair.first;
    cur_pos_ = fast_pair.second;
  }
  uint32_t Get(data_size_t idx) override {
    while (cur_pos_ < idx && i_delta_ < bin_data_->num_vals_) {
      ++i_delta_;
      cur_pos_ += bin_data_->delta_[i_delta_];
    }
    if (idx == cur_pos_ && i_delta_ >= 0
      && i_delta_ < bin_data_->vals_.size()) {
      return bin_data_->vals_[i_delta_];
    } else { return 0; }
  }

private:
  const SparseBin<VAL_T>* bin_data_;
  data_size_t cur_pos_ = 0;
  data_size_t i_delta_ = 0;
};

template <typename VAL_T>
BinIterator* SparseBin<VAL_T>::GetIterator(data_size_t start_idx) const {
  return new SparseBinIterator<VAL_T>(this, start_idx);
}

}  // namespace LightGBM
#endif   // LightGBM_IO_SPARSE_BIN_HPP_
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <set>

// Keep sys/socket first.
#include <sys/socket.h>
#include <arpa/inet.h>
#include <libproc.h>

#include <osquery/core.h>
#include <osquery/logger.h>
#include <osquery/tables.h>

namespace osquery {
namespace tables {

enum {
  SOCKET_TYPE_LOCAL,
  SOCKET_TYPE_FOREIGN,
};

enum descriptor_type {
  DESCRIPTORS_TYPE_SOCKET,
  DESCRIPTORS_TYPE_VNODE,
};

// From processes.cpp
std::set<int> getProcList();

std::string socketIpAsString(const struct in_sockinfo *in,
                             int type,
                             int family) {
  char dst[INET6_ADDRSTRLEN];
  memset(dst, 0, sizeof(dst));

  // The caller determines whether to parse the local or remote address.
  if (type == SOCKET_TYPE_LOCAL) {
    // The input struct insi_vflag determines protocol type.
    if ((in->insi_vflag & INI_IPV4) != 0 || family == AF_INET) {
      inet_ntop(AF_INET, &(in->insi_laddr.ina_46.i46a_addr4), dst, sizeof(dst));
    } else {
      inet_ntop(AF_INET6, &(in->insi_laddr.ina_6), dst, sizeof(dst));
    }
  } else {
    if ((in->insi_vflag & INI_IPV4) != 0 || family == AF_INET) {
      inet_ntop(AF_INET, &(in->insi_faddr.ina_46.i46a_addr4), dst, sizeof(dst));
    } else {
      inet_ntop(AF_INET6, &(in->insi_faddr.ina_6), dst, sizeof(dst));
    }
  }

  std::string address(dst);
  return address;
}

void parseNetworkSocket(const struct socket_fdinfo socket_info, Row &r) {
  // Set socket protocol.
  const struct in_sockinfo *in;
  if (socket_info.psi.soi_kind == SOCKINFO_TCP) {
    in = &socket_info.psi.soi_proto.pri_tcp.tcpsi_ini;
  } else {
    in = &socket_info.psi.soi_proto.pri_in;
  }

  auto family = socket_info.psi.soi_family;
  r["local_address"] = socketIpAsString(in, SOCKET_TYPE_LOCAL, family);
  r["local_port"] = INTEGER(ntohs(in->insi_lport));
  r["remote_address"] = socketIpAsString(in, SOCKET_TYPE_FOREIGN, family);
  r["remote_port"] = INTEGER(ntohs(in->insi_fport));
}

void genFileDescriptor(int pid, int descriptor, QueryData &results) {
  struct vnode_fdinfowithpath vi;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDVNODEPATHINFO,
                     &vi,
                     PROC_PIDFDVNODEPATHINFO_SIZE) <= 0) {
    return;
  }

  Row r;
  r["pid"] = INTEGER(pid);
  r["fd"] = INTEGER(descriptor);
  r["path"] = std::string(vi.pvip.vip_path);
  results.push_back(r);
}

void genSocketDescriptor(int pid, int descriptor, QueryData &results) {
  struct socket_fdinfo si;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDSOCKETINFO,
                     &si,
                     PROC_PIDFDSOCKETINFO_SIZE) <= 0) {
    return;
  }

  if (si.psi.soi_kind == SOCKINFO_IN || si.psi.soi_kind == SOCKINFO_TCP) {
    Row r;

    r["pid"] = INTEGER(pid);
    r["socket"] = INTEGER(descriptor);

    // Darwin/OSX SOCKINFO_TCP is not IPPROTO_TCP
    if (si.psi.soi_kind == SOCKINFO_TCP) {
      r["protocol"] = INTEGER(6);
    } else {
      r["protocol"] = INTEGER(17);
    }

    // Darwin/OSX AF_INET6 == 30
    if (si.psi.soi_family == AF_INET) {
      r["family"] = INTEGER(2);
    } else {
      r["family"] = INTEGER(10);
    }

    parseNetworkSocket(si, r);
    results.push_back(r);
  }
}

void genOpenDescriptors(int pid, descriptor_type type, QueryData &results) {
  // std::vector<OpenFile> open_files;
  int bufsize = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0);
  if (bufsize == -1) {
    VLOG(1) << "Could not list descriptors for pid: " << pid;
    return;
  }

  // Allocate structs for each descriptor.
  proc_fdinfo fds[bufsize / PROC_PIDLISTFD_SIZE];

  for (auto fd_info : fds) {
    if (type == DESCRIPTORS_TYPE_VNODE &&
        fd_info.proc_fdtype == PROX_FDTYPE_VNODE) {
      genFileDescriptor(pid, fd_info.proc_fd, results);
    } else if (type == DESCRIPTORS_TYPE_SOCKET &&
               fd_info.proc_fdtype == PROX_FDTYPE_SOCKET) {
      genSocketDescriptor(pid, fd_info.proc_fd, results);
    }
  }
}

QueryData genOpenSockets(QueryContext &context) {
  QueryData results;
  auto pidlist = getProcList();

  for (auto &pid : pidlist) {
    if (!context.constraints["pid"].matches(pid)) {
      // Optimize by not searching when a pid is a constraint.
      continue;
    }

    genOpenDescriptors(pid, DESCRIPTORS_TYPE_SOCKET, results);
  }

  return results;
}

QueryData genOpenFiles(QueryContext &context) {
  QueryData results;
  auto pidlist = getProcList();

  for (auto &pid : pidlist) {
    if (!context.constraints["pid"].matches(pid)) {
      // Optimize by not searching when a pid is a constraint.
      continue;
    }

    genOpenDescriptors(pid, DESCRIPTORS_TYPE_VNODE, results);
  }

  return results;
}
}
}
<commit_msg>Fixed open sockets on OS X<commit_after>/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <set>

// Keep sys/socket first.
#include <sys/socket.h>
#include <arpa/inet.h>
#include <libproc.h>

#include <osquery/core.h>
#include <osquery/logger.h>
#include <osquery/tables.h>

namespace osquery {
namespace tables {

enum {
  SOCKET_TYPE_LOCAL,
  SOCKET_TYPE_FOREIGN,
};

enum descriptor_type {
  DESCRIPTORS_TYPE_SOCKET,
  DESCRIPTORS_TYPE_VNODE,
};

// From processes.cpp
std::set<int> getProcList();

std::string socketIpAsString(const struct in_sockinfo *in,
                             int type,
                             int family) {
  char dst[INET6_ADDRSTRLEN];
  memset(dst, 0, sizeof(dst));

  // The caller determines whether to parse the local or remote address.
  if (type == SOCKET_TYPE_LOCAL) {
    // The input struct insi_vflag determines protocol type.
    if ((in->insi_vflag & INI_IPV4) != 0 || family == AF_INET) {
      inet_ntop(AF_INET, &(in->insi_laddr.ina_46.i46a_addr4), dst, sizeof(dst));
    } else {
      inet_ntop(AF_INET6, &(in->insi_laddr.ina_6), dst, sizeof(dst));
    }
  } else {
    if ((in->insi_vflag & INI_IPV4) != 0 || family == AF_INET) {
      inet_ntop(AF_INET, &(in->insi_faddr.ina_46.i46a_addr4), dst, sizeof(dst));
    } else {
      inet_ntop(AF_INET6, &(in->insi_faddr.ina_6), dst, sizeof(dst));
    }
  }

  std::string address(dst);
  return address;
}

void parseNetworkSocket(const struct socket_fdinfo socket_info, Row &r) {
  // Set socket protocol.
  const struct in_sockinfo *in;
  if (socket_info.psi.soi_kind == SOCKINFO_TCP) {
    in = &socket_info.psi.soi_proto.pri_tcp.tcpsi_ini;
  } else {
    in = &socket_info.psi.soi_proto.pri_in;
  }

  auto family = socket_info.psi.soi_family;
  r["local_address"] = socketIpAsString(in, SOCKET_TYPE_LOCAL, family);
  r["local_port"] = INTEGER(ntohs(in->insi_lport));
  r["remote_address"] = socketIpAsString(in, SOCKET_TYPE_FOREIGN, family);
  r["remote_port"] = INTEGER(ntohs(in->insi_fport));
}

void genFileDescriptor(int pid, int descriptor, QueryData &results) {
  struct vnode_fdinfowithpath vi;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDVNODEPATHINFO,
                     &vi,
                     PROC_PIDFDVNODEPATHINFO_SIZE) <= 0) {
    return;
  }

  Row r;
  r["pid"] = INTEGER(pid);
  r["fd"] = INTEGER(descriptor);
  r["path"] = std::string(vi.pvip.vip_path);
  results.push_back(r);
}

void genSocketDescriptor(int pid, int descriptor, QueryData &results) {
  struct socket_fdinfo si;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDSOCKETINFO,
                     &si,
                     PROC_PIDFDSOCKETINFO_SIZE) <= 0) {
    return;
  }
  if (si.psi.soi_kind == SOCKINFO_IN || si.psi.soi_kind == SOCKINFO_TCP) {
    Row r;

    r["pid"] = INTEGER(pid);
    r["socket"] = INTEGER(descriptor);

    // Darwin/OSX SOCKINFO_TCP is not IPPROTO_TCP
    if (si.psi.soi_kind == SOCKINFO_TCP) {
      r["protocol"] = INTEGER(6);
    } else {
      r["protocol"] = INTEGER(17);
    }

    // Darwin/OSX AF_INET6 == 30
    if (si.psi.soi_family == AF_INET) {
      r["family"] = INTEGER(2);
    } else {
      r["family"] = INTEGER(10);
    }

    parseNetworkSocket(si, r);
    results.push_back(r);
  }
}

void genOpenDescriptors(int pid, descriptor_type type, QueryData &results) {
  int bufsize = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0);
  if (bufsize == -1) {
    VLOG(1) << "Could not list descriptors for pid: " << pid;
    return;
  }

  // Allocate structs for each descriptor.
  proc_fdinfo fds[bufsize / PROC_PIDLISTFD_SIZE];
  proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds, bufsize);

  for (auto fd_info : fds) {
    if (type == DESCRIPTORS_TYPE_VNODE &&
        fd_info.proc_fdtype == PROX_FDTYPE_VNODE) {
      genFileDescriptor(pid, fd_info.proc_fd, results);
    } else if (type == DESCRIPTORS_TYPE_SOCKET &&
        fd_info.proc_fdtype == PROX_FDTYPE_SOCKET) {
      genSocketDescriptor(pid, fd_info.proc_fd, results);
    }
  }
}

QueryData genOpenSockets(QueryContext &context) {
  QueryData results;
  auto pidlist = getProcList();

  for (auto &pid : pidlist) {
    if (!context.constraints["pid"].matches(pid)) {
      // Optimize by not searching when a pid is a constraint.
      continue;
    }
    genOpenDescriptors(pid, DESCRIPTORS_TYPE_SOCKET, results);
  }

  return results;
}

QueryData genOpenFiles(QueryContext &context) {
  QueryData results;
  auto pidlist = getProcList();

  for (auto &pid : pidlist) {
    if (!context.constraints["pid"].matches(pid)) {
      // Optimize by not searching when a pid is a constraint.
      continue;
    }

    genOpenDescriptors(pid, DESCRIPTORS_TYPE_VNODE, results);
  }

  return results;
}
}
}
<|endoftext|>


<commit_before>// Thomas Alexander Steinholz
// South River High School
// C++ w/ Gaming : 1A

#include <iostream>
#include <string>

struct Code
{
    enum Peg
    {
        RED,
        BLUE,
        YELLOW,
        GREEN,
        WHITE,
        ORANGE,
        NOTHING,
    };

    Code()
    {
        Peg temp[4];
        for(int i = 0; i < 4; i++)
        {
            switch(rand() % 6)
            {
                case 0:
                    temp[i] = RED;
                    break;
                case 1:
                    temp[i] = BLUE;
                    break;
                case 2:
                    temp[i] = YELLOW;
                    break;
                case 3:
                    temp[i] = GREEN;
                    break;
                case 4:
                    temp[i] = WHITE;
                    break;
                case 5:
                    temp[i] = ORANGE;
                    break;
            }
        }
        A = temp[0];
        B = temp[1];
        C = temp[2];
        D = temp[3];
    }

    Code(Peg x)
        : A(x), B(x), C(x), D(x) {}

    Code(Peg a, Peg b, Peg c, Peg d)
        : A(a), B(b), C(c), D(d) {}

    Code(const Code& copy)
        : A(copy.A), B(copy.B), C(copy.C), D(copy.D) {}

    Peg A, B, C, D;

    //TODO
    void PrintState()
    {
        std::cout<<ToString(A)<<" "<<ToString(B)<<" "<<ToString(C)<<" "<<ToString(D)<<" "<<std::endl;
    }

    bool Verify()
    {
        return A != NOTHING &&
               B != NOTHING &&
               C != NOTHING &&
               D != NOTHING;
    }

    static Peg ToPeg(const char x)
    {
        switch (x)
        {
            case 'r':
            case 'R':
                return RED;
            case 'b':
            case 'B':
                return BLUE;
            case 'y':
            case 'Y':
                return YELLOW;
            case 'g':
            case 'G':
                return GREEN;
            case 'w':
            case 'W':
                return WHITE;
            case 'o':
            case 'O':
                return ORANGE;
            default:
                return NOTHING;
        }
    }

    static std::string ToString(const Peg x)
    {
        switch(x)
        {
            case RED:
                return "Red";
            case BLUE:
                return "Blue";
            case YELLOW:
                return "Yellow";
            case GREEN:
                return "Green";
            case WHITE:
                return "White";
            case ORANGE:
                return "Orange";
            default:
            case NOTHING:
                return "Nothing";
        }
    }

    bool operator==(const Code &c) const
    {
        return (A == c.A) &&
               (B == c.B) &&
               (C == c.C) &&
               (D == c.D);
    }

    bool operator!=(const Code &c) const
    {
        return !((A == c.A) ||
                 (B == c.B) ||
                 (C == c.C) ||
                 (D == c.D));
    }
};

Code* Turn()
{
    Code* out = NULL;
    bool correct = false;
    char result[4];
    while (!correct)
    {
        std::cout << "GUESS: ";
        std::cin.get(result, 5);

        Code::Peg A = Code::ToPeg(result[0]);
        if (A != Code::Peg::NOTHING)
        {
            Code::Peg B = Code::ToPeg(result[1]);
            if (B != Code::Peg::NOTHING)
            {
                Code::Peg C = Code::ToPeg(result[2]);
                if (C != Code::Peg::NOTHING)
                {
                    Code::Peg D = Code::ToPeg(result[3]);
                    if (D != Code::Peg::NOTHING)
                    {
                        out = new Code(A, B, C, D);
                        out->PrintState();
                    }
                    else std::cout<<std::endl<<"ERROR: Col 4 '"<<result[3]<<"'"<<std::endl;
                }
                else std::cout<<std::endl<<"ERROR: Col 3 '"<<result[2]<<"'"<<std::endl;
            }
            else std::cout<<std::endl<<"ERROR: Col 2 '"<<result[1]<<"'"<<std::endl;
        }
        else std::cout<<std::endl<<"ERROR: Col 1 '"<<result[0]<<"'" <<std::endl;

        correct = out->Verify();

        //if (!correct){ std::cout << std::end; }
    }
    return out;
}

//TODO
void Feedback(Code* code, Code* guess)
{

}

int main()
{
    srand(time(NULL));
    bool executing = true;
    int guesses = 0;
    Code* code = new Code();
    code->PrintState();//DEBUG
    Code* guess = NULL;
    std::cout << "Welcome to Mastermind by Thomas Steinholz!" << std::endl;
    std::cout << "You are playing as the \"Code Breaker\" that means you will need to guess the combonations" << std::endl;
    std::cout << "of colors that the AI will generate. Your options are R-B-Y-G-W-O. For example to type in" << std::endl;
    std::cout << "the colors red, blue, yellow, and orange you would type \"RBYO\" untill you get the right combo." << std::endl;
    std::cout << "Good Luck, and don't forget to have fun!" << std::endl << std::endl;

    while (executing)
    {
        guesses++;
        std::cout << "|-------------|" << std::endl;
        std::cout << "[ Guess #" << guesses << "/10 ]" << std::endl;
        std::cout << "|-------------|" << std::endl;

        guess = Turn();
        Feedback(code, guess);

        if (code == guess)
        {
            executing = false;
            std::cout << "----------------------------------" << std::endl;
            std::cout << "Good Work! You just won the game!!" << std::endl;
            std::cout << "----------------------------------" << std::endl;
        }

        if (guesses > 10)
        {
            executing = false;
            std::cout << "-----------------------------------------------------" << std::endl;
            std::cout << "Sorry! You lost because you have used all 10 guesses!" << std::endl;
            std::cout << "-----------------------------------------------------" << std::endl;
        }
    }

    delete code;
    delete guess;

    return 0;
}<commit_msg>check point<commit_after>// Thomas Alexander Steinholz
// South River High School
// C++ w/ Gaming : 1A

#include <iostream>
#include <string>

struct Code
{
    enum Peg
    {
        RED,
        BLUE,
        YELLOW,
        GREEN,
        WHITE,
        ORANGE,
        NOTHING,
    };

    Code()
    {
        Peg temp[4];
        for(int i = 0; i < 4; i++)
        {
            switch(rand() % 6)
            {
                case 0:
                    temp[i] = RED;
                    break;
                case 1:
                    temp[i] = BLUE;
                    break;
                case 2:
                    temp[i] = YELLOW;
                    break;
                case 3:
                    temp[i] = GREEN;
                    break;
                case 4:
                    temp[i] = WHITE;
                    break;
                case 5:
                    temp[i] = ORANGE;
                    break;
            }
        }
        A = temp[0];
        B = temp[1];
        C = temp[2];
        D = temp[3];
    }

    Code(Peg x)
        : A(x), B(x), C(x), D(x) {}

    Code(Peg a, Peg b, Peg c, Peg d)
        : A(a), B(b), C(c), D(d) {}

    Code(const Code& copy)
        : A(copy.A), B(copy.B), C(copy.C), D(copy.D) {}

    Peg A, B, C, D;

    //TODO
    void PrintState()
    {
        std::cout<<ToString(A)<<" "<<ToString(B)<<" "<<ToString(C)<<" "<<ToString(D)<<" "<<std::endl;
    }

    bool Verify()
    {
        return A != NOTHING &&
               B != NOTHING &&
               C != NOTHING &&
               D != NOTHING;
    }

    static Peg ToPeg(const char x)
    {
        switch (x)
        {
            case 'r':
            case 'R':
                return RED;
            case 'b':
            case 'B':
                return BLUE;
            case 'y':
            case 'Y':
                return YELLOW;
            case 'g':
            case 'G':
                return GREEN;
            case 'w':
            case 'W':
                return WHITE;
            case 'o':
            case 'O':
                return ORANGE;
            default:
                return NOTHING;
        }
    }

    static std::string ToString(const Peg x)
    {
        switch(x)
        {
            case RED:
                return "Red";
            case BLUE:
                return "Blue";
            case YELLOW:
                return "Yellow";
            case GREEN:
                return "Green";
            case WHITE:
                return "White";
            case ORANGE:
                return "Orange";
            default:
            case NOTHING:
                return "Nothing";
        }
    }

    bool operator==(const Code &c) const
    {
        return (A == c.A) &&
               (B == c.B) &&
               (C == c.C) &&
               (D == c.D);
    }

    bool operator!=(const Code &c) const
    {
        return !((A == c.A) ||
                 (B == c.B) ||
                 (C == c.C) ||
                 (D == c.D));
    }
};

Code* Turn()
{
    std::string result;
    std::cout << "GUESS: ";
    std::getline(std::cin, result);

    if (result.length() > 3)
    {
        Code::Peg A = Code::ToPeg(result.at(0));
        if (A != Code::Peg::NOTHING)
        {
            Code::Peg B = Code::ToPeg(result.at(1));
            if (B != Code::Peg::NOTHING)
            {
                Code::Peg C = Code::ToPeg(result.at(2));
                if (C != Code::Peg::NOTHING)
                {
                    Code::Peg D = Code::ToPeg(result.at(3));
                    if (D != Code::Peg::NOTHING)
                    {
                        return new Code(A, B, C, D);
                    }
                    else std::cout << std::endl << "ERROR: Col 4 '" << result.at(3) << "'" << std::endl;
                }
                else std::cout << std::endl << "ERROR: Col 3 '" << result.at(2) << "'" << std::endl;
            }
            else std::cout << std::endl << "ERROR: Col 2 '" << result.at(1) << "'" << std::endl;
        }
        else std::cout << std::endl << "ERROR: Col 1 '" << result.at(0) << "'" << std::endl;
    }
    return NULL;
}

//TODO
void Feedback(Code* code, Code* guess)
{

}

int main()
{
    srand(time(NULL));
    bool executing = true;
    int guesses = 0;
    Code* code = new Code();
    code->PrintState();//DEBUG
    Code* guess = NULL;
    std::cout << "Welcome to Mastermind by Thomas Steinholz!" << std::endl;
    std::cout << "You are playing as the \"Code Breaker\" that means you will need to guess the combonations" << std::endl;
    std::cout << "of colors that the AI will generate. Your options are R-B-Y-G-W-O. For example to type in" << std::endl;
    std::cout << "the colors red, blue, yellow, and orange you would type \"RBYO\" untill you get the right combo." << std::endl;
    std::cout << "Scoring Code:" << std::endl << "o - Right Color, Right Place" << std::endl;
    std::cout << "~ - Right Color, Wrong Place" << std::endl << "x - Neither" << std::endl;
    std::cout << "Good Luck, and don't forget to have fun!" << std::endl << std::endl;

    while (executing)
    {
        guesses++;
        std::cout << "|------------|" << std::endl;
        std::cout << "[ Guess " << guesses << "/10 ]" << std::endl;
        std::cout << "|------------|" << std::endl;

        guess = NULL;
        while (!guess) guess = Turn();
        Feedback(code, guess);

        if (code == guess)
        {
            executing = false;
            std::cout << "----------------------------------" << std::endl;
            std::cout << "Good Work! You just won the game!!" << std::endl;
            std::cout << "----------------------------------" << std::endl;
        }

        if (guesses > 9)
        {
            executing = false;
            std::cout << "-----------------------------------------------------" << std::endl;
            std::cout << "Sorry! You lost because you have used all 10 guesses!" << std::endl;
            std::cout << "-----------------------------------------------------" << std::endl;
        }
    }

    delete code;
    delete guess;

    return 0;
}<|endoftext|>


<commit_before>/*
 * Retina.cpp
 *
 *  Created on: Jul 29, 2008
 *
 */

#include "HyPerLayer.hpp"
#include "Retina.hpp"
#include "../io/io.h"
#include "../include/default_params.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

namespace PV {

// default values
fileread_params RetinaParams =
{
   0.0, 0.0, 1.0, 1.0*(NOISE_AMP==0.0)+0.5*(NOISE_AMP>0.0),
   0.0*(NOISE_AMP==0.0)+0.01*(NOISE_AMP>0.0),
   0.0, 0.0,         /* burstFreg, burstDuration */
   0.0, 0.0, 1000.0  /* marginWidth, beginStim, endStim */
};

Retina::Retina(const char * name, HyPerCol * hc)
  : HyPerLayer(name, hc)
{
   this->img = new Image("Image", hc, hc->inputFile());
   initialize(TypeRetina);
}

Retina::Retina(const char * name, HyPerCol * hc, Image * img)
  : HyPerLayer(name, hc)
{
   this->img = img;
   initialize(TypeRetina);
}

Retina::Retina(const char * name, HyPerCol * hc, const char * filename)
  : HyPerLayer(name, hc)
{
   this->img = new Image("Image", hc, filename);
   initialize(TypeRetina);
}

int Retina::initialize(PVLayerType type)
{
   int n, status = 0;
   PVLayer  * l   = clayer;

   this->clayer->layerType = type;

   setParams(parent->parameters(), &RetinaParams);

   fileread_params * params = (fileread_params *) l->params;

   l->loc = img->getImageLoc();
   l->loc.nPad   = params->marginWidth;
   l->loc.nBands = 1;

   // the size of the Retina may have changed due size of image
   //
   const int nx = l->loc.nx;
   const int ny = l->loc.ny;
   const int nBorder = l->loc.nPad;
   l->numFeatures = l->loc.nBands;
   l->numNeurons  = nx * ny * l->numFeatures;
#ifdef EXTEND_BORDER_INDEX
   l->numExtended = (nx + 2*nBorder) * (ny + 2*nBorder) * l->numFeatures;
#else
   l->numExtended = l->numNeurons;
#endif // EXTEND_BORDER_INDEX

   PVParams * pvParams = parent->parameters();

   fireOffPixels = 0;
   if (pvParams->present(name, "fireOffPixels")) {
      fireOffPixels = pvParams->value(name, "fireOffPixels");
   }

   status = parent->addLayer(this);

   // at least for the Retina, V is extended size, so resize
   if (l->numExtended != l->numNeurons) {
      free(l->V);
      l->V = (pvdata_t *) calloc(l->numExtended, sizeof(float));
   }

   // TODO - could free other layer parameters as they are not used

   // use image's data buffer
   updateImage(parent->simulationTime(), parent->getDeltaTime());
   copyFromImageBuffer();

   pvdata_t * V = l->V;

   if (params->invert) {
      for (n = 0; n < l->numExtended; n++) {
         V[n] = 1 - V[n];
      }
   }

   if (params->uncolor) {
      for (n = 0; n < l->numExtended; n++) {
         V[n] = (V[n] == 0.0) ? 0.0 : 1.0;
      }
   }

   return status;
}
//!
/*!
 *
 * dt is in seconds here!
 *
 */
int Retina::setParams(PVParams * params, fileread_params * p)
{
   float dt = parent->getDeltaTime() * .001;  // seconds

   clayer->params = (float *) malloc(sizeof(*p));
   assert(clayer->params != NULL);
   memcpy(clayer->params, p, sizeof(*p));

   clayer->numParams = sizeof(*p) / sizeof(float);

   fileread_params * cp = (fileread_params *) clayer->params;

   if (params->present(name, "invert"))  cp->invert  = params->value(name, "invert");
   if (params->present(name, "uncolor")) cp->uncolor = params->value(name, "uncolor");

   if (params->present(name, "spikingFlag"))
      cp->spikingFlag      = params->value(name, "spikingFlag");
   if (params->present(name, "poissonEdgeProb"))
      cp->poissonEdgeProb  = params->value(name, "poissonEdgeProb");
   if (params->present(name, "poissonBlankProb"))
      cp->poissonBlankProb = params->value(name, "poissonBlankProb");
   if (params->present(name, "burstFreq"))
      cp->burstFreq  = params->value(name, "burstFreq");
   if (params->present(name, "burstDuration"))
      cp->burstDuration  = params->value(name, "burstDuration");
   if (params->present(name, "marginWidth"))
      cp->marginWidth      = params->value(name, "marginWidth");

   if (params->present(name, "noiseOnFreq")) {
      cp->poissonEdgeProb  = params->value(name, "noiseOnFreq") * dt;
      if (cp->poissonEdgeProb > 1.0) cp->poissonEdgeProb = 1.0;
   }
   if (params->present(name, "noiseOffFreq")) {
      cp->poissonBlankProb  = params->value(name, "noiseOffFreq") * dt;
      if (cp->poissonBlankProb > 1.0) cp->poissonBlankProb = 1.0;
   }

   if (params->present(name, "beginStim")) cp->beginStim = params->value(name, "beginStim");
   if (params->present(name, "endStim"))   cp->endStim   = params->value(name, "endStim");

   return 0;
}

int Retina::recvSynapticInput(HyPerLayer* lSource, PVLayerCube* cube)
{
   return 0; //PV_Retina_recv_synaptic_input();
}

//! Sets the V data buffer
/*!
 *
 * REMARKS:
 *      - this method is called from  updateImage()
 *      - copies from the Image data buffer into the V buffer
 *      - it normalizes the V buffer so that V <= 1.
 *      .
 *
 *
 */
int Retina::copyFromImageBuffer()
{
   const int nf = clayer->numFeatures;
   pvdata_t * V = clayer->V;

   PVLayerLoc imageLoc = img->getImageLoc();

   assert(clayer->loc.nx == imageLoc.nx && clayer->loc.ny == imageLoc.ny);

   pvdata_t * ibuf = img->getImageBuffer();

   // for now
   assert(nf == 1);

   HyPerLayer::copyToBuffer(V, ibuf, &imageLoc, true, 1.0f);

   // normalize so that V <= 1.0
   pvdata_t vmax = 0;
   for (int k = 0; k < clayer->numNeurons; k++) {
      vmax = V[k] > vmax ? V[k] : vmax;
   }
   if (vmax != 0){
      for (int k = 0; k < clayer->numNeurons; k++) {
         V[k] = V[k] / vmax;
      }
   }

   //
   // otherwise handle OFF/ON cells

   // f[0] are OFF, f[1] are ON cells
//   const int count = imageLoc.nx * imageLoc.ny;
//   if (fireOffPixels) {
//      for (int k = 0; k < count; k++) {
//         V[2*k]   = 1 - ibuf[k] / Imax;
//         V[2*k+1] = ibuf[k] / Imax;
//      }
//   }
//   else {
//      for (int k = 0; k < count; k++) {
//         V[2*k]   = ibuf[k] / Imax;
//         V[2*k+1] = ibuf[k] / Imax;
//      }

   return 0;
}

//! updates the Image that Retina is exposed to
/*!
 *
 * REMARKS:
 *      - This depends on the Image class. The data buffer is generally modulated
 *      by the intensity at the image location.
 *
 *
 */
int Retina::updateImage(float time, float dt)
{
   bool changed = img->updateImage(time, dt);
   if (not changed) return 0;

   return copyFromImageBuffer();
}

//! Updates the state of the Retina
/*!
 * REMARKS:
 *      - prevActivity[] buffer holds the time when a neuron last spiked.
 *      - it sets the probStim and probBase.
 *              - probStim = poissonEdgeProb * V[k];
 *              - probBase = poissonBlankProb
 *              .
 *      - activity[] is set to 0 or 1 depending on the return of spike()
 *      - this depends on the last time a neuron spiked as well as on V[]
 *      at the location of the neuron. This V[] is set by calling updateImage()
 *      .
 *
 *
 */
int Retina::updateState(float time, float dt)
{
   float probSpike = 0.0;
   fileread_params * params = (fileread_params *) clayer->params;

   pvdata_t * V = clayer->V;
   pvdata_t * activity = clayer->activity->data;
   float    * prevActivity = clayer->prevActivity;

   const float nx = clayer->loc.nx;
   const float ny = clayer->loc.ny;
   const float nf = clayer->numFeatures;

   const float marginWidth = clayer->loc.nPad;

   updateImage(time, dt);

   // make sure activity in border is zero
   //
   int numActive = 0;
   for (int k = 0; k < clayer->numExtended; k++) {
      activity[k] = 0.0;
   }

   if (params->spikingFlag == 1) {
      for (int k = 0; k < clayer->numNeurons; k++) {
         int kex = kIndexExtended(k, nx, ny, nf, marginWidth);
         float probStim = params->poissonEdgeProb * V[k];
         float probBase = params->poissonBlankProb;
         float prevTime = prevActivity[kex];
         activity[kex]  = spike(time, dt, prevTime, probBase, probStim, &probSpike);
         prevActivity[kex] = (activity[kex] > 0.0) ? time : prevTime;
         if (activity[kex] > 0.0) {
            clayer->activeIndices[numActive++] = k;
         }
      }
   }
   else {
      // retina is non spiking, pass scaled image through to activity
      //
      for (int k = 0; k < clayer->numNeurons; k++) {
         int kex = kIndexExtended(k, nx, ny, nf, marginWidth);
         // scale output according to poissonEdgeProb, this could
         // perhaps be renamed when non spiking
         float maxRetinalActivity = params->poissonEdgeProb;
         activity[kex] = maxRetinalActivity * V[k];
         prevActivity[kex] = activity[kex];
         clayer->activeIndices[numActive++] = k;
      }
   }
   clayer->numActive = numActive;

   return 0;
}

int Retina::writeState(const char * path, float time)
{
   HyPerLayer::writeState(path, time);

   // print activity at center of image

#ifdef DEBUG_OUTPUT
   int sx = clayer->numFeatures;
   int sy = sx*clayer->loc.nx;
   pvdata_t * a = clayer->activity->data;

   for (int i = 0; i < clayer->numExtended; i++) {
      if (a[i] == 1.0) printf("a[%d] == 1\n", i);
   }

  int n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
  for (int f = 0; f < clayer->numFeatures; f++) {
     printf("a[%d] = %f\n", n, a[n]);
     n += 1;
  }
#endif

   return 0;
}

//! Spiking method for Retina
/*!
 * Returns 1 if an event should occur, 0 otherwise (let prob = 1 for nonspiking)
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *       spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *      spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFrq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *      an integer, the burstStatus is set to 1.
 *      - The burstStatus is also set by the condition that
 *      beginStim < t < endStim. These parameters are set in the input
 *      params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *      or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases
 *       with probStim.
 *      - When the probability is negative, the neuron does not spike.
 */
int Retina::spike(float time, float dt, float prev, float probBase, float probStim, float * probSpike)
{
   fileread_params * params = (fileread_params *) clayer->params;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < ABS_REFACTORY_PERIOD) {
      return 0;
   }
   else {
      float delta = time - prev - ABS_REFACTORY_PERIOD;
      float refact = 1.0f - expf(-delta/REFACTORY_PERIOD);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      sinAmp = cos( 2 * PI * time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = fmodf(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   *probSpike = probBase;

   if ((int)burstStatus) {
      *probSpike += probStim * sinAmp;  // negative prob is OK
    }
   return ( rand() < (*probSpike * RAND_MAX));
}

} // namespace PV
<commit_msg>Casts (and the like, mostly to ints) to remove compiler warnings on Lobo.<commit_after>/*
 * Retina.cpp
 *
 *  Created on: Jul 29, 2008
 *
 */

#include "HyPerLayer.hpp"
#include "Retina.hpp"
#include "../io/io.h"
#include "../include/default_params.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

namespace PV {

// default values
fileread_params RetinaParams =
{
   0.0, 0.0, 1.0, 1.0*(NOISE_AMP==0.0)+0.5*(NOISE_AMP>0.0),
   0.0*(NOISE_AMP==0.0)+0.01*(NOISE_AMP>0.0),
   0.0, 0.0,         /* burstFreg, burstDuration */
   0.0, 0.0, 1000.0  /* marginWidth, beginStim, endStim */
};

Retina::Retina(const char * name, HyPerCol * hc)
  : HyPerLayer(name, hc)
{
   this->img = new Image("Image", hc, hc->inputFile());
   initialize(TypeRetina);
}

Retina::Retina(const char * name, HyPerCol * hc, Image * img)
  : HyPerLayer(name, hc)
{
   this->img = img;
   initialize(TypeRetina);
}

Retina::Retina(const char * name, HyPerCol * hc, const char * filename)
  : HyPerLayer(name, hc)
{
   this->img = new Image("Image", hc, filename);
   initialize(TypeRetina);
}

int Retina::initialize(PVLayerType type)
{
   int n, status = 0;
   PVLayer  * l   = clayer;

   this->clayer->layerType = type;

   setParams(parent->parameters(), &RetinaParams);

   fileread_params * params = (fileread_params *) l->params;

   l->loc = img->getImageLoc();
   l->loc.nPad = (int) params->marginWidth;
   l->loc.nBands = 1;

   // the size of the Retina may have changed due size of image
   //
   const int nx = l->loc.nx;
   const int ny = l->loc.ny;
   const int nBorder = l->loc.nPad;
   l->numFeatures = l->loc.nBands;
   l->numNeurons  = nx * ny * l->numFeatures;
#ifdef EXTEND_BORDER_INDEX
   l->numExtended = (nx + 2*nBorder) * (ny + 2*nBorder) * l->numFeatures;
#else
   l->numExtended = l->numNeurons;
#endif // EXTEND_BORDER_INDEX

   PVParams * pvParams = parent->parameters();

   fireOffPixels = (int) pvParams->value(name, "fireOffPixels", 0);

   status = parent->addLayer(this);

   // at least for the Retina, V is extended size, so resize
   if (l->numExtended != l->numNeurons) {
      free(l->V);
      l->V = (pvdata_t *) calloc(l->numExtended, sizeof(float));
   }

   // TODO - could free other layer parameters as they are not used

   // use image's data buffer
   updateImage(parent->simulationTime(), parent->getDeltaTime());
   copyFromImageBuffer();

   pvdata_t * V = l->V;

   if (params->invert) {
      for (n = 0; n < l->numExtended; n++) {
         V[n] = 1 - V[n];
      }
   }

   if (params->uncolor) {
      for (n = 0; n < l->numExtended; n++) {
         V[n] = (V[n] == 0.0) ? 0.0 : 1.0;
      }
   }

   return status;
}
//!
/*!
 *
 * dt is in seconds here!
 *
 */
int Retina::setParams(PVParams * params, fileread_params * p)
{
   float dt = parent->getDeltaTime() * .001;  // seconds

   clayer->params = (float *) malloc(sizeof(*p));
   assert(clayer->params != NULL);
   memcpy(clayer->params, p, sizeof(*p));

   clayer->numParams = sizeof(*p) / sizeof(float);

   fileread_params * cp = (fileread_params *) clayer->params;

   if (params->present(name, "invert"))  cp->invert  = params->value(name, "invert");
   if (params->present(name, "uncolor")) cp->uncolor = params->value(name, "uncolor");

   if (params->present(name, "spikingFlag"))
      cp->spikingFlag      = params->value(name, "spikingFlag");
   if (params->present(name, "poissonEdgeProb"))
      cp->poissonEdgeProb  = params->value(name, "poissonEdgeProb");
   if (params->present(name, "poissonBlankProb"))
      cp->poissonBlankProb = params->value(name, "poissonBlankProb");
   if (params->present(name, "burstFreq"))
      cp->burstFreq  = params->value(name, "burstFreq");
   if (params->present(name, "burstDuration"))
      cp->burstDuration  = params->value(name, "burstDuration");
   if (params->present(name, "marginWidth"))
      cp->marginWidth      = params->value(name, "marginWidth");

   if (params->present(name, "noiseOnFreq")) {
      cp->poissonEdgeProb  = params->value(name, "noiseOnFreq") * dt;
      if (cp->poissonEdgeProb > 1.0) cp->poissonEdgeProb = 1.0;
   }
   if (params->present(name, "noiseOffFreq")) {
      cp->poissonBlankProb  = params->value(name, "noiseOffFreq") * dt;
      if (cp->poissonBlankProb > 1.0) cp->poissonBlankProb = 1.0;
   }

   if (params->present(name, "beginStim")) cp->beginStim = params->value(name, "beginStim");
   if (params->present(name, "endStim"))   cp->endStim   = params->value(name, "endStim");

   return 0;
}

int Retina::recvSynapticInput(HyPerLayer* lSource, PVLayerCube* cube)
{
   return 0; //PV_Retina_recv_synaptic_input();
}

//! Sets the V data buffer
/*!
 *
 * REMARKS:
 *      - this method is called from  updateImage()
 *      - copies from the Image data buffer into the V buffer
 *      - it normalizes the V buffer so that V <= 1.
 *      .
 *
 *
 */
int Retina::copyFromImageBuffer()
{
   const int nf = clayer->numFeatures;
   pvdata_t * V = clayer->V;

   PVLayerLoc imageLoc = img->getImageLoc();

   assert(clayer->loc.nx == imageLoc.nx && clayer->loc.ny == imageLoc.ny);

   pvdata_t * ibuf = img->getImageBuffer();

   // for now
   assert(nf == 1);

   HyPerLayer::copyToBuffer(V, ibuf, &imageLoc, true, 1.0f);

   // normalize so that V <= 1.0
   pvdata_t vmax = 0;
   for (int k = 0; k < clayer->numNeurons; k++) {
      vmax = V[k] > vmax ? V[k] : vmax;
   }
   if (vmax != 0){
      for (int k = 0; k < clayer->numNeurons; k++) {
         V[k] = V[k] / vmax;
      }
   }

   //
   // otherwise handle OFF/ON cells

   // f[0] are OFF, f[1] are ON cells
//   const int count = imageLoc.nx * imageLoc.ny;
//   if (fireOffPixels) {
//      for (int k = 0; k < count; k++) {
//         V[2*k]   = 1 - ibuf[k] / Imax;
//         V[2*k+1] = ibuf[k] / Imax;
//      }
//   }
//   else {
//      for (int k = 0; k < count; k++) {
//         V[2*k]   = ibuf[k] / Imax;
//         V[2*k+1] = ibuf[k] / Imax;
//      }

   return 0;
}

//! updates the Image that Retina is exposed to
/*!
 *
 * REMARKS:
 *      - This depends on the Image class. The data buffer is generally modulated
 *      by the intensity at the image location.
 *
 *
 */
int Retina::updateImage(float time, float dt)
{
   bool changed = img->updateImage(time, dt);
   if (not changed) return 0;

   return copyFromImageBuffer();
}

//! Updates the state of the Retina
/*!
 * REMARKS:
 *      - prevActivity[] buffer holds the time when a neuron last spiked.
 *      - it sets the probStim and probBase.
 *              - probStim = poissonEdgeProb * V[k];
 *              - probBase = poissonBlankProb
 *              .
 *      - activity[] is set to 0 or 1 depending on the return of spike()
 *      - this depends on the last time a neuron spiked as well as on V[]
 *      at the location of the neuron. This V[] is set by calling updateImage()
 *      .
 *
 *
 */
int Retina::updateState(float time, float dt)
{
   float probSpike = 0.0;
   fileread_params * params = (fileread_params *) clayer->params;

   pvdata_t * V = clayer->V;
   pvdata_t * activity = clayer->activity->data;
   float    * prevActivity = clayer->prevActivity;

   const int nx = clayer->loc.nx;
   const int ny = clayer->loc.ny;
   const int nf = clayer->numFeatures;

   const int marginWidth = clayer->loc.nPad;

   updateImage(time, dt);

   // make sure activity in border is zero
   //
   int numActive = 0;
   for (int k = 0; k < clayer->numExtended; k++) {
      activity[k] = 0.0;
   }

   if (params->spikingFlag == 1) {
      for (int k = 0; k < clayer->numNeurons; k++) {
         int kex = kIndexExtended(k, nx, ny, nf, marginWidth);
         float probStim = params->poissonEdgeProb * V[k];
         float probBase = params->poissonBlankProb;
         float prevTime = prevActivity[kex];
         activity[kex]  = spike(time, dt, prevTime, probBase, probStim, &probSpike);
         prevActivity[kex] = (activity[kex] > 0.0) ? time : prevTime;
         if (activity[kex] > 0.0) {
            clayer->activeIndices[numActive++] = k;
         }
      }
   }
   else {
      // retina is non spiking, pass scaled image through to activity
      //
      for (int k = 0; k < clayer->numNeurons; k++) {
         int kex = kIndexExtended(k, nx, ny, nf, marginWidth);
         // scale output according to poissonEdgeProb, this could
         // perhaps be renamed when non spiking
         float maxRetinalActivity = params->poissonEdgeProb;
         activity[kex] = maxRetinalActivity * V[k];
         prevActivity[kex] = activity[kex];
         clayer->activeIndices[numActive++] = k;
      }
   }
   clayer->numActive = numActive;

   return 0;
}

int Retina::writeState(const char * path, float time)
{
   HyPerLayer::writeState(path, time);

   // print activity at center of image

#ifdef DEBUG_OUTPUT
   int sx = clayer->numFeatures;
   int sy = sx*clayer->loc.nx;
   pvdata_t * a = clayer->activity->data;

   for (int i = 0; i < clayer->numExtended; i++) {
      if (a[i] == 1.0) printf("a[%d] == 1\n", i);
   }

  int n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
  for (int f = 0; f < clayer->numFeatures; f++) {
     printf("a[%d] = %f\n", n, a[n]);
     n += 1;
  }
#endif

   return 0;
}

//! Spiking method for Retina
/*!
 * Returns 1 if an event should occur, 0 otherwise (let prob = 1 for nonspiking)
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *       spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *      spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFrq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *      an integer, the burstStatus is set to 1.
 *      - The burstStatus is also set by the condition that
 *      beginStim < t < endStim. These parameters are set in the input
 *      params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *      or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases
 *       with probStim.
 *      - When the probability is negative, the neuron does not spike.
 */
int Retina::spike(float time, float dt, float prev, float probBase, float probStim, float * probSpike)
{
   fileread_params * params = (fileread_params *) clayer->params;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < ABS_REFACTORY_PERIOD) {
      return 0;
   }
   else {
      float delta = time - prev - ABS_REFACTORY_PERIOD;
      float refact = 1.0f - expf(-delta/REFACTORY_PERIOD);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      sinAmp = cos( 2 * PI * time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = fmodf(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   *probSpike = probBase;

   if ((int)burstStatus) {
      *probSpike += probStim * sinAmp;  // negative prob is OK
    }
   return ( rand() < (*probSpike * RAND_MAX));
}

} // namespace PV
<|endoftext|>


<commit_before>/*
 * Retina.cpp
 *
 *  Created on: Jul 29, 2008
 *
 */

#include "HyPerLayer.hpp"
#include "Retina.hpp"
#include "../io/io.h"
#include "../include/default_params.h"
#include "../utils/cl_random.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

void Retina_update_state (
    const float time,
    const float dt,
    const int nx,
    const int ny,
    const int nf,
    const int nb,
    Retina_params * params,
    uint4 * rnd,
    float * phiExc,
    float * phiInh,
    float * activity,
    float * prevTime);

#ifdef __cplusplus
}
#endif

namespace PV {

Retina::Retina(const char * name, HyPerCol * hc)
  : HyPerLayer(name, hc, NUM_RETINA_CHANNELS)
{
#ifdef OBSOLETE
   this->img = new Image("Image", hc, hc->inputFile());
#endif
   initialize(TypeRetina);
}

Retina::~Retina()
{
   free(rand_state);

#ifdef PV_USE_OPENCL
   free(evList);

   delete clPhiE;
   delete clPhiI;
   delete clActivity;
   delete clPrevTime;
#endif
}

int Retina::initialize(PVLayerType type)
{
   int status = 0;
   PVLayer * l = clayer;

   clayer->layerType = type;
   setParams(parent->parameters());

   // the size of the Retina may have changed due to size of image
   //
   const int nx = l->loc.nx;
   const int ny = l->loc.ny;
   const int nf = l->loc.nf;
   const int nb = l->loc.nb;
   l->numNeurons  = nx * ny * nf;
   l->numExtended = (nx + 2*nb) * (ny + 2*nb) * nf;

   // a random state variable is needed for every neuron/clthread
   rand_state = cl_random_init(l->numNeurons);

   status = parent->addLayer(this);

#ifdef PV_USE_OPENCL
   numEvents = NUM_RETINA_EVENTS;
   evList = (cl_event *) malloc(numEvents*sizeof(cl_event));
   assert(evList != NULL);

   initializeThreadBuffers();
   initializeThreadKernels();
#endif

   return status;
}

#ifdef PV_USE_OPENCL
/**
 * Initialize OpenCL buffers.  This must be called after PVLayer data have
 * been allocated.
 */
int Retina::initializeThreadBuffers()
{
   int status = CL_SUCCESS;

   const size_t size    = clayer->numNeurons  * sizeof(pvdata_t);
   const size_t size_ex = clayer->numExtended * sizeof(pvdata_t);

   CLDevice * device = parent->getCLDevice();

   // these buffers are shared between host and device
   //

   clV = NULL;

   // TODO - use constant memory
   clParams = device->createBuffer(CL_MEM_COPY_HOST_PTR, sizeof(rParams), &rParams);
   clRand   = device->createBuffer(CL_MEM_COPY_HOST_PTR, getNumNeurons()*sizeof(uint4), rand_state);

   clPhiE = device->createBuffer(CL_MEM_COPY_HOST_PTR, size, getChannel(CHANNEL_EXC));
   clPhiI = device->createBuffer(CL_MEM_COPY_HOST_PTR, size, getChannel(CHANNEL_INH));

   assert(numChannels < 3);
   clPhiIB = NULL;

   clActivity = device->createBuffer(CL_MEM_COPY_HOST_PTR, size_ex, clayer->activity->data);
   clPrevTime = device->createBuffer(CL_MEM_COPY_HOST_PTR, size_ex, clayer->prevActivity);

   return status;
}

int Retina::initializeThreadKernels()
{
   char kernelPath[256];
   char kernelFlags[256];

   int status = CL_SUCCESS;
   CLDevice * device = parent->getCLDevice();

   sprintf(kernelPath,  "%s/src/kernels/Retina_update_state.cl", parent->getPath());
   sprintf(kernelFlags, "-D PV_USE_OPENCL -I %s/src/kernels/",   parent->getPath());

   // create kernels
   //
   krUpdate = device->createKernel(kernelPath, "Retina_update_state", kernelFlags);

   int argid = 0;

   status |= krUpdate->setKernelArg(argid++, parent->simulationTime());
   status |= krUpdate->setKernelArg(argid++, parent->getDeltaTime());

   status |= krUpdate->setKernelArg(argid++, clayer->loc.nx);
   status |= krUpdate->setKernelArg(argid++, clayer->loc.ny);
   status |= krUpdate->setKernelArg(argid++, clayer->loc.nf);
   status |= krUpdate->setKernelArg(argid++, clayer->loc.nb);

   status |= krUpdate->setKernelArg(argid++, clParams);
   status |= krUpdate->setKernelArg(argid++, clRand);

   status |= krUpdate->setKernelArg(argid++, clPhiE);
   status |= krUpdate->setKernelArg(argid++, clPhiI);
   status |= krUpdate->setKernelArg(argid++, clActivity);
   status |= krUpdate->setKernelArg(argid++, clPrevTime);

   return status;
}
#endif

int Retina::setParams(PVParams * p)
{
   float dt_sec = parent->getDeltaTime() * .001;  // seconds

   clayer->loc.nf = 1;
   clayer->loc.nb = (int) p->value(name, "marginWidth", 0.0);

   clayer->params = &rParams;

   spikingFlag = (int) p->value(name, "spikingFlag", 1);

   float probStim = p->value(name, "poissonEdgeProb" , 1.0f);
   float probBase = p->value(name, "poissonBlankProb", 0.0f);

   if (p->present(name, "noiseOnFreq")) {
      probStim = p->value(name, "noiseOnFreq") * dt_sec;
      if (probStim > 1.0) probStim = 1.0;
   }
   if (p->present(name, "noiseOffFreq")) {
      probBase = p->value(name, "noiseOffFreq") * dt_sec;
      if (probBase > 1.0) probBase = 1.0;
   }

   // default parameters
   //
   rParams.probStim  = probStim;
   rParams.probBase  = probBase;
   rParams.beginStim = p->value(name, "beginStim", 0.0f);
   rParams.endStim   = p->value(name, "endStim"  , 99999999.9f);
   rParams.burstFreq = p->value(name, "burstFreq", 40);         // frequency of bursts
   rParams.burstDuration = p->value(name, "burstDuration", 20); // duration of each burst, <=0 -> sinusoidal
   rParams.refactory_period = REFACTORY_PERIOD;
   rParams.abs_refactory_period = REFACTORY_PERIOD;

   return 0;
}

int Retina::updateStateOpenCL(float time, float dt)
{
   int status = CL_SUCCESS;

   update_timer->start();

#ifdef PV_USE_OPENCL
   // wait for memory to be copied to device
   status |= clWaitForEvents(numWait, evList);
   for (int i = 1; i < numWait; i++) {
      clReleaseEvent(evList[i]);
   }
   numWait = 0;

   nxl = nyl = 1;

   status |= krUpdate->setKernelArg(0, time);
   status |= krUpdate->setKernelArg(1, dt);
   status |= krUpdate->run(getNumNeurons(), nxl*nyl, 0, NULL, &evUpdate);

   status |= clPhiE    ->copyFromDevice(1, &evUpdate, &evList[EV_R_PHI_E]);
   status |= clPhiI    ->copyFromDevice(1, &evUpdate, &evList[EV_R_PHI_I]);
   status |= clActivity->copyFromDevice(1, &evUpdate, &evList[EV_R_ACTIVITY]);

   numWait += 3;
#endif

   update_timer->start();

   return status;
}

int Retina::triggerReceive(InterColComm* comm)
{
   int status = HyPerLayer::triggerReceive(comm);

   // copy data to device
   //
#ifdef PV_USE_OPENCL
   status |= clPhiE->copyToDevice(&evList[EV_R_PHI_E]);
   status |= clPhiI->copyToDevice(&evList[EV_R_PHI_I]);
   numWait += 2;
#endif

   return status;
}

int Retina::waitOnPublish(InterColComm* comm)
{
   int status = HyPerLayer::waitOnPublish(comm);

   // copy activity to device
   //
#ifdef PV_USE_OPENCL
   status |= clActivity->copyToDevice(&evList[EV_R_ACTIVITY]);
   numWait += 1;
#endif

   return status;
}

//! Updates the state of the Retina
/*!
 * REMARKS:
 *      - prevActivity[] buffer holds the time when a neuron last spiked.
 *      - not used if nonspiking
 *      - it sets the probStim and probBase.
 *              - probStim = poissonEdgeProb * V[k];
 *              - probBase = poissonBlankProb
 *              .
 *      - activity[] is set to 0 or 1 depending on the return of spike()
 *      - this depends on the last time a neuron spiked as well as on V[]
 *      at the location of the neuron. This V[] is set by calling updateImage().
 *      - V points to the same memory space as data in the Image so that when Image
 *      is updated, V gets updated too.
 *      .
 * NOTES:
 *      - poissonEdgeProb = noiseOnFreq * dT
 *      - poissonBlankProb = noiseOffFreq * dT
 *      .
 *
 *
 */
int Retina::updateState(float time, float dt)
{
#ifndef PV_USE_OPENCL
   update_timer->start();

   const int nx = clayer->loc.nx;
   const int ny = clayer->loc.ny;
   const int nf = clayer->loc.nf;
   const int nb = clayer->loc.nb;

   pvdata_t * phiExc   = getChannel(CHANNEL_EXC);
   pvdata_t * phiInh   = getChannel(CHANNEL_INH);
   pvdata_t * activity = clayer->activity->data;

   if (spikingFlag == 1) {
      Retina_update_state(time, dt, nx, ny, nf, nb,
                          &rParams, rand_state,
                          phiExc, phiInh, activity, clayer->prevActivity);
   }
   else {
      // retina is non spiking, pass scaled image through to activity
      // scale by poissonEdgeProb (maxRetinalActivity)
      //
      for (int k = 0; k < clayer->numNeurons; k++) {
         const int kex = kIndexExtended(k, nx, ny, nf, nb);
         activity[kex] = rParams.probStim * (phiExc[k] - phiInh[k]);
         // TODO - get rid of this for performance
         clayer->activeIndices[k] = globalIndexFromLocal(k, clayer->loc);

         // reset accumulation buffers
         phiExc[k] = 0.0;
         phiInh[k] = 0.0;
      }
      clayer->numActive = clayer->numNeurons;
   }
   update_timer->stop();
#else

   updateStateOpenCL(time, dt);

#endif

#ifdef DEBUG_PRINT
   char filename[132];
   sprintf(filename, "r_%d.tiff", (int)(2*time));
   this->writeActivity(filename, time);

   printf("----------------\n");
   for (int k = 0; k < 6; k++) {
      printf("host:: k==%d h_exc==%f h_inh==%f\n", k, phiExc[k], phiInh[k]);
   }
   printf("----------------\n");

#endif

   return 0;
}

int Retina::writeState(const char * path, float time)
{
   HyPerLayer::writeState(path, time);

   // print activity at center of image

#ifdef DEBUG_OUTPUT
   int sx = clayer->numFeatures;
   int sy = sx*clayer->loc.nx;
   pvdata_t * a = clayer->activity->data;

   for (int k = 0; k < clayer->numExtended; k++) {
      if (a[k] == 1.0) printf("a[%d] == 1\n", k);
   }

  int n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
  for (int f = 0; f < clayer->numFeatures; f++) {
     printf("a[%d] = %f\n", n, a[n]);
     n += 1;
  }
#endif

   return 0;
}

//! Spiking method for Retina
/*!
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *       spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *      spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *      an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *      beginStim < t < endStim. These parameters are set in the input
 *      params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *      or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases
 *       with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *      .
 * NOTES:
 *      - time is measured in milliseconds.
 *      .
 */
#ifdef OBSOLETE
int Retina::spike(float time, float dt, float prev, float probBase, float probStim, float * probSpike)
{
   fileread_params * params = (fileread_params *) clayer->params;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < ABS_REFACTORY_PERIOD) {
      return 0;
   }
   else {
      float delta = time - prev - ABS_REFACTORY_PERIOD;
      float refact = 1.0f - expf(-delta/REFACTORY_PERIOD);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration < 0 || params->burstFreq == 0) {
      sinAmp = cos( 2 * PI * time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = fmodf(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   *probSpike = probBase;

   if ((int)burstStatus) {
      *probSpike += probStim * sinAmp;  // negative prob is OK
    }
   return ( pv_random_prob() < *probSpike );
}
#endif

} // namespace PV

///////////////////////////////////////////////////////
//
// implementation of Retina kernels
//

#ifdef __cplusplus
extern "C" {
#endif

#ifndef PV_USE_OPENCL
#  include "../kernels/Retina_update_state.cl"
#endif

#ifdef __cplusplus
}
#endif
<commit_msg>Removed dead code related to numActive (moved calculation of numActive to writeActivitySparse).<commit_after>/*
 * Retina.cpp
 *
 *  Created on: Jul 29, 2008
 *
 */

#include "HyPerLayer.hpp"
#include "Retina.hpp"
#include "../io/io.h"
#include "../include/default_params.h"
#include "../utils/cl_random.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

void Retina_update_state (
    const float time,
    const float dt,
    const int nx,
    const int ny,
    const int nf,
    const int nb,
    Retina_params * params,
    uint4 * rnd,
    float * phiExc,
    float * phiInh,
    float * activity,
    float * prevTime);

#ifdef __cplusplus
}
#endif

namespace PV {

Retina::Retina(const char * name, HyPerCol * hc)
  : HyPerLayer(name, hc, NUM_RETINA_CHANNELS)
{
#ifdef OBSOLETE
   this->img = new Image("Image", hc, hc->inputFile());
#endif
   initialize(TypeRetina);
}

Retina::~Retina()
{
   free(rand_state);

#ifdef PV_USE_OPENCL
   free(evList);

   delete clPhiE;
   delete clPhiI;
   delete clActivity;
   delete clPrevTime;
#endif
}

int Retina::initialize(PVLayerType type)
{
   int status = 0;
   PVLayer * l = clayer;

   clayer->layerType = type;
   setParams(parent->parameters());

   // the size of the Retina may have changed due to size of image
   //
   const int nx = l->loc.nx;
   const int ny = l->loc.ny;
   const int nf = l->loc.nf;
   const int nb = l->loc.nb;
   l->numNeurons  = nx * ny * nf;
   l->numExtended = (nx + 2*nb) * (ny + 2*nb) * nf;

   // a random state variable is needed for every neuron/clthread
   rand_state = cl_random_init(l->numNeurons);

   status = parent->addLayer(this);

#ifdef PV_USE_OPENCL
   numEvents = NUM_RETINA_EVENTS;
   evList = (cl_event *) malloc(numEvents*sizeof(cl_event));
   assert(evList != NULL);

   initializeThreadBuffers();
   initializeThreadKernels();
#endif

   return status;
}

#ifdef PV_USE_OPENCL
/**
 * Initialize OpenCL buffers.  This must be called after PVLayer data have
 * been allocated.
 */
int Retina::initializeThreadBuffers()
{
   int status = CL_SUCCESS;

   const size_t size    = clayer->numNeurons  * sizeof(pvdata_t);
   const size_t size_ex = clayer->numExtended * sizeof(pvdata_t);

   CLDevice * device = parent->getCLDevice();

   // these buffers are shared between host and device
   //

   clV = NULL;

   // TODO - use constant memory
   clParams = device->createBuffer(CL_MEM_COPY_HOST_PTR, sizeof(rParams), &rParams);
   clRand   = device->createBuffer(CL_MEM_COPY_HOST_PTR, getNumNeurons()*sizeof(uint4), rand_state);

   clPhiE = device->createBuffer(CL_MEM_COPY_HOST_PTR, size, getChannel(CHANNEL_EXC));
   clPhiI = device->createBuffer(CL_MEM_COPY_HOST_PTR, size, getChannel(CHANNEL_INH));

   assert(numChannels < 3);
   clPhiIB = NULL;

   clActivity = device->createBuffer(CL_MEM_COPY_HOST_PTR, size_ex, clayer->activity->data);
   clPrevTime = device->createBuffer(CL_MEM_COPY_HOST_PTR, size_ex, clayer->prevActivity);

   return status;
}

int Retina::initializeThreadKernels()
{
   char kernelPath[256];
   char kernelFlags[256];

   int status = CL_SUCCESS;
   CLDevice * device = parent->getCLDevice();

   sprintf(kernelPath,  "%s/src/kernels/Retina_update_state.cl", parent->getPath());
   sprintf(kernelFlags, "-D PV_USE_OPENCL -I %s/src/kernels/",   parent->getPath());

   // create kernels
   //
   krUpdate = device->createKernel(kernelPath, "Retina_update_state", kernelFlags);

   int argid = 0;

   status |= krUpdate->setKernelArg(argid++, parent->simulationTime());
   status |= krUpdate->setKernelArg(argid++, parent->getDeltaTime());

   status |= krUpdate->setKernelArg(argid++, clayer->loc.nx);
   status |= krUpdate->setKernelArg(argid++, clayer->loc.ny);
   status |= krUpdate->setKernelArg(argid++, clayer->loc.nf);
   status |= krUpdate->setKernelArg(argid++, clayer->loc.nb);

   status |= krUpdate->setKernelArg(argid++, clParams);
   status |= krUpdate->setKernelArg(argid++, clRand);

   status |= krUpdate->setKernelArg(argid++, clPhiE);
   status |= krUpdate->setKernelArg(argid++, clPhiI);
   status |= krUpdate->setKernelArg(argid++, clActivity);
   status |= krUpdate->setKernelArg(argid++, clPrevTime);

   return status;
}
#endif

int Retina::setParams(PVParams * p)
{
   float dt_sec = parent->getDeltaTime() * .001;  // seconds

   clayer->loc.nf = 1;
   clayer->loc.nb = (int) p->value(name, "marginWidth", 0.0);

   clayer->params = &rParams;

   spikingFlag = (int) p->value(name, "spikingFlag", 1);

   float probStim = p->value(name, "poissonEdgeProb" , 1.0f);
   float probBase = p->value(name, "poissonBlankProb", 0.0f);

   if (p->present(name, "noiseOnFreq")) {
      probStim = p->value(name, "noiseOnFreq") * dt_sec;
      if (probStim > 1.0) probStim = 1.0;
   }
   if (p->present(name, "noiseOffFreq")) {
      probBase = p->value(name, "noiseOffFreq") * dt_sec;
      if (probBase > 1.0) probBase = 1.0;
   }

   // default parameters
   //
   rParams.probStim  = probStim;
   rParams.probBase  = probBase;
   rParams.beginStim = p->value(name, "beginStim", 0.0f);
   rParams.endStim   = p->value(name, "endStim"  , 99999999.9f);
   rParams.burstFreq = p->value(name, "burstFreq", 40);         // frequency of bursts
   rParams.burstDuration = p->value(name, "burstDuration", 20); // duration of each burst, <=0 -> sinusoidal
   rParams.refactory_period = REFACTORY_PERIOD;
   rParams.abs_refactory_period = REFACTORY_PERIOD;

   return 0;
}

int Retina::updateStateOpenCL(float time, float dt)
{
   int status = CL_SUCCESS;

   update_timer->start();

#ifdef PV_USE_OPENCL
   // wait for memory to be copied to device
   status |= clWaitForEvents(numWait, evList);
   for (int i = 1; i < numWait; i++) {
      clReleaseEvent(evList[i]);
   }
   numWait = 0;

   nxl = nyl = 1;

   status |= krUpdate->setKernelArg(0, time);
   status |= krUpdate->setKernelArg(1, dt);
   status |= krUpdate->run(getNumNeurons(), nxl*nyl, 0, NULL, &evUpdate);

   status |= clPhiE    ->copyFromDevice(1, &evUpdate, &evList[EV_R_PHI_E]);
   status |= clPhiI    ->copyFromDevice(1, &evUpdate, &evList[EV_R_PHI_I]);
   status |= clActivity->copyFromDevice(1, &evUpdate, &evList[EV_R_ACTIVITY]);

   numWait += 3;
#endif

   update_timer->start();

   return status;
}

int Retina::triggerReceive(InterColComm* comm)
{
   int status = HyPerLayer::triggerReceive(comm);

   // copy data to device
   //
#ifdef PV_USE_OPENCL
   status |= clPhiE->copyToDevice(&evList[EV_R_PHI_E]);
   status |= clPhiI->copyToDevice(&evList[EV_R_PHI_I]);
   numWait += 2;
#endif

   return status;
}

int Retina::waitOnPublish(InterColComm* comm)
{
   int status = HyPerLayer::waitOnPublish(comm);

   // copy activity to device
   //
#ifdef PV_USE_OPENCL
   status |= clActivity->copyToDevice(&evList[EV_R_ACTIVITY]);
   numWait += 1;
#endif

   return status;
}

//! Updates the state of the Retina
/*!
 * REMARKS:
 *      - prevActivity[] buffer holds the time when a neuron last spiked.
 *      - not used if nonspiking
 *      - it sets the probStim and probBase.
 *              - probStim = poissonEdgeProb * V[k];
 *              - probBase = poissonBlankProb
 *              .
 *      - activity[] is set to 0 or 1 depending on the return of spike()
 *      - this depends on the last time a neuron spiked as well as on V[]
 *      at the location of the neuron. This V[] is set by calling updateImage().
 *      - V points to the same memory space as data in the Image so that when Image
 *      is updated, V gets updated too.
 *      .
 * NOTES:
 *      - poissonEdgeProb = noiseOnFreq * dT
 *      - poissonBlankProb = noiseOffFreq * dT
 *      .
 *
 *
 */
int Retina::updateState(float time, float dt)
{
#ifndef PV_USE_OPENCL
   update_timer->start();

   const int nx = clayer->loc.nx;
   const int ny = clayer->loc.ny;
   const int nf = clayer->loc.nf;
   const int nb = clayer->loc.nb;

   pvdata_t * phiExc   = getChannel(CHANNEL_EXC);
   pvdata_t * phiInh   = getChannel(CHANNEL_INH);
   pvdata_t * activity = clayer->activity->data;

   if (spikingFlag == 1) {
      Retina_update_state(time, dt, nx, ny, nf, nb,
                          &rParams, rand_state,
                          phiExc, phiInh, activity, clayer->prevActivity);
   }
   else {
      // retina is non spiking, pass scaled image through to activity
      // scale by poissonEdgeProb (maxRetinalActivity)
      //
      for (int k = 0; k < clayer->numNeurons; k++) {
         const int kex = kIndexExtended(k, nx, ny, nf, nb);
         activity[kex] = rParams.probStim * (phiExc[k] - phiInh[k]);
         // reset accumulation buffers
         phiExc[k] = 0.0;
         phiInh[k] = 0.0;
      }
   }
   update_timer->stop();
#else

   updateStateOpenCL(time, dt);

#endif

#ifdef DEBUG_PRINT
   char filename[132];
   sprintf(filename, "r_%d.tiff", (int)(2*time));
   this->writeActivity(filename, time);

   printf("----------------\n");
   for (int k = 0; k < 6; k++) {
      printf("host:: k==%d h_exc==%f h_inh==%f\n", k, phiExc[k], phiInh[k]);
   }
   printf("----------------\n");

#endif

   return 0;
}

int Retina::writeState(const char * path, float time)
{
   HyPerLayer::writeState(path, time);

   // print activity at center of image

#ifdef DEBUG_OUTPUT
   int sx = clayer->numFeatures;
   int sy = sx*clayer->loc.nx;
   pvdata_t * a = clayer->activity->data;

   for (int k = 0; k < clayer->numExtended; k++) {
      if (a[k] == 1.0) printf("a[%d] == 1\n", k);
   }

  int n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
  for (int f = 0; f < clayer->numFeatures; f++) {
     printf("a[%d] = %f\n", n, a[n]);
     n += 1;
  }
#endif

   return 0;
}

//! Spiking method for Retina
/*!
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *       spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *      spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *      an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *      beginStim < t < endStim. These parameters are set in the input
 *      params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *      or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases
 *       with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *      .
 * NOTES:
 *      - time is measured in milliseconds.
 *      .
 */
#ifdef OBSOLETE
int Retina::spike(float time, float dt, float prev, float probBase, float probStim, float * probSpike)
{
   fileread_params * params = (fileread_params *) clayer->params;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < ABS_REFACTORY_PERIOD) {
      return 0;
   }
   else {
      float delta = time - prev - ABS_REFACTORY_PERIOD;
      float refact = 1.0f - expf(-delta/REFACTORY_PERIOD);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration < 0 || params->burstFreq == 0) {
      sinAmp = cos( 2 * PI * time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = fmodf(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   *probSpike = probBase;

   if ((int)burstStatus) {
      *probSpike += probStim * sinAmp;  // negative prob is OK
    }
   return ( pv_random_prob() < *probSpike );
}
#endif

} // namespace PV

///////////////////////////////////////////////////////
//
// implementation of Retina kernels
//

#ifdef __cplusplus
extern "C" {
#endif

#ifndef PV_USE_OPENCL
#  include "../kernels/Retina_update_state.cl"
#endif

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>/*
   Copyright 2014 Kristina Simpson <sweet.kristas@gmail.com>

   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 <boost/range/adaptor/reversed.hpp>

#include "asserts.hpp"
#include "layout_widget.hpp"

namespace gui
{
	layout::layout(const std::vector<widget_ptr>& children, LayoutType lt, const rectf& pos, Justify justify)
		: widget(pos, justify),
		  layout_type_(lt)
	{
		for(auto& c : children) {
			children_.emplace(c);
		}
	}

	layout::layout(const std::vector<widget_ptr>* children, LayoutType lt,Justify justify)
		: widget(point(), justify),
		  layout_type_(lt)
	{
		if(children != nullptr) {
			for(auto& c : *children) {
				children_.emplace(c);
			}
		}
	}

	void layout::add_child(widget_ptr w)
	{
		children_.emplace(w);
	}

	void layout::handle_init()
	{
	}

	void layout::handle_draw(const rect& r, float rotation, float scale) const
	{
		for(auto& w : children_) {
			// This will work for absolutely positioned elements, not for relative ones.
			w->draw(r, rotation, scale);
		}
	}

	bool layout::handle_events(SDL_Event* evt, bool claimed)
	{
		for(auto& w : boost::adaptors::reverse(children_)) {
			SDL_Event evtcpy(*evt);
			if((claimed = w->process_events(&evtcpy, claimed)) == true) {
				return claimed;
			}
		}
		return claimed;
	}

	void layout::recalc_dimensions()
	{
		int lx = 0;
		int ly = 0;
		int lw = 0;
		int lh = 0;
		if(layout_type_ == LayoutType::LT_RELATIVE) {
			/*for(auto& w : children_) {
				ASSERT_LOG(w->w() < fixed_width_, "width of child widget is greater than width of layout widget");
				if(lx + w->w() > fixed_width_) {
					ly += lh;
					lh = 0;
				}
				lh = std::max(lh, w->h());
				w->setLoc(lx, ly);
				lx += w->w();
				lw = std::max(lw, lx);
			}*/
			ASSERT_LOG(false, "add code for relative layout.");
		} else if(layout_type_ == LayoutType::LT_ABSOLUTE) {
			// do nothing
			for(auto& w : children_) {
				lw = std::max(lw, w->w());
				lh = std::max(lh, w->h());
			}
		} else {
			ASSERT_LOG(false, "Incorrect layout style");
		}
		if(!is_area_set()) {
			set_dim(lw, lh);
		}
	}

	void layout::handle_window_resize(int w, int h)
	{
	}

}
<commit_msg>Fixed a bug with the layout widget not normalizing mouse events.<commit_after>/*
   Copyright 2014 Kristina Simpson <sweet.kristas@gmail.com>

   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 <boost/range/adaptor/reversed.hpp>

#include "asserts.hpp"
#include "layout_widget.hpp"

namespace gui
{
	layout::layout(const std::vector<widget_ptr>& children, LayoutType lt, const rectf& pos, Justify justify)
		: widget(pos, justify),
		  layout_type_(lt)
	{
		for(auto& c : children) {
			children_.emplace(c);
		}
	}

	layout::layout(const std::vector<widget_ptr>* children, LayoutType lt,Justify justify)
		: widget(point(), justify),
		  layout_type_(lt)
	{
		if(children != nullptr) {
			for(auto& c : *children) {
				children_.emplace(c);
			}
		}
	}

	void layout::add_child(widget_ptr w)
	{
		children_.emplace(w);
	}

	void layout::handle_init()
	{
	}

	void layout::handle_draw(const rect& r, float rotation, float scale) const
	{
		for(auto& w : children_) {
			// This will work for absolutely positioned elements, not for relative ones.
			w->draw(r, rotation, scale);
		}
	}

	bool layout::handle_events(SDL_Event* evt, bool claimed)
	{
		SDL_Event evtcpy(*evt);
		normalize_event(&evtcpy, physical_area().top_left());

		for(auto& w : boost::adaptors::reverse(children_)) {
			if((claimed = w->process_events(&evtcpy, claimed)) == true) {
				return claimed;
			}
		}
		return claimed;
	}

	void layout::recalc_dimensions()
	{
		int lx = 0;
		int ly = 0;
		int lw = 0;
		int lh = 0;
		if(layout_type_ == LayoutType::LT_RELATIVE) {
			/*for(auto& w : children_) {
				ASSERT_LOG(w->w() < fixed_width_, "width of child widget is greater than width of layout widget");
				if(lx + w->w() > fixed_width_) {
					ly += lh;
					lh = 0;
				}
				lh = std::max(lh, w->h());
				w->setLoc(lx, ly);
				lx += w->w();
				lw = std::max(lw, lx);
			}*/
			ASSERT_LOG(false, "add code for relative layout.");
		} else if(layout_type_ == LayoutType::LT_ABSOLUTE) {
			// do nothing
			for(auto& w : children_) {
				lw = std::max(lw, w->w());
				lh = std::max(lh, w->h());
			}
		} else {
			ASSERT_LOG(false, "Incorrect layout style");
		}
		if(!is_area_set()) {
			set_dim(lw, lh);
		}
	}

	void layout::handle_window_resize(int w, int h)
	{
	}

}
<|endoftext|>