<commit_before>#ifndef PICOLIB_STREAM_H_
#define PICOLIB_STREAM_H_

namespace Pico {

    class IO
    {
        public:
            VIRTUAL_METHOD IO& in(void *, size_t) = 0;
            VIRTUAL_METHOD IO& out(const void *, size_t) = 0;

            METHOD IO& read(void *ptr, size_t count) {
                return in(ptr, count);
            }

            METHOD IO& write(const void *ptr, size_t count) {
                return out(ptr, count);
            }

            METHOD IO& read(Memory::Buffer const& buffer) {
                return read(buffer.pointer(), buffer.size());
            }

            METHOD IO& write(Memory::Buffer const& buffer) {
                return write(buffer.pointer(), buffer.size());
            }

            METHOD friend IO& operator <<(IO &io, Memory::Buffer const& buffer)
            {
                return io.write(buffer);
            }

            METHOD friend IO& operator >>(IO &io, Memory::Buffer const& buffer)
            {
                return io.read(buffer);
            }

            METHOD friend IO& operator <<(Memory::Buffer const& buffer, IO &io)
            {
                return io >> buffer;
            }

            METHOD friend IO& operator >>(Memory::Buffer const& buffer, IO &io)
            {
                return io << buffer;
            }
    };

    class Stream : public IO
    {
        public:
            FUNCTION Stream standard_input();
            FUNCTION Stream standard_output();
            FUNCTION Stream standard_error();

            CONSTRUCTOR Stream() = default;
            CONSTRUCTOR Stream(int fd) : fd(fd) {}

            METHOD Stream& in(void *ptr, size_t count);
            METHOD Stream& out(const void *ptr, size_t count);

            METHOD Stream duplicate();
            METHOD void replace(Stream const&);
            METHOD int file_desc() const { return fd; }
            METHOD int close();

        protected:
            int fd = -1;
    };

    template <class Rx, class Tx = Rx>
    class BiStream : public IO
    {
        public:
            CONSTRUCTOR BiStream() = default;
            CONSTRUCTOR BiStream(Rx rx, Tx tx) : rx(rx), tx(tx) {}
            CONSTRUCTOR BiStream(int rfd, int wfd) : rx(Stream(rfd)), tx(Stream(wfd)) {}

            METHOD BiStream& in(void *ptr, size_t count) {
                rx.read(ptr, count);
                return *this;
            }

            METHOD BiStream& out(const void *ptr, size_t count) {
                tx.write(ptr, count);
                return *this;
            }

        protected:
            Rx rx;
            Tx tx;
    };
}

#endif
<commit_msg>pico/stream: close method<commit_after>#ifndef PICOLIB_STREAM_H_
#define PICOLIB_STREAM_H_

namespace Pico {

    class IO
    {
        public:
            VIRTUAL_METHOD IO& in(void *, size_t) = 0;
            VIRTUAL_METHOD IO& out(const void *, size_t) = 0;
            VIRTUAL_METHOD int close() = 0;

            METHOD IO& read(void *ptr, size_t count) {
                return in(ptr, count);
            }

            METHOD IO& write(const void *ptr, size_t count) {
                return out(ptr, count);
            }

            METHOD IO& read(Memory::Buffer const& buffer) {
                return read(buffer.pointer(), buffer.size());
            }

            METHOD IO& write(Memory::Buffer const& buffer) {
                return write(buffer.pointer(), buffer.size());
            }

            METHOD friend IO& operator <<(IO &io, Memory::Buffer const& buffer)
            {
                return io.write(buffer);
            }

            METHOD friend IO& operator >>(IO &io, Memory::Buffer const& buffer)
            {
                return io.read(buffer);
            }

            METHOD friend IO& operator <<(Memory::Buffer const& buffer, IO &io)
            {
                return io >> buffer;
            }

            METHOD friend IO& operator >>(Memory::Buffer const& buffer, IO &io)
            {
                return io << buffer;
            }
    };

    class Stream : public IO
    {
        public:
            FUNCTION Stream standard_input();
            FUNCTION Stream standard_output();
            FUNCTION Stream standard_error();

            CONSTRUCTOR Stream() = default;
            CONSTRUCTOR Stream(int fd) : fd(fd) {}

            METHOD Stream& in(void *ptr, size_t count);
            METHOD Stream& out(const void *ptr, size_t count);

            METHOD Stream duplicate();
            METHOD void replace(Stream const&);
            METHOD int file_desc() const { return fd; }
            METHOD int close();

        protected:
            int fd = -1;
    };

    template <class Rx, class Tx = Rx>
    class BiStream : public IO
    {
        public:
            CONSTRUCTOR BiStream() = default;
            CONSTRUCTOR BiStream(Rx rx, Tx tx) : rx(rx), tx(tx) {}
            CONSTRUCTOR BiStream(int rfd, int wfd) : rx(Stream(rfd)), tx(Stream(wfd)) {}

            METHOD BiStream& in(void *ptr, size_t count) {
                rx.read(ptr, count);
                return *this;
            }

            METHOD BiStream& out(const void *ptr, size_t count) {
                tx.write(ptr, count);
                return *this;
            }

            METHOD int close() {
                return rx.close() | tx.close();
            }

        protected:
            Rx rx;
            Tx tx;
    };
}

#endif
<|endoftext|>


<commit_before>// festus/algebraic-path-test.cc
//
// 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.
//
// Copyright 2016 Google, Inc.
// Author: mjansche@google.com (Martin Jansche)
//
// \file
// Unit test for algebraic path computation.

#include "festus/algebraic-path.h"

#include <cmath>

#include <fst/compat.h>
#include <fst/fstlib.h>
#include <gtest/gtest.h>

#include "festus/arc.h"
#include "festus/float-weight-star.h"
#include "festus/max-times-semiring.h"
#include "festus/modular-int-semiring.h"
#include "festus/quaternion-semiring.h"
#include "festus/real-weight.h"
#include "festus/value-weight-static.h"

DEFINE_double(delta, fst::kDelta,
              "Convergence threshold for ShortestDistance");
DEFINE_bool(modular_int, false,
            "Try to compute ShortestDistance in modular int semiring");
DEFINE_bool(quaternion, false,
            "Try to compute ShortestDistance in quaternion semiring");

