text: //
  //  CRF++ -- Yet Another CRF toolkit
  //
  //  $Id: node.h 1595 2007-02-24 10:18:32Z taku $;
  //
  //  Copyright(C) 2005-2007 Taku Kudo <taku@chasen.org>
  //
  #ifndef CRFPP_NODE_H_
  #define CRFPP_NODE_H_
  
  #include <vector>
  #include <cmath>
  #include "path.h"
  #include "common.h"
  
  #define LOG2               0.69314718055
  #define MINUS_LOG_EPSILON  50
  
  namespace CRFPP {
  // log(exp(x) + exp(y));
  //    this can be used recursivly
  // e.g., log(exp(log(exp(x) + exp(y))) + exp(z)) =
  // log(exp (x) + exp(y) + exp(z))
  inline double logsumexp(double x, double y, bool flg) {
    if (flg) return y;  // init mode
    const double vmin = std::min(x, y);
    const double vmax = std::max(x, y);
    if (vmax > vmin + MINUS_LOG_EPSILON) {
      return vmax;
    } else {
      return vmax + std::log(std::exp(vmin - vmax) + 1.0);
    }
  }
  
  struct Path;
  
  struct Node {
    unsigned int         x;
    unsigned short int   y;
    double               alpha;
    double               beta;
    double               cost;
    double               bestCost;
    Node                *prev;
    const int           *fvector;
    std::vector<Path *>  lpath;
    std::vector<Path *>  rpath;
  
    void calcAlpha();
    void calcBeta();
    void calcExpectation(double *expected, double, size_t) const;
  
    void clear() {
      x = y = 0;
      alpha = beta = cost = 0.0;
      prev = 0;
      fvector = 0;
      lpath.clear();
      rpath.clear();
    }
  
    void shrink() {
      std::vector<Path *>(lpath).swap(lpath);
      std::vector<Path *>(rpath).swap(rpath);
    }
  
    Node() : x(0), y(0), alpha(0.0), beta(0.0),
             cost(0.0), bestCost(0.0), prev(0), fvector(0) {}
  };
  }
  #endif
  