<commit_before>// cpsm - fuzzy path matcher
// Copyright (C) 2015 Jamie Liu
//
// 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 "matcher.h"

#include <algorithm>
#include <cstdint>
#include <utility>

#include <boost/range/adaptor/reversed.hpp>

#include "path_util.h"
#include "str_util.h"

namespace cpsm {

Matcher::Matcher(std::string query, MatcherOpts opts)
    : query_(std::move(query)), opts_(std::move(opts)) {
  if (opts_.is_path) {
    switch (opts_.query_path_mode) {
      case MatcherOpts::QueryPathMode::NORMAL:
        require_full_part_ = false;
        break;
      case MatcherOpts::QueryPathMode::STRICT:
        require_full_part_ = true;
        break;
      case MatcherOpts::QueryPathMode::AUTO:
        require_full_part_ = (query_.find_first_of('/') != std::string::npos);
        break;
    }
    for (boost::string_ref const query_part : path_components_of(query_)) {
      std::vector<char32_t> query_part_chars;
      decompose_utf8_string(query_part, query_part_chars);
      query_parts_chars_.emplace_back(std::move(query_part_chars));
    }
  } else {
    require_full_part_ = false;
    std::vector<char32_t> query_chars;
    decompose_utf8_string(query_, query_chars);
    query_parts_chars_.emplace_back(std::move(query_chars));
  }
  // Queries are smartcased (case-sensitive only if any uppercase appears in the
  // query).
  is_case_sensitive_ = std::any_of(query_.begin(), query_.end(), is_uppercase);
  cur_file_parts_ = path_components_of(opts_.cur_file);
  // Keeping the filename in cur_file_parts_ causes the path distance metric to
  // favor the currently open file. While we don't want to exclude the
  // currently open file from being matched, it shouldn't be favored over its
  // siblings on path distance.
  if (!cur_file_parts_.empty()) {
    cur_file_parts_.pop_back();
  }
}

bool Matcher::match_base(boost::string_ref const item, MatchBase& m,
                         std::vector<char32_t>* item_part_chars) const {
  m = MatchBase();
  if (query_parts_chars_.empty()) {
    return true;
  }

  std::vector<char32_t> item_part_chars_local;
  if (!item_part_chars) {
    item_part_chars = &item_part_chars_local;
  }

  std::vector<boost::string_ref> item_parts;
  if (opts_.is_path) {
    item_parts = path_components_of(item);
    m.path_distance = path_distance_between(cur_file_parts_, item_parts);
  } else {
    item_parts.push_back(item);
  }

  // Since for paths (the common case) we prefer rightmost path components, we
  // scan path components right-to-left.
  auto query_part_chars_it = query_parts_chars_.rbegin();
  auto const query_part_chars_end = query_parts_chars_.rend();
  // Index of the last unmatched character in query_part.
  std::ptrdiff_t end = std::ptrdiff_t(query_part_chars_it->size()) - 1;
  // Index into item_parts, counting from the right.
  CharCount part_index = 0;
  for (boost::string_ref const item_part :
       boost::adaptors::reverse(item_parts)) {
    auto const& query_part_chars = *query_part_chars_it;
    item_part_chars->clear();
    decompose_utf8_string(item_part, *item_part_chars);
    if (part_index == 0) {
      m.unmatched_len = item_part_chars->size();
    }

    // Since path components are matched right-to-left, query characters must be
    // consumed greedily right-to-left.
    std::ptrdiff_t start = end;  // index of last unmatched query char
    if (start >= 0) {
      for (char32_t const c : boost::adaptors::reverse(*item_part_chars)) {
        if (match_char(c, query_part_chars[start])) {
          start--;
          if (start < 0) {
            break;
          }
        }
      }
    }
    if (require_full_part_ && start >= 0) {
      // Didn't consume all characters, but strict query path mode is on, so the
      // consumed characters don't count.
      part_index++;
      continue;
    }
    std::ptrdiff_t const next_end = start;

    // Since within a path component we usually prefer leftmost character
    // matches, we pick the leftmost match for each consumed character.
    start++;  // now index of first matched query char
    if (start <= end) {
      const auto is_word_prefix = [&](std::size_t const i) -> bool {
        if (i == 0) {
          return true;
        }
        if (is_alphanumeric((*item_part_chars)[i]) &&
            !is_alphanumeric((*item_part_chars)[i - 1])) {
          return true;
        }
        if (is_uppercase((*item_part_chars)[i]) &&
            !is_uppercase((*item_part_chars)[i - 1])) {
          return true;
        }
        return false;
      };
      bool at_word_start = false;
      for (std::size_t i = 0; i < item_part_chars->size(); i++) {
        if (match_char((*item_part_chars)[i], query_part_chars[start])) {
          if (part_index == 0) {
            if (is_word_prefix(i)) {
              at_word_start = true;
            }
            if (at_word_start) {
              m.word_prefix_len++;
            }
            if (i == 0 && start == 0) {
              m.prefix_match = MatchBase::PrefixMatch::PARTIAL;
            }
          }
          start++;
          if (start > end) {
            if (part_index == 0) {
              m.unmatched_len = item_part_chars->size() - (i + 1);
              if (i == std::size_t(end) && next_end < 0) {
                m.prefix_match = MatchBase::PrefixMatch::FULL;
              }
            }
            break;
          }
        } else {
          at_word_start = false;
        }
      }
    }

    // Did we match anything in this item part?
    if (end != next_end) {
      end = next_end;
      m.part_index_sum += part_index;
    }
    if (end < 0) {
      query_part_chars_it++;
      if (query_part_chars_it == query_part_chars_end) {
        return true;
      }
      end = std::ptrdiff_t(query_part_chars_it->size()) - 1;
    }
    part_index++;
  }

  return false;
}

bool Matcher::match_char(char32_t item, char32_t const query) const {
  if (!is_case_sensitive_) {
    // The query must not contain any uppercase letters since otherwise the
    // query would be case-sensitive, so just force all uppercase characters to
    // lowercase.
    if (is_uppercase(item)) {
      item = to_lowercase(item);
    }
  }
  return item == query;
}

}  // namespace cpsm
<commit_msg>Fix use of path distance for empty queries<commit_after>// cpsm - fuzzy path matcher
// Copyright (C) 2015 Jamie Liu
//
// 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 "matcher.h"

#include <algorithm>
#include <cstdint>
#include <utility>

#include <boost/range/adaptor/reversed.hpp>

#include "path_util.h"
#include "str_util.h"

namespace cpsm {

Matcher::Matcher(std::string query, MatcherOpts opts)
    : query_(std::move(query)), opts_(std::move(opts)) {
  if (opts_.is_path) {
    switch (opts_.query_path_mode) {
      case MatcherOpts::QueryPathMode::NORMAL:
        require_full_part_ = false;
        break;
      case MatcherOpts::QueryPathMode::STRICT:
        require_full_part_ = true;
        break;
      case MatcherOpts::QueryPathMode::AUTO:
        require_full_part_ = (query_.find_first_of('/') != std::string::npos);
        break;
    }
    for (boost::string_ref const query_part : path_components_of(query_)) {
      std::vector<char32_t> query_part_chars;
      decompose_utf8_string(query_part, query_part_chars);
      query_parts_chars_.emplace_back(std::move(query_part_chars));
    }
  } else {
    require_full_part_ = false;
    std::vector<char32_t> query_chars;
    decompose_utf8_string(query_, query_chars);
    query_parts_chars_.emplace_back(std::move(query_chars));
  }
  // Queries are smartcased (case-sensitive only if any uppercase appears in the
  // query).
  is_case_sensitive_ = std::any_of(query_.begin(), query_.end(), is_uppercase);
  cur_file_parts_ = path_components_of(opts_.cur_file);
  // Keeping the filename in cur_file_parts_ causes the path distance metric to
  // favor the currently open file. While we don't want to exclude the
  // currently open file from being matched, it shouldn't be favored over its
  // siblings on path distance.
  if (!cur_file_parts_.empty()) {
    cur_file_parts_.pop_back();
  }
}

bool Matcher::match_base(boost::string_ref const item, MatchBase& m,
                         std::vector<char32_t>* item_part_chars) const {
  m = MatchBase();

  std::vector<char32_t> item_part_chars_local;
  if (!item_part_chars) {
    item_part_chars = &item_part_chars_local;
  }

  std::vector<boost::string_ref> item_parts;
  if (opts_.is_path) {
    item_parts = path_components_of(item);
    m.path_distance = path_distance_between(cur_file_parts_, item_parts);
  } else {
    item_parts.push_back(item);
  }

  if (query_parts_chars_.empty()) {
    return true;
  }

  // Since for paths (the common case) we prefer rightmost path components, we
  // scan path components right-to-left.
  auto query_part_chars_it = query_parts_chars_.rbegin();
  auto const query_part_chars_end = query_parts_chars_.rend();
  // Index of the last unmatched character in query_part.
  std::ptrdiff_t end = std::ptrdiff_t(query_part_chars_it->size()) - 1;
  // Index into item_parts, counting from the right.
  CharCount part_index = 0;
  for (boost::string_ref const item_part :
       boost::adaptors::reverse(item_parts)) {
    auto const& query_part_chars = *query_part_chars_it;
    item_part_chars->clear();
    decompose_utf8_string(item_part, *item_part_chars);
    if (part_index == 0) {
      m.unmatched_len = item_part_chars->size();
    }

    // Since path components are matched right-to-left, query characters must be
    // consumed greedily right-to-left.
    std::ptrdiff_t start = end;  // index of last unmatched query char
    if (start >= 0) {
      for (char32_t const c : boost::adaptors::reverse(*item_part_chars)) {
        if (match_char(c, query_part_chars[start])) {
          start--;
          if (start < 0) {
            break;
          }
        }
      }
    }
    if (require_full_part_ && start >= 0) {
      // Didn't consume all characters, but strict query path mode is on, so the
      // consumed characters don't count.
      part_index++;
      continue;
    }
    std::ptrdiff_t const next_end = start;

    // Since within a path component we usually prefer leftmost character
    // matches, we pick the leftmost match for each consumed character.
    start++;  // now index of first matched query char
    if (start <= end) {
      const auto is_word_prefix = [&](std::size_t const i) -> bool {
        if (i == 0) {
          return true;
        }
        if (is_alphanumeric((*item_part_chars)[i]) &&
            !is_alphanumeric((*item_part_chars)[i - 1])) {
          return true;
        }
        if (is_uppercase((*item_part_chars)[i]) &&
            !is_uppercase((*item_part_chars)[i - 1])) {
          return true;
        }
        return false;
      };
      bool at_word_start = false;
      for (std::size_t i = 0; i < item_part_chars->size(); i++) {
        if (match_char((*item_part_chars)[i], query_part_chars[start])) {
          if (part_index == 0) {
            if (is_word_prefix(i)) {
              at_word_start = true;
            }
            if (at_word_start) {
              m.word_prefix_len++;
            }
            if (i == 0 && start == 0) {
              m.prefix_match = MatchBase::PrefixMatch::PARTIAL;
            }
          }
          start++;
          if (start > end) {
            if (part_index == 0) {
              m.unmatched_len = item_part_chars->size() - (i + 1);
              if (i == std::size_t(end) && next_end < 0) {
                m.prefix_match = MatchBase::PrefixMatch::FULL;
              }
            }
            break;
          }
        } else {
          at_word_start = false;
        }
      }
    }

    // Did we match anything in this item part?
    if (end != next_end) {
      end = next_end;
      m.part_index_sum += part_index;
    }
    if (end < 0) {
      query_part_chars_it++;
      if (query_part_chars_it == query_part_chars_end) {
        return true;
      }
      end = std::ptrdiff_t(query_part_chars_it->size()) - 1;
    }
    part_index++;
  }

  return false;
}

bool Matcher::match_char(char32_t item, char32_t const query) const {
  if (!is_case_sensitive_) {
    // The query must not contain any uppercase letters since otherwise the
    // query would be case-sensitive, so just force all uppercase characters to
    // lowercase.
    if (is_uppercase(item)) {
      item = to_lowercase(item);
    }
  }
  return item == query;
}

}  // namespace cpsm
<|endoftext|>