namespace {

template <class Arc>
void TestOneStateLoop(
    typename Arc::Weight loop_weight,
    typename Arc::Weight final_weight,
    typename Arc::Weight expected_sum_total,
    float comparison_delta,
    int power_series_terms,
    bool use_shortest_distance,
    const char *msg) {
  typedef typename Arc::Weight Weight;

  // One-state FST with a loop at its only (initial and final) state.
  fst::VectorFst<Arc> fst;
  const auto state = fst.AddState();
  fst.SetStart(state);
  fst.AddArc(state, Arc(0, 0, loop_weight, state));
  fst.SetFinal(state, final_weight);

  const Weight sum_total = festus::SumTotalWeight(fst);
  EXPECT_TRUE(ApproxEqual(sum_total, expected_sum_total, comparison_delta));

  VLOG(0) << "sum total = " << sum_total << " ~= " << expected_sum_total;

  if (power_series_terms) {
    Weight power = Weight::One();
    Weight series = Weight::One();
    VLOG(0) << "\\sum_{n=0}^0 loop_weight^n = " << series;
    VLOG(0) << "  sum x final = " << Times(series, final_weight);
    for (int n = 1; n <= power_series_terms; ++n) {
      power = Times(power, loop_weight);
      series = Plus(series, power);
      VLOG(0) << "\\sum_{n=0}^" << n << " loop_weight^n = " << series;
      VLOG(0) << "  sum x final = " << Times(series, final_weight);
    }
  }

  if (use_shortest_distance) {
    VLOG(0) << msg;
    VLOG(0) << "shortest distance = "
            << fst::ShortestDistance(fst, FLAGS_delta);
  }
}

TEST(AlgebraicPathTest, Log) {
  typedef fst::LogArc Arc;
  typedef Arc::Weight Weight;

  constexpr float q = 1.0f / 32768.0f;

  TestOneStateLoop<Arc>(
      Weight(-std::log1p(-q)), Weight(-std::log(q)), Weight::One(), 1e-9, 9,
      true, "shortest distance computation will be slow and imprecise");

  // Internal implementation detail:
  EXPECT_EQ(0, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

TEST(AlgebraicPathTest, LimitedMaxTimes) {
  // Note that this semiring is not k-closed.
  typedef festus::LimitedMaxTimesSemiring<int8, 3, 2> SemiringType;
  typedef festus::ValueWeightStatic<SemiringType> Weight;
  typedef festus::ValueArcTpl<Weight> Arc;

  TestOneStateLoop<Arc>(
      Weight::From(1), Weight::From(1), Weight::From(2), 1e-30, 3,
      true, "shortest distance computation will be fast and different");

  // Internal implementation detail:
  EXPECT_EQ(1, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

TEST(AlgebraicPathTest, IntegersMod13) {
  // Note that this semiring is not k-closed.
  typedef festus::IntegersMod<13> SemiringType;
  typedef festus::ValueWeightStatic<SemiringType> Weight;
  typedef festus::ValueArcTpl<Weight> Arc;

  TestOneStateLoop<Arc>(
      Weight::From(3), Weight::From(11), Weight::One(), 1e-30, 5,
      FLAGS_modular_int, "shortest distance computation will not terminate");

  // Internal implementation detail:
  EXPECT_EQ(1, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

TEST(AlgebraicPathTest, Quaternion) {
  // Note that this semiring is not k-closed.
  typedef festus::QuaternionWeightTpl<festus::RealSemiring<float>> Weight;
  typedef festus::ValueArcTpl<Weight> Arc;

  const Weight p = Weight::From(-0.5f, 0.5f, 0.5f, 0.5f);
  const Weight q = Minus(Weight::One(), p);

  TestOneStateLoop<Arc>(
      p, q, Weight::One(), 1e-9, 5,
      FLAGS_quaternion, "shortest distance computation will not terminate");

  // Internal implementation detail:
  EXPECT_EQ(1, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

}  // namespace

int main(int argc, char *argv[]) {
  testing::InitGoogleTest(&argc, argv);
  SET_FLAGS(argv[0], &argc, &argv, true);
  return RUN_ALL_TESTS();
}
<commit_msg>Documentation for algebraic path test.<commit_after>// festus/algebraic-path-test.cc
//
// 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.
//
// Copyright 2016 Google, Inc.
// Author: mjansche@google.com (Martin Jansche)
//
// \file
// Unit test for algebraic path computation.
//
// This also illustrates the different behaviors of fst::ShortestDistance(fst)
// vs. festus::SumTotalWeight(fst):
//
// * ShortestDistance() requires, but cannot check, that the weight semiring
//   is (approximately) k-closed. It uses this assumption to compute an
//   implicitly defined Star() closure of the semiring by expanding out a
//   power series until (approximate) convergence.
//
// * SumTotalWeight() requires that a Star() operation has been explicitly
//   defined which satisfies the Star axiom. It makes no assumptions about
//   Star() being equivalent to a convergent power series.
//
// The behavior of these two functions differs in at least the following
// situations:
//
// * The power series for all observed cycles converge; the limit of a
//   convergent power series is also provided by the corresponding Star()
//   operation. This means that, for all practical purposes and with only minor
//   hand-waving, the semiring is approximately k-closed. This is the case,
//   inter alia, for the log semiring and graphs/FSTs without negative weight
//   cycles, i.e. all real weights fall into [0;1), so the geometric power
//   series converges.
//
//   In this situation SumTotalWeight() and ShortestDistance() will eventually
//   give approximately the same answer. However, there are differences in
//   terms of speed and quality.
//
//   SumTotalWeight() will give a generally more precise answer in terms of
//   Star(), which is quick to compute by itself, but uses an algorithm with
//   worst-case cubic running time in the number of state/vertices
//   (TODO: cubic in the size of the largest strongly connected component).
//
//   ShortestDistance() will give an answer in terms of the limit of a
//   convergent power series, but in order to do so it has to expand out the
//   terms of the power series one-by-one (without acceleration) until
//   approximate convergence. For high-probability cycles (whose real
//   probabilities are close to 1), convergence can be slow. The quality of the
//   answer also depends on the configured convergence threshold.
//
// * A cycle weight can be computed via a convergent power series, but its
//   limit differs from the result of the defined Star() operation. This is
//   the case for the particular instance of LimitedMaxTimesSemiring below,
//   where 2 == Star(1) != max(1^0, 1^1, 1^2, 1^3, ...) == 1.
//
//   In this situation SumTotalWeight() will give an answer in terms of Star(),
//   and ShortestDistance() will give a different answer in terms of the limit
//   of the convergent power series.
//
// * The power series for a cycle weight diverges, but the corresponding Star()
//   value is well-defined. This is the case, inter alia, for the finite field
//   of integers modulo a prime, and for the division ring of quaternions. In
//   all division rings (and hence all fields), whenever Star(x) is defined, it
//   must be defined as Star(x) := (1 - x)^{-1}; and in all rings, Star(x) must
//   be undefined when 1 - x == 0.
//
//   In this situation SumTotalWeight() will give an answer in terms of Star(),
//   and ShortestDistance() will not terminate.

#include "festus/algebraic-path.h"

#include <cmath>

#include <fst/compat.h>
#include <fst/fstlib.h>
#include <gtest/gtest.h>

#include "festus/arc.h"
#include "festus/float-weight-star.h"
#include "festus/max-times-semiring.h"
#include "festus/modular-int-semiring.h"
#include "festus/quaternion-semiring.h"
#include "festus/real-weight.h"
#include "festus/value-weight-static.h"

DEFINE_double(delta, fst::kDelta,
              "Convergence threshold for ShortestDistance");
DEFINE_bool(modular_int, false,
            "Try to compute ShortestDistance in modular int semiring");
DEFINE_bool(quaternion, false,
            "Try to compute ShortestDistance in quaternion semiring");

namespace {

template <class Arc>
void TestOneStateLoop(
    typename Arc::Weight loop_weight,
    typename Arc::Weight final_weight,
    typename Arc::Weight expected_sum_total,
    float comparison_delta,
    int power_series_terms,
    bool use_shortest_distance,
    const char *msg) {
  typedef typename Arc::Weight Weight;

  // One-state FST with a loop at its only (initial and final) state.
  fst::VectorFst<Arc> fst;
  const auto state = fst.AddState();
  fst.SetStart(state);
  fst.AddArc(state, Arc(0, 0, loop_weight, state));
  fst.SetFinal(state, final_weight);

  const Weight sum_total = festus::SumTotalWeight(fst);
  EXPECT_TRUE(ApproxEqual(sum_total, expected_sum_total, comparison_delta));

  VLOG(0) << "sum total = " << sum_total << " ~= " << expected_sum_total;

  if (power_series_terms) {
    Weight power = Weight::One();
    Weight series = Weight::One();
    VLOG(0) << "\\sum_{n=0}^0 loop_weight^n = " << series;
    VLOG(0) << "  sum x final = " << Times(series, final_weight);
    for (int n = 1; n <= power_series_terms; ++n) {
      power = Times(power, loop_weight);
      series = Plus(series, power);
      VLOG(0) << "\\sum_{n=0}^" << n << " loop_weight^n = " << series;
      VLOG(0) << "  sum x final = " << Times(series, final_weight);
    }
  }

  if (use_shortest_distance) {
    VLOG(0) << msg;
    VLOG(0) << "shortest distance = "
            << fst::ShortestDistance(fst, FLAGS_delta);
  }
}

TEST(AlgebraicPathTest, Log) {
  typedef fst::LogArc Arc;
  typedef Arc::Weight Weight;

  constexpr float q = 1.0f / 32768.0f;

  TestOneStateLoop<Arc>(
      Weight(-std::log1p(-q)), Weight(-std::log(q)), Weight::One(), 1e-9, 9,
      true, "shortest distance computation will be slow and imprecise");

  // Internal implementation detail:
  EXPECT_EQ(0, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

TEST(AlgebraicPathTest, LimitedMaxTimes) {
  // Note that this semiring is not k-closed.
  typedef festus::LimitedMaxTimesSemiring<int8, 3, 2> SemiringType;
  typedef festus::ValueWeightStatic<SemiringType> Weight;
  typedef festus::ValueArcTpl<Weight> Arc;

  TestOneStateLoop<Arc>(
      Weight::From(1), Weight::From(1), Weight::From(2), 1e-30, 3,
      true, "shortest distance computation will be fast and different");

  // Internal implementation detail:
  EXPECT_EQ(1, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

TEST(AlgebraicPathTest, IntegersMod13) {
  // Note that this semiring is not k-closed.
  typedef festus::IntegersMod<13> SemiringType;
  typedef festus::ValueWeightStatic<SemiringType> Weight;
  typedef festus::ValueArcTpl<Weight> Arc;

  TestOneStateLoop<Arc>(
      Weight::From(3), Weight::From(11), Weight::One(), 1e-30, 5,
      FLAGS_modular_int, "shortest distance computation will not terminate");

  // Internal implementation detail:
  EXPECT_EQ(1, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

TEST(AlgebraicPathTest, Quaternion) {
  // Note that this semiring is not k-closed.
  typedef festus::QuaternionWeightTpl<festus::RealSemiring<float>> Weight;
  typedef festus::ValueArcTpl<Weight> Arc;

  const Weight p = Weight::From(-0.5f, 0.5f, 0.5f, 0.5f);
  const Weight q = Minus(Weight::One(), p);

  TestOneStateLoop<Arc>(
      p, q, Weight::One(), 1e-9, 5,
      FLAGS_quaternion, "shortest distance computation will not terminate");

  // Internal implementation detail:
  EXPECT_EQ(1, festus::internal::SemiringFor<Weight>::IsSpecialized());
}

}  // namespace

int main(int argc, char *argv[]) {
  testing::InitGoogleTest(&argc, argv);
  SET_FLAGS(argv[0], &argc, &argv, true);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>///
/// @file  primecount.hpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMECOUNT_HPP
#define PRIMECOUNT_HPP

#include <stdexcept>
#include <string>
#include <stdint.h>

#define PRIMECOUNT_VERSION "1.1"
#define PRIMECOUNT_VERSION_MAJOR 1
#define PRIMECOUNT_VERSION_MINOR 1

namespace primecount {

class primecount_error : public std::runtime_error
{
public:
  primecount_error(const std::string& msg)
    : std::runtime_error(msg)
  { }
};

/// Alias for the fastest prime counting function in primecount.
int64_t pi(int64_t x);

/// Alias for the fastest prime counting function in primecount.
/// @param x  integer or arithmetic expression like 10^12.
/// @pre   x  <= primecount::max().
///
std::string pi(const std::string& x);

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat(int64_t x);

/// Calculate the number of primes below x using Legendre's formula.
/// Run time: O(x) operations, O(x^(1/2)) space.
///
int64_t pi_legendre(int64_t x);

/// Calculate the number of primes below x using Lehmer's formula.
/// Run time: O(x/(log x)^4) operations, O(x^(1/2)) space.
///
int64_t pi_lehmer(int64_t x);

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3) / log x) operations, O(x^(1/3) * (log x)^2) space.
///
int64_t pi_lmo(int64_t x);

/// Calculate the number of primes below x using Meissel's formula.
/// Run time: O(x/(log x)^3) operations, O(x^(1/2) / log x) space.
///
int64_t pi_meissel(int64_t x);

/// Calculate the number of primes below x using an optimized
/// segmented sieve of Eratosthenes implementation.
/// Run time: O(x log log x) operations, O(x^(1/2)) space.
///
int64_t pi_primesieve(int64_t x);

/// Calculate the nth prime using a combination of an efficient prime
/// counting function implementation and the sieve of Eratosthenes.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/2)) space.
///
int64_t nth_prime(int64_t n);

/// Partial sieve function (a.k.a. Legendre-sum).
/// phi(x, a) counts the numbers <= x that are not divisible
/// by any of the first a primes.
///
int64_t phi(int64_t x, int64_t a);

/// Calculate the offset logarithmic integral which is a very
/// accurate approximation of the number of primes below x.
/// @post Li(x) > pi(x) for 24 <= x <= ~ 10^316
///
int64_t Li(int64_t x);

/// Calculate the inverse logarithmic integral Li^-1(x) which is
/// a very accurate approximation of the nth prime.
/// @post Li_inverse(x) < nth_prime(x) for 7 <= x <= ~ 10^316
///
int64_t Li_inverse(int64_t x);

// Set the number of threads.
void set_num_threads(int num_threads);

// Get the currently set number of threads.
int get_num_threads();

/// Returns the largest integer that can be used with
/// pi(std::string x). The return type is a string as max may be a
/// 128-bit integer which is not supported by all compilers.
///
std::string max();

/// Test all prime counting function implementations.
/// @return true if success else false.
///
bool test();

} // namespace primecount

#endif
<commit_msg>Update documentation<commit_after>///
/// @file  primecount.hpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMECOUNT_HPP
#define PRIMECOUNT_HPP

#include <stdexcept>
#include <string>
#include <stdint.h>

#define PRIMECOUNT_VERSION "1.1"
#define PRIMECOUNT_VERSION_MAJOR 1
#define PRIMECOUNT_VERSION_MINOR 1

namespace primecount {

class primecount_error : public std::runtime_error
{
public:
  primecount_error(const std::string& msg)
    : std::runtime_error(msg)
  { }
};

/// Alias for the fastest prime counting function in primecount.
int64_t pi(int64_t x);

/// 128-bit prime counting function.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
/// @param expr  Integer arithmetic expression e.g. "1000", "10^22"
/// @pre   expr  <= primecount::max()
///
std::string pi(const std::string& x);

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat(int64_t x);

/// Calculate the number of primes below x using Legendre's formula.
/// Run time: O(x) operations, O(x^(1/2)) space.
///
int64_t pi_legendre(int64_t x);

/// Calculate the number of primes below x using Lehmer's formula.
/// Run time: O(x/(log x)^4) operations, O(x^(1/2)) space.
///
int64_t pi_lehmer(int64_t x);

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3) / log x) operations, O(x^(1/3) * (log x)^2) space.
///
int64_t pi_lmo(int64_t x);

/// Calculate the number of primes below x using Meissel's formula.
/// Run time: O(x/(log x)^3) operations, O(x^(1/2) / log x) space.
///
int64_t pi_meissel(int64_t x);

/// Calculate the number of primes below x using an optimized
/// segmented sieve of Eratosthenes implementation.
/// Run time: O(x log log x) operations, O(x^(1/2)) space.
///
int64_t pi_primesieve(int64_t x);

/// Calculate the nth prime using a combination of an efficient prime
/// counting function implementation and the sieve of Eratosthenes.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/2)) space.
///
int64_t nth_prime(int64_t n);

/// Partial sieve function (a.k.a. Legendre-sum).
/// phi(x, a) counts the numbers <= x that are not divisible
/// by any of the first a primes.
///
int64_t phi(int64_t x, int64_t a);

/// Calculate the offset logarithmic integral which is a very
/// accurate approximation of the number of primes below x.
/// @post Li(x) > pi(x) for 24 <= x <= ~ 10^316
///
int64_t Li(int64_t x);

/// Calculate the inverse logarithmic integral Li^-1(x) which is
/// a very accurate approximation of the nth prime.
/// @post Li_inverse(x) < nth_prime(x) for 7 <= x <= ~ 10^316
///
int64_t Li_inverse(int64_t x);

/// Set the number of threads.
void set_num_threads(int num_threads);

/// Get the currently set number of threads.
int get_num_threads();

/// Largest integer supported by pi(const std::string& x).
/// The return type is a string as max may be a 128-bit integer
/// which is not supported by all compilers.
/// @return 2^63-1 for 32-bit CPUs, 10^27 for 64-bit CPUs
///
std::string max();

/// Test all prime counting function implementations.
/// @return true if success else false.
///
bool test();

} // namespace primecount

#endif
<|endoftext|>


<commit_before>/***************************************************
  This is a library for the HDC1000 Humidity & Temp Sensor

  Designed specifically to work with the HDC1008 sensor from Adafruit
  ----> https://www.adafruit.com/products/2635

  These sensors use I2C to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution

  Modified for Photon  needs application.h for types  RMB
 ****************************************************/
#include "application.h"
#include "Adafruit_HDC1000/Adafruit_HDC1000.h"

Adafruit_HDC1000::Adafruit_HDC1000() {
}

boolean Adafruit_HDC1000::begin(uint8_t addr) {
  _i2caddr = addr;

  Wire.begin();

  reset();
  if (read16(HDC1000_MANUFID) != 0x5449) return false;
  if (read16(HDC1000_DEVICEID) != 0x1000) return false;
  return true;
}

void Adafruit_HDC1000::reset(void) {
  // reset,combined temp/humidity measurement,and select 14 bit temp & humidity resolution
  uint16_t config = HDC1000_CONFIG_RST | HDC1000_CONFIG_MODE | HDC1000_CONFIG_TRES_14 | HDC1000_CONFIG_HRES_14;

  Wire.beginTransmission(_i2caddr);
  Wire.write(HDC1000_CONFIG);   // set pointer register to configuration register   RMB
  Wire.write(config>>8);        // now write out 2 bytes MSB first    RMB
  Wire.write(config&0xFF);
  Wire.endTransmission();
  delay(15);
}

float Adafruit_HDC1000::readTemperature(void) {

  float temp = (read32(HDC1000_TEMP, 20) >> 16);
  temp /= 65536;
  temp *= 165;
  temp -= 40;

  return temp;
}

float Adafruit_HDC1000::readHumidity(void) {
  // reads both temp and humidity but masks out temp in highest 16 bits
  // originally used hum but humidity declared in private section of class
  float humidity = (read32(HDC1000_TEMP, 20) & 0xFFFF);

  humidity /= 65536;
  humidity *= 100;

  return humidity;
}

void Adafruit_HDC1000::ReadTempHumidity(void) {
  // HDC1008 setup to measure both temperature and humidity in one conversion
  // this is a different way to access data in ONE read
  // this sets internal private variables that can be accessed by Get() functions

  uint32_t rt,rh ;  // working variables

  rt = read32(HDC1000_TEMP, 20);    // get temp and humidity reading together
  rh = rt;                          // save a copy for humidity processing

  float temp = (rt >> 16);        // convert to temp first
  temp /= 65536;
  temp *= 165;
  temp -= 40;

  float humidity = (rh & 0xFFFF);   // now convert to humidity
  humidity /= 65536;
  humidity *= 100;
}

float Adafruit_HDC1000::GetTemperature(void) {
  // getter function to access private temp variable

  return temp ;
}

float Adafruit_HDC1000::GetHumidity(void) {
  // getter function to access private humidity variable

  return humidity ;
}

// Add ability to test battery voltage, useful in remote monitoring, TRUE if <2.8V
// usually called after Temp/Humid reading  RMB
// Thanks to KFricke for micropython-hdc1008 example on GitHub
boolean Adafruit_HDC1000::batteryLOW(void)  {

  uint16_t battLOW = (read16(HDC1000_CONFIG_BATT, 20));

  battLOW &= HDC1000_CONFIG_BATT;   // mask off other bits, bit 11 will be 1 if voltage < 2.8V

  if (battLOW> 0) return true;
  return  false;
}

/*********************************************************************/

uint16_t Adafruit_HDC1000::read16(uint8_t a, uint8_t d) {
  Wire.beginTransmission(_i2caddr);
  Wire.write(a);
  Wire.endTransmission();
  delay(d);
  Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)2);
  uint16_t r = Wire.read();
  r <<= 8;
  r |= Wire.read();
  //Serial.println(r, HEX);
  return r;
}

uint32_t Adafruit_HDC1000::read32(uint8_t a, uint8_t d) {
  Wire.beginTransmission(_i2caddr);
  Wire.write(a);
  Wire.endTransmission();
  // delay was hardcoded as 50, should use d   RMB
  delay(d);
  Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)4);
  uint32_t r = Wire.read();
  // assembles temp into highest 16 bits, humidity into lowest 16 bits
  r <<= 8;
  r |= Wire.read();
  r <<= 8;
  r |= Wire.read();
  r <<= 8;
  r |= Wire.read();
  //Serial.println(r, HEX);
  return r;
}
<commit_msg>problems with private variables temp and humidity<commit_after>/***************************************************
  This is a library for the HDC1000 Humidity & Temp Sensor

  Designed specifically to work with the HDC1008 sensor from Adafruit
  ----> https://www.adafruit.com/products/2635

  These sensors use I2C to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution

  Modified for Photon  needs application.h for types  RMB
 ****************************************************/
#include "application.h"
#include "Adafruit_HDC1000/Adafruit_HDC1000.h"

Adafruit_HDC1000::Adafruit_HDC1000() {
}

boolean Adafruit_HDC1000::begin(uint8_t addr) {
  _i2caddr = addr;

  Wire.begin();

  reset();
  if (read16(HDC1000_MANUFID) != 0x5449) return false;
  if (read16(HDC1000_DEVICEID) != 0x1000) return false;
  return true;
}

void Adafruit_HDC1000::reset(void) {
  // reset,combined temp/humidity measurement,and select 14 bit temp & humidity resolution
  uint16_t config = HDC1000_CONFIG_RST | HDC1000_CONFIG_MODE | HDC1000_CONFIG_TRES_14 | HDC1000_CONFIG_HRES_14;

  Wire.beginTransmission(_i2caddr);
  Wire.write(HDC1000_CONFIG);   // set pointer register to configuration register   RMB
  Wire.write(config>>8);        // now write out 2 bytes MSB first    RMB
  Wire.write(config&0xFF);
  Wire.endTransmission();
  delay(15);
}

float Adafruit_HDC1000::readTemperature(void) {

  float temp = (read32(HDC1000_TEMP, 20) >> 16);
  temp /= 65536;
  temp *= 165;
  temp -= 40;

  return temp;
}

float Adafruit_HDC1000::readHumidity(void) {
  // reads both temp and humidity but masks out temp in highest 16 bits
  // originally used hum but humidity declared in private section of class
  float humidity = (read32(HDC1000_TEMP, 20) & 0xFFFF);

  humidity /= 65536;
  humidity *= 100;

  return humidity;
}

void Adafruit_HDC1000::ReadTempHumidity(void) {
  // HDC1008 setup to measure both temperature and humidity in one conversion
  // this is a different way to access data in ONE read
  // this sets internal private variables that can be accessed by Get() functions

  uint32_t rt,rh ;  // working variables

  rt = read32(HDC1000_TEMP, 20);    // get temp and humidity reading together
  rh = rt;                          // save a copy for humidity processing

  float temp = (rt >> 16);        // convert to temp first
  temp /= 65536;
  temp *= 165;
  temp -= 40;
  Serial.print("temp=",temp);

  float humidity = (rh & 0xFFFF);   // now convert to humidity
  humidity /= 65536;
  humidity *= 100;
  Serial.println("\thumidity=",humidity);
}

float Adafruit_HDC1000::GetTemperature(void) {
  // getter function to access private temp variable

  return temp ;
}

float Adafruit_HDC1000::GetHumidity(void) {
  // getter function to access private humidity variable

  return humidity ;
}

// Add ability to test battery voltage, useful in remote monitoring, TRUE if <2.8V
// usually called after Temp/Humid reading  RMB
// Thanks to KFricke for micropython-hdc1008 example on GitHub
boolean Adafruit_HDC1000::batteryLOW(void)  {

  uint16_t battLOW = (read16(HDC1000_CONFIG_BATT, 20));

  battLOW &= HDC1000_CONFIG_BATT;   // mask off other bits, bit 11 will be 1 if voltage < 2.8V

  if (battLOW> 0) return true;
  return  false;
}

/*********************************************************************/

uint16_t Adafruit_HDC1000::read16(uint8_t a, uint8_t d) {
  Wire.beginTransmission(_i2caddr);
  Wire.write(a);
  Wire.endTransmission();
  delay(d);
  Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)2);
  uint16_t r = Wire.read();
  r <<= 8;
  r |= Wire.read();
  //Serial.println(r, HEX);
  return r;
}

uint32_t Adafruit_HDC1000::read32(uint8_t a, uint8_t d) {
  Wire.beginTransmission(_i2caddr);
  Wire.write(a);
  Wire.endTransmission();
  // delay was hardcoded as 50, should use d   RMB
  delay(d);
  Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)4);
  uint32_t r = Wire.read();
  // assembles temp into highest 16 bits, humidity into lowest 16 bits
  r <<= 8;
  r |= Wire.read();
  r <<= 8;
  r |= Wire.read();
  r <<= 8;
  r |= Wire.read();
  //Serial.println(r, HEX);
  return r;
}
<|endoftext|>


<commit_before>/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gameproject.h"
#include "gameprojectprivate.h"
#include "gdlhandler.h"
#include "debughelper.h"

#include <QtCore/QStringList>
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QMetaClassInfo>

REGISTER_OBJECTTYPE(Gluon,GameProject)
Q_DECLARE_METATYPE(Gluon::GameObject*);

using namespace Gluon;

GameProject::GameProject(QObject * parent)
    : GluonObject(parent)
{
    d = new GameProjectPrivate;
    setGameProject(this);

    #warning Q_PROPERTY does not currently handle namespaced types - see bugreports.qt.nokia.com/browse/QTBUG-2151
    QVariant somethingEmpty;
    GameObject * theObject = NULL;
    somethingEmpty.setValue<GameObject*>(theObject);
    setProperty("entryPoint", somethingEmpty);
}

GameProject::GameProject(const GameProject &other, QObject * parent)
    : GluonObject(parent)
    , d(other.d)
{
}

GameProject::~GameProject()
{
}

GameProject *
GameProject::instantiate()
{
    return new GameProject(this);
}

GluonObject *
GameProject::findItemByName(QString qualifiedName)
{
    return d->findItemByNameInObject(qualifiedName.split('.'), this);
}

bool
GameProject::saveToFile() const
{
    QFile *projectFile = new QFile(filename().toLocalFile());
    if(!projectFile->open(QIODevice::WriteOnly))
        return false;

    QList<const GluonObject*> thisProject;
    thisProject.append(this);

    QTextStream projectWriter(projectFile);
    projectWriter << GDLHandler::instance()->serializeGDL(thisProject);
    projectFile->close();

    delete(projectFile);
    return true;
}

bool
GameProject::loadFromFile()
{
    DEBUG_FUNC_NAME
    QFile *projectFile = new QFile(filename().toLocalFile());
    if(!projectFile->open(QIODevice::ReadOnly))
        return false;

    QTextStream projectReader(projectFile);
    QString fileContents = projectReader.readAll();
    projectFile->close();

    if(fileContents.isEmpty())
        return false;

    QList<GluonObject*> objectList = GDLHandler::instance()->parseGDL(fileContents, this->parent());
    if(objectList.count() > 0)
    {
        if(objectList[0]->metaObject())
        {
            // If the first object in the list is a GluonProject, then let's
            // adapt ourselves to represent that object...
            if(objectList[0]->metaObject()->className() == this->metaObject()->className())
            {
                DEBUG_TEXT("Project successfully parsed - applying to local instance");
                GameProject* loadedProject = qobject_cast<GameProject*>(objectList[0]);

                // First things first - clean ourselves out, all the children
                // and the media info list should be gone-ified
                qDeleteAll(this->children());

                // Reassign all the children of the newly loaded project to
                // ourselves...
                foreach(QObject* child, loadedProject->children())
                {
                    GluonObject* theChild = qobject_cast<GluonObject*>(child);
                    theChild->setParent(this);
                }

                // Set all the interesting values...
                setName(loadedProject->name());

                // Copy accross all the properties
                const QMetaObject *metaobject = loadedProject->metaObject();
                int count = metaobject->propertyCount();
                for(int i = 0; i < count; ++i)
                {
                    QMetaProperty metaproperty = metaobject->property(i);
                    const QString theName(metaproperty.name());
                    if(theName == "objectName" || theName == "name")
                        continue;
                    setProperty(metaproperty.name(), loadedProject->property(metaproperty.name()));
                }

                // Then get all the dynamic ones (in case any such exist)
                QList<QByteArray> propertyNames = loadedProject->dynamicPropertyNames();
                foreach(QByteArray propName, propertyNames)
                    setProperty(propName, loadedProject->property(propName));

                // Sanitize me!
                this->sanitize();

                // Finally, get rid of the left-overs
                qDeleteAll(objectList);

                DEBUG_TEXT("Project loading successful!");
            }
            // Otherwise it is not a GluonProject, and should fail!
            else
            {
                DEBUG_TEXT(QString("First object loaded is not a Gluon::GameProject."));
                DEBUG_TEXT(QString("Type of loaded object:").arg(objectList[0]->metaObject()->className()));
                DEBUG_TEXT(QString("Name of loaded object:").arg(objectList[0]->name()));
                return false;
            }
        }
        else
            return false;
    }

    delete(projectFile);
    return true;
}

bool
GameProject::loadFromFile(QUrl filename)
{
    setFilename(filename);
    return loadFromFile();
}

/******************************************************************************
 * Property Getter-setters
 *****************************************************************************/

QString
GameProject::description() const
{
    return d->description;
}
void
GameProject::setDescription(QString newDescription)
{
    d->description = newDescription;
}

QUrl
GameProject::homepage() const
{
    return d->homepage;
}
void
GameProject::setHomepage(QUrl newHomepage)
{
    d->homepage = newHomepage;
}

QList<QUrl>
GameProject::mediaInfo() const
{
    return d->mediaInfo;
}
void
GameProject::setMediaInfo(QList<QUrl> newMediaInfo)
{
    d->mediaInfo = newMediaInfo;
}

QUrl
GameProject::filename() const
{
    return d->filename;
}
void
GameProject::setFilename(QUrl newFilename)
{
    d->filename = newFilename;
}

GameObject *
GameProject::entryPoint() const
{
//    return d->entryPoint;
    return property("entryPoint").value<GameObject*>();
}
void
GameProject::setEntryPoint(GameObject * newEntryPoint)
{
    //d->entryPoint = newEntryPoint;
    QVariant theNewValue;
    theNewValue.setValue<GameObject*>(newEntryPoint);
    setProperty("entryPoint", theNewValue);
}

#include "gameproject.moc"
<commit_msg>copy the dynamic property value<commit_after>/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gameproject.h"
#include "gameprojectprivate.h"
#include "gdlhandler.h"
#include "debughelper.h"

#include <QtCore/QStringList>
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QMetaClassInfo>

REGISTER_OBJECTTYPE(Gluon,GameProject)
Q_DECLARE_METATYPE(Gluon::GameObject*);

using namespace Gluon;

GameProject::GameProject(QObject * parent)
    : GluonObject(parent)
{
    d = new GameProjectPrivate;
    setGameProject(this);

    #warning Q_PROPERTY does not currently handle namespaced types - see bugreports.qt.nokia.com/browse/QTBUG-2151
    QVariant somethingEmpty;
    GameObject * theObject = NULL;
    somethingEmpty.setValue<GameObject*>(theObject);
    setProperty("entryPoint", somethingEmpty);
}

GameProject::GameProject(const GameProject &other, QObject * parent)
    : GluonObject(parent)
    , d(other.d)
{
    setProperty("entryPoint", other.property("entryPoint"));
}

GameProject::~GameProject()
{
}

GameProject *
GameProject::instantiate()
{
    return new GameProject(this);
}

GluonObject *
GameProject::findItemByName(QString qualifiedName)
{
    return d->findItemByNameInObject(qualifiedName.split('.'), this);
}

bool
GameProject::saveToFile() const
{
    QFile *projectFile = new QFile(filename().toLocalFile());
    if(!projectFile->open(QIODevice::WriteOnly))
        return false;

    QList<const GluonObject*> thisProject;
    thisProject.append(this);

    QTextStream projectWriter(projectFile);
    projectWriter << GDLHandler::instance()->serializeGDL(thisProject);
    projectFile->close();

    delete(projectFile);
    return true;
}

bool
GameProject::loadFromFile()
{
    DEBUG_FUNC_NAME
    QFile *projectFile = new QFile(filename().toLocalFile());
    if(!projectFile->open(QIODevice::ReadOnly))
        return false;

    QTextStream projectReader(projectFile);
    QString fileContents = projectReader.readAll();
    projectFile->close();

    if(fileContents.isEmpty())
        return false;

    QList<GluonObject*> objectList = GDLHandler::instance()->parseGDL(fileContents, this->parent());
    if(objectList.count() > 0)
    {
        if(objectList[0]->metaObject())
        {
            // If the first object in the list is a GluonProject, then let's
            // adapt ourselves to represent that object...
            if(objectList[0]->metaObject()->className() == this->metaObject()->className())
            {
                DEBUG_TEXT("Project successfully parsed - applying to local instance");
                GameProject* loadedProject = qobject_cast<GameProject*>(objectList[0]);

                // First things first - clean ourselves out, all the children
                // and the media info list should be gone-ified
                qDeleteAll(this->children());

                // Reassign all the children of the newly loaded project to
                // ourselves...
                foreach(QObject* child, loadedProject->children())
                {
                    GluonObject* theChild = qobject_cast<GluonObject*>(child);
                    theChild->setParent(this);
                }

                // Set all the interesting values...
                setName(loadedProject->name());

                // Copy accross all the properties
                const QMetaObject *metaobject = loadedProject->metaObject();
                int count = metaobject->propertyCount();
                for(int i = 0; i < count; ++i)
                {
                    QMetaProperty metaproperty = metaobject->property(i);
                    const QString theName(metaproperty.name());
                    if(theName == "objectName" || theName == "name")
                        continue;
                    setProperty(metaproperty.name(), loadedProject->property(metaproperty.name()));
                }

                // Then get all the dynamic ones (in case any such exist)
                QList<QByteArray> propertyNames = loadedProject->dynamicPropertyNames();
                foreach(QByteArray propName, propertyNames)
                    setProperty(propName, loadedProject->property(propName));

                // Sanitize me!
                this->sanitize();

                // Finally, get rid of the left-overs
                qDeleteAll(objectList);

                DEBUG_TEXT("Project loading successful!");
            }
            // Otherwise it is not a GluonProject, and should fail!
            else
            {
                DEBUG_TEXT(QString("First object loaded is not a Gluon::GameProject."));
                DEBUG_TEXT(QString("Type of loaded object:").arg(objectList[0]->metaObject()->className()));
                DEBUG_TEXT(QString("Name of loaded object:").arg(objectList[0]->name()));
                return false;
            }
        }
        else
            return false;
    }

    delete(projectFile);
    return true;
}

bool
GameProject::loadFromFile(QUrl filename)
{
    setFilename(filename);
    return loadFromFile();
}

/******************************************************************************
 * Property Getter-setters
 *****************************************************************************/

QString
GameProject::description() const
{
    return d->description;
}
void
GameProject::setDescription(QString newDescription)
{
    d->description = newDescription;
}

QUrl
GameProject::homepage() const
{
    return d->homepage;
}
void
GameProject::setHomepage(QUrl newHomepage)
{
    d->homepage = newHomepage;
}

QList<QUrl>
GameProject::mediaInfo() const
{
    return d->mediaInfo;
}
void
GameProject::setMediaInfo(QList<QUrl> newMediaInfo)
{
    d->mediaInfo = newMediaInfo;
}

QUrl
GameProject::filename() const
{
    return d->filename;
}
void
GameProject::setFilename(QUrl newFilename)
{
    d->filename = newFilename;
}

GameObject *
GameProject::entryPoint() const
{
//    return d->entryPoint;
    return property("entryPoint").value<GameObject*>();
}
void
GameProject::setEntryPoint(GameObject * newEntryPoint)
{
    //d->entryPoint = newEntryPoint;
    QVariant theNewValue;
    theNewValue.setValue<GameObject*>(newEntryPoint);
    setProperty("entryPoint", theNewValue);
}

#include "gameproject.moc"
<|endoftext|>


<commit_before>// PythonStuff.cpp
// Copyright 2011, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "PythonStuff.h"

#include "Area.h"
#include "Point.h"
#include "AreaDxf.h"
#include "kurve/geometry.h"

#if _DEBUG
#undef _DEBUG
#include <Python.h>
#define _DEBUG
#else
#include <Python.h>
#endif

#ifdef __GNUG__
#pragma implementation
#endif

#include <boost/progress.hpp>
#include <boost/timer.hpp>
#include <boost/foreach.hpp>
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>

#include "clipper.hpp"
using namespace clipper;

namespace bp = boost::python;

boost::python::list getVertices(const CCurve& curve) {
	boost::python::list vlist;
	BOOST_FOREACH(const CVertex& vertex, curve.m_vertices) {
		vlist.append(vertex);
    }
	return vlist;
}

boost::python::list getCurves(const CArea& area) {
	boost::python::list clist;
	BOOST_FOREACH(const CCurve& curve, area.m_curves) {
		clist.append(curve);
    }
	return clist;
}

boost::python::tuple transformed_point(const geoff_geometry::Matrix &matrix, double x, double y, double z)
{
	geoff_geometry::Point3d p(x,y,z);
	p = p.Transform(matrix);

	return bp::make_tuple(p.x,p.y,p.z);
}

static void print_curve(const CCurve& c)
{
	unsigned int nvertices = c.m_vertices.size();
	printf("number of vertices = %d\n", nvertices);
	int i = 0;
	for(std::list<CVertex>::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++, i++)
	{
		const CVertex& vertex = *It;
		printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::m_units, vertex.m_p.y / CArea::m_units);
		if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::m_units, vertex.m_c.y / CArea::m_units);
		printf("\n");
	}
}

static void print_area(const CArea &a)
{
	for(std::list<CCurve>::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++)
	{
		const CCurve& curve = *It;
		print_curve(curve);
	}
}

static unsigned int num_vertices(const CCurve& curve)
{
	return curve.m_vertices.size();
}

static CVertex FirstVertex(const CCurve& curve)
{
	return curve.m_vertices.front();
}

static CVertex LastVertex(const CCurve& curve)
{
	return curve.m_vertices.back();
}

static void set_units(double units)
{
	CArea::m_units = units;
}

static double get_units()
{
	return CArea::m_units;
}

static bool holes_linked()
{
	return CArea::HolesLinked();
}

static CArea AreaFromDxf(const char* filepath)
{
	CArea area;
	AreaDxfRead dxf(&area, filepath);
	dxf.DoRead();
	return area;
}

static void append_point(CCurve& c, const Point& p)
{
	c.m_vertices.push_back(CVertex(p));
}

static boost::python::tuple nearest_point_to_curve(CCurve& c1, const CCurve& c2)
{
	double dist;
	Point p = c1.NearestPoint(c2, &dist);

	return bp::make_tuple(p, dist);
}

boost::python::list MakePocketToolpath(const CArea& a, double tool_radius, double extra_offset, double stepover, bool from_center, bool use_zig_zag, double zig_angle)
{
	std::list<CCurve> toolpath;

	CAreaPocketParams params(tool_radius, extra_offset, stepover, from_center, use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, zig_angle);
	a.SplitAndMakePocketToolpath(toolpath, params);

	boost::python::list clist;
	BOOST_FOREACH(const CCurve& c, toolpath) {
		clist.append(c);
    }
	return clist;
}

boost::python::list SplitArea(const CArea& a)
{
	std::list<CArea> areas;
	a.Split(areas);

	boost::python::list alist;
	BOOST_FOREACH(const CArea& a, areas) {
		alist.append(a);
    }
	return alist;
}

void dxfArea(CArea& area, const char* str)
{
	area = CArea();
}

boost::python::list getCurveSpans(const CCurve& c)
{
	boost::python::list span_list;
	const Point *prev_p = NULL;

	for(std::list<CVertex>::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); VIt++)
	{
		const CVertex& vertex = *VIt;

		if(prev_p)
		{
			span_list.append(Span(*prev_p, vertex));
		}
		prev_p = &(vertex.m_p);
	}

	return span_list;
}

Span getFirstCurveSpan(const CCurve& c)
{
	if(c.m_vertices.size() < 2)return Span();

	std::list<CVertex>::const_iterator VIt = c.m_vertices.begin();
	const Point &p = (*VIt).m_p;
	VIt++;
	return Span(p, *VIt, true);
}

Span getLastCurveSpan(const CCurve& c)
{
	if(c.m_vertices.size() < 2)return Span();

	std::list<CVertex>::const_reverse_iterator VIt = c.m_vertices.rbegin();
	const CVertex &v = (*VIt);
	VIt++;

	return Span((*VIt).m_p, v, c.m_vertices.size() == 2);
}

bp::tuple TangentialArc(const Point &p0, const Point &p1, const Point &v0)
{
  Point c;
  int dir;
  tangential_arc(p0, p1, v0, c, dir);

  return bp::make_tuple(c, dir);
}

boost::python::list spanIntersect(const Span& span1, const Span& span2) {
	boost::python::list plist;
	std::list<Point> pts;
	span1.Intersect(span2, pts);
	BOOST_FOREACH(const Point& p, pts) {
		plist.append(p);
    }
	return plist;
}

//Matrix(boost::python::list &l){}

boost::shared_ptr<geoff_geometry::Matrix> matrix_constructor(const boost::python::list& lst) {
	double m[16] = {1,0,0,0,0,1,0,0, 0,0,1,0, 0,0,0,1};

  boost::python::ssize_t n = boost::python::len(lst);
  int j = 0;
  for(boost::python::ssize_t i=0;i<n;i++) {
    boost::python::object elem = lst[i];
	m[j] = boost::python::extract<double>(elem.attr("__float__")());
	j++;
	if(j>=16)break;
  }

  return boost::shared_ptr<geoff_geometry::Matrix>( new geoff_geometry::Matrix(m) );
}