<commit_before>// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rmath.h>

#include <vector>
#include <cassert>

#include "vmat.h"
#include "gmat.h"
#include "DataPairs.h"
#include "quadrule.h"
#include "pn.h"
#include "functions.h"

using namespace Rcpp;
using namespace arma;
using namespace std;

const double twopi = 2*datum::pi;

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Full loglikelihood */
double loglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  data.pi_gen(row, u); // Estimation of pi based on u

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  double res = 0; // Initialising output (loglik contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = logdF2(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += logdF1(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){
	    // Unconditional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){
    vmat sig = sigmaU; // Variance-covariance matrix of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }

  /* Return */
  return(res);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Score function of full loglikelihood */
rowvec Dloglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  /* Estimation of pi, dpidu and dlogpidu */
  data.pi_gen(row, u);
  data.dpidu_gen(row, u);
  data.dlogpidu_gen(row, u);

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  rowvec res = zeros<rowvec>(data.ncauses); // Initialising output (score contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = dlogdF2du(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  rowvec probdu = dF1du(row, j, i, data);
	  lik -= prob;
	  likdu -= probdu;
	}
	res += (1/lik)*likdu;
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	}
	res += (1/lik)*likdu;
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      rowvec likdu = zeros<rowvec>(data.ncauses);
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	  likdu -= probdu;
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  rowvec probdu = dF2du(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	  likdu += probdu;
	}
      }
      res = (1/lik)*likdu;
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += dlogdF1du(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  rowvec likdu = zeros<rowvec>(data.ncauses);
	  if (cause < 0){ // Uncondtional
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else { // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    rowvec probdu = dF1du(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  res += (1/lik)*likdu;
	}
      }
    }
  }
  /* Contribution from u */
  if (full){

    vmat sig = sigmaU; // Variance-covariance matrix etc. of u

    // Adding to the score
    res += -u.t()*sig.inv;
  };
  return(res);
}

/////////////////////////////////////////////////////////////////////////////
// FOR TESTING

// [[Rcpp::export]]
double loglikout(mat sigma, vec u, int ncauses, imat causes, mat alpha, mat dalpha, mat beta, mat gamma){

  // Initialising gmats of sigma (Joint, Cond)
  gmat sigmaJoint = gmat(ncauses, ncauses);
  gmat sigmaCond = gmat(ncauses, ncauses);
  gmat sigmaMarg = gmat(ncauses, 1);

  // Vectors for extracting rows and columns from sigma
  uvec rcJ(2); /* for joint */
  uvec rc1(1); /* for conditional */
  uvec rc2(ncauses+1); /* for conditional */
  uvec rcu(ncauses);
  for (int h=0; h<ncauses; h++){
    rcu(h) = ncauses + h;
  };

  // Calculating and setting sigmaJoint
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rcJ(0)=h;
      rcJ(1)=ncauses+i;
      vmat x = vmat(sigma, rcJ, rcu);
      sigmaJoint.set(h,i,x);
    };
  };

  // Calculating and setting sigmaMarg
  for (int h=0; h<ncauses; h++){
    rc1(0) = h;
    vmat x = vmat(sigma, rc1, rcu);
    sigmaMarg.set(h,1,x);
  };

  // Calculating and setting sigmaCond
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rc1(0) = h;
      rc2(0) = i;
      for (int j=0; j<ncauses; j++){
	rc2(j+1) = rcu(j);
      };
      vmat x = vmat(sigma, rc1, rc2);
      sigmaCond.set(h,i,x);
    };
  };

  Rcpp::Rcout << "here " <<std::endl;

  // vmat of the us
  mat matU = sigma.submat(rcu,rcu);
  vmat sigmaU = vmat(matU);

  Rcpp::Rcout << "there " <<std::endl;

  // Generating DataPairs
  DataPairs data = DataPairs(ncauses, causes, alpha, dalpha, beta, gamma);

  unsigned row = 1;

  // Estimating likelihood contribution
  double loglik = loglikfull(row, data, sigmaMarg, sigmaJoint, sigmaCond, sigmaU, u);

  Rcpp::Rcout << "everywhere " <<std::endl;

  // Return
  return loglik;
};

//rowvec Dloglikout(unsigned row, mat sigma, mat data, vec u){

  // Generating gmats of sigma (Marg, Joint, MargCond, sigU)

  // Generating DataPairs

  // Estimating score contribution
//  rowvec score = Dloglikfull(unsigned row, DataPairs data, gmat sigmaJoint, gmat sigmaMargCond, vmat sigmaU, vec u, bool full=1);

  // Return
//  return score;
//};
<commit_msg>export<commit_after>// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rmath.h>

#include <vector>
#include <cassert>

#include "vmat.h"
#include "gmat.h"
#include "DataPairs.h"
#include "quadrule.h"
#include "pn.h"
#include "functions.h"

using namespace Rcpp;
using namespace arma;
using namespace std;

const double twopi = 2*datum::pi;

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Full loglikelihood */
double loglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  data.pi_gen(row, u); // Estimation of pi based on u

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  double res = 0; // Initialising output (loglik contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = logdF2(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += logdF1(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){
	    // Unconditional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){
    vmat sig = sigmaU; // Variance-covariance matrix of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }

  /* Return */
  return(res);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Score function of full loglikelihood */
rowvec Dloglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaCond, vmat sigmaU, vec u, bool full=1){

  /* Estimation of pi, dpidu and dlogpidu */
  data.pi_gen(row, u);
  data.dpidu_gen(row, u);
  data.dlogpidu_gen(row, u);

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  rowvec res = zeros<rowvec>(data.ncauses); // Initialising output (score contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = dlogdF2du(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  rowvec probdu = dF1du(row, j, i, data);
	  lik -= prob;
	  likdu -= probdu;
	}
	res += (1/lik)*likdu;
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(data.ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	}
	res += (1/lik)*likdu;
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      rowvec likdu = zeros<rowvec>(data.ncauses);
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	  likdu -= probdu;
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  rowvec probdu = dF2du(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	  likdu += probdu;
	}
      }
      res = (1/lik)*likdu;
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += dlogdF1du(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  rowvec likdu = zeros<rowvec>(data.ncauses);
	  if (cause < 0){ // Uncondtional
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else { // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaCond, u);
	    rowvec probdu = dF1du(row, j, i, cond_cause, data, sigmaCond, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  res += (1/lik)*likdu;
	}
      }
    }
  }
  /* Contribution from u */
  if (full){

    vmat sig = sigmaU; // Variance-covariance matrix etc. of u

    // Adding to the score
    res += -u.t()*sig.inv;
  };
  return(res);
}

/////////////////////////////////////////////////////////////////////////////
// FOR TESTING