boost::python::list InsideCurves(const CArea& a, const CCurve& curve) {
	boost::python::list plist;

	std::list<CCurve> curves_inside;
	a.InsideCurves(curve, curves_inside);
	BOOST_FOREACH(const CCurve& c, curves_inside) {
		plist.append(c);
    }
	return plist;
}

BOOST_PYTHON_MODULE(area) {
	bp::class_<Point>("Point")
        .def(bp::init<double, double>())
        .def(bp::init<Point>())
        .def(bp::other<double>() * bp::self)
        .def(bp::self * bp::other<double>())
        .def(bp::self / bp::other<double>())
        .def(bp::self * bp::other<Point>())
        .def(bp::self - bp::other<Point>())
        .def(bp::self + bp::other<Point>())
        .def(bp::self ^ bp::other<Point>())
        .def(bp::self == bp::other<Point>())
        .def(bp::self != bp::other<Point>())
        .def(-bp::self)
        .def(~bp::self)
        .def("dist", &Point::dist)
        .def("length", &Point::length)
        .def("normalize", &Point::normalize)
		.def("Rotate", static_cast< void (Point::*)(double, double) >(&Point::Rotate))
		.def("Rotate", static_cast< void (Point::*)(double) >(&Point::Rotate))
        .def_readwrite("x", &Point::x)
        .def_readwrite("y", &Point::y)
		.def("Transform", &Point::Transform)
    ;

	bp::class_<CVertex>("Vertex")
        .def(bp::init<CVertex>())
        .def(bp::init<int, Point, Point>())
        .def(bp::init<Point>())
        .def(bp::init<int, Point, Point, int>())
        .def_readwrite("type", &CVertex::m_type)
        .def_readwrite("p", &CVertex::m_p)
        .def_readwrite("c", &CVertex::m_c)
        .def_readwrite("user_data", &CVertex::m_user_data)
    ;

	bp::class_<Span>("Span")
        .def(bp::init<Span>())
        .def(bp::init<Point, CVertex, bool>())
		.def("NearestPoint", static_cast< Point (Span::*)(const Point& p)const >(&Span::NearestPoint))
		.def("NearestPoint", static_cast< Point (Span::*)(const Span& p, double *d)const >(&Span::NearestPoint))
		.def("GetBox", &Span::GetBox)
		.def("IncludedAngle", &Span::IncludedAngle)
		.def("GetArea", &Span::GetArea)
		.def("On", &Span::On)
		.def("MidPerim", &Span::MidPerim)
		.def("MidParam", &Span::MidParam)
		.def("Length", &Span::Length)
		.def("GetVector", &Span::GetVector)
		.def("Intersect", &spanIntersect)
        .def_readwrite("p", &Span::m_p)
		.def_readwrite("v", &Span::m_v)
    ;

	bp::class_<CCurve>("Curve")
        .def(bp::init<CCurve>())
        .def("getVertices", &getVertices)
        .def("append",&CCurve::append)
        .def("append",&append_point)
        .def("text", &print_curve)
		.def("NearestPoint", static_cast< Point (CCurve::*)(const Point& p)const >(&CCurve::NearestPoint))
		.def("NearestPoint", &nearest_point_to_curve)
		.def("Reverse", &CCurve::Reverse)
		.def("getNumVertices", &num_vertices)
		.def("FirstVertex", &FirstVertex)
		.def("LastVertex", &LastVertex)
		.def("GetArea", &CCurve::GetArea)
		.def("IsClockwise", &CCurve::IsClockwise)
		.def("IsClosed", &CCurve::IsClosed)
        .def("ChangeStart",&CCurve::ChangeStart)
        .def("ChangeEnd",&CCurve::ChangeEnd)
        .def("Offset",&CCurve::Offset)
        .def("OffsetForward",&CCurve::OffsetForward)
        .def("GetSpans",&getCurveSpans)
        .def("GetFirstSpan",&getFirstCurveSpan)
        .def("GetLastSpan",&getLastCurveSpan)
        .def("Break",&CCurve::Break)
        .def("Perim",&CCurve::Perim)
        .def("PerimToPoint",&CCurve::PerimToPoint)
        .def("PointToPerim",&CCurve::PointToPerim)
		.def("FitArcs",&CCurve::FitArcs)
        .def("UnFitArcs",&CCurve::UnFitArcs)
    ;

	bp::class_<CBox2D>("Box")
        .def(bp::init<CBox2D>())
		.def("MinX", &CBox2D::MinX)
		.def("MaxX", &CBox2D::MaxX)
		.def("MinY", &CBox2D::MinY)
		.def("MaxY", &CBox2D::MaxY)
    ;

	bp::class_<CArea>("Area")
        .def(bp::init<CArea>())
        .def("getCurves", &getCurves)
        .def("append",&CArea::append)
        .def("Subtract",&CArea::Subtract)
        .def("Intersect",&CArea::Intersect)
        .def("Union",&CArea::Union)
        .def("Offset",&CArea::Offset)
        .def("FitArcs",&CArea::FitArcs)
        .def("text", &print_area)
		.def("num_curves", &CArea::num_curves)
		.def("NearestPoint", &CArea::NearestPoint)
		.def("GetBox", &CArea::GetBox)
		.def("Reorder", &CArea::Reorder)
		.def("MakePocketToolpath", &MakePocketToolpath)
		.def("Split", &SplitArea)
		.def("InsideCurves", &InsideCurves)
    ;

	bp::class_<geoff_geometry::Matrix, boost::shared_ptr<geoff_geometry::Matrix> > ("Matrix")
        .def(bp::init<geoff_geometry::Matrix>())
	    .def("__init__", bp::make_constructor(&matrix_constructor))
	    .def("TransformedPoint", &transformed_point)
		.def("Multiply", &geoff_geometry::Matrix::Multiply)
	;

    bp::def("set_units", set_units);
    bp::def("get_units", get_units);
    bp::def("holes_linked", holes_linked);
    bp::def("AreaFromDxf", AreaFromDxf);
    bp::def("TangentialArc", TangentialArc);
}
<commit_msg>I exported the CArea::Thicken function to Python<commit_after>// PythonStuff.cpp
// Copyright 2011, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "PythonStuff.h"

#include "Area.h"
#include "Point.h"
#include "AreaDxf.h"
#include "kurve/geometry.h"

#if _DEBUG
#undef _DEBUG
#include <Python.h>
#define _DEBUG
#else
#include <Python.h>
#endif

#ifdef __GNUG__
#pragma implementation
#endif

#include <boost/progress.hpp>
#include <boost/timer.hpp>
#include <boost/foreach.hpp>
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>

#include "clipper.hpp"
using namespace clipper;

namespace bp = boost::python;

boost::python::list getVertices(const CCurve& curve) {
	boost::python::list vlist;
	BOOST_FOREACH(const CVertex& vertex, curve.m_vertices) {
		vlist.append(vertex);
    }
	return vlist;
}

boost::python::list getCurves(const CArea& area) {
	boost::python::list clist;
	BOOST_FOREACH(const CCurve& curve, area.m_curves) {
		clist.append(curve);
    }
	return clist;
}

boost::python::tuple transformed_point(const geoff_geometry::Matrix &matrix, double x, double y, double z)
{
	geoff_geometry::Point3d p(x,y,z);
	p = p.Transform(matrix);

	return bp::make_tuple(p.x,p.y,p.z);
}

static void print_curve(const CCurve& c)
{
	unsigned int nvertices = c.m_vertices.size();
	printf("number of vertices = %d\n", nvertices);
	int i = 0;
	for(std::list<CVertex>::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++, i++)
	{
		const CVertex& vertex = *It;
		printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::m_units, vertex.m_p.y / CArea::m_units);
		if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::m_units, vertex.m_c.y / CArea::m_units);
		printf("\n");
	}
}

static void print_area(const CArea &a)
{
	for(std::list<CCurve>::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++)
	{
		const CCurve& curve = *It;
		print_curve(curve);
	}
}

static unsigned int num_vertices(const CCurve& curve)
{
	return curve.m_vertices.size();
}

static CVertex FirstVertex(const CCurve& curve)
{
	return curve.m_vertices.front();
}

static CVertex LastVertex(const CCurve& curve)
{
	return curve.m_vertices.back();
}

static void set_units(double units)
{
	CArea::m_units = units;
}

static double get_units()
{
	return CArea::m_units;
}

static bool holes_linked()
{
	return CArea::HolesLinked();
}

static CArea AreaFromDxf(const char* filepath)
{
	CArea area;
	AreaDxfRead dxf(&area, filepath);
	dxf.DoRead();
	return area;
}

static void append_point(CCurve& c, const Point& p)
{
	c.m_vertices.push_back(CVertex(p));
}

static boost::python::tuple nearest_point_to_curve(CCurve& c1, const CCurve& c2)
{
	double dist;
	Point p = c1.NearestPoint(c2, &dist);

	return bp::make_tuple(p, dist);
}

boost::python::list MakePocketToolpath(const CArea& a, double tool_radius, double extra_offset, double stepover, bool from_center, bool use_zig_zag, double zig_angle)
{
	std::list<CCurve> toolpath;

	CAreaPocketParams params(tool_radius, extra_offset, stepover, from_center, use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, zig_angle);
	a.SplitAndMakePocketToolpath(toolpath, params);

	boost::python::list clist;
	BOOST_FOREACH(const CCurve& c, toolpath) {
		clist.append(c);
    }
	return clist;
}