// [[Rcpp::export]]
double loglikout(mat sigma, vec u, int ncauses, imat causes, mat alpha, mat dalpha, mat beta, mat gamma){

  // Initialising gmats of sigma (Joint, Cond)
  gmat sigmaJoint = gmat(ncauses, ncauses);
  gmat sigmaCond = gmat(ncauses, ncauses);
  gmat sigmaMarg = gmat(ncauses, 1);

  // Vectors for extracting rows and columns from sigma
  uvec rcJ(2); /* for joint */
  uvec rc1(1); /* for conditional */
  uvec rc2(ncauses+1); /* for conditional */
  uvec rcu(ncauses);
  for (int h=0; h<ncauses; h++){
    rcu(h) = ncauses + h;
  };

  // Calculating and setting sigmaJoint
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rcJ(0)=h;
      rcJ(1)=ncauses+i;
      vmat x = vmat(sigma, rcJ, rcu);
      sigmaJoint.set(h,i,x);
    };
  };

  Rcpp::Rcout << "here " <<std::endl;

  // Calculating and setting sigmaMarg
  for (int h=0; h<ncauses; h++){
    rc1(0) = h;
    vmat x = vmat(sigma, rc1, rcu);
    sigmaMarg.set(h,1,x);
  };

  // Calculating and setting sigmaCond
  for (int h=0; h<ncauses; h++){
    for (int i=0; i<ncauses; i++){
      rc1(0) = h;
      rc2(0) = i;
      for (int j=0; j<ncauses; j++){
	rc2(j+1) = rcu(j);
      };
      vmat x = vmat(sigma, rc1, rc2);
      sigmaCond.set(h,i,x);
    };
  };

  // vmat of the us
  mat matU = sigma.submat(rcu,rcu);
  vmat sigmaU = vmat(matU);

  Rcpp::Rcout << "there " <<std::endl;

  // Generating DataPairs
  DataPairs data = DataPairs(ncauses, causes, alpha, dalpha, beta, gamma);

  unsigned row = 1;

  // Estimating likelihood contribution
  double loglik = loglikfull(row, data, sigmaMarg, sigmaJoint, sigmaCond, sigmaU, u);

  Rcpp::Rcout << "everywhere " <<std::endl;

  // Return
  return loglik;
};

//rowvec Dloglikout(unsigned row, mat sigma, mat data, vec u){

  // Generating gmats of sigma (Marg, Joint, MargCond, sigU)

  // Generating DataPairs

  // Estimating score contribution
//  rowvec score = Dloglikfull(unsigned row, DataPairs data, gmat sigmaJoint, gmat sigmaMargCond, vmat sigmaU, vec u, bool full=1);

  // Return
//  return score;
//};
<|endoftext|>


<commit_before>// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
#include <Rmath.h>

#include <vector>
#include <cassert>

#include "vmat.h"
#include "gmat.h"
#include "DataPairs.h"
#include "quadrule.h"
#include "pn.h"
#include "functions.h"

using namespace Rcpp;
using namespace arma;
using namespace std;

const double twopi = 2*datum::pi;

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Full loglikelihood */
double loglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaMargCond, vmat sigmaU, vec u, bool full=1){

  data.pi_gen(row, u); // Estimation of pi based on u

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  double res = 0; // Initialising output (loglik contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = logdF2(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += logdF1(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){
	    // Unconditional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaMargCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){
    vmat sig = sigmaU; // Variance-covariance matrix of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }

  /* Return */
  return(res);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Score function of full loglikelihood */
rowvec Dloglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaMargCond, vmat sigmaU, vec u, bool full=1){

  /* Estimation of pi, dpidu and dlogpidu */
  data.pi_gen(row, u);
  data.dpidu_gen(row, u);
  data.dlogpidu_gen(row, u);

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  rowvec res(data.ncauses); // Initialising output (score contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = dlogdF2du(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += dlogdF1du(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){ // Uncondtional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else { // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaMargCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){

    vmat sig = sigmaU; // Variance-covariance matrix etc. of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }
  return(res);
}

<commit_msg>Dloglikfull<commit_after>// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
#include <Rmath.h>

#include <vector>
#include <cassert>

#include "vmat.h"
#include "gmat.h"
#include "DataPairs.h"
#include "quadrule.h"
#include "pn.h"
#include "functions.h"

using namespace Rcpp;
using namespace arma;
using namespace std;

const double twopi = 2*datum::pi;

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Full loglikelihood */
double loglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaMargCond, vmat sigmaU, vec u, bool full=1){

  data.pi_gen(row, u); // Estimation of pi based on u

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  double res = 0; // Initialising output (loglik contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = logdF2(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  lik -= prob;
	}
	res += log(lik);
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	  }
	}
	res += log(lik);
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	}
      }
      res = log(lik);
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += logdF1(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  if (cause < 0){
	    // Unconditional
	    double prob = F1(row, j, i, data);
	    lik -= prob;
	  }
	  else {
	    // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaMargCond, u);
	    lik -= prob;
	  }
	  res += log(lik);
	}
      }
    }
  }
  /* Contribution from u */
  if (full){
    vmat sig = sigmaU; // Variance-covariance matrix of u
    double inner = as_scalar(u*sig.inv*u.t());

    // PDF of u
    double logpdfu = log(pow(twopi,-(data.ncauses/2))) + sig.loginvsqdet - 0.5*inner;

    // Adding to the loglik
    res += logpdfu;
  }

  /* Return */
  return(res);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/* Score function of full loglikelihood */
rowvec Dloglikfull(unsigned row, DataPairs &data, const gmat &sigmaMarg, const gmat &sigmaJoint, const gmat &sigmaMargCond, vmat sigmaU, vec u, bool full=1){

  /* Estimation of pi, dpidu and dlogpidu */
  data.pi_gen(row, u);
  data.dpidu_gen(row, u);
  data.dlogpidu_gen(row, u);

  irowvec causes = data.causes_get(row); // Failure causes for pair in question

  rowvec res = zeros<rowvec>(ncauses); // Initialising output (score contribution)

  if ((causes(0) > 0) & (causes(1) > 0)){
    /* Both individuals experience failure */
    res = dlogdF2du(row, causes, data, sigmaJoint, u);
  }
  else if((causes(0) <= 0) & (causes(1) <= 0)){
    /* Neither individual experience failure */

    if ((causes(0) < 0) & (causes(1) < 0)){
      // Full follow-up for both individuals
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data);
	  rowvec probdu = dF1du(row, j, i, data);
	  lik -= prob;
	  likdu -= probdu;
	}
	res += (1/lik)*likdu;
      }
    }
    else if (((causes(0) < 0) & (causes(1) == 0)) | ((causes(0) == 0) & (causes(1) < 0))){
      // Full follow-up for only one individual
      for (unsigned i=1; i<=2; i++){ // Over individuals
	double lik = 1;
	rowvec likdu = zeros<rowvec>(ncauses);
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  if (causes(i-1) < 0){
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else {
	    double prob = F1(row, j, i, data, sigmaMarg, u);
	    double probdu = dF1du(row, j, i, data, sigmaMarg, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	}
	res += (1/lik)*likdu;
      }
    }
    else {
      // Full follow-up for neither individual
      double lik = 1;
      rowvec likdu = zeros<rowvec>(ncauses);
      // Marginal probabilities
      for (unsigned i=1; i<=2; i++){ // Over individuals
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double prob = F1(row, j, i, data, sigmaMarg, u);
	  rowvec probdu = dF1du(row, j, i, data, sigmaMarg, u);
	  lik -= prob; // Subtracting
	  likdu -= probdu;
	}
      }
      // Bivariate probabilities
      for (unsigned k=1; k<=data.ncauses; k++){ // Over failure causes
	for (unsigned l=1; l<=data.ncauses; l++){
	  irowvec vcauses(2);
	  vcauses(0) = k; vcauses(1) = l;
	  double prob = F2(row, vcauses, data, sigmaJoint, u);
	  rowvec probdu = dF2du(row, vcauses, data, sigmaJoint, u);
	  lik += prob; // Adding
	  likdu += probdu;
	}
      }
      res = (1/lik)*likdu;
    }
  }
  else {
    /* One individual experiences failure the other does not */
    for (unsigned i=1; i<=2; i++){ // Over individuals
      unsigned cause = causes(i-1);
      if (cause > 0){
	// Marginal probability of failure
	res += dlogdF1du(row, cause, i, data, sigmaMarg, u);
      }
      else {
	// Marginal probability of no failure
	unsigned cond_cause;
	if (i==1){
	  cond_cause = causes(1);
	}
	else {
	  cond_cause = causes(0);
	}
	for (unsigned j=1; j<=data.ncauses; j++){ // Over failure causes
	  double lik = 1;
	  rowvec likdu = zeros<rowvec>(ncauses);
	  if (cause < 0){ // Uncondtional
	    double prob = F1(row, j, i, data);
	    rowvec probdu = dF1du(row, j, i, data);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  else { // Conditional
	    double prob = F1(row, j, i, cond_cause, data, sigmaMargCond, u);
	    rowvec probdu = dF1du(row, j, i, cond_cause, data, sigmaMargCond, u);
	    lik -= prob;
	    likdu -= probdu;
	  }
	  res += (1/lik)*likdu;
	}
      }
    }
  }
  /* Contribution from u */
  if (full){

    vmat sig = sigmaU; // Variance-covariance matrix etc. of u

    // Adding to the score
    rowvec res += -u.t()*sig.inv;
  };
  return(res);
}

<|endoftext|>