boost::python::list SplitArea(const CArea& a)
{
	std::list<CArea> areas;
	a.Split(areas);

	boost::python::list alist;
	BOOST_FOREACH(const CArea& a, areas) {
		alist.append(a);
    }
	return alist;
}

void dxfArea(CArea& area, const char* str)
{
	area = CArea();
}

boost::python::list getCurveSpans(const CCurve& c)
{
	boost::python::list span_list;
	const Point *prev_p = NULL;

	for(std::list<CVertex>::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); VIt++)
	{
		const CVertex& vertex = *VIt;

		if(prev_p)
		{
			span_list.append(Span(*prev_p, vertex));
		}
		prev_p = &(vertex.m_p);
	}

	return span_list;
}

Span getFirstCurveSpan(const CCurve& c)
{
	if(c.m_vertices.size() < 2)return Span();

	std::list<CVertex>::const_iterator VIt = c.m_vertices.begin();
	const Point &p = (*VIt).m_p;
	VIt++;
	return Span(p, *VIt, true);
}

Span getLastCurveSpan(const CCurve& c)
{
	if(c.m_vertices.size() < 2)return Span();

	std::list<CVertex>::const_reverse_iterator VIt = c.m_vertices.rbegin();
	const CVertex &v = (*VIt);
	VIt++;

	return Span((*VIt).m_p, v, c.m_vertices.size() == 2);
}

bp::tuple TangentialArc(const Point &p0, const Point &p1, const Point &v0)
{
  Point c;
  int dir;
  tangential_arc(p0, p1, v0, c, dir);

  return bp::make_tuple(c, dir);
}

boost::python::list spanIntersect(const Span& span1, const Span& span2) {
	boost::python::list plist;
	std::list<Point> pts;
	span1.Intersect(span2, pts);
	BOOST_FOREACH(const Point& p, pts) {
		plist.append(p);
    }
	return plist;
}

//Matrix(boost::python::list &l){}

boost::shared_ptr<geoff_geometry::Matrix> matrix_constructor(const boost::python::list& lst) {
	double m[16] = {1,0,0,0,0,1,0,0, 0,0,1,0, 0,0,0,1};

  boost::python::ssize_t n = boost::python::len(lst);
  int j = 0;
  for(boost::python::ssize_t i=0;i<n;i++) {
    boost::python::object elem = lst[i];
	m[j] = boost::python::extract<double>(elem.attr("__float__")());
	j++;
	if(j>=16)break;
  }

  return boost::shared_ptr<geoff_geometry::Matrix>( new geoff_geometry::Matrix(m) );
}

boost::python::list InsideCurves(const CArea& a, const CCurve& curve) {
	boost::python::list plist;

	std::list<CCurve> curves_inside;
	a.InsideCurves(curve, curves_inside);
	BOOST_FOREACH(const CCurve& c, curves_inside) {
		plist.append(c);
    }
	return plist;
}

BOOST_PYTHON_MODULE(area) {
	bp::class_<Point>("Point")
        .def(bp::init<double, double>())
        .def(bp::init<Point>())
        .def(bp::other<double>() * bp::self)
        .def(bp::self * bp::other<double>())
        .def(bp::self / bp::other<double>())
        .def(bp::self * bp::other<Point>())
        .def(bp::self - bp::other<Point>())
        .def(bp::self + bp::other<Point>())
        .def(bp::self ^ bp::other<Point>())
        .def(bp::self == bp::other<Point>())
        .def(bp::self != bp::other<Point>())
        .def(-bp::self)
        .def(~bp::self)
        .def("dist", &Point::dist)
        .def("length", &Point::length)
        .def("normalize", &Point::normalize)
		.def("Rotate", static_cast< void (Point::*)(double, double) >(&Point::Rotate))
		.def("Rotate", static_cast< void (Point::*)(double) >(&Point::Rotate))
        .def_readwrite("x", &Point::x)
        .def_readwrite("y", &Point::y)
		.def("Transform", &Point::Transform)
    ;

	bp::class_<CVertex>("Vertex")
        .def(bp::init<CVertex>())
        .def(bp::init<int, Point, Point>())
        .def(bp::init<Point>())
        .def(bp::init<int, Point, Point, int>())
        .def_readwrite("type", &CVertex::m_type)
        .def_readwrite("p", &CVertex::m_p)
        .def_readwrite("c", &CVertex::m_c)
        .def_readwrite("user_data", &CVertex::m_user_data)
    ;

	bp::class_<Span>("Span")
        .def(bp::init<Span>())
        .def(bp::init<Point, CVertex, bool>())
		.def("NearestPoint", static_cast< Point (Span::*)(const Point& p)const >(&Span::NearestPoint))
		.def("NearestPoint", static_cast< Point (Span::*)(const Span& p, double *d)const >(&Span::NearestPoint))
		.def("GetBox", &Span::GetBox)
		.def("IncludedAngle", &Span::IncludedAngle)
		.def("GetArea", &Span::GetArea)
		.def("On", &Span::On)
		.def("MidPerim", &Span::MidPerim)
		.def("MidParam", &Span::MidParam)
		.def("Length", &Span::Length)
		.def("GetVector", &Span::GetVector)
		.def("Intersect", &spanIntersect)
        .def_readwrite("p", &Span::m_p)
		.def_readwrite("v", &Span::m_v)
    ;

	bp::class_<CCurve>("Curve")
        .def(bp::init<CCurve>())
        .def("getVertices", &getVertices)
        .def("append",&CCurve::append)
        .def("append",&append_point)
        .def("text", &print_curve)
		.def("NearestPoint", static_cast< Point (CCurve::*)(const Point& p)const >(&CCurve::NearestPoint))
		.def("NearestPoint", &nearest_point_to_curve)
		.def("Reverse", &CCurve::Reverse)
		.def("getNumVertices", &num_vertices)
		.def("FirstVertex", &FirstVertex)
		.def("LastVertex", &LastVertex)
		.def("GetArea", &CCurve::GetArea)
		.def("IsClockwise", &CCurve::IsClockwise)
		.def("IsClosed", &CCurve::IsClosed)
        .def("ChangeStart",&CCurve::ChangeStart)
        .def("ChangeEnd",&CCurve::ChangeEnd)
        .def("Offset",&CCurve::Offset)
        .def("OffsetForward",&CCurve::OffsetForward)
        .def("GetSpans",&getCurveSpans)
        .def("GetFirstSpan",&getFirstCurveSpan)
        .def("GetLastSpan",&getLastCurveSpan)
        .def("Break",&CCurve::Break)
        .def("Perim",&CCurve::Perim)
        .def("PerimToPoint",&CCurve::PerimToPoint)
        .def("PointToPerim",&CCurve::PointToPerim)
		.def("FitArcs",&CCurve::FitArcs)
        .def("UnFitArcs",&CCurve::UnFitArcs)
    ;

	bp::class_<CBox2D>("Box")
        .def(bp::init<CBox2D>())
		.def("MinX", &CBox2D::MinX)
		.def("MaxX", &CBox2D::MaxX)
		.def("MinY", &CBox2D::MinY)
		.def("MaxY", &CBox2D::MaxY)
    ;

	bp::class_<CArea>("Area")
        .def(bp::init<CArea>())
        .def("getCurves", &getCurves)
        .def("append",&CArea::append)
        .def("Subtract",&CArea::Subtract)
        .def("Intersect",&CArea::Intersect)
        .def("Union",&CArea::Union)
        .def("Offset",&CArea::Offset)
        .def("FitArcs",&CArea::FitArcs)
        .def("text", &print_area)
		.def("num_curves", &CArea::num_curves)
		.def("NearestPoint", &CArea::NearestPoint)
		.def("GetBox", &CArea::GetBox)
		.def("Reorder", &CArea::Reorder)
		.def("MakePocketToolpath", &MakePocketToolpath)
		.def("Split", &SplitArea)
		.def("InsideCurves", &InsideCurves)
		.def("Thicken"), &CArea::Thicken)
    ;

	bp::class_<geoff_geometry::Matrix, boost::shared_ptr<geoff_geometry::Matrix> > ("Matrix")
        .def(bp::init<geoff_geometry::Matrix>())
	    .def("__init__", bp::make_constructor(&matrix_constructor))
	    .def("TransformedPoint", &transformed_point)
		.def("Multiply", &geoff_geometry::Matrix::Multiply)
	;

    bp::def("set_units", set_units);
    bp::def("get_units", get_units);
    bp::def("holes_linked", holes_linked);
    bp::def("AreaFromDxf", AreaFromDxf);
    bp::def("TangentialArc", TangentialArc);
}
<|endoftext|>


<commit_before>#include "dynet/nodes.h"
#include "dynet/dynet.h"
#include "dynet/training.h"
#include "dynet/timing.h"
#include "dynet/rnn.h"
#include "dynet/gru.h"
#include "dynet/lstm.h"
#include "dynet/dict.h"
#include "dynet/expr.h"
#include "dynet/cfsm-builder.h"
#include "dynet/hsm-builder.h"
#include "dynet/globals.h"
#include "dynet/io.h"
#include "../utils/getpid.h"
#include "../utils/cl-args.h"

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;
using namespace dynet;

unsigned LAYERS = 0;
unsigned INPUT_DIM = 0;
unsigned HIDDEN_DIM = 0;
unsigned VOCAB_SIZE = 0;
float DROPOUT = 0;
bool SAMPLE = false;
SoftmaxBuilder* cfsm = nullptr;

dynet::Dict d;
int kSOS;
int kEOS;

volatile bool INTERRUPTED = false;

template <class Builder>
struct RNNLanguageModel {
  LookupParameter p_c;
  Parameter p_R;
  Parameter p_bias;
  Builder builder;
  explicit RNNLanguageModel(ParameterCollection& model) : builder(LAYERS, INPUT_DIM, HIDDEN_DIM, model) {
    p_c = model.add_lookup_parameters(VOCAB_SIZE, {INPUT_DIM});
    p_R = model.add_parameters({VOCAB_SIZE, HIDDEN_DIM});
    p_bias = model.add_parameters({VOCAB_SIZE});
  }

  // return Expression of total loss
  Expression BuildLMGraph(const vector<int>& sent, ComputationGraph& cg, bool apply_dropout) {
    const unsigned slen = sent.size();
    if (apply_dropout) {
      builder.set_dropout(DROPOUT);
    } else {
      builder.disable_dropout();
    }
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();
    if (cfsm) cfsm->new_graph(cg);
    Expression R = parameter(cg, p_R); // hidden -> word rep parameter
    Expression bias = parameter(cg, p_bias);  // word bias
    vector<Expression> errs(slen + 1);
    Expression h_t = builder.add_input(lookup(cg, p_c, kSOS)); // read <s>
    for (unsigned t = 0; t < slen; ++t) { // h_t = RNN(x_0,...,x_t)
      if (cfsm) { // class-factored softmax
        errs[t] = cfsm->neg_log_softmax(h_t, sent[t]);
      } else { // regular softmax
        Expression u_t = affine_transform({bias, R, h_t});
        errs[t] = pickneglogsoftmax(u_t, sent[t]);
      }
      Expression x_t = lookup(cg, p_c, sent[t]);
      h_t = builder.add_input(x_t);
    }
    // it reamins to deal predict </s>
    if (cfsm) {
      errs.back() = cfsm->neg_log_softmax(h_t, kEOS);
    } else {
      Expression u_last = affine_transform({bias, R, h_t});
      errs.back() = pickneglogsoftmax(u_last, kEOS); // predict </s>
    }
    return sum(errs);
  }

  void RandomSample(int max_len = 200) {
    ComputationGraph cg;
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();
    if (cfsm) cfsm->new_graph(cg);
    Expression R = parameter(cg, p_R); // hidden -> word rep parameter
    Expression bias = parameter(cg, p_bias);  // word bias
    Expression h_t = builder.add_input(lookup(cg, p_c, kSOS)); // read <s>
    int cur = kSOS;
    int len = 0;
    while (len < max_len) {
      if (cfsm) { // class-factored softmax
        cur = cfsm->sample(h_t);
      } else { // regular softmax
        Expression u_t = affine_transform({bias, R, h_t});
        Expression dist_expr = softmax(u_t);
        auto dist = as_vector(cg.incremental_forward(dist_expr));
        double p = rand01();
        cur = 0;
        for (; cur < dist.size(); ++cur) {
          p -= dist[cur];
          if (p < 0.0) { break; }
        }
        if (cur == dist.size()) cur = kEOS;
      }
      if (cur == kEOS) break;
      ++len;
      cerr << (len == 1 ? "" : " ") << d.convert(cur);
      Expression x_t = lookup(cg, p_c, cur);
      h_t = builder.add_input(x_t);
    }
    cerr << endl;
  }
};

void inline read_fields(string line, vector<string>& fields, string delimiter = "|||") {
  string field;
  int start = 0, end = 0, delim_size = delimiter.size();
  while (true) {
    end = line.find(delimiter, start);
    fields.push_back(line.substr(start, end - start));
    if (end == std::string::npos) break;
    start = end + delim_size;
  }
}

int main(int argc, char** argv) {
  cerr << "COMMAND LINE:";
  for (unsigned i = 0; i < static_cast<unsigned>(argc); ++i) cerr << ' ' << argv[i];
  cerr << endl;

  // Fetch dynet params ----------------------------------------------------------------------------
  auto dyparams = dynet::extract_dynet_params(argc, argv);
  dynet::initialize(dyparams);

  // Fetch program specific parameters (see ../utils/cl-args.h) ------------------------------------
  Params params;

  get_args(argc, argv, params, TRAIN);

  kSOS = d.convert("<s>");
  kEOS = d.convert("</s>");
  LAYERS = params.LAYERS;
  INPUT_DIM = params.INPUT_DIM;
  HIDDEN_DIM = params.HIDDEN_DIM;
  SAMPLE = params.sample;
  if (params.dropout_rate)
    DROPOUT = params.dropout_rate;
  Model model;
  if (params.clusters_file != "")
    cfsm = new ClassFactoredSoftmaxBuilder(HIDDEN_DIM, params.clusters_file, d, model);
  else if (params.paths_file != "")
    cfsm = new HierarchicalSoftmaxBuilder(HIDDEN_DIM, params.paths_file, d, model);
  float eta_decay_rate = params.eta_decay_rate;
  unsigned eta_decay_onset_epoch = params.eta_decay_onset_epoch;
  vector<vector<int>> training, dev, test;
  string line;
  int tlc = 0;
  int ttoks = 0;
  {
    string trainf = params.train_file;
    cerr << "Reading training data from " << trainf << " ...\n";
    ifstream in(trainf);
    assert(in);
    while (getline(in, line)) {
      ++tlc;
      training.push_back(read_sentence(line, d));
      ttoks += training.back().size();
      if (training.back().front() == kSOS || training.back().back() == kEOS) {
        cerr << "Training sentence in " << argv[1] << ":" << tlc << " started with <s> or ended with </s>\n";
        abort();
      }
    }
    cerr << tlc << " lines, " << ttoks << " tokens, " << d.size() << " types\n";
  }
  d.freeze(); // no new word types allowed
  d.set_unk("<unk>");
  VOCAB_SIZE = d.size();
  if (!cfsm)
    cfsm = new StandardSoftmaxBuilder(HIDDEN_DIM, VOCAB_SIZE, model);

  if (params.test_file != "") {
    string testf = params.test_file;
    cerr << "Reading test data from " << testf << " ...\n";
    ifstream in(testf);
    assert(in);
    while (getline(in, line)) {
      test.push_back(read_sentence(line, d));
      if (test.back().front() == kSOS || test.back().back() == kEOS) {
        cerr << "Test sentence in " << argv[2] << ":" << tlc << " started with <s> or ended with </s>\n";
        abort();
      }
    }
  }

  Trainer* sgd = new SimpleSGDTrainer(model);
  sgd->eta0 = sgd->eta = params.eta0;
  RNNLanguageModel<LSTMBuilder> lm(model);

  bool has_model_to_load = params.model_file != "";
  if (has_model_to_load) {
    string fname = params.model_file;
    cerr << "Reading parameters from " << fname << "...\n";
    TextFileSaver saver(fname);
    saver.save(model);
  }

  bool TRAIN = (params.train_file != "");

  if (TRAIN) {
    int dlc = 0;
    int dtoks = 0;
    if (params.dev_file == "") {
      cerr << "You must specify a development set (--dev file.txt) with --train" << endl;
      abort();
    } else {
      string devf = params.dev_file;
      cerr << "Reading dev data from " << devf << " ...\n";
      ifstream in(devf);
      assert(in);
      while (getline(in, line)) {
        ++dlc;
        dev.push_back(read_sentence(line, d));
        dtoks += dev.back().size();
        if (dev.back().front() == kSOS || dev.back().back() == kEOS) {
          cerr << "Dev sentence in " << argv[2] << ":" << tlc << " started with <s> or ended with </s>\n";
          abort();
        }
      }
      cerr << dlc << " lines, " << dtoks << " tokens\n";
    }
    ostringstream os;
    os << "lm"
       << '_' << DROPOUT
       << '_' << LAYERS
       << '_' << INPUT_DIM
       << '_' << HIDDEN_DIM
       << "-pid" << getpid() << ".params";
    const string fname = os.str();
    cerr << "Parameters will be written to: " << fname << endl;
    double best = 9e+99;
    unsigned report_every_i = 100;
    unsigned dev_every_i_reports = 25;
    unsigned si = training.size();
    if (report_every_i > si) report_every_i = si;
    vector<unsigned> order(training.size());
    for (unsigned i = 0; i < order.size(); ++i) order[i] = i;
    bool first = true;
    int report = 0;
    double lines = 0;
    int completed_epoch = -1;
    while (!INTERRUPTED) {
      if (SAMPLE) lm.RandomSample();
      Timer iteration("completed in");
      double loss = 0;
      unsigned chars = 0;
      for (unsigned i = 0; i < report_every_i; ++i) {
        if (si == training.size()) {
          si = 0;
          if (first) { first = false; } else { sgd->update_epoch(); }
          cerr << "**SHUFFLE\n";
          completed_epoch++;
          if (eta_decay_onset_epoch && completed_epoch >= (int)eta_decay_onset_epoch)
            sgd->eta *= eta_decay_rate;
          shuffle(order.begin(), order.end(), *rndeng);
        }

        // build graph for this instance
        ComputationGraph cg;
        auto& sent = training[order[si]];
        chars += sent.size();
        ++si;
        Expression loss_expr = lm.BuildLMGraph(sent, cg, DROPOUT > 0.f);
        loss += as_scalar(cg.forward(loss_expr));
        cg.backward(loss_expr);
        sgd->update();
        ++lines;
      }
      report++;
      cerr << '#' << report << " [epoch=" << (lines / training.size()) << " eta=" << sgd->eta << "] E = " << (loss / chars) << " ppl=" << exp(loss / chars) << ' ';

      // show score on dev data?
      if (report % dev_every_i_reports == 0) {
        double dloss = 0;
        int dchars = 0;
        for (auto& sent : dev) {
          ComputationGraph cg;
          Expression loss_expr = lm.BuildLMGraph(sent, cg, false);
          dloss += as_scalar(cg.forward(loss_expr));
          dchars += sent.size();
        }
        if (dloss < best) {
          best = dloss;
          TextFileSaver saver(fname);
          saver.save(model);
        }
        cerr << "\n***DEV [epoch=" << (lines / training.size()) << "] E = " << (dloss / dchars) << " ppl=" << exp(dloss / dchars) << ' ';
      }
    }
  }  // train?
  if (params.test_file != "") {
    cerr << "Evaluating test data...\n";
    double tloss = 0;
    int tchars = 0;
    for (auto& sent : test) {
      ComputationGraph cg;
      Expression loss_expr = lm.BuildLMGraph(sent, cg, false);
      tloss += as_scalar(cg.forward(loss_expr));
      tchars += sent.size();
    }
    cerr << "TEST                -LLH = " << tloss << endl;
    cerr << "TEST CROSS ENTOPY (NATS) = " << (tloss / tchars) << endl;
    cerr << "TEST                 PPL = " << exp(tloss / tchars) << endl;
  }

  // N-best scoring
  if (params.nbest_file != "") {
    // cdec: index ||| hypothesis ||| feature=val ... ||| ...
    // Moses: index ||| hypothesis ||| feature= val(s) ... ||| ...
    const int HYP_FIELD = 1;
    const int FEAT_FIELD = 2;
    const string FEAT_NAME = "RNNLM";
    // Input
    string nbestf = params.nbest_file;
    cerr << "Scoring N-best list " << nbestf << " ..." << endl;
    shared_ptr<istream> in;
    if (nbestf == "-") {
      in.reset(&cin, [](...) {});
    } else {
      in.reset(new ifstream(nbestf));
    }
    // Match spacing of input file
    string sep = "=";
    bool sep_detected = false;
    // Input lines
    while (getline(*in, line)) {
      vector<string> fields;
      read_fields(line, fields);
      // Check sep if needed
      if (!sep_detected) {
        sep_detected = true;
        int i = fields[FEAT_FIELD].find("=");
        if (fields[FEAT_FIELD].substr(i + 1, 1) == " ") {
          sep = "= ";
        }
      }
      // Score hypothesis
      ComputationGraph cg;
      Expression loss_expr = lm.BuildLMGraph(read_sentence(fields[HYP_FIELD], d), cg, false);
      double loss = as_scalar(cg.forward(loss_expr));
      // Add score
      ostringstream os;
      os << fields[FEAT_FIELD] << " " << FEAT_NAME << sep << loss;
      fields[FEAT_FIELD] = os.str();
      // Write augmented line
      for (unsigned f = 0; f < fields.size(); ++f) {
        if (f > 0)
          cout << " ||| ";
        cout << fields[f];
      }
      cout << endl;
    }
  }

  delete sgd;
}
<commit_msg>Fixed compile error in example<commit_after>#include "dynet/nodes.h"
#include "dynet/dynet.h"
#include "dynet/training.h"
#include "dynet/timing.h"
#include "dynet/rnn.h"
#include "dynet/gru.h"
#include "dynet/lstm.h"
#include "dynet/dict.h"
#include "dynet/expr.h"
#include "dynet/cfsm-builder.h"
#include "dynet/hsm-builder.h"
#include "dynet/globals.h"
#include "dynet/io.h"
#include "../utils/getpid.h"
#include "../utils/cl-args.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <memory>

using namespace std;
using namespace dynet;

unsigned LAYERS = 0;
unsigned INPUT_DIM = 0;
unsigned HIDDEN_DIM = 0;
unsigned VOCAB_SIZE = 0;
float DROPOUT = 0;
bool SAMPLE = false;
SoftmaxBuilder* cfsm = nullptr;

dynet::Dict d;
int kSOS;
int kEOS;

volatile bool INTERRUPTED = false;

template <class Builder>
struct RNNLanguageModel {
  LookupParameter p_c;
  Parameter p_R;
  Parameter p_bias;
  Builder builder;
  explicit RNNLanguageModel(ParameterCollection& model) : builder(LAYERS, INPUT_DIM, HIDDEN_DIM, model) {
    p_c = model.add_lookup_parameters(VOCAB_SIZE, {INPUT_DIM});
    p_R = model.add_parameters({VOCAB_SIZE, HIDDEN_DIM});
    p_bias = model.add_parameters({VOCAB_SIZE});
  }