<commit_before>/**
 * @file options.cc
 * @author Konrad Zemek
 * @copyright (C) 2014 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#include "options.h"

#include "veilConfig.h"
#include "veilErrors.h"
#include "veilException.h"
#include "veilfs.h"

#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/xpressive/xpressive.hpp>
#include <fuse/fuse_lowlevel.h>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <utility>

using namespace boost::program_options;

namespace veil
{
namespace client
{

Options::Options()
    : m_common("Common config file and environment options")
    , m_restricted("Global config file restricted options")
    , m_commandline("General options")
    , m_fuse("FUSE options")
    , m_hidden("Hidden commandline options")
{
    setDescriptions();
}

Options::~Options()
{
}

void Options::setDescriptions()
{
    // Common options found in environment, global and user config files
    add_cluster_hostname(m_common);
    add_cluster_port(m_common);
    add_peer_certificate_file(m_common);
    add_no_check_certificate(m_common);
    add_fuse_group_id(m_common);
    add_enable_attr_cache(m_common);
    add_attr_cache_expiration_time(m_common);
    add_log_dir(m_common);
    add_fuse_id(m_common);
    add_jobscheduler_threads(m_common);
    add_enable_dir_prefetch(m_common);
    add_enable_parallel_getattr(m_common);
    add_enable_location_cache(m_common);

    // Restricted options exclusive to global config file
    m_restricted.add_options()
            ("enable_env_option_override", value<bool>()->default_value(true));
    add_cluster_ping_interval(m_restricted);
    add_alive_meta_connections_count(m_restricted);
    add_alive_data_connections_count(m_restricted);
    add_write_buffer_max_size(m_restricted);
    add_read_buffer_max_size(m_restricted);
    add_write_buffer_max_file_size(m_restricted);
    add_read_buffer_max_file_size(m_restricted);
    add_file_buffer_prefered_block_size(m_restricted);

    // General commandline options
    m_commandline.add_options()
            ("help,h",    "print help")
            ("version,V", "print version")
            ("config",    value<std::string>(), "path to user config file");
    add_switch_debug(m_commandline);
    add_switch_debug_gsi(m_commandline);
    add_switch_no_check_certificate(m_commandline);

    // FUSE-specific commandline options
    m_fuse.add_options()
            (",o", value<std::vector<std::string> >()->value_name("opt,..."), "mount options")
            (",f", "foreground operation")
            (",s", "disable multi-threaded operation");

    // Hidden commandline options (positional)
    m_hidden.add_options()
            ("mountpoint", value<std::string>(), "mount point");
}

void Options::parseConfigs(const int argc, const char * const argv[])
{
    if(argc > 0)
        argv0 = argv[0];

    try
    {
        parseCommandLine(argc, argv);
    }
    catch(boost::program_options::error &e)
    {
        LOG(ERROR) << "Error while parsing command line arguments: " << e.what();
        throw VeilException(VEINVAL, e.what());
    }

    variables_map fileConfigMap;
    try
    {
        parseUserConfig(fileConfigMap);
    }
    catch(boost::program_options::unknown_option &e)
    {
        LOG(ERROR) << "Error while parsing user configuration file: " << e.what();
        if(m_restricted.find_nothrow(e.get_option_name(), false))
            throw VeilException(VEINVAL,
                                "restricted option '" + e.get_option_name() +
                                "' found in user configuration file");

        throw VeilException(VEINVAL, e.what());
    }
    catch(boost::program_options::error &e)
    {
        LOG(ERROR) << "Error while parsing user configuration file: " << e.what();
        throw VeilException(VEINVAL, e.what());
    }

    try
    {
        parseGlobalConfig(fileConfigMap);
    }
    catch(boost::program_options::error &e)
    {
        LOG(ERROR) << "Error while parsing global configuration file: " << e.what();
        throw VeilException(VEINVAL, e.what());
    }

    // If override is allowed then we merge in environment variables first
    if(fileConfigMap.at("enable_env_option_override").as<bool>())
    {
        parseEnv();
        m_vm.insert(fileConfigMap.begin(), fileConfigMap.end());
    }
    else
    {
        m_vm.insert(fileConfigMap.begin(), fileConfigMap.end());
        parseEnv();
    }

    notify(m_vm);
}

/**
 * Parses commandline-options with dashes as commandline_options with
 * underscores.
 * @param str The command line argument to parse.
 * @returns A pair of argument name and argument value parsed from the input
 * string. The argument name has dashes replaced with underscores.
 */
static std::pair<std::string, std::string> cmdParser(const std::string &str)
{
    using namespace boost::xpressive;

    static const sregex rex =
            sregex::compile("\\s*--([\\w\\-]+)(=(\\S+))?\\s*");

    smatch what;
    if(regex_match(str, what, rex))
        return std::make_pair(
            boost::algorithm::replace_all_copy(what[1].str(), "-", "_"),
            what.size() > 2 ? what[3].str() : std::string());

    return std::pair<std::string, std::string>();
}

void Options::parseCommandLine(const int argc, const char * const argv[])
{
    positional_options_description pos;
    pos.add("mountpoint", 1);

    options_description all("Allowed options");
    all.add(m_commandline).add(m_fuse).add(m_hidden);

    store(command_line_parser(argc, argv)
            .options(all).positional(pos).extra_parser(cmdParser).run(), m_vm);

    if(m_vm.count("help"))
    {
        options_description visible("");
        visible.add(m_commandline).add(m_fuse);

        std::cout << "Usage: " << argv[0] << " [options] mountpoint" << std::endl;
        std::cout << visible;
        exit(EXIT_SUCCESS);
    }

    if(m_vm.count("version"))
    {
        std::cout << "VeilFuse version: " << VeilClient_VERSION_MAJOR << "." <<
                     VeilClient_VERSION_MINOR << "." <<
                     VeilClient_VERSION_PATCH << std::endl;
        std::cout << "FUSE library version: " << FUSE_MAJOR_VERSION << "." <<
                     FUSE_MINOR_VERSION << std::endl;
        exit(EXIT_SUCCESS);
    }
}

void Options::parseUserConfig(variables_map &fileConfigMap)
{
    using namespace boost::filesystem;
    if(!m_vm.count("config"))
        return;

    const path userConfigPath = absolute(m_vm.at("config").as<std::string>());
    std::ifstream userConfig(userConfigPath.c_str());

    if(userConfig)
        LOG(INFO) << "Parsing user configuration file " << userConfigPath;
    else
        LOG(WARNING) << "Couldn't open user configuration file " << userConfigPath;

    store(parse_config_file(userConfig, m_common), fileConfigMap);
}

void Options::parseGlobalConfig(variables_map &fileConfigMap)
{
    using namespace boost::filesystem;

    options_description global("Global configuration");
    global.add(m_restricted).add(m_common);

    const path globalConfigPath = path(VeilClient_INSTALL_PATH) /
            VeilClient_CONFIG_DIR / GLOBAL_CONFIG_FILE;
    std::ifstream globalConfig(globalConfigPath.c_str());

    if(globalConfig)
        LOG(INFO) << "Parsing global configuration file " << globalConfigPath;
    else
        LOG(WARNING) << "Couldn't open global configuration file " << globalConfigPath;

    store(parse_config_file(globalConfig, global), fileConfigMap);
}

std::string Options::mapEnvNames(std::string env) const
{
    boost::algorithm::to_lower(env);
    if(m_common.find_nothrow(env, false) && m_vm.count(env) == 0)
    {
        LOG(INFO) << "Using environment configuration variable " << env;
        return env;
    }

    return std::string();
}

void Options::parseEnv()
{
    LOG(INFO) << "Parsing environment variables";
    store(parse_environment(m_common,
                            boost::bind(&Options::mapEnvNames, this, _1)),
          m_vm);
}

struct fuse_args Options::getFuseArgs() const
{
    struct fuse_args args = FUSE_ARGS_INIT(0, 0);

    fuse_opt_add_arg(&args, argv0.c_str());
    fuse_opt_add_arg(&args, "-obig_writes");

    if(m_vm.count("-d")) fuse_opt_add_arg(&args, "-d");
    if(m_vm.count("-f")) fuse_opt_add_arg(&args, "-f");
    if(m_vm.count("-s")) fuse_opt_add_arg(&args, "-s");

    if(m_vm.count("-o"))
    {
        BOOST_FOREACH(const std::string &opt,
                      m_vm.at("-o").as<std::vector<std::string> >())
                fuse_opt_add_arg(&args, ("-o" + opt).c_str());
    }

    if(m_vm.count("mountpoint"))
        fuse_opt_add_arg(&args, m_vm.at("mountpoint").as<std::string>().c_str());

    return args;
}

}
}
<commit_msg>Check for "debug" insted of "-d" when passing parameters to FUSE.<commit_after>/**
 * @file options.cc
 * @author Konrad Zemek
 * @copyright (C) 2014 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#include "options.h"

#include "veilConfig.h"
#include "veilErrors.h"
#include "veilException.h"
#include "veilfs.h"

#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/xpressive/xpressive.hpp>
#include <fuse/fuse_lowlevel.h>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <utility>

using namespace boost::program_options;

namespace veil
{
namespace client
{

Options::Options()
    : m_common("Common config file and environment options")
    , m_restricted("Global config file restricted options")
    , m_commandline("General options")
    , m_fuse("FUSE options")
    , m_hidden("Hidden commandline options")
{
    setDescriptions();
}

Options::~Options()
{
}

void Options::setDescriptions()
{
    // Common options found in environment, global and user config files
    add_cluster_hostname(m_common);
    add_cluster_port(m_common);
    add_peer_certificate_file(m_common);
    add_no_check_certificate(m_common);
    add_fuse_group_id(m_common);
    add_enable_attr_cache(m_common);
    add_attr_cache_expiration_time(m_common);
    add_log_dir(m_common);
    add_fuse_id(m_common);
    add_jobscheduler_threads(m_common);
    add_enable_dir_prefetch(m_common);
    add_enable_parallel_getattr(m_common);
    add_enable_location_cache(m_common);

    // Restricted options exclusive to global config file
    m_restricted.add_options()
            ("enable_env_option_override", value<bool>()->default_value(true));
    add_cluster_ping_interval(m_restricted);
    add_alive_meta_connections_count(m_restricted);
    add_alive_data_connections_count(m_restricted);
    add_write_buffer_max_size(m_restricted);
    add_read_buffer_max_size(m_restricted);
    add_write_buffer_max_file_size(m_restricted);
    add_read_buffer_max_file_size(m_restricted);
    add_file_buffer_prefered_block_size(m_restricted);

    // General commandline options
    m_commandline.add_options()
            ("help,h",    "print help")
            ("version,V", "print version")
            ("config",    value<std::string>(), "path to user config file");
    add_switch_debug(m_commandline);
    add_switch_debug_gsi(m_commandline);
    add_switch_no_check_certificate(m_commandline);

    // FUSE-specific commandline options
    m_fuse.add_options()
            (",o", value<std::vector<std::string> >()->value_name("opt,..."), "mount options")
            (",f", "foreground operation")
            (",s", "disable multi-threaded operation");

    // Hidden commandline options (positional)
    m_hidden.add_options()
            ("mountpoint", value<std::string>(), "mount point");
}

void Options::parseConfigs(const int argc, const char * const argv[])
{
    if(argc > 0)
        argv0 = argv[0];

    try
    {
        parseCommandLine(argc, argv);
    }
    catch(boost::program_options::error &e)
    {
        LOG(ERROR) << "Error while parsing command line arguments: " << e.what();
        throw VeilException(VEINVAL, e.what());
    }

    variables_map fileConfigMap;
    try
    {
        parseUserConfig(fileConfigMap);
    }
    catch(boost::program_options::unknown_option &e)
    {
        LOG(ERROR) << "Error while parsing user configuration file: " << e.what();
        if(m_restricted.find_nothrow(e.get_option_name(), false))
            throw VeilException(VEINVAL,
                                "restricted option '" + e.get_option_name() +
                                "' found in user configuration file");

        throw VeilException(VEINVAL, e.what());
    }
    catch(boost::program_options::error &e)
    {
        LOG(ERROR) << "Error while parsing user configuration file: " << e.what();
        throw VeilException(VEINVAL, e.what());
    }

    try
    {
        parseGlobalConfig(fileConfigMap);
    }
    catch(boost::program_options::error &e)
    {
        LOG(ERROR) << "Error while parsing global configuration file: " << e.what();
        throw VeilException(VEINVAL, e.what());
    }

    // If override is allowed then we merge in environment variables first
    if(fileConfigMap.at("enable_env_option_override").as<bool>())
    {
        parseEnv();
        m_vm.insert(fileConfigMap.begin(), fileConfigMap.end());
    }
    else
    {
        m_vm.insert(fileConfigMap.begin(), fileConfigMap.end());
        parseEnv();
    }

    notify(m_vm);
}

/**
 * Parses commandline-options with dashes as commandline_options with
 * underscores.
 * @param str The command line argument to parse.
 * @returns A pair of argument name and argument value parsed from the input
 * string. The argument name has dashes replaced with underscores.
 */
static std::pair<std::string, std::string> cmdParser(const std::string &str)
{
    using namespace boost::xpressive;

    static const sregex rex =
            sregex::compile("\\s*--([\\w\\-]+)(=(\\S+))?\\s*");

    smatch what;
    if(regex_match(str, what, rex))
        return std::make_pair(
            boost::algorithm::replace_all_copy(what[1].str(), "-", "_"),
            what.size() > 2 ? what[3].str() : std::string());

    return std::pair<std::string, std::string>();
}

void Options::parseCommandLine(const int argc, const char * const argv[])
{
    positional_options_description pos;
    pos.add("mountpoint", 1);

    options_description all("Allowed options");
    all.add(m_commandline).add(m_fuse).add(m_hidden);

    store(command_line_parser(argc, argv)
            .options(all).positional(pos).extra_parser(cmdParser).run(), m_vm);

    if(m_vm.count("help"))
    {
        options_description visible("");
        visible.add(m_commandline).add(m_fuse);

        std::cout << "Usage: " << argv[0] << " [options] mountpoint" << std::endl;
        std::cout << visible;
        exit(EXIT_SUCCESS);
    }

    if(m_vm.count("version"))
    {
        std::cout << "VeilFuse version: " << VeilClient_VERSION_MAJOR << "." <<
                     VeilClient_VERSION_MINOR << "." <<
                     VeilClient_VERSION_PATCH << std::endl;
        std::cout << "FUSE library version: " << FUSE_MAJOR_VERSION << "." <<
                     FUSE_MINOR_VERSION << std::endl;
        exit(EXIT_SUCCESS);
    }
}

void Options::parseUserConfig(variables_map &fileConfigMap)
{
    using namespace boost::filesystem;
    if(!m_vm.count("config"))
        return;

    const path userConfigPath = absolute(m_vm.at("config").as<std::string>());
    std::ifstream userConfig(userConfigPath.c_str());

    if(userConfig)
        LOG(INFO) << "Parsing user configuration file " << userConfigPath;
    else
        LOG(WARNING) << "Couldn't open user configuration file " << userConfigPath;

    store(parse_config_file(userConfig, m_common), fileConfigMap);
}

void Options::parseGlobalConfig(variables_map &fileConfigMap)
{
    using namespace boost::filesystem;

    options_description global("Global configuration");
    global.add(m_restricted).add(m_common);

    const path globalConfigPath = path(VeilClient_INSTALL_PATH) /
            VeilClient_CONFIG_DIR / GLOBAL_CONFIG_FILE;
    std::ifstream globalConfig(globalConfigPath.c_str());

    if(globalConfig)
        LOG(INFO) << "Parsing global configuration file " << globalConfigPath;
    else
        LOG(WARNING) << "Couldn't open global configuration file " << globalConfigPath;

    store(parse_config_file(globalConfig, global), fileConfigMap);
}

std::string Options::mapEnvNames(std::string env) const
{
    boost::algorithm::to_lower(env);
    if(m_common.find_nothrow(env, false) && m_vm.count(env) == 0)
    {
        LOG(INFO) << "Using environment configuration variable " << env;
        return env;
    }

    return std::string();
}

void Options::parseEnv()
{
    LOG(INFO) << "Parsing environment variables";
    store(parse_environment(m_common,
                            boost::bind(&Options::mapEnvNames, this, _1)),
          m_vm);
}

struct fuse_args Options::getFuseArgs() const
{
    struct fuse_args args = FUSE_ARGS_INIT(0, 0);

    fuse_opt_add_arg(&args, argv0.c_str());
    fuse_opt_add_arg(&args, "-obig_writes");

    if(m_vm.count("debug")) fuse_opt_add_arg(&args, "-d");
    if(m_vm.count("-f")) fuse_opt_add_arg(&args, "-f");
    if(m_vm.count("-s")) fuse_opt_add_arg(&args, "-s");

    if(m_vm.count("-o"))
    {
        BOOST_FOREACH(const std::string &opt,
                      m_vm.at("-o").as<std::vector<std::string> >())
                fuse_opt_add_arg(&args, ("-o" + opt).c_str());
    }

    if(m_vm.count("mountpoint"))
        fuse_opt_add_arg(&args, m_vm.at("mountpoint").as<std::string>().c_str());

    return args;
}

}
}
<|endoftext|>


<commit_before>#include "GLFWController.hpp"
#include "ModelView.hpp"
#include "AffinePoint.hpp"
#include "AffineVector.hpp"
#include "ModelViewWithShader.hpp"
#include "Block.hpp"
#include "DependencyContainer.hpp"
#include "otuchaConfig.h"
#include "Matrix3x3.hpp"
#include "TextureAtlas.hpp"
#include "TextureFont.hpp"
#include "vec.hpp"
#include "VertexBuffer.hpp"

#include <memory>
#include <iostream>

using namespace otucha;

void set3DViewingInformation(std::shared_ptr<terasca::ModelView> modelView, double xyz[6])
{
	modelView->setMCRegionOfInterest(xyz);

	rffalcon::AffinePoint eye(1.0, 1.0, 1.0);
	rffalcon::AffinePoint center(0, 0, 0);
	rffalcon::AffineVector up(0, 1, 0);

	modelView->setEyeCenterUp(eye, center, up);

	double zpp = -1.0;
	double zmin = -99.0;
	double zmax = -0.01;

	modelView->setZProjectionPlane(zpp);
	modelView->setEyeCoordinatesZMinZMax(zmin, zmax);
}

typedef struct {
	float x, y, z;
	float s, t;
	float r, g, b, a;
} Vertex;

void addText(std::shared_ptr<rffalcon::VertexBuffer> buffer, std::shared_ptr<rffalcon::TextureFont> font,
	const std::wstring &text, rffalcon::vec2 pen, const rffalcon::vec4 color)
{
	int textLength = text.length();
	for (int index = 0; index < textLength; ++index)
	{
		std::shared_ptr<rffalcon::TextureGlyph> glyph = font->getGlyph(text[index]);
		if (glyph != nullptr)
		{
			auto glyph1 = *glyph;
			float kerning = 0.0f;
			if (index > 0)
			{
				kerning = glyph->getKerning(text[index]);
			}
			pen.x += kerning;
			int x0 = static_cast<int>(pen.x + glyph->offsetX);
			int y0 = static_cast<int>(pen.y + glyph->offsetY);
			int x1 = static_cast<int>(x0 + glyph->width);
			int y1 = static_cast<int>(y0 - glyph->height);
			GLuint i[6] = { 0, 1, 2, 0, 2, 3 };
			std::shared_ptr<std::vector<GLuint>> indices = std::make_shared<std::vector<GLuint>>(i, i+6);
			Vertex v[4] = {
				{ static_cast<float>(x0), static_cast<float>(y0), 0.0f, glyph->s0, glyph->t0, color.r, color.g, color.b, color.a },
				{ static_cast<float>(x0), static_cast<float>(y1), 0.0f, glyph->s0, glyph->t1, color.r, color.g, color.b, color.a },
				{ static_cast<float>(x1), static_cast<float>(y1), 0.0f, glyph->s1, glyph->t1, color.r, color.g, color.b, color.a },
				{ static_cast<float>(x1), static_cast<float>(y0), 0.0f, glyph->s1, glyph->t0, color.r, color.g, color.b, color.a }

			};
			std::shared_ptr<std::vector<void*>> vertices = std::make_shared<std::vector<void*>>();
			vertices->push_back(&v[0]);
			vertices->push_back(&v[1]);
			vertices->push_back(&v[2]);
			vertices->push_back(&v[3]);
			buffer->push(vertices, indices);
			pen.x += glyph->advanceX;
		}
	}
}

std::shared_ptr<rffalcon::VertexBuffer> testText(const std::string &appDir)
{
	std::shared_ptr<rffalcon::TextureAtlas> atlas = std::make_shared<rffalcon::TextureAtlas>(512, 512, 3);
	rffalcon::vec2 pen = { { 5, 5 } };
	rffalcon::vec4 black = { { 0, 0, 0, 1 } };
	std::shared_ptr<rffalcon::TextureFont> font = std::make_shared<rffalcon::TextureFont>(atlas, 32.0f, appDir + "DejaVuSansMono.ttf");
	pen.x = 5;
	std::wstring text = L"#WORKSINMAIN";
	font->loadGlyphs(text);
	std::shared_ptr<rffalcon::VertexBuffer> buffer = std::make_shared<rffalcon::VertexBuffer>("vertex:3f,texCoord:2f,color:4f");
	addText(buffer, font, text, pen, black);

	glBindTexture(GL_TEXTURE_2D, atlas->getGLTextureId());
	return buffer;
}

int main(int argc, char* argv[])
{
	// these two lines included for Emscripten which is excluding the constructors otherwise :(
	rffalcon::Matrix4x4 matrix;
	rffalcon::Matrix3x3 matrix2;

	fprintf(stdout, "%s Version %d.%d\n", argv[0], otucha_VERSION_MAJOR, otucha_VERSION_MINOR);
	terasca::GLFWController c("otucha", terasca::Controller::DEPTH);
	c.reportVersions(std::cout);
	std::string appPath(argv[0]);
	DependencyContainer::getSingleton()->setAppDir(appPath);
	std::string appDir = DependencyContainer::getSingleton()->getAppDir();
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	double xyz[6];

	// Block model
	std::shared_ptr<terasca::ModelView> blockModelView = std::make_shared<terasca::ModelViewWithShader>(appDir + "simple.vsh", appDir + "simple.fsh");
	std::shared_ptr<rffalcon::ModelBase> blockModel = std::make_shared<rffalcon::Block>(-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f);
	blockModelView->addModel(blockModel);
	blockModelView->getMCBoundingBox(xyz);
	set3DViewingInformation(blockModelView, xyz);

	// Text model
	std::shared_ptr<rffalcon::VertexBuffer> textModel = testText(appDir);
	std::shared_ptr<terasca::ModelView> textModelView = std::make_shared<terasca::ModelViewWithShader>(appDir + "v3f-t2f-c4f.vsh", appDir + "v3f-t2f-c4f.fsh");
	textModelView->addModel(textModel);
	textModelView->setProjectionType(ORTHOGRAPHIC);
	textModelView->getMCBoundingBox(xyz);
	set3DViewingInformation(textModelView, xyz);

	// add models to view, order matters
	c.addModelView(textModelView);
	c.addModelView(blockModelView);

	// test console code to be removed later
	DependencyContainer::getSingleton()->getConsole()->registerCommand(L"test", [](warbler::t_consoleArgs_ptr args) {
		std::cout << "Console online" << std::endl;
	}, std::make_shared<warbler::t_consoleArgTypes>());
	DependencyContainer::getSingleton()->getConsole()->executeCommand(L"test");
	// end test console code

	c.run();

	return 0;
}

<commit_msg>struct Vertex<commit_after>#include "GLFWController.hpp"
#include "ModelView.hpp"
#include "AffinePoint.hpp"
#include "AffineVector.hpp"
#include "ModelViewWithShader.hpp"
#include "Block.hpp"
#include "DependencyContainer.hpp"
#include "otuchaConfig.h"
#include "Matrix3x3.hpp"
#include "TextureAtlas.hpp"
#include "TextureFont.hpp"
#include "vec.hpp"
#include "VertexBuffer.hpp"

#include <memory>
#include <iostream>

using namespace otucha;

void set3DViewingInformation(std::shared_ptr<terasca::ModelView> modelView, double xyz[6])
{
	modelView->setMCRegionOfInterest(xyz);

	rffalcon::AffinePoint eye(1.0, 1.0, 1.0);
	rffalcon::AffinePoint center(0, 0, 0);
	rffalcon::AffineVector up(0, 1, 0);

	modelView->setEyeCenterUp(eye, center, up);

	double zpp = -1.0;
	double zmin = -99.0;
	double zmax = -0.01;

	modelView->setZProjectionPlane(zpp);
	modelView->setEyeCoordinatesZMinZMax(zmin, zmax);
}

struct Vertex {
	float x, y, z;
	float s, t;
	float r, g, b, a;
};

void addText(std::shared_ptr<rffalcon::VertexBuffer> buffer, std::shared_ptr<rffalcon::TextureFont> font,
	const std::wstring &text, rffalcon::vec2 pen, const rffalcon::vec4 color)
{
	int textLength = text.length();
	for (int index = 0; index < textLength; ++index)
	{
		std::shared_ptr<rffalcon::TextureGlyph> glyph = font->getGlyph(text[index]);
		if (glyph != nullptr)
		{
			auto glyph1 = *glyph;
			float kerning = 0.0f;
			if (index > 0)
			{
				kerning = glyph->getKerning(text[index]);
			}
			pen.x += kerning;
			int x0 = static_cast<int>(pen.x + glyph->offsetX);
			int y0 = static_cast<int>(pen.y + glyph->offsetY);
			int x1 = static_cast<int>(x0 + glyph->width);
			int y1 = static_cast<int>(y0 - glyph->height);
			GLuint i[6] = { 0, 1, 2, 0, 2, 3 };
			std::shared_ptr<std::vector<GLuint>> indices = std::make_shared<std::vector<GLuint>>(i, i+6);
			Vertex v[4] = {
				{ static_cast<float>(x0), static_cast<float>(y0), 0.0f, glyph->s0, glyph->t0, color.r, color.g, color.b, color.a },
				{ static_cast<float>(x0), static_cast<float>(y1), 0.0f, glyph->s0, glyph->t1, color.r, color.g, color.b, color.a },
				{ static_cast<float>(x1), static_cast<float>(y1), 0.0f, glyph->s1, glyph->t1, color.r, color.g, color.b, color.a },
				{ static_cast<float>(x1), static_cast<float>(y0), 0.0f, glyph->s1, glyph->t0, color.r, color.g, color.b, color.a }

			};
			std::shared_ptr<std::vector<void*>> vertices = std::make_shared<std::vector<void*>>();
			vertices->push_back(&v[0]);
			vertices->push_back(&v[1]);
			vertices->push_back(&v[2]);
			vertices->push_back(&v[3]);
			buffer->push(vertices, indices);
			pen.x += glyph->advanceX;
		}
	}
}

std::shared_ptr<rffalcon::VertexBuffer> testText(const std::string &appDir)
{
	std::shared_ptr<rffalcon::TextureAtlas> atlas = std::make_shared<rffalcon::TextureAtlas>(512, 512, 3);
	rffalcon::vec2 pen = { { 5, 5 } };
	rffalcon::vec4 black = { { 0, 0, 0, 1 } };
	std::shared_ptr<rffalcon::TextureFont> font = std::make_shared<rffalcon::TextureFont>(atlas, 32.0f, appDir + "DejaVuSansMono.ttf");
	pen.x = 5;
	std::wstring text = L"#WORKSINMAIN";
	font->loadGlyphs(text);
	std::shared_ptr<rffalcon::VertexBuffer> buffer = std::make_shared<rffalcon::VertexBuffer>("vertex:3f,texCoord:2f,color:4f");
	addText(buffer, font, text, pen, black);

	glBindTexture(GL_TEXTURE_2D, atlas->getGLTextureId());
	return buffer;
}

int main(int argc, char* argv[])
{
	// these two lines included for Emscripten which is excluding the constructors otherwise :(
	rffalcon::Matrix4x4 matrix;
	rffalcon::Matrix3x3 matrix2;

	fprintf(stdout, "%s Version %d.%d\n", argv[0], otucha_VERSION_MAJOR, otucha_VERSION_MINOR);
	terasca::GLFWController c("otucha", terasca::Controller::DEPTH);
	c.reportVersions(std::cout);
	std::string appPath(argv[0]);
	DependencyContainer::getSingleton()->setAppDir(appPath);
	std::string appDir = DependencyContainer::getSingleton()->getAppDir();
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	double xyz[6];

	// Block model
	std::shared_ptr<terasca::ModelView> blockModelView = std::make_shared<terasca::ModelViewWithShader>(appDir + "simple.vsh", appDir + "simple.fsh");
	std::shared_ptr<rffalcon::ModelBase> blockModel = std::make_shared<rffalcon::Block>(-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f);
	blockModelView->addModel(blockModel);
	blockModelView->getMCBoundingBox(xyz);
	set3DViewingInformation(blockModelView, xyz);

	// Text model
	std::shared_ptr<rffalcon::VertexBuffer> textModel = testText(appDir);
	std::shared_ptr<terasca::ModelView> textModelView = std::make_shared<terasca::ModelViewWithShader>(appDir + "v3f-t2f-c4f.vsh", appDir + "v3f-t2f-c4f.fsh");
	textModelView->addModel(textModel);
	textModelView->setProjectionType(ORTHOGRAPHIC);
	textModelView->getMCBoundingBox(xyz);
	set3DViewingInformation(textModelView, xyz);

	// add models to view, order matters
	c.addModelView(textModelView);
	c.addModelView(blockModelView);

	// test console code to be removed later
	DependencyContainer::getSingleton()->getConsole()->registerCommand(L"test", [](warbler::t_consoleArgs_ptr args) {
		std::cout << "Console online" << std::endl;
	}, std::make_shared<warbler::t_consoleArgTypes>());
	DependencyContainer::getSingleton()->getConsole()->executeCommand(L"test");
	// end test console code

	c.run();

	return 0;
}

<|endoftext|>


<commit_before>#include "output.h"
#include "buffer_pool.h"
#include "compress.h"
#include "cso.h"

namespace maxcso {

// TODO: Tune, less may be better.
static const size_t QUEUE_SIZE = 128;

Output::Output(uv_loop_t *loop, const Task &task)
	: loop_(loop), flags_(task.flags), state_(STATE_INIT), srcSize_(-1), index_(nullptr) {
	for (size_t i = 0; i < QUEUE_SIZE; ++i) {
		freeSectors_.push_back(new Sector(task.flags));
	}
}

Output::~Output() {
	for (Sector *sector : freeSectors_) {
		delete sector;
	}
	for (auto pair : pendingSectors_) {
		delete pair.second;
	}
	freeSectors_.clear();
	pendingSectors_.clear();

	delete [] index_;
	index_ = nullptr;
}

void Output::SetFile(uv_file file, int64_t srcSize) {
	file_ = file;
	srcSize_ = srcSize;
	srcPos_ = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize >> SECTOR_SHIFT);
	// Start after the header and index, which we'll fill in later.
	index_ = new uint32_t[sectors + 1];
	// Start after the end of the index data and header.
	dstPos_ = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);

	// TODO: We might be able to optimize shift better by running through the data.
	// That would require either a second pass or keeping the entire result in RAM.
	// For now, just take worst case (all blocks stored uncompressed.)
	int64_t worstSize = dstPos_ + srcSize;
	shift_ = 0;
	for (int i = 62; i >= 31; --i) {
		int64_t max = 1LL << i;
		if (worstSize >= max) {
			// This means we need i + 1 bits to store the position.
			// We have to shift enough off to fit into 31.
			shift_ = i + 1 - 31;
			break;
		}
	}

	// If the shift is above 11, the padding could make it need more space.
	// But that would be > 4 TB anyway, so let's not worry about it.
	align_ = 1 << shift_;
	Align(dstPos_);

	state_ |= STATE_HAS_FILE;
}

int32_t Output::Align(int64_t &pos) {
	uint32_t off = static_cast<uint32_t>(pos % align_);
	if (off != 0) {
		pos += align_ - off;
		return align_ - off;
	}
	return 0;
}

void Output::Enqueue(int64_t pos, uint8_t *buffer) {
	Sector *sector = freeSectors_.back();
	freeSectors_.pop_back();

	// We might not compress all blocks.
	const bool tryCompress = ShouldCompress(pos);

	// Sector takes ownership of buffer either way.
	if (tryCompress) {
		sector->Process(loop_, pos, buffer, [this, sector](bool status, const char *reason) {
			HandleReadySector(sector);
		});
	} else {
		sector->Reserve(pos, buffer);
		HandleReadySector(sector);
	}
}

void Output::HandleReadySector(Sector *sector) {
	if (sector != nullptr) {
		if (srcPos_ != sector->Pos()) {
			// We're not there yet in the file stream.  Queue this, get to it later.
			pendingSectors_[sector->Pos()] = sector;
			return;
		}
	} else {
		// If no sector was provided, we're looking at the first in the queue.
		if (pendingSectors_.empty()) {
			return;
		}
		sector = pendingSectors_.begin()->second;
		if (srcPos_ != sector->Pos()) {
			return;
		}

		// Remove it from the queue, and then run with it.
		pendingSectors_.erase(pendingSectors_.begin());
	}

	// Check for any sectors that immediately follow the one we're writing.
	// We'll just write them all together.
	std::vector<Sector *> sectors;
	sectors.push_back(sector);
	// TODO: Try other numbers.
	static const size_t MAX_BUFS = 4;
	int64_t nextPos = srcPos_ + SECTOR_SIZE;
	auto it = pendingSectors_.find(nextPos);
	while (it != pendingSectors_.end()) {
		sectors.push_back(it->second);
		pendingSectors_.erase(it);
		nextPos += SECTOR_SIZE;
		it = pendingSectors_.find(nextPos);

		// Don't do more than 4 at a time.
		if (sectors.size() >= MAX_BUFS) {
			break;
		}
	}

	int64_t dstPos = dstPos_;
	uv_buf_t bufs[MAX_BUFS * 2];
	unsigned int nbufs = 0;
	static char padding[2048] = {0};
	for (size_t i = 0; i < sectors.size(); ++i) {
		bufs[nbufs++] = uv_buf_init(reinterpret_cast<char *>(sectors[i]->BestBuffer()), sectors[i]->BestSize());

		// Update the index.
		const int32_t s = static_cast<int32_t>(sectors[i]->Pos() >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);
		if (!sectors[i]->Compressed()) {
			index_[s] |= CSO_INDEX_UNCOMPRESSED;
		}

		dstPos += sectors[i]->BestSize();
		int32_t padSize = Align(dstPos);
		if (padSize != 0) {
			// We need uv to write the padding out as well.
			bufs[nbufs++] = uv_buf_init(padding, padSize);
		}
	}

	// If we're working on the last sectors, then the index is ready to write.
	if (nextPos == srcSize_) {
		state_ |= STATE_INDEX_READY;
		Flush();
	}

	const int64_t totalWrite = dstPos - dstPos_;
	uv_.fs_write(loop_, sector->WriteReq(), file_, bufs, nbufs, dstPos_, [this, sectors, nextPos, totalWrite](uv_fs_t *req) {
		for (Sector *sector : sectors) {
			sector->Release();
			freeSectors_.push_back(sector);
		}

		if (req->result != totalWrite) {
			finish_(false, "Data could not be written to output file");
			uv_fs_req_cleanup(req);
			return;
		}
		uv_fs_req_cleanup(req);

		srcPos_ = nextPos;
		dstPos_ += totalWrite;

		// TODO: Better (including index?)
		float prog = static_cast<float>(srcPos_) / static_cast<float>(srcSize_);
		progress_(prog);

		if (nextPos == srcSize_) {
			state_ |= STATE_DATA_WRITTEN;
			CheckFinish();
		} else {
			// Check if there's more data to write out.
			HandleReadySector(nullptr);
		}
	});
}

bool Output::ShouldCompress(int64_t pos) {
	if (flags_ & TASKFLAG_FORCE_ALL) {
		return true;
	}

	// TODO
	return true;
}

bool Output::QueueFull() {
	return freeSectors_.empty();
}

void Output::OnProgress(OutputCallback callback) {
	progress_ = callback;
}

void Output::OnFinish(OutputFinishCallback callback) {
	finish_ = callback;
}

void Output::Flush() {
	if (!(state_ & STATE_INDEX_READY)) {
		finish_(false, "Flush called before index finalized");
		return;
	}

	CSOHeader *header = new CSOHeader;
	memcpy(header->magic, CSO_MAGIC, sizeof(header->magic));
	header->header_size = sizeof(CSOHeader);
	header->uncompressed_size = srcSize_;
	header->sector_size = SECTOR_SIZE;
	header->version = 1;
	header->index_shift = shift_;
	header->unused[0] = 0;
	header->unused[1] = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize_ >> SECTOR_SHIFT);

	uv_buf_t bufs[2];
	bufs[0] = uv_buf_init(reinterpret_cast<char *>(header), sizeof(CSOHeader));
	bufs[1] = uv_buf_init(reinterpret_cast<char *>(index_), (sectors + 1) * sizeof(uint32_t));
	const size_t totalBytes = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);
	uv_.fs_write(loop_, &flush_, file_, bufs, 2, 0, [this, header, totalBytes](uv_fs_t *req) {
		if (req->result != totalBytes) {
			finish_(false, "Unable to write header data");
		} else {
			state_ |= STATE_INDEX_WRITTEN;
			CheckFinish();
		}
		uv_fs_req_cleanup(req);
		delete header;
	});
}

void Output::CheckFinish() {
	if ((state_ & STATE_INDEX_WRITTEN) && (state_ & STATE_DATA_WRITTEN)) {
		finish_(true, nullptr);
	}
}

};
<commit_msg>Write the correct final index entry.<commit_after>#include "output.h"
#include "buffer_pool.h"
#include "compress.h"
#include "cso.h"