  // return Expression of total loss
  Expression BuildLMGraph(const vector<int>& sent, ComputationGraph& cg, bool apply_dropout) {
    const unsigned slen = sent.size();
    if (apply_dropout) {
      builder.set_dropout(DROPOUT);
    } else {
      builder.disable_dropout();
    }
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();
    if (cfsm) cfsm->new_graph(cg);
    Expression R = parameter(cg, p_R); // hidden -> word rep parameter
    Expression bias = parameter(cg, p_bias);  // word bias
    vector<Expression> errs(slen + 1);
    Expression h_t = builder.add_input(lookup(cg, p_c, kSOS)); // read <s>
    for (unsigned t = 0; t < slen; ++t) { // h_t = RNN(x_0,...,x_t)
      if (cfsm) { // class-factored softmax
        errs[t] = cfsm->neg_log_softmax(h_t, sent[t]);
      } else { // regular softmax
        Expression u_t = affine_transform({bias, R, h_t});
        errs[t] = pickneglogsoftmax(u_t, sent[t]);
      }
      Expression x_t = lookup(cg, p_c, sent[t]);
      h_t = builder.add_input(x_t);
    }
    // it reamins to deal predict </s>
    if (cfsm) {
      errs.back() = cfsm->neg_log_softmax(h_t, kEOS);
    } else {
      Expression u_last = affine_transform({bias, R, h_t});
      errs.back() = pickneglogsoftmax(u_last, kEOS); // predict </s>
    }
    return sum(errs);
  }

  void RandomSample(int max_len = 200) {
    ComputationGraph cg;
    builder.new_graph(cg);  // reset RNN builder for new graph
    builder.start_new_sequence();
    if (cfsm) cfsm->new_graph(cg);
    Expression R = parameter(cg, p_R); // hidden -> word rep parameter
    Expression bias = parameter(cg, p_bias);  // word bias
    Expression h_t = builder.add_input(lookup(cg, p_c, kSOS)); // read <s>
    int cur = kSOS;
    int len = 0;
    while (len < max_len) {
      if (cfsm) { // class-factored softmax
        cur = cfsm->sample(h_t);
      } else { // regular softmax
        Expression u_t = affine_transform({bias, R, h_t});
        Expression dist_expr = softmax(u_t);
        auto dist = as_vector(cg.incremental_forward(dist_expr));
        double p = rand01();
        cur = 0;
        for (; cur < dist.size(); ++cur) {
          p -= dist[cur];
          if (p < 0.0) { break; }
        }
        if (cur == dist.size()) cur = kEOS;
      }
      if (cur == kEOS) break;
      ++len;
      cerr << (len == 1 ? "" : " ") << d.convert(cur);
      Expression x_t = lookup(cg, p_c, cur);
      h_t = builder.add_input(x_t);
    }
    cerr << endl;
  }
};

void inline read_fields(string line, vector<string>& fields, string delimiter = "|||") {
  string field;
  int start = 0, end = 0, delim_size = delimiter.size();
  while (true) {
    end = line.find(delimiter, start);
    fields.push_back(line.substr(start, end - start));
    if (end == (int)std::string::npos) break;
    start = end + delim_size;
  }
}

int main(int argc, char** argv) {
  cerr << "COMMAND LINE:";
  for (unsigned i = 0; i < static_cast<unsigned>(argc); ++i) cerr << ' ' << argv[i];
  cerr << endl;

  // Fetch dynet params ----------------------------------------------------------------------------
  auto dyparams = dynet::extract_dynet_params(argc, argv);
  dynet::initialize(dyparams);

  // Fetch program specific parameters (see ../utils/cl-args.h) ------------------------------------
  Params params;

  get_args(argc, argv, params, TRAIN);

  kSOS = d.convert("<s>");
  kEOS = d.convert("</s>");
  LAYERS = params.LAYERS;
  INPUT_DIM = params.INPUT_DIM;
  HIDDEN_DIM = params.HIDDEN_DIM;
  SAMPLE = params.sample;
  if (params.dropout_rate)
    DROPOUT = params.dropout_rate;
  Model model;
  if (params.clusters_file != "")
    cfsm = new ClassFactoredSoftmaxBuilder(HIDDEN_DIM, params.clusters_file, d, model);
  else if (params.paths_file != "")
    cfsm = new HierarchicalSoftmaxBuilder(HIDDEN_DIM, params.paths_file, d, model);
  float eta_decay_rate = params.eta_decay_rate;
  unsigned eta_decay_onset_epoch = params.eta_decay_onset_epoch;
  vector<vector<int>> training, dev, test;
  string line;
  int tlc = 0;
  int ttoks = 0;
  {
    string trainf = params.train_file;
    cerr << "Reading training data from " << trainf << " ...\n";
    ifstream in(trainf);
    assert(in);
    while (getline(in, line)) {
      ++tlc;
      training.push_back(read_sentence(line, d));
      ttoks += training.back().size();
      if (training.back().front() == kSOS || training.back().back() == kEOS) {
        cerr << "Training sentence in " << argv[1] << ":" << tlc << " started with <s> or ended with </s>\n";
        abort();
      }
    }
    cerr << tlc << " lines, " << ttoks << " tokens, " << d.size() << " types\n";
  }
  d.freeze(); // no new word types allowed
  d.set_unk("<unk>");
  VOCAB_SIZE = d.size();
  if (!cfsm)
    cfsm = new StandardSoftmaxBuilder(HIDDEN_DIM, VOCAB_SIZE, model);

  if (params.test_file != "") {
    string testf = params.test_file;
    cerr << "Reading test data from " << testf << " ...\n";
    ifstream in(testf);
    assert(in);
    while (getline(in, line)) {
      test.push_back(read_sentence(line, d));
      if (test.back().front() == kSOS || test.back().back() == kEOS) {
        cerr << "Test sentence in " << argv[2] << ":" << tlc << " started with <s> or ended with </s>\n";
        abort();
      }
    }
  }

  Trainer* sgd = new SimpleSGDTrainer(model);
  sgd->eta0 = sgd->eta = params.eta0;
  RNNLanguageModel<LSTMBuilder> lm(model);

  bool has_model_to_load = params.model_file != "";
  if (has_model_to_load) {
    string fname = params.model_file;
    cerr << "Reading parameters from " << fname << "...\n";
    TextFileSaver saver(fname);
    saver.save(model);
  }

  bool TRAIN = (params.train_file != "");

  if (TRAIN) {
    int dlc = 0;
    int dtoks = 0;
    if (params.dev_file == "") {
      cerr << "You must specify a development set (--dev file.txt) with --train" << endl;
      abort();
    } else {
      string devf = params.dev_file;
      cerr << "Reading dev data from " << devf << " ...\n";
      ifstream in(devf);
      assert(in);
      while (getline(in, line)) {
        ++dlc;
        dev.push_back(read_sentence(line, d));
        dtoks += dev.back().size();
        if (dev.back().front() == kSOS || dev.back().back() == kEOS) {
          cerr << "Dev sentence in " << argv[2] << ":" << tlc << " started with <s> or ended with </s>\n";
          abort();
        }
      }
      cerr << dlc << " lines, " << dtoks << " tokens\n";
    }
    ostringstream os;
    os << "lm"
       << '_' << DROPOUT
       << '_' << LAYERS
       << '_' << INPUT_DIM
       << '_' << HIDDEN_DIM
       << "-pid" << getpid() << ".params";
    const string fname = os.str();
    cerr << "Parameters will be written to: " << fname << endl;
    double best = 9e+99;
    unsigned report_every_i = 100;
    unsigned dev_every_i_reports = 25;
    unsigned si = training.size();
    if (report_every_i > si) report_every_i = si;
    vector<unsigned> order(training.size());
    for (unsigned i = 0; i < order.size(); ++i) order[i] = i;
    bool first = true;
    int report = 0;
    double lines = 0;
    int completed_epoch = -1;
    while (!INTERRUPTED) {
      if (SAMPLE) lm.RandomSample();
      Timer iteration("completed in");
      double loss = 0;
      unsigned chars = 0;
      for (unsigned i = 0; i < report_every_i; ++i) {
        if (si == training.size()) {
          si = 0;
          if (first) { first = false; } else { sgd->update_epoch(); }
          cerr << "**SHUFFLE\n";
          completed_epoch++;
          if (eta_decay_onset_epoch && completed_epoch >= (int)eta_decay_onset_epoch)
            sgd->eta *= eta_decay_rate;
          shuffle(order.begin(), order.end(), *rndeng);
        }

        // build graph for this instance
        ComputationGraph cg;
        auto& sent = training[order[si]];
        chars += sent.size();
        ++si;
        Expression loss_expr = lm.BuildLMGraph(sent, cg, DROPOUT > 0.f);
        loss += as_scalar(cg.forward(loss_expr));
        cg.backward(loss_expr);
        sgd->update();
        ++lines;
      }
      report++;
      cerr << '#' << report << " [epoch=" << (lines / training.size()) << " eta=" << sgd->eta << "] E = " << (loss / chars) << " ppl=" << exp(loss / chars) << ' ';

      // show score on dev data?
      if (report % dev_every_i_reports == 0) {
        double dloss = 0;
        int dchars = 0;
        for (auto& sent : dev) {
          ComputationGraph cg;
          Expression loss_expr = lm.BuildLMGraph(sent, cg, false);
          dloss += as_scalar(cg.forward(loss_expr));
          dchars += sent.size();
        }
        if (dloss < best) {
          best = dloss;
          TextFileSaver saver(fname);
          saver.save(model);
        }
        cerr << "\n***DEV [epoch=" << (lines / training.size()) << "] E = " << (dloss / dchars) << " ppl=" << exp(dloss / dchars) << ' ';
      }
    }
  }  // train?
  if (params.test_file != "") {
    cerr << "Evaluating test data...\n";
    double tloss = 0;
    int tchars = 0;
    for (auto& sent : test) {
      ComputationGraph cg;
      Expression loss_expr = lm.BuildLMGraph(sent, cg, false);
      tloss += as_scalar(cg.forward(loss_expr));
      tchars += sent.size();
    }
    cerr << "TEST                -LLH = " << tloss << endl;
    cerr << "TEST CROSS ENTOPY (NATS) = " << (tloss / tchars) << endl;
    cerr << "TEST                 PPL = " << exp(tloss / tchars) << endl;
  }

  // N-best scoring
  if (params.nbest_file != "") {
    // cdec: index ||| hypothesis ||| feature=val ... ||| ...
    // Moses: index ||| hypothesis ||| feature= val(s) ... ||| ...
    const int HYP_FIELD = 1;
    const int FEAT_FIELD = 2;
    const string FEAT_NAME = "RNNLM";
    // Input
    string nbestf = params.nbest_file;
    cerr << "Scoring N-best list " << nbestf << " ..." << endl;
    shared_ptr<istream> in;
    if (nbestf == "-") {
      in.reset(&cin, [](...) {});
    } else {
      in.reset(new ifstream(nbestf));
    }
    // Match spacing of input file
    string sep = "=";
    bool sep_detected = false;
    // Input lines
    while (getline(*in, line)) {
      vector<string> fields;
      read_fields(line, fields);
      // Check sep if needed
      if (!sep_detected) {
        sep_detected = true;
        int i = fields[FEAT_FIELD].find("=");
        if (fields[FEAT_FIELD].substr(i + 1, 1) == " ") {
          sep = "= ";
        }
      }
      // Score hypothesis
      ComputationGraph cg;
      Expression loss_expr = lm.BuildLMGraph(read_sentence(fields[HYP_FIELD], d), cg, false);
      double loss = as_scalar(cg.forward(loss_expr));
      // Add score
      ostringstream os;
      os << fields[FEAT_FIELD] << " " << FEAT_NAME << sep << loss;
      fields[FEAT_FIELD] = os.str();
      // Write augmented line
      for (unsigned f = 0; f < fields.size(); ++f) {
        if (f > 0)
          cout << " ||| ";
        cout << fields[f];
      }
      cout << endl;
    }
  }

  delete sgd;
}
<|endoftext|>