namespace maxcso {

// TODO: Tune, less may be better.
static const size_t QUEUE_SIZE = 128;

Output::Output(uv_loop_t *loop, const Task &task)
	: loop_(loop), flags_(task.flags), state_(STATE_INIT), srcSize_(-1), index_(nullptr) {
	for (size_t i = 0; i < QUEUE_SIZE; ++i) {
		freeSectors_.push_back(new Sector(task.flags));
	}
}

Output::~Output() {
	for (Sector *sector : freeSectors_) {
		delete sector;
	}
	for (auto pair : pendingSectors_) {
		delete pair.second;
	}
	freeSectors_.clear();
	pendingSectors_.clear();

	delete [] index_;
	index_ = nullptr;
}

void Output::SetFile(uv_file file, int64_t srcSize) {
	file_ = file;
	srcSize_ = srcSize;
	srcPos_ = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize >> SECTOR_SHIFT);
	// Start after the header and index, which we'll fill in later.
	index_ = new uint32_t[sectors + 1];
	// Start after the end of the index data and header.
	dstPos_ = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);

	// TODO: We might be able to optimize shift better by running through the data.
	// That would require either a second pass or keeping the entire result in RAM.
	// For now, just take worst case (all blocks stored uncompressed.)
	int64_t worstSize = dstPos_ + srcSize;
	shift_ = 0;
	for (int i = 62; i >= 31; --i) {
		int64_t max = 1LL << i;
		if (worstSize >= max) {
			// This means we need i + 1 bits to store the position.
			// We have to shift enough off to fit into 31.
			shift_ = i + 1 - 31;
			break;
		}
	}

	// If the shift is above 11, the padding could make it need more space.
	// But that would be > 4 TB anyway, so let's not worry about it.
	align_ = 1 << shift_;
	Align(dstPos_);

	state_ |= STATE_HAS_FILE;
}

int32_t Output::Align(int64_t &pos) {
	uint32_t off = static_cast<uint32_t>(pos % align_);
	if (off != 0) {
		pos += align_ - off;
		return align_ - off;
	}
	return 0;
}

void Output::Enqueue(int64_t pos, uint8_t *buffer) {
	Sector *sector = freeSectors_.back();
	freeSectors_.pop_back();

	// We might not compress all blocks.
	const bool tryCompress = ShouldCompress(pos);

	// Sector takes ownership of buffer either way.
	if (tryCompress) {
		sector->Process(loop_, pos, buffer, [this, sector](bool status, const char *reason) {
			HandleReadySector(sector);
		});
	} else {
		sector->Reserve(pos, buffer);
		HandleReadySector(sector);
	}
}

void Output::HandleReadySector(Sector *sector) {
	if (sector != nullptr) {
		if (srcPos_ != sector->Pos()) {
			// We're not there yet in the file stream.  Queue this, get to it later.
			pendingSectors_[sector->Pos()] = sector;
			return;
		}
	} else {
		// If no sector was provided, we're looking at the first in the queue.
		if (pendingSectors_.empty()) {
			return;
		}
		sector = pendingSectors_.begin()->second;
		if (srcPos_ != sector->Pos()) {
			return;
		}

		// Remove it from the queue, and then run with it.
		pendingSectors_.erase(pendingSectors_.begin());
	}

	// Check for any sectors that immediately follow the one we're writing.
	// We'll just write them all together.
	std::vector<Sector *> sectors;
	sectors.push_back(sector);
	// TODO: Try other numbers.
	static const size_t MAX_BUFS = 4;
	int64_t nextPos = srcPos_ + SECTOR_SIZE;
	auto it = pendingSectors_.find(nextPos);
	while (it != pendingSectors_.end()) {
		sectors.push_back(it->second);
		pendingSectors_.erase(it);
		nextPos += SECTOR_SIZE;
		it = pendingSectors_.find(nextPos);

		// Don't do more than 4 at a time.
		if (sectors.size() >= MAX_BUFS) {
			break;
		}
	}

	int64_t dstPos = dstPos_;
	uv_buf_t bufs[MAX_BUFS * 2];
	unsigned int nbufs = 0;
	static char padding[2048] = {0};
	for (size_t i = 0; i < sectors.size(); ++i) {
		bufs[nbufs++] = uv_buf_init(reinterpret_cast<char *>(sectors[i]->BestBuffer()), sectors[i]->BestSize());

		// Update the index.
		const int32_t s = static_cast<int32_t>(sectors[i]->Pos() >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);
		if (!sectors[i]->Compressed()) {
			index_[s] |= CSO_INDEX_UNCOMPRESSED;
		}

		dstPos += sectors[i]->BestSize();
		int32_t padSize = Align(dstPos);
		if (padSize != 0) {
			// We need uv to write the padding out as well.
			bufs[nbufs++] = uv_buf_init(padding, padSize);
		}
	}

	// If we're working on the last sectors, then the index is ready to write.
	if (nextPos == srcSize_) {
		// Update the final index entry.
		const int32_t s = static_cast<int32_t>(srcSize_ >> SECTOR_SHIFT);
		index_[s] = static_cast<int32_t>(dstPos >> shift_);

		state_ |= STATE_INDEX_READY;
		Flush();
	}

	const int64_t totalWrite = dstPos - dstPos_;
	uv_.fs_write(loop_, sector->WriteReq(), file_, bufs, nbufs, dstPos_, [this, sectors, nextPos, totalWrite](uv_fs_t *req) {
		for (Sector *sector : sectors) {
			sector->Release();
			freeSectors_.push_back(sector);
		}

		if (req->result != totalWrite) {
			finish_(false, "Data could not be written to output file");
			uv_fs_req_cleanup(req);
			return;
		}
		uv_fs_req_cleanup(req);

		srcPos_ = nextPos;
		dstPos_ += totalWrite;

		// TODO: Better (including index?)
		float prog = static_cast<float>(srcPos_) / static_cast<float>(srcSize_);
		progress_(prog);

		if (nextPos == srcSize_) {
			state_ |= STATE_DATA_WRITTEN;
			CheckFinish();
		} else {
			// Check if there's more data to write out.
			HandleReadySector(nullptr);
		}
	});
}

bool Output::ShouldCompress(int64_t pos) {
	if (flags_ & TASKFLAG_FORCE_ALL) {
		return true;
	}

	// TODO
	return true;
}

bool Output::QueueFull() {
	return freeSectors_.empty();
}

void Output::OnProgress(OutputCallback callback) {
	progress_ = callback;
}

void Output::OnFinish(OutputFinishCallback callback) {
	finish_ = callback;
}

void Output::Flush() {
	if (!(state_ & STATE_INDEX_READY)) {
		finish_(false, "Flush called before index finalized");
		return;
	}

	CSOHeader *header = new CSOHeader;
	memcpy(header->magic, CSO_MAGIC, sizeof(header->magic));
	header->header_size = sizeof(CSOHeader);
	header->uncompressed_size = srcSize_;
	header->sector_size = SECTOR_SIZE;
	header->version = 1;
	header->index_shift = shift_;
	header->unused[0] = 0;
	header->unused[1] = 0;

	const uint32_t sectors = static_cast<uint32_t>(srcSize_ >> SECTOR_SHIFT);

	uv_buf_t bufs[2];
	bufs[0] = uv_buf_init(reinterpret_cast<char *>(header), sizeof(CSOHeader));
	bufs[1] = uv_buf_init(reinterpret_cast<char *>(index_), (sectors + 1) * sizeof(uint32_t));
	const size_t totalBytes = sizeof(CSOHeader) + (sectors + 1) * sizeof(uint32_t);
	uv_.fs_write(loop_, &flush_, file_, bufs, 2, 0, [this, header, totalBytes](uv_fs_t *req) {
		if (req->result != totalBytes) {
			finish_(false, "Unable to write header data");
		} else {
			state_ |= STATE_INDEX_WRITTEN;
			CheckFinish();
		}
		uv_fs_req_cleanup(req);
		delete header;
	});
}

void Output::CheckFinish() {
	if ((state_ & STATE_INDEX_WRITTEN) && (state_ & STATE_DATA_WRITTEN)) {
		finish_(true, nullptr);
	}
}

};
<|endoftext|>


<commit_before>/* Copyright (c) 2009, Sebastien Mirolo
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of fortylines nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY Sebastien Mirolo ''AS IS'' AND ANY
   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL Sebastien Mirolo BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

#include "payment.hh"
#include "todo.hh"
#include "aws.hh"

void awsPayment::fetch( session& s, const boost::filesystem::path& pathname ) {
    awsStandardButton button(s.valueOf("awsAccessKey"),
			     s.valueOf("awsSecretKey"),
			     s.valueOf("awsCertificate"));
    button.description = "Vote for a todo item with your dollars";
    button.returnUrl = url(s.valueOf("domainName") + "/todoVoteSuccess");

    button.build(todouuid(pathname),1);
    button.writehtml(std::cout);
}
<commit_msg>prefix domainName with http protocol<commit_after>/* Copyright (c) 2009, Sebastien Mirolo
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of fortylines nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY Sebastien Mirolo ''AS IS'' AND ANY
   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL Sebastien Mirolo BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

#include "payment.hh"
#include "todo.hh"
#include "aws.hh"

void awsPayment::fetch( session& s, const boost::filesystem::path& pathname ) {
    awsStandardButton button(s.valueOf("awsAccessKey"),
			     s.valueOf("awsSecretKey"),
			     s.valueOf("awsCertificate"));
    button.description = "Vote for a todo item with your dollars";
    button.returnUrl = url(std::string("http://") + s.valueOf("domainName") + "/todoVoteSuccess");

    button.build(todouuid(pathname),1);
    button.writehtml(std::cout);
}
<|endoftext|>