<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020  The Symbiflow Authors
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "clocks.h"
#include "propagation.h"
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"

USING_YOSYS_NAMESPACE

PRIVATE_NAMESPACE_BEGIN

struct ReadSdcCmd : public Frontend {
    ReadSdcCmd() : Frontend("sdc", "Read SDC file") {}

    void help() override {
	//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
	log("\n");
	log("    read_sdc <filename>\n");
	log("\n");
	log("Read SDC file.\n");
	log("\n");
    }

    void execute(std::istream*& f, std::string filename,
                 std::vector<std::string> args, RTLIL::Design*) override {
	if (args.size() < 2) {
	    log_cmd_error("Missing script file.\n");
	}
	size_t argidx = 1;
	extra_args(f, filename, args, argidx);
	std::string content{std::istreambuf_iterator<char>(*f),
	                    std::istreambuf_iterator<char>()};
	log("%s\n", content.c_str());
	Tcl_Interp* interp = yosys_get_tcl_interp();
	if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) {
	    log_cmd_error("TCL interpreter returned an error: %s\n",
	                  Tcl_GetStringResult(interp));
	}
    }
};

struct CreateClockCmd : public Pass {
    CreateClockCmd(Clocks& clocks)
        : Pass("create_clock", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    create_clock [ -name clock_name ] -period period_value "
	    "[-waveform <edge_list>] <target>\n");
	log("Define a clock.\n");
	log("If name is not specified then the name of the first target is "
	    "selected as the clock's name.\n");
	log("Period is expressed in nanoseconds.\n");
	log("The waveform option specifies the duty cycle (the rising a "
	    "falling edges) of the clock.\n");
	log("It is specified as a list of two elements/time values: the first "
	    "rising edge and the next falling edge.\n");
	log("\n");
    }

    void execute(std::vector<std::string> args,
                 RTLIL::Design* design) override {
	size_t argidx;
	std::string name;
	float rising_edge(0);
	float falling_edge(0);
	float period(0);
	if (args.size() < 4) {
	    log_cmd_error("Incorrect number of arguments\n");
	}
	for (argidx = 1; argidx < args.size(); argidx++) {
	    std::string arg = args[argidx];
	    if (arg == "-name" && argidx + 1 < args.size()) {
		name = args[++argidx];
		continue;
	    }
	    if (arg == "-period" && argidx + 1 < args.size()) {
		period = std::stof(args[++argidx]);
		continue;
	    }
	    if (arg == "-waveform" && argidx + 2 < args.size()) {
		rising_edge = std::stof(args[++argidx]);
		falling_edge = std::stof(args[++argidx]);
		continue;
	    }
	    break;
	}
	if (period <= 0) {
	    log_cmd_error("Incorrect period value\n");
	}
	// Add "w:" prefix to selection arguments to enforce wire object
	// selection
	AddWirePrefix(args, argidx);
	extra_args(args, argidx, design);
	// If clock name is not specified then take the name of the first target
	std::vector<RTLIL::Wire*> selected_wires;
	for (auto module : design->modules()) {
	    if (!design->selected(module)) {
		continue;
	    }
	    for (auto wire : module->wires()) {
		if (design->selected(module, wire)) {
		    log("Selected wire %s\n", wire->name.c_str());
		    selected_wires.push_back(wire);
		}
	    }
	}
	if (selected_wires.size() == 0) {
	    log_cmd_error("Target selection is empty\n");
	}
	if (name.empty()) {
	    name = selected_wires.at(0)->name.str();
	}
	clocks_.AddClockWires(name, selected_wires, period, rising_edge,
	                 falling_edge);
	log("Created clock %s with period %f, waveform %f,%f\n", name.c_str(),
	    period, rising_edge, falling_edge);
    }

    void AddWirePrefix(std::vector<std::string>& args, size_t argidx) {
	auto selection_begin = args.begin() + argidx;
	std::transform(selection_begin, args.end(), selection_begin,
	               [](std::string& w) { return "w:" + w; });
    }

    Clocks& clocks_;
};

struct GetClocksCmd : public Pass {
    GetClocksCmd(Clocks& clocks)
        : Pass("get_clocks", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    get_clocks\n");
	log("\n");
	log("Returns all clocks in the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 __attribute__((unused)) RTLIL::Design* design) override {
	std::vector<std::string> clock_names(clocks_.GetClockNames());
	if (clock_names.size() == 0) {
	    log_warning("No clocks found in design\n");
	}
	Tcl_Interp *interp = yosys_get_tcl_interp();
	Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL);
	for (auto name : clock_names) {
	    Tcl_Obj* name_obj = Tcl_NewStringObj(name.c_str(), name.size());
	    Tcl_ListObjAppendElement(interp, tcl_list, name_obj);
	}
	Tcl_SetObjResult(interp, tcl_list);
    }

    Clocks& clocks_;
};

struct PropagateClocksCmd : public Pass {
    PropagateClocksCmd(Clocks& clocks)
        : Pass("propagate_clocks", "Propagate clock information"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    propagate_clocks\n");
	log("\n");
	log("Propagate clock information throughout the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 RTLIL::Design* design) override {

	if (!design->top_module()) {
	    log_cmd_error("No top module selected\n");
	}
	NaturalPropagation natural_propagation(design, this);
	natural_propagation.Run(clocks_);
	/* BufferPropagation buffer(design); */
	/* buffer.RunPass(clocks_); */
    }

    Clocks& clocks_;
};

class SdcPlugin {
   public:
    SdcPlugin()
        : create_clock_cmd_(clocks_),
          get_clocks_cmd_(clocks_),
          propagate_clocks_cmd_(clocks_) {
	log("Loaded SDC plugin\n");
    }

    ReadSdcCmd read_sdc_cmd_;
    CreateClockCmd create_clock_cmd_;
    GetClocksCmd get_clocks_cmd_;
    PropagateClocksCmd propagate_clocks_cmd_;

   private:
    Clocks clocks_;
} SdcPlugin;

PRIVATE_NAMESPACE_END
<commit_msg>SDC: Run passes in common loop<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020  The Symbiflow Authors
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "clocks.h"
#include "propagation.h"
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"

USING_YOSYS_NAMESPACE

PRIVATE_NAMESPACE_BEGIN

struct ReadSdcCmd : public Frontend {
    ReadSdcCmd() : Frontend("sdc", "Read SDC file") {}

    void help() override {
	//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
	log("\n");
	log("    read_sdc <filename>\n");
	log("\n");
	log("Read SDC file.\n");
	log("\n");
    }

    void execute(std::istream*& f, std::string filename,
                 std::vector<std::string> args, RTLIL::Design*) override {
	if (args.size() < 2) {
	    log_cmd_error("Missing script file.\n");
	}
	size_t argidx = 1;
	extra_args(f, filename, args, argidx);
	std::string content{std::istreambuf_iterator<char>(*f),
	                    std::istreambuf_iterator<char>()};
	log("%s\n", content.c_str());
	Tcl_Interp* interp = yosys_get_tcl_interp();
	if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) {
	    log_cmd_error("TCL interpreter returned an error: %s\n",
	                  Tcl_GetStringResult(interp));
	}
    }
};

struct CreateClockCmd : public Pass {
    CreateClockCmd(Clocks& clocks)
        : Pass("create_clock", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    create_clock [ -name clock_name ] -period period_value "
	    "[-waveform <edge_list>] <target>\n");
	log("Define a clock.\n");
	log("If name is not specified then the name of the first target is "
	    "selected as the clock's name.\n");
	log("Period is expressed in nanoseconds.\n");
	log("The waveform option specifies the duty cycle (the rising a "
	    "falling edges) of the clock.\n");
	log("It is specified as a list of two elements/time values: the first "
	    "rising edge and the next falling edge.\n");
	log("\n");
    }

    void execute(std::vector<std::string> args,
                 RTLIL::Design* design) override {
	size_t argidx;
	std::string name;
	float rising_edge(0);
	float falling_edge(0);
	float period(0);
	if (args.size() < 4) {
	    log_cmd_error("Incorrect number of arguments\n");
	}
	for (argidx = 1; argidx < args.size(); argidx++) {
	    std::string arg = args[argidx];
	    if (arg == "-name" && argidx + 1 < args.size()) {
		name = args[++argidx];
		continue;
	    }
	    if (arg == "-period" && argidx + 1 < args.size()) {
		period = std::stof(args[++argidx]);
		continue;
	    }
	    if (arg == "-waveform" && argidx + 2 < args.size()) {
		rising_edge = std::stof(args[++argidx]);
		falling_edge = std::stof(args[++argidx]);
		continue;
	    }
	    break;
	}
	if (period <= 0) {
	    log_cmd_error("Incorrect period value\n");
	}
	// Add "w:" prefix to selection arguments to enforce wire object
	// selection
	AddWirePrefix(args, argidx);
	extra_args(args, argidx, design);
	// If clock name is not specified then take the name of the first target
	std::vector<RTLIL::Wire*> selected_wires;
	for (auto module : design->modules()) {
	    if (!design->selected(module)) {
		continue;
	    }
	    for (auto wire : module->wires()) {
		if (design->selected(module, wire)) {
		    log("Selected wire %s\n", wire->name.c_str());
		    selected_wires.push_back(wire);
		}
	    }
	}
	if (selected_wires.size() == 0) {
	    log_cmd_error("Target selection is empty\n");
	}
	if (name.empty()) {
	    name = selected_wires.at(0)->name.str();
	}
	clocks_.AddClockWires(name, selected_wires, period, rising_edge,
	                 falling_edge);
	log("Created clock %s with period %f, waveform %f,%f\n", name.c_str(),
	    period, rising_edge, falling_edge);
    }

    void AddWirePrefix(std::vector<std::string>& args, size_t argidx) {
	auto selection_begin = args.begin() + argidx;
	std::transform(selection_begin, args.end(), selection_begin,
	               [](std::string& w) { return "w:" + w; });
    }

    Clocks& clocks_;
};

struct GetClocksCmd : public Pass {
    GetClocksCmd(Clocks& clocks)
        : Pass("get_clocks", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    get_clocks\n");
	log("\n");
	log("Returns all clocks in the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 __attribute__((unused)) RTLIL::Design* design) override {
	std::vector<std::string> clock_names(clocks_.GetClockNames());
	if (clock_names.size() == 0) {
	    log_warning("No clocks found in design\n");
	}
	Tcl_Interp *interp = yosys_get_tcl_interp();
	Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL);
	for (auto name : clock_names) {
	    Tcl_Obj* name_obj = Tcl_NewStringObj(name.c_str(), name.size());
	    Tcl_ListObjAppendElement(interp, tcl_list, name_obj);
	}
	Tcl_SetObjResult(interp, tcl_list);
    }

    Clocks& clocks_;
};

struct PropagateClocksCmd : public Pass {
    PropagateClocksCmd(Clocks& clocks)
        : Pass("propagate_clocks", "Propagate clock information"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    propagate_clocks\n");
	log("\n");
	log("Propagate clock information throughout the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 RTLIL::Design* design) override {

	if (!design->top_module()) {
	    log_cmd_error("No top module selected\n");
	}

	std::array<std::unique_ptr<Propagation>, 2> passes{
	    std::unique_ptr<NaturalPropagation>(
	        new NaturalPropagation(design, this)),
	    std::unique_ptr<BufferPropagation>(new BufferPropagation(design))};

	for (auto& pass : passes) {
	    pass->Run(clocks_);
	}
    }

    Clocks& clocks_;
};

class SdcPlugin {
   public:
    SdcPlugin()
        : create_clock_cmd_(clocks_),
          get_clocks_cmd_(clocks_),
          propagate_clocks_cmd_(clocks_) {
	log("Loaded SDC plugin\n");
    }

    ReadSdcCmd read_sdc_cmd_;
    CreateClockCmd create_clock_cmd_;
    GetClocksCmd get_clocks_cmd_;
    PropagateClocksCmd propagate_clocks_cmd_;

   private:
    Clocks clocks_;
} SdcPlugin;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/* TTElement.hpp
 *
 * Kubo Ryosuke
 */

#ifndef SUNFISH_TT_TTSLOT_HPP__
#define SUNFISH_TT_TTSLOT_HPP__

#include "search/eval/Score.hpp"
#include "core/move/Move.hpp"
#include "core/position/Zobrist.hpp"
#include <cstdint>
#include <cassert>

// 1st quad word
#define TT_MATE_MASK   0x8000000000000000LLU
#define TT_HASH_MASK   0x7fffffffffffffffLLU

#define TT_HASH_WIDTH  63
#define TT_MATE_WIDTH   1

#define TT_MATE_SHIFT  63

static_assert(TT_MATE_WIDTH
            + TT_HASH_WIDTH <= 64, "invalid data size");
static_assert(TT_MATE_MASK == (((1LLU << TT_MATE_WIDTH) - 1LLU) << TT_MATE_SHIFT), "invalid status");
static_assert(TT_HASH_MASK == ~TT_MATE_MASK, "invalid status");

// 2nd quad word
#define TT_MOVE_MASK  0x000000000000ffffLLU
#define TT_SCORE_MASK 0x00000000ffff0000LLU
#define TT_STYPE_MASK 0x0000000300000000LLU
#define TT_DEPTH_MASK 0x00000ffc00000000LLU
#define TT_CSUM_MASK  0xffff000000000000LLU

#define TT_MOVE_WIDTH  16
#define TT_SCORE_WIDTH 16
#define TT_STYPE_WIDTH  2
#define TT_DEPTH_WIDTH 10
#define TT_CSUM_WIDTH  16

#define TT_MOVE_SHIFT  0
#define TT_SCORE_SHIFT (TT_MOVE_SHIFT + TT_MOVE_WIDTH)
#define TT_STYPE_SHIFT (TT_SCORE_SHIFT + TT_SCORE_WIDTH)
#define TT_DEPTH_SHIFT (TT_STYPE_SHIFT + TT_STYPE_WIDTH)

static_assert(TT_MOVE_WIDTH
            + TT_SCORE_WIDTH
            + TT_STYPE_WIDTH
            + TT_DEPTH_WIDTH
            + TT_CSUM_WIDTH <= 64, "invalid data size");
static_assert(TT_MOVE_MASK  == (((1LLU << TT_MOVE_WIDTH) - 1) << TT_MOVE_SHIFT), "invalid status");
static_assert(TT_SCORE_MASK == (((1LLU << TT_SCORE_WIDTH) - 1) << TT_SCORE_SHIFT), "invalid status");
static_assert(TT_STYPE_MASK == (((1LLU << TT_STYPE_WIDTH) - 1) << TT_STYPE_SHIFT), "invalid status");
static_assert(TT_DEPTH_MASK == (((1LLU << TT_DEPTH_WIDTH) - 1) << TT_DEPTH_SHIFT), "invalid status");
static_assert(TT_CSUM_MASK  == (~((1LLU << (64 - TT_CSUM_WIDTH)) - 1)), "invalid status");

static_assert(sizeof(sunfish::Score::RawType) == 2, "invalid data size");

static_assert(TT_CSUM_WIDTH == 16, "invalid data size");
static_assert(TT_CSUM_MASK == 0xffff000000000000LLU, "invalid data size");

namespace sunfish {

enum class TTScoreType : int {
  Exact = 0,
  Upper, /* = 1 */
  Lower, /* = 2 */
  None, /* = 3 */
};

class TTElement {
public:

  using QuadWord = uint64_t;

private:

  QuadWord w1_;
  QuadWord w2_;

  bool update(Zobrist::Type newHash,
              Score newScore,
              TTScoreType newScoreType,
              int newDepth,
              int ply,
              Move move,
              bool mateThreat);

  QuadWord calcCheckSum() const {
    return
      (
        (w1_) ^
        (w1_ << 16) ^
        (w1_ << 32) ^
        (w1_ << 48) ^
        (w2_ << 16) ^
        (w2_ << 32) ^
        (w2_ << 48)
      );
  }

public:
  TTElement() :
      w1_(0),
      w2_(TT_CSUM_MASK) {
  }

  bool update(Zobrist::Type newHash,
              Score alpha,
              Score beta,
              Score newScore,
              int newDepth, int ply,
              const Move& move,
              bool mateThreat) {
    TTScoreType newScoreType;
    if (newScore >= beta) {
      newScoreType = TTScoreType::Lower;
    } else if (newScore <= alpha) {
      newScoreType = TTScoreType::Upper;
    } else {
      newScoreType = TTScoreType::Exact;
    }

    return update(newHash,
                  newScore,
                  newScoreType,
                  newDepth,
                  ply,
                  move,
                  mateThreat);
  }

  void updatePV(Zobrist::Type newHash,
                Score newScore,
                int newDepth,
                Move move);

  bool isLive() const {
    return ((w2_ ^ calcCheckSum()) & TT_CSUM_MASK) == 0LLU;
  }

  bool checkHash(Zobrist::Type hash) const {
    return ((w1_ ^ hash) & TT_HASH_MASK) == 0LLU && isLive();
  }

  Zobrist::Type hash() const {
    return w1_ & TT_HASH_MASK;
  }

  Score score(int ply) const {
    auto data = (w2_ & TT_SCORE_MASK) >> TT_SCORE_SHIFT;
    auto u16 = static_cast<uint16_t>(data);
    auto rawValue = static_cast<Score::RawType>(u16);
    Score s(rawValue);

    TTScoreType st = scoreType();
    ASSERT(st == TTScoreType::None || s >= -Score::infinity());
    ASSERT(st == TTScoreType::None || s <= Score::infinity());

    if (s >= Score::mate()) {
      if (st == TTScoreType::Lower) { return s - ply; }
    } else if (s <= -Score::mate()) {
      if (st == TTScoreType::Upper) { return s + ply; }
    }

    return s;
  }

  TTScoreType scoreType() const {
    auto data = (w2_ & TT_STYPE_MASK) >> TT_STYPE_SHIFT;
    return static_cast<TTScoreType>(data);
  }

  int depth() const {
    auto data = (w2_ & TT_DEPTH_MASK) >> TT_DEPTH_SHIFT;
    return static_cast<int>(data);
  }

  Move move() const {
    auto data = (w2_ & TT_MOVE_MASK) >> TT_MOVE_SHIFT;
    auto rawValue = static_cast<Move::RawType16>(data);
    return Move::deserialize(rawValue);
  }

  bool isMateThreat() const {
    return w1_ & TT_MATE_MASK;
  }

};

} // namespace sunfish

inline std::ostream& operator<<(std::ostream& os, sunfish::TTScoreType scrState) {
  switch (scrState) {
  case sunfish::TTScoreType::Exact:
    os << "Exact";
    break;
  case sunfish::TTScoreType::Upper:
    os << "Upper";
    break;
  case sunfish::TTScoreType::Lower:
    os << "Lower";
    break;
  case sunfish::TTScoreType::None:
    os << "None";
    break;
  }
  return os;
}

#endif // SUNFISH_TT_TTSLOT_HPP__
<commit_msg>Revert "Fix TT"<commit_after>/* TTElement.hpp
 *
 * Kubo Ryosuke
 */

#ifndef SUNFISH_TT_TTSLOT_HPP__
#define SUNFISH_TT_TTSLOT_HPP__

#include "search/eval/Score.hpp"
#include "core/move/Move.hpp"
#include "core/position/Zobrist.hpp"
#include <cstdint>
#include <cassert>

// 1st quad word
#define TT_MATE_MASK   0x0000000000000001LLU
#define TT_HASH_MASK   0xfffffffffffffffeLLU

#define TT_MATE_WIDTH   1
#define TT_HASH_WIDTH  63

#define TT_MATE_SHIFT   0

static_assert(TT_MATE_WIDTH
            + TT_HASH_WIDTH <= 64, "invalid data size");
static_assert(TT_MATE_MASK == (((1LLU << TT_MATE_WIDTH) - 1LLU) << TT_MATE_SHIFT), "invalid status");
static_assert(TT_HASH_MASK == (~((1LLU << (64 - TT_HASH_WIDTH)) - 1)), "invalid status");

// 2nd quad word
#define TT_MOVE_MASK  0x000000000000ffffLLU
#define TT_SCORE_MASK 0x00000000ffff0000LLU
#define TT_STYPE_MASK 0x0000000300000000LLU
#define TT_DEPTH_MASK 0x00000ffc00000000LLU
#define TT_CSUM_MASK  0xffff000000000000LLU

#define TT_MOVE_WIDTH  16
#define TT_SCORE_WIDTH 16
#define TT_STYPE_WIDTH  2
#define TT_DEPTH_WIDTH 10
#define TT_CSUM_WIDTH  16

#define TT_MOVE_SHIFT  0
#define TT_SCORE_SHIFT (TT_MOVE_SHIFT + TT_MOVE_WIDTH)
#define TT_STYPE_SHIFT (TT_SCORE_SHIFT + TT_SCORE_WIDTH)
#define TT_DEPTH_SHIFT (TT_STYPE_SHIFT + TT_STYPE_WIDTH)

static_assert(TT_MOVE_WIDTH
            + TT_SCORE_WIDTH
            + TT_STYPE_WIDTH
            + TT_DEPTH_WIDTH
            + TT_CSUM_WIDTH <= 64, "invalid data size");
static_assert(TT_MOVE_MASK  == (((1LLU << TT_MOVE_WIDTH) - 1) << TT_MOVE_SHIFT), "invalid status");
static_assert(TT_SCORE_MASK == (((1LLU << TT_SCORE_WIDTH) - 1) << TT_SCORE_SHIFT), "invalid status");
static_assert(TT_STYPE_MASK == (((1LLU << TT_STYPE_WIDTH) - 1) << TT_STYPE_SHIFT), "invalid status");
static_assert(TT_DEPTH_MASK == (((1LLU << TT_DEPTH_WIDTH) - 1) << TT_DEPTH_SHIFT), "invalid status");
static_assert(TT_CSUM_MASK  == (~((1LLU << (64 - TT_CSUM_WIDTH)) - 1)), "invalid status");

static_assert(sizeof(sunfish::Score::RawType) == 2, "invalid data size");

static_assert(TT_CSUM_WIDTH == 16, "invalid data size");
static_assert(TT_CSUM_MASK == 0xffff000000000000LLU, "invalid data size");

namespace sunfish {

enum class TTScoreType : int {
  Exact = 0,
  Upper, /* = 1 */
  Lower, /* = 2 */
  None, /* = 3 */
};

class TTElement {
public:

  using QuadWord = uint64_t;

private:

  QuadWord w1_;
  QuadWord w2_;

  bool update(Zobrist::Type newHash,
              Score newScore,
              TTScoreType newScoreType,
              int newDepth,
              int ply,
              Move move,
              bool mateThreat);

  QuadWord calcCheckSum() const {
    return
      (
        (w1_) ^
        (w1_ << 16) ^
        (w1_ << 32) ^
        (w1_ << 48) ^
        (w2_ << 16) ^
        (w2_ << 32) ^
        (w2_ << 48)
      );
  }

public:
  TTElement() :
      w1_(0),
      w2_(TT_CSUM_MASK) {
  }

  bool update(Zobrist::Type newHash,
              Score alpha,
              Score beta,
              Score newScore,
              int newDepth, int ply,
              const Move& move,
              bool mateThreat) {
    TTScoreType newScoreType;
    if (newScore >= beta) {
      newScoreType = TTScoreType::Lower;
    } else if (newScore <= alpha) {
      newScoreType = TTScoreType::Upper;
    } else {
      newScoreType = TTScoreType::Exact;
    }

    return update(newHash,
                  newScore,
                  newScoreType,
                  newDepth,
                  ply,
                  move,
                  mateThreat);
  }

  void updatePV(Zobrist::Type newHash,
                Score newScore,
                int newDepth,
                Move move);

  bool isLive() const {
    return ((w2_ ^ calcCheckSum()) & TT_CSUM_MASK) == 0LLU;
  }

  bool checkHash(Zobrist::Type hash) const {
    return ((w1_ ^ hash) & TT_HASH_MASK) == 0LLU && isLive();
  }

  Zobrist::Type hash() const {
    return w1_ & TT_HASH_MASK;
  }

  Score score(int ply) const {
    auto data = (w2_ & TT_SCORE_MASK) >> TT_SCORE_SHIFT;
    auto u16 = static_cast<uint16_t>(data);
    auto rawValue = static_cast<Score::RawType>(u16);
    Score s(rawValue);

    TTScoreType st = scoreType();
    ASSERT(st == TTScoreType::None || s >= -Score::infinity());
    ASSERT(st == TTScoreType::None || s <= Score::infinity());

    if (s >= Score::mate()) {
      if (st == TTScoreType::Lower) { return s - ply; }
    } else if (s <= -Score::mate()) {
      if (st == TTScoreType::Upper) { return s + ply; }
    }

    return s;
  }

  TTScoreType scoreType() const {
    auto data = (w2_ & TT_STYPE_MASK) >> TT_STYPE_SHIFT;
    return static_cast<TTScoreType>(data);
  }

  int depth() const {
    auto data = (w2_ & TT_DEPTH_MASK) >> TT_DEPTH_SHIFT;
    return static_cast<int>(data);
  }

  Move move() const {
    auto data = (w2_ & TT_MOVE_MASK) >> TT_MOVE_SHIFT;
    auto rawValue = static_cast<Move::RawType16>(data);
    return Move::deserialize(rawValue);
  }

  bool isMateThreat() const {
    return w1_ & TT_MATE_MASK;
  }

};

} // namespace sunfish

inline std::ostream& operator<<(std::ostream& os, sunfish::TTScoreType scrState) {
  switch (scrState) {
  case sunfish::TTScoreType::Exact:
    os << "Exact";
    break;
  case sunfish::TTScoreType::Upper:
    os << "Upper";
    break;
  case sunfish::TTScoreType::Lower:
    os << "Lower";
    break;
  case sunfish::TTScoreType::None:
    os << "None";
    break;
  }
  return os;
}

#endif // SUNFISH_TT_TTSLOT_HPP__
<|endoftext|>


<commit_before>//===-- llvm-bcanalyzer.cpp - Byte Code Analyzer --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool may be invoked in the following manner:
//  llvm-bcanalyzer [options]      - Read LLVM bytecode from stdin
//  llvm-bcanalyzer [options] x.bc - Read LLVM bytecode from the x.bc file
//
//  Options:
//      --help      - Output information about command line switches
//      --nodetails - Don't print out detailed informaton about individual
//                    blocks and functions
//      --dump      - Dump low-level bytecode structure in readable format
//
// This tool provides analytical information about a bytecode file. It is
// intended as an aid to developers of bytecode reading and writing software. It
// produces on std::out a summary of the bytecode file that shows various
// statistics about the contents of the file. By default this information is
// detailed and contains information about individual bytecode blocks and the
// functions in the module. To avoid this more detailed output, use the
// -nodetails option to limit the output to just module level information.
// The tool is also able to print a bytecode file in a straight forward text
// format that shows the containment and relationships of the information in
// the bytecode file (-dump option).
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bytecode/Analyzer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compressor.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Signals.h"
#include <fstream>
#include <iostream>
using namespace llvm;

static cl::opt<std::string>
  InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));

static cl::opt<std::string>
  OutputFilename("-o", cl::init("-"), cl::desc("<output file>"));

static cl::opt<bool> NoDetails("nodetails", cl::desc("Skip detailed output"));
static cl::opt<bool> Dump("dump", cl::desc("Dump low level bytecode trace"));
static cl::opt<bool> Verify("verify", cl::desc("Progressively verify module"));
static cl::opt<bool> Bitcode("bitcode", cl::desc("Read a bitcode file"));

/// CurStreamType - If we can sniff the flavor of this stream, we can produce
/// better dump info.
static enum {
  UnknownBitstream,
  LLVMIRBitstream
} CurStreamType;

/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
static int AnalyzeBitcode() {
  // Read the input file.
  MemoryBuffer *Buffer;
  if (InputFilename == "-")
    Buffer = MemoryBuffer::getSTDIN();
  else
    Buffer = MemoryBuffer::getFile(&InputFilename[0], InputFilename.size());

  if (Buffer == 0) {
    std::cerr << "Error reading '" << InputFilename << "'.\n";
    return 1;
  }

  if (Buffer->getBufferSize() & 3) {
    std::cerr << "Bitcode stream should be a multiple of 4 bytes in length\n";
    return 1;
  }

  unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
  BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());

  // Read the stream signature.
  char Signature[6];
  Signature[0] = Stream.Read(8);
  Signature[1] = Stream.Read(8);
  Signature[2] = Stream.Read(4);
  Signature[3] = Stream.Read(4);
  Signature[4] = Stream.Read(4);
  Signature[5] = Stream.Read(4);

  CurStreamType = UnknownBitstream;
  if (Signature[0] == 'B' && Signature[1] == 'C' &&
      Signature[2] == 0x0 && Signature[3] == 0xC &&
      Signature[4] == 0xE && Signature[5] == 0xD)
    CurStreamType = LLVMIRBitstream;

  std::cerr << "Summary of " << InputFilename << ":\n";
  std::cerr << "  Stream type: ";
  switch (CurStreamType) {
  default: assert(0 && "Unknown bitstream type");
  case UnknownBitstream: std::cerr << "unknown\n"; break;
  case LLVMIRBitstream:  std::cerr << "LLVM IR\n"; break;
  }

  return 0;
}

int main(int argc, char **argv) {
  llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
  cl::ParseCommandLineOptions(argc, argv, " llvm-bcanalyzer file analyzer\n");

  sys::PrintStackTraceOnErrorSignal();

  if (Bitcode)
    return AnalyzeBitcode();

  try {
    std::ostream *Out = &std::cout;  // Default to printing to stdout...
    std::string ErrorMessage;
    BytecodeAnalysis bca;

    /// Determine what to generate
    bca.detailedResults = !NoDetails;
    bca.progressiveVerify = Verify;

    /// Analyze the bytecode file
    Module* M = AnalyzeBytecodeFile(InputFilename, bca,
                                    Compressor::decompressToNewBuffer,
                                    &ErrorMessage, (Dump?Out:0));

    // All that bcanalyzer does is write the gathered statistics to the output
    PrintBytecodeAnalysis(bca,*Out);

    if (M && Verify) {
      std::string verificationMsg;
      if (verifyModule(*M, ReturnStatusAction, &verificationMsg))
        std::cerr << "Final Verification Message: " << verificationMsg << "\n";
    }

    if (Out != &std::cout) {
      ((std::ofstream*)Out)->close();
      delete Out;
    }
    return 0;
  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
  } catch (...) {
    std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
  }
  return 1;
}
<commit_msg>Implement support to read an arbitrary bitcode file.  Next up, dumping the file symbolically and actually computing statistics.<commit_after>//===-- llvm-bcanalyzer.cpp - Byte Code Analyzer --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool may be invoked in the following manner:
//  llvm-bcanalyzer [options]      - Read LLVM bytecode from stdin
//  llvm-bcanalyzer [options] x.bc - Read LLVM bytecode from the x.bc file
//
//  Options:
//      --help      - Output information about command line switches
//      --nodetails - Don't print out detailed informaton about individual
//                    blocks and functions
//      --dump      - Dump low-level bytecode structure in readable format
//
// This tool provides analytical information about a bytecode file. It is
// intended as an aid to developers of bytecode reading and writing software. It
// produces on std::out a summary of the bytecode file that shows various
// statistics about the contents of the file. By default this information is
// detailed and contains information about individual bytecode blocks and the
// functions in the module. To avoid this more detailed output, use the
// -nodetails option to limit the output to just module level information.
// The tool is also able to print a bytecode file in a straight forward text
// format that shows the containment and relationships of the information in
// the bytecode file (-dump option).
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bytecode/Analyzer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compressor.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Signals.h"
#include <fstream>
#include <iostream>
using namespace llvm;

static cl::opt<std::string>
  InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));

static cl::opt<std::string>
  OutputFilename("-o", cl::init("-"), cl::desc("<output file>"));

static cl::opt<bool> NoDetails("nodetails", cl::desc("Skip detailed output"));
static cl::opt<bool> Dump("dump", cl::desc("Dump low level bytecode trace"));
static cl::opt<bool> Verify("verify", cl::desc("Progressively verify module"));

//===----------------------------------------------------------------------===//
// Bitcode specific analysis.
//===----------------------------------------------------------------------===//

static cl::opt<bool> Bitcode("bitcode", cl::desc("Read a bitcode file"));

/// CurStreamType - If we can sniff the flavor of this stream, we can produce
/// better dump info.
static enum {
  UnknownBitstream,
  LLVMIRBitstream
} CurStreamType;

/// Error - All bitcode analysis errors go through this function, making this a
/// good place to breakpoint if debugging.
static bool Error(const std::string &Err) {
  std::cerr << Err << "\n";
  return true;
}

/// ParseBlock - Read a block, updating statistics, etc.
static bool ParseBlock(BitstreamReader &Stream) {
  unsigned BlockID = Stream.ReadSubBlockID();

  // TODO: Compute per-block-id stats.
  BlockID = BlockID;

  if (Stream.EnterSubBlock())
    return Error("Malformed block record");

  SmallVector<uint64_t, 64> Record;

  // Read all the records for this block.
  while (1) {
    if (Stream.AtEndOfStream())
      return Error("Premature end of bitstream");

    // Read the code for this record.
    unsigned AbbrevID = Stream.ReadCode();
    switch (AbbrevID) {
    case bitc::END_BLOCK:
      if (Stream.ReadBlockEnd())
        return Error("Error at end of block");
      return false;
    case bitc::ENTER_SUBBLOCK:
      if (ParseBlock(Stream))
        return true;
      break;
    case bitc::DEFINE_ABBREV:
      Stream.ReadAbbrevRecord();
      break;
    default:
      Record.clear();
      unsigned Code = Stream.ReadRecord(AbbrevID, Record);
      // TODO: Compute per-blockid/code stats.
      Code = Code;
      break;
    }
  }
}

/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
static int AnalyzeBitcode() {
  // Read the input file.
  MemoryBuffer *Buffer;
  if (InputFilename == "-")
    Buffer = MemoryBuffer::getSTDIN();
  else
    Buffer = MemoryBuffer::getFile(&InputFilename[0], InputFilename.size());

  if (Buffer == 0)
    return Error("Error reading '" + InputFilename + "'.");

  if (Buffer->getBufferSize() & 3)
    return Error("Bitcode stream should be a multiple of 4 bytes in length");

  unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
  BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());

  // Read the stream signature.
  char Signature[6];
  Signature[0] = Stream.Read(8);
  Signature[1] = Stream.Read(8);
  Signature[2] = Stream.Read(4);
  Signature[3] = Stream.Read(4);
  Signature[4] = Stream.Read(4);
  Signature[5] = Stream.Read(4);

  // Autodetect the file contents, if it is one we know.
  CurStreamType = UnknownBitstream;
  if (Signature[0] == 'B' && Signature[1] == 'C' &&
      Signature[2] == 0x0 && Signature[3] == 0xC &&
      Signature[4] == 0xE && Signature[5] == 0xD)
    CurStreamType = LLVMIRBitstream;

  // Parse the top-level structure.  We only allow blocks at the top-level.
  while (!Stream.AtEndOfStream()) {
    unsigned Code = Stream.ReadCode();
    if (Code != bitc::ENTER_SUBBLOCK)
      return Error("Invalid record at top-level");

    if (ParseBlock(Stream))
      return true;
  }

  // Print a summary of the read file.

  std::cerr << "Summary of " << InputFilename << ":\n";
  std::cerr << "  Stream type: ";
  switch (CurStreamType) {
  default: assert(0 && "Unknown bitstream type");
  case UnknownBitstream: std::cerr << "unknown\n"; break;
  case LLVMIRBitstream:  std::cerr << "LLVM IR\n"; break;
  }

  // TODO: Stats!

  return 0;
}

//===----------------------------------------------------------------------===//
// Bytecode specific analysis.
//===----------------------------------------------------------------------===//

int main(int argc, char **argv) {
  llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
  cl::ParseCommandLineOptions(argc, argv, " llvm-bcanalyzer file analyzer\n");

  sys::PrintStackTraceOnErrorSignal();

  if (Bitcode)
    return AnalyzeBitcode();

  try {
    std::ostream *Out = &std::cout;  // Default to printing to stdout...
    std::string ErrorMessage;
    BytecodeAnalysis bca;

    /// Determine what to generate
    bca.detailedResults = !NoDetails;
    bca.progressiveVerify = Verify;

    /// Analyze the bytecode file
    Module* M = AnalyzeBytecodeFile(InputFilename, bca,
                                    Compressor::decompressToNewBuffer,
                                    &ErrorMessage, (Dump?Out:0));

    // All that bcanalyzer does is write the gathered statistics to the output
    PrintBytecodeAnalysis(bca,*Out);

    if (M && Verify) {
      std::string verificationMsg;
      if (verifyModule(*M, ReturnStatusAction, &verificationMsg))
        std::cerr << "Final Verification Message: " << verificationMsg << "\n";
    }

    if (Out != &std::cout) {
      ((std::ofstream*)Out)->close();
      delete Out;
    }
    return 0;
  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
  } catch (...) {
    std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
  }
  return 1;
}
<|endoftext|>


<commit_before>#pragma once
/*
**  Copyright (C) 2013 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QITYPE_DETAILS_TYPETUPLE_HXX_
#define _QITYPE_DETAILS_TYPETUPLE_HXX_

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <qitype/details/accessor.hxx>
#include <qi/preproc.hpp>

namespace qi
{
  namespace detail {

    //keep only the class name. (remove :: and namespaces)
    QITYPE_API std::string normalizeClassName(const std::string &name);

    template<typename T> void setFromStorage(T& ref, void* storage)
    {
      ref = *(T*)typeOf<T>()->ptrFromStorage(&storage);
    }

    /* Helpers around accessors
     */
    template<typename A> TypeInterface* fieldType(A)
    {
      static TypeInterface* res =
        qi::typeOf<typename detail::Accessor<A>::value_type>();
      return res;
    }

    template<typename C, typename A> void* fieldStorage(C* inst, A accessor)
    {
      return fieldType(accessor)->initializeStorage(
        (void*)&detail::Accessor<A>::access(inst, accessor));
    }

    template<typename C, typename A>
    typename detail::Accessor<A>::value_type&
    fieldValue(C* instance, A accessor, void** data)
    {
      typedef typename detail::Accessor<A>::value_type T;
      return *(T*)fieldType(accessor)->ptrFromStorage(data);
    }
  }
}

#define __QI_TYPE_STRUCT_DECLARE(name, extra)                             \
namespace qi {                                                            \
  template<> struct TypeImpl<name>: public ::qi::StructTypeInterface                \
  {                                                                       \
  public:                                                                 \
    typedef name ClassType;                                               \
    virtual std::vector< ::qi::TypeInterface*> memberTypes();                      \
    virtual std::vector<std::string> elementsName();                      \
    virtual std::string className();                                      \
    virtual void* get(void* storage, unsigned int index);                 \
    virtual void set(void** storage, unsigned int index, void* valStorage); \
    extra                                                                   \
    _QI_BOUNCE_TYPE_METHODS(::qi::DefaultTypeImplMethods<name>);            \
 }; }

#define __QI_TUPLE_TYPE(_, what, field) res.push_back(::qi::typeOf(ptr->field));
#define __QI_TUPLE_GET(_, what, field) if (i == index) return ::qi::typeOf(ptr->field)->initializeStorage(&ptr->field); i++;
#define __QI_TUPLE_SET(_, what, field) if (i == index) ::qi::detail::setFromStorage(ptr->field, valueStorage); i++;
#define __QI_TUPLE_FIELD_NAME(_, what, field) res.push_back(BOOST_PP_STRINGIZE(QI_DELAY(field)));
#define __QI_TYPE_STRUCT_IMPLEMENT(name, inl, onSet, ...)                                    \
namespace qi {                                                                        \
  inl std::vector< ::qi::TypeInterface*> TypeImpl<name>::memberTypes()                                \
  {                                                                                \
    name* ptr = 0;                                                                    \
    std::vector< ::qi::TypeInterface*> res;                                                           \
    QI_VAARGS_APPLY(__QI_TUPLE_TYPE, _, __VA_ARGS__);                                 \
    return res;                                                                       \
  }                                                                                \
  inl void* TypeImpl<name>::get(void* storage, unsigned int index)                    \
  {                                                                                \
    unsigned int i = 0;                                                                        \
    name* ptr = (name*)ptrFromStorage(&storage);                                      \
    QI_VAARGS_APPLY(__QI_TUPLE_GET, _, __VA_ARGS__);                                  \
    return 0;                                                                         \
  }                                                                                \
  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
  {                                                                                \
    unsigned int i=0;                                                                 \
    name* ptr = (name*)ptrFromStorage(storage);                                       \
    QI_VAARGS_APPLY(__QI_TUPLE_SET, _, __VA_ARGS__);                                  \
    onSet                                                                      \
  }\
  inl std::vector<std::string> TypeImpl<name>::elementsName() \
  {  \
    std::vector<std::string> res; \
    QI_VAARGS_APPLY(__QI_TUPLE_FIELD_NAME, _, __VA_ARGS__); \
    return res; \
  }\
  inl std::string TypeImpl<name>::className() \
  {\
    return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name));\
  }\
}

/// Declare a struct field using an helper function
#define QI_STRUCT_HELPER(name, func) (name, func, FUNC)
/// Declare a struct feld that is a member (member value or member accessor function)
#define QI_STRUCT_FIELD(name, field) (name, field, FIELD)

// construct pointer-to accessor from free-function
#define __QI_STRUCT_ACCESS_FUNC(fname, field) &field
// construct pointer-to-accessor from member function/field
#define __QI_STRUCT_ACCESS_FIELD(fname, field) &ClassType::field

// invoke the correct __QI_STRUCT_ACCESS_ macro using type
#define __QI_STRUCT_ACCESS_BOUNCE2(name, accessor, type) \
  QI_CAT(__QI_STRUCT_ACCESS_, type)(name, accessor)

// bounce with default value FIELD for argument 3
#define __QI_STRUCT_ACCESS_BOUNCE1(x, y) \
  __QI_STRUCT_ACCESS_BOUNCE2(x, y, FIELD)

// arg-count overload, bounce to __QI_STRUCT_ACCESS_BOUNCE<N>
#define __QI_STRUCT_ACCESS_BOUNCE(...) \
 QI_CAT(__QI_STRUCT_ACCESS_BOUNCE, QI_LIST_VASIZE((__VA_ARGS__)))(__VA_ARGS__)

// accept (name, accessor, type) and (name, accessor) defaulting type to field
#define __QI_STRUCT_ACCESS(tuple) QI_DELAY(__QI_STRUCT_ACCESS_BOUNCE)tuple

#define __QI_ATUPLE_TYPE(_, what, field) res.push_back(::qi::detail::fieldType(__QI_STRUCT_ACCESS(field)));
#define __QI_ATUPLE_GET(_, what, field) if (i == index) return ::qi::detail::fieldStorage(ptr, __QI_STRUCT_ACCESS(field)); i++;
#define __QI_ATUPLE_FIELD_NAME(_, what, field) res.push_back(QI_PAIR_FIRST(field));
#define __QI_ATUPLE_FROMDATA(idx, what, field) ::qi::detail::fieldValue(ptr, __QI_STRUCT_ACCESS(field), const_cast<void**>(&data[idx]))
#define __QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_IMPLEMENT(name, inl, onSet, ...)\
  namespace qi {                                                                        \
  inl std::vector< ::qi::TypeInterface*> TypeImpl<name>::memberTypes()                                \
  {                                                                                \
    std::vector< ::qi::TypeInterface*> res;                                                           \
    QI_VAARGS_APPLY(__QI_ATUPLE_TYPE, name, __VA_ARGS__);                                 \
    return res;                                                                       \
  }                                                                                \
  \
  inl void* TypeImpl<name>::get(void* storage, unsigned int index)                    \
  {                                                                                \
    unsigned int i = 0;                                                                        \
    name* ptr = (name*)ptrFromStorage(&storage);                                      \
    QI_VAARGS_APPLY(__QI_ATUPLE_GET, name, __VA_ARGS__);                                  \
    return 0;                                                                         \
  }                                                                                \
  \
  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
  {\
    throw std::runtime_error("single-field set not implemented");\
  }\
  \
  inl void TypeImpl<name>::set(void** storage, const std::vector<void*>& data) \
  {\
    name* ptr = (name*)ptrFromStorage(storage);         \
    *ptr = name(QI_VAARGS_MAP(__QI_ATUPLE_FROMDATA, name, __VA_ARGS__)); \
  }\
  \
  inl std::vector<std::string> TypeImpl<name>::elementsName() \
  {  \
    std::vector<std::string> res; \
    QI_VAARGS_APPLY(__QI_ATUPLE_FIELD_NAME, _, __VA_ARGS__); \
    return res; \
  }\
  inl std::string TypeImpl<name>::className() \
  \
  { \
    return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name));\
  } \
  }

/// Allow the QI_TYPE_STRUCT macro and variants to access private members
#define QI_TYPE_STRUCT_PRIVATE_ACCESS(name) \
friend class qi::TypeImpl<name>;

/** Declare a simple struct to the type system.
 * First argument is the structure name. Remaining arguments are the structure
 * fields.
 * This macro must be called outside any namespace.
 * This macro should be called in the header file defining the structure 'name',
 * or in a header included by all source files using the structure.
 * See QI_TYPE_STRUCT_REGISTER for a similar macro that can be called from a
 * single source file.
 */
#define QI_TYPE_STRUCT(name, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, /**/, __VA_ARGS__)

/** Similar to QI_TYPE_STRUCT, but evaluates 'onSet' after writting to an instance.
 * The instance is accessible through the variable 'ptr'.
 */
#define QI_TYPE_STRUCT_EX(name, onSet, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, onSet, __VA_ARGS__)

#define QI_TYPE_STRUCT_IMPLEMENT(name, ...) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, /**/, /**/, __VA_ARGS__)

/** Register a struct with member field/function getters, and constructor setter
 *
 * Call like that:
 *    QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(Point,
 *       ("x", getX),
 *       ("y", y))
 *
 * The first macro argument is the class full name including namespace.
 * Remaining arguments can be:
 *  - (fieldName, accessor): accessor must be:
 *        - a member function returning a const T& with no argument
 *        - a member field
 *  - QI_STRUCT_FIELD(fieldName, accessor): Same thing as above, provided for
 *      consistency.
 *  - QI_STRUCT_HELPER(fieldName, function). Function must be a free function
 *       taking a class pointer, and returning a const T&
 *
 * The class must provide a constructor that accepts all fields as argument, in
 * the order in which they are declared in the macro.
 *
 * Must be called outside any namespace.
 */
#define QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(name, ...)     \
  __QI_TYPE_STRUCT_DECLARE(name,                             \
    virtual void set(void** storage, const std::vector<void*>&);) \
    __QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_IMPLEMENT(name, inline, /**/, __VA_ARGS__)

/** Similar to QI_TYPE_STRUCT, but using the runtime factory instead of the
 * compile-time template.
 *
 */
#define QI_TYPE_STRUCT_REGISTER(name, ...) \
namespace _qi_ {                           \
    QI_TYPE_STRUCT(name, __VA_ARGS__);     \
}                                          \
QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)

/** Similar to QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR,
 * but using the runtime factory instead of the
 * compile-time template.
 *
 */
#define QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_REGISTER(name, ...) \
namespace _qi_ {                           \
    QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(name, __VA_ARGS__);     \
}                                          \
QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)

/** Declares that name is equivalent to type bounceTo, and that instances
 * can be converted using the conversion function with signature 'bounceTo* (name*)'.
 * This macro should be called in a header included by all code using the 'name'
 * class.
 * See QI_TYPE_STRUCT_BOUNCE_REGISTER for a similar macro that can be called from a
 * single source file.
 */
#define QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion)                 \
namespace qi {                                                            \
template<> class TypeImpl<name>: public ::qi::StructTypeInterfaceBouncer<name, bounceTo>  \
{                                                                         \
public:                                                                   \
  void adaptStorage(void** storage, void** adapted)                       \
  {                                                                       \
    name* ptr = (name*)ptrFromStorage(storage);                           \
    bounceTo * tptr = conversion(ptr);                                    \
    *adapted = bounceType()->initializeStorage(tptr);                     \
  }                                                                       \
};}

/** Similar to QI_TYPE_STRUCT_BOUNCE, but using the runtime factory instead of the
 * compile-time template.
 */
#define QI_TYPE_STRUCT_BOUNCE_REGISTER(name, bounceTo, conversion)        \
namespace _qi_ {                                                          \
    QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion);                    \
}                                                                         \
QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)

namespace qi {
  //TODO
  template<typename T, typename TO>
  class StructTypeInterfaceBouncer: public StructTypeInterface
  {
  public:
    StructTypeInterface* bounceType()
    {
      static TypeInterface* result = 0;
      if (!result)
        result = typeOf<TO>();
      return static_cast<StructTypeInterface*>(result);
    }

    virtual void adaptStorage(void** storage, void** adapted) = 0;

    typedef DefaultTypeImplMethods<T> Methods;
    virtual std::vector<TypeInterface*> memberTypes()
    {
      return bounceType()->memberTypes();
    }

    virtual void* get(void* storage, unsigned int index)
    {
      void* astorage;
      adaptStorage(&storage, &astorage);
      return bounceType()->get(astorage, index);
    }

    virtual void set(void** storage, unsigned int index, void* valStorage)
    {
      void* astorage;
      adaptStorage(storage, &astorage);
      bounceType()->set(&astorage, index, valStorage);
    }

    virtual std::vector<std::string> elementsName()
    {
      return bounceType()->elementsName();
    }

    _QI_BOUNCE_TYPE_METHODS(Methods);
  };

  template<typename F, typename S>
  class TypeImpl<std::pair<F, S> >: public StructTypeInterface
  {
  public:
    typedef DefaultTypeImplMethods<std::pair<F, S> > Methods;
    typedef typename std::pair<F, S> BackendType;
    std::vector<TypeInterface*> memberTypes()
    {
      static std::vector<TypeInterface*>* result=0;
      if (!result)
      {
        result = new std::vector<TypeInterface*>();
        result->push_back(typeOf<F>());
        result->push_back(typeOf<S>());
      }
      return *result;
    }
    void* get(void* storage, unsigned int index)
    {
      BackendType* ptr = (BackendType*)ptrFromStorage(&storage);
      // Will work if F or S are references
      if (!index)
        return typeOf<F>()->initializeStorage(const_cast<void*>((void*)&ptr->first));
      else
        return typeOf<S>()->initializeStorage(const_cast<void*>((void*)&ptr->second));
    }
    void set(void** storage, unsigned int index, void* valStorage)
    {
      BackendType* ptr = (BackendType*)ptrFromStorage(storage);
      if (!index)
        detail::TypeManagerDefault<F>::copy(const_cast<void*>((void*)&ptr->first), typeOf<F>()->ptrFromStorage(&valStorage));
      else
        detail::TypeManagerDefault<S>::copy(const_cast<void*>((void*)&ptr->second), typeOf<S>()->ptrFromStorage(&valStorage));
    }
    _QI_BOUNCE_TYPE_METHODS(Methods);
  };

}
#endif  // _QITYPE_DETAILS_TYPETUPLE_HXX_
<commit_msg>Document QI_TYPE_STRUCT*<commit_after>#pragma once
/*
**  Copyright (C) 2013 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QITYPE_DETAILS_TYPETUPLE_HXX_
#define _QITYPE_DETAILS_TYPETUPLE_HXX_

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <qitype/details/accessor.hxx>
#include <qi/preproc.hpp>

namespace qi
{
  namespace detail {

    //keep only the class name. (remove :: and namespaces)
    QITYPE_API std::string normalizeClassName(const std::string &name);

    template<typename T> void setFromStorage(T& ref, void* storage)
    {
      ref = *(T*)typeOf<T>()->ptrFromStorage(&storage);
    }

    /* Helpers around accessors
     */
    template<typename A> TypeInterface* fieldType(A)
    {
      static TypeInterface* res =
        qi::typeOf<typename detail::Accessor<A>::value_type>();
      return res;
    }

    template<typename C, typename A> void* fieldStorage(C* inst, A accessor)
    {
      return fieldType(accessor)->initializeStorage(
        (void*)&detail::Accessor<A>::access(inst, accessor));
    }

    template<typename C, typename A>
    typename detail::Accessor<A>::value_type&
    fieldValue(C* instance, A accessor, void** data)
    {
      typedef typename detail::Accessor<A>::value_type T;
      return *(T*)fieldType(accessor)->ptrFromStorage(data);
    }
  }
}

#define __QI_TYPE_STRUCT_DECLARE(name, extra)                             \
namespace qi {                                                            \
  template<> struct TypeImpl<name>: public ::qi::StructTypeInterface                \
  {                                                                       \
  public:                                                                 \
    typedef name ClassType;                                               \
    virtual std::vector< ::qi::TypeInterface*> memberTypes();                      \
    virtual std::vector<std::string> elementsName();                      \
    virtual std::string className();                                      \
    virtual void* get(void* storage, unsigned int index);                 \
    virtual void set(void** storage, unsigned int index, void* valStorage); \
    extra                                                                   \
    _QI_BOUNCE_TYPE_METHODS(::qi::DefaultTypeImplMethods<name>);            \
 }; }

#define __QI_TUPLE_TYPE(_, what, field) res.push_back(::qi::typeOf(ptr->field));
#define __QI_TUPLE_GET(_, what, field) if (i == index) return ::qi::typeOf(ptr->field)->initializeStorage(&ptr->field); i++;
#define __QI_TUPLE_SET(_, what, field) if (i == index) ::qi::detail::setFromStorage(ptr->field, valueStorage); i++;
#define __QI_TUPLE_FIELD_NAME(_, what, field) res.push_back(BOOST_PP_STRINGIZE(QI_DELAY(field)));
#define __QI_TYPE_STRUCT_IMPLEMENT(name, inl, onSet, ...)                                    \
namespace qi {                                                                        \
  inl std::vector< ::qi::TypeInterface*> TypeImpl<name>::memberTypes()                                \
  {                                                                                \
    name* ptr = 0;                                                                    \
    std::vector< ::qi::TypeInterface*> res;                                                           \
    QI_VAARGS_APPLY(__QI_TUPLE_TYPE, _, __VA_ARGS__);                                 \
    return res;                                                                       \
  }                                                                                \
  inl void* TypeImpl<name>::get(void* storage, unsigned int index)                    \
  {                                                                                \
    unsigned int i = 0;                                                                        \
    name* ptr = (name*)ptrFromStorage(&storage);                                      \
    QI_VAARGS_APPLY(__QI_TUPLE_GET, _, __VA_ARGS__);                                  \
    return 0;                                                                         \
  }                                                                                \
  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
  {                                                                                \
    unsigned int i=0;                                                                 \
    name* ptr = (name*)ptrFromStorage(storage);                                       \
    QI_VAARGS_APPLY(__QI_TUPLE_SET, _, __VA_ARGS__);                                  \
    onSet                                                                      \
  }\
  inl std::vector<std::string> TypeImpl<name>::elementsName() \
  {  \
    std::vector<std::string> res; \
    QI_VAARGS_APPLY(__QI_TUPLE_FIELD_NAME, _, __VA_ARGS__); \
    return res; \
  }\
  inl std::string TypeImpl<name>::className() \
  {\
    return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name));\
  }\
}

/// Declare a struct field using an helper function
#define QI_STRUCT_HELPER(name, func) (name, func, FUNC)
/// Declare a struct feld that is a member (member value or member accessor function)
#define QI_STRUCT_FIELD(name, field) (name, field, FIELD)

// construct pointer-to accessor from free-function
#define __QI_STRUCT_ACCESS_FUNC(fname, field) &field
// construct pointer-to-accessor from member function/field
#define __QI_STRUCT_ACCESS_FIELD(fname, field) &ClassType::field

// invoke the correct __QI_STRUCT_ACCESS_ macro using type
#define __QI_STRUCT_ACCESS_BOUNCE2(name, accessor, type) \
  QI_CAT(__QI_STRUCT_ACCESS_, type)(name, accessor)

// bounce with default value FIELD for argument 3
#define __QI_STRUCT_ACCESS_BOUNCE1(x, y) \
  __QI_STRUCT_ACCESS_BOUNCE2(x, y, FIELD)

// arg-count overload, bounce to __QI_STRUCT_ACCESS_BOUNCE<N>
#define __QI_STRUCT_ACCESS_BOUNCE(...) \
 QI_CAT(__QI_STRUCT_ACCESS_BOUNCE, QI_LIST_VASIZE((__VA_ARGS__)))(__VA_ARGS__)

// accept (name, accessor, type) and (name, accessor) defaulting type to field
#define __QI_STRUCT_ACCESS(tuple) QI_DELAY(__QI_STRUCT_ACCESS_BOUNCE)tuple

#define __QI_ATUPLE_TYPE(_, what, field) res.push_back(::qi::detail::fieldType(__QI_STRUCT_ACCESS(field)));
#define __QI_ATUPLE_GET(_, what, field) if (i == index) return ::qi::detail::fieldStorage(ptr, __QI_STRUCT_ACCESS(field)); i++;
#define __QI_ATUPLE_FIELD_NAME(_, what, field) res.push_back(QI_PAIR_FIRST(field));
#define __QI_ATUPLE_FROMDATA(idx, what, field) ::qi::detail::fieldValue(ptr, __QI_STRUCT_ACCESS(field), const_cast<void**>(&data[idx]))
#define __QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_IMPLEMENT(name, inl, onSet, ...)\
  namespace qi {                                                                        \
  inl std::vector< ::qi::TypeInterface*> TypeImpl<name>::memberTypes()                                \
  {                                                                                \
    std::vector< ::qi::TypeInterface*> res;                                                           \
    QI_VAARGS_APPLY(__QI_ATUPLE_TYPE, name, __VA_ARGS__);                                 \
    return res;                                                                       \
  }                                                                                \
  \
  inl void* TypeImpl<name>::get(void* storage, unsigned int index)                    \
  {                                                                                \
    unsigned int i = 0;                                                                        \
    name* ptr = (name*)ptrFromStorage(&storage);                                      \
    QI_VAARGS_APPLY(__QI_ATUPLE_GET, name, __VA_ARGS__);                                  \
    return 0;                                                                         \
  }                                                                                \
  \
  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
  {\
    throw std::runtime_error("single-field set not implemented");\
  }\
  \
  inl void TypeImpl<name>::set(void** storage, const std::vector<void*>& data) \
  {\
    name* ptr = (name*)ptrFromStorage(storage);         \
    *ptr = name(QI_VAARGS_MAP(__QI_ATUPLE_FROMDATA, name, __VA_ARGS__)); \
  }\
  \
  inl std::vector<std::string> TypeImpl<name>::elementsName() \
  {  \
    std::vector<std::string> res; \
    QI_VAARGS_APPLY(__QI_ATUPLE_FIELD_NAME, _, __VA_ARGS__); \
    return res; \
  }\
  inl std::string TypeImpl<name>::className() \
  \
  { \
    return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name));\
  } \
  }

/// Allow the QI_TYPE_STRUCT macro and variants to access private members
#define QI_TYPE_STRUCT_PRIVATE_ACCESS(name) \
friend class qi::TypeImpl<name>;

/** Declare a simple struct to the type system.
 * First argument is the structure name. Remaining arguments are the structure
 * fields.
 * This macro must be called outside any namespace.
 * This macro should be called in the header file defining the structure 'name',
 * or in a header included by all source files using the structure.
 * See QI_TYPE_STRUCT_REGISTER for a similar macro that can be called from a
 * single source file.
 */
#define QI_TYPE_STRUCT(name, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, /**/, __VA_ARGS__)

/** Similar to QI_TYPE_STRUCT, but evaluates 'onSet' after writting to an instance.
 * The instance is accessible through the variable 'ptr'.
 */
#define QI_TYPE_STRUCT_EX(name, onSet, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, onSet, __VA_ARGS__)

#define QI_TYPE_STRUCT_IMPLEMENT(name, ...) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, /**/, /**/, __VA_ARGS__)

/** Register a struct with member field/function getters, and constructor setter
 *
 * Call like that:
 *    QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(Point,
 *       ("x", getX),
 *       ("y", y))
 *
 * The first macro argument is the class full name including namespace.
 * Remaining arguments can be:
 *  - (fieldName, accessor): accessor must be:
 *        - a member function returning a const T& with no argument
 *        - a member field
 *  - QI_STRUCT_FIELD(fieldName, accessor): Same thing as above, provided for
 *      consistency.
 *  - QI_STRUCT_HELPER(fieldName, function). Function must be a free function
 *       taking a class pointer, and returning a const T&
 *
 * The class must provide a constructor that accepts all fields as argument, in
 * the order in which they are declared in the macro.
 *
 * Must be called outside any namespace.
 */
#define QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(name, ...)     \
  __QI_TYPE_STRUCT_DECLARE(name,                             \
    virtual void set(void** storage, const std::vector<void*>&);) \
    __QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_IMPLEMENT(name, inline, /**/, __VA_ARGS__)

/** Similar to QI_TYPE_STRUCT, but using the runtime factory instead of the
 * compile-time template. This macro will register the struct at static
 * initialization time, and thus should only be called from one compilation
 * unit. To ensure this, the simplest option is to use this macro from a .cpp
 * source file. It should *not* be used in a header.
 */
#define QI_TYPE_STRUCT_REGISTER(name, ...) \
namespace _qi_ {                           \
    QI_TYPE_STRUCT(name, __VA_ARGS__);     \
}                                          \
QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)

/** Similar to QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR,
 * but using the runtime factory instead of the
 * compile-time template.
 *
 */
#define QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_REGISTER(name, ...) \
namespace _qi_ {                           \
    QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(name, __VA_ARGS__);     \
}                                          \
QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)

/** Declares that name is equivalent to type bounceTo, and that instances
 * can be converted using the conversion function with signature 'bounceTo* (name*)'.
 * This macro should be called in a header included by all code using the 'name'
 * class.
 * See QI_TYPE_STRUCT_BOUNCE_REGISTER for a similar macro that can be called from a
 * single source file.
 */
#define QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion)                 \
namespace qi {                                                            \
template<> class TypeImpl<name>: public ::qi::StructTypeInterfaceBouncer<name, bounceTo>  \
{                                                                         \
public:                                                                   \
  void adaptStorage(void** storage, void** adapted)                       \
  {                                                                       \
    name* ptr = (name*)ptrFromStorage(storage);                           \
    bounceTo * tptr = conversion(ptr);                                    \
    *adapted = bounceType()->initializeStorage(tptr);                     \
  }                                                                       \
};}

/** Similar to QI_TYPE_STRUCT_BOUNCE, but using the runtime factory instead of the
 * compile-time template.
 */
#define QI_TYPE_STRUCT_BOUNCE_REGISTER(name, bounceTo, conversion)        \
namespace _qi_ {                                                          \
    QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion);                    \
}                                                                         \
QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)

namespace qi {
  //TODO
  template<typename T, typename TO>
  class StructTypeInterfaceBouncer: public StructTypeInterface
  {
  public:
    StructTypeInterface* bounceType()
    {
      static TypeInterface* result = 0;
      if (!result)
        result = typeOf<TO>();
      return static_cast<StructTypeInterface*>(result);
    }

    virtual void adaptStorage(void** storage, void** adapted) = 0;

    typedef DefaultTypeImplMethods<T> Methods;
    virtual std::vector<TypeInterface*> memberTypes()
    {
      return bounceType()->memberTypes();
    }

    virtual void* get(void* storage, unsigned int index)
    {
      void* astorage;
      adaptStorage(&storage, &astorage);
      return bounceType()->get(astorage, index);
    }

    virtual void set(void** storage, unsigned int index, void* valStorage)
    {
      void* astorage;
      adaptStorage(storage, &astorage);
      bounceType()->set(&astorage, index, valStorage);
    }

    virtual std::vector<std::string> elementsName()
    {
      return bounceType()->elementsName();
    }

    _QI_BOUNCE_TYPE_METHODS(Methods);
  };

  template<typename F, typename S>
  class TypeImpl<std::pair<F, S> >: public StructTypeInterface
  {
  public:
    typedef DefaultTypeImplMethods<std::pair<F, S> > Methods;
    typedef typename std::pair<F, S> BackendType;
    std::vector<TypeInterface*> memberTypes()
    {
      static std::vector<TypeInterface*>* result=0;
      if (!result)
      {
        result = new std::vector<TypeInterface*>();
        result->push_back(typeOf<F>());
        result->push_back(typeOf<S>());
      }
      return *result;
    }
    void* get(void* storage, unsigned int index)
    {
      BackendType* ptr = (BackendType*)ptrFromStorage(&storage);
      // Will work if F or S are references
      if (!index)
        return typeOf<F>()->initializeStorage(const_cast<void*>((void*)&ptr->first));
      else
        return typeOf<S>()->initializeStorage(const_cast<void*>((void*)&ptr->second));
    }
    void set(void** storage, unsigned int index, void* valStorage)
    {
      BackendType* ptr = (BackendType*)ptrFromStorage(storage);
      if (!index)
        detail::TypeManagerDefault<F>::copy(const_cast<void*>((void*)&ptr->first), typeOf<F>()->ptrFromStorage(&valStorage));
      else
        detail::TypeManagerDefault<S>::copy(const_cast<void*>((void*)&ptr->second), typeOf<S>()->ptrFromStorage(&valStorage));
    }
    _QI_BOUNCE_TYPE_METHODS(Methods);
  };

}
#endif  // _QITYPE_DETAILS_TYPETUPLE_HXX_
<|endoftext|>


<commit_before>#include <stdio.h>
#include "Filesystem.h"
#include "Stream.h"
#include "Path.h"
#include "String.h"
#include "Hash.h"
#include "Resource.h"
#include "ResourceArchive.h"
#include "FileStream.h"
#include "Pixel.h"
#include "TextureResource.h"
#include <cstring>

using namespace crown;

struct TGAHeader
{

	char		id_length;			// 00h  Size of Image ID field
	char		color_map_type;		// 01h  Color map type
	char		image_type;			// 02h  Image type code
	char		c_map_spec[5];		// 03h  Color map origin 05h Color map length 07h Depth of color map entries
	uint16_t	x_offset;			// 08h  X origin of image
	uint16_t	y_offset;			// 0Ah  Y origin of image
	uint16_t	width;				// 0Ch  Width of image
	uint16_t	height;				// 0Eh  Height of image
	char		pixel_depth;     	// 10h  Image pixel size
	char		image_descriptor;	// 11h  Image descriptor byte
};

void load_uncompressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels);
void load_compressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels);
void swap_red_blue(uint8_t* data, uint64_t size, uint32_t channels);

/// TGA compiler for "tga" resource type
/// TODO: Explain supported formats, usage etc.
int main(int argc, char** argv)
{
	if (argc != 4)
	{
		printf("Usage: %s /path/to/resources resource_in.tga resource_out.tga\n", argv[0]);
		return -1;
	}

	Filesystem fs_root(argv[1]);

	const char* resource = argv[2];
	const char* resource_out = argv[3];

	if (!fs_root.exists(resource))
	{
		printf("Fatal: resource %s does not exists. Aborting.\n", resource);
		return -1;
	}

	char resource_basename[256];
	char resource_extension[256];

	path::filename_without_extension(resource, resource_basename, 256);
	path::extension(resource, resource_extension, 256);

	printf("Resource basename  : %s\n", resource_basename);
	printf("Resource extension : %s\n", resource_extension);

	uint32_t resource_basename_hash = hash::fnv1a_32(resource_basename, string::strlen(resource_basename));
	uint32_t resource_extension_hash = hash::fnv1a_32(resource_extension, string::strlen(resource_extension));

	printf("Resource basename  (hash) : %X\n", resource_basename_hash);
	printf("Resource extension (hash) : %X\n", resource_extension_hash);

	FileStream* src_file = (FileStream*)fs_root.open(resource, SOM_READ);

	//-------------------------------------------------------------------------
	// Read TGA Header
	//-------------------------------------------------------------------------

	// The TGA header used throughout the code
	TGAHeader header;
	memset(&header, 0, sizeof(TGAHeader));

	// Read the header
	src_file->read(&header, sizeof(TGAHeader));

	// Skip TGA ID
	src_file->skip(header.id_length);

	// Pixel format currently unknown
	PixelFormat format = PF_UNKNOWN;

	// Compute color channels
	uint32_t channels = header.pixel_depth / 8;

	// Compute image size
	uint64_t image_size = header.width * header.height;

	uint8_t* image_data = NULL;

	// Select the appropriate pixel format and allocate resource data based on tga size and channels
	switch (channels)
	{
		case 2:
		case 3:
		{
			format = PF_RGB_8;
			image_data = new uint8_t[(uint32_t)(image_size * 3)];

			break;
		}
		case 4:
		{
			format = PF_RGBA_8;
			image_data = new uint8_t[(uint32_t)(image_size * channels)];

			break;
		}
		default:
		{
			printf("Fatal: Unable to determine TGA channels. Aborting.\n");
			return -1;
		}
	}

	printf("Debug: w = %d, h = %d, channels = %d\n", header.width, header.height, channels);

	// Determine image type (compressed/uncompressed) and call proper function to load TGA
	switch (header.image_type)
	{
		case 0:
		{
			printf("Fatal: The resource does not contain image data. Aborting.");
			return -1;
		}
		case 2:
		{
			printf("Debug: loading uncompressed...\n");
			load_uncompressed(image_data, src_file, header.width, header.height, channels);
			break;
		}

		case 10:
		{
			printf("Debug: loading compressed...\n");
			load_compressed(image_data, src_file, header.width, header.height, channels);
			break;
		}

		default:
		{
			printf("Fatal: Image type not supported. Aborting.");
			return -1;
		}
	}

	// FIXME Fixed options for now until proper settings management implemented
	TextureMode		mode = TM_MODULATE;
	TextureFilter	filter = TF_BILINEAR;
	TextureWrap		wrap = TW_REPEAT;

	// Open output file
	FileStream* dest_file = (FileStream*)fs_root.open(resource_out, SOM_WRITE);

	ArchiveEntry archive_entry;
	archive_entry.name = resource_basename_hash;
	archive_entry.type = resource_extension_hash;
	archive_entry.offset = sizeof(ArchiveEntry);
	archive_entry.size = image_size * channels + sizeof(PixelFormat) + sizeof(uint16_t) * 2 +
							sizeof(TextureMode) + sizeof(TextureFilter) + sizeof(TextureWrap);

	// Write out the archive entry
	dest_file->write(&archive_entry, sizeof(ArchiveEntry));

	// Write out the data
	dest_file->write(&format, sizeof(PixelFormat));
	dest_file->write(&header.width, sizeof(uint16_t));
	dest_file->write(&header.height, sizeof(uint16_t));

	dest_file->write(&mode, sizeof(TextureMode));
	dest_file->write(&filter, sizeof(TextureFilter));
	dest_file->write(&wrap, sizeof(TextureWrap));

	dest_file->write(image_data, image_size * channels);

	// Done, free the resources and exit
	if (image_data != NULL)
	{
		delete[] image_data;
	}

	fs_root.close(dest_file);

	return 0;
}

//-----------------------------------------------------------------------------
void load_uncompressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels)
{
	uint64_t size = width * height;

	uint8_t* data = (uint8_t*)dest;

	if (channels == 2)
	{
		int32_t j = 0;

		for (uint64_t i = 0; i < size * channels; i++)
		{
			uint16_t pixel_data;

			stream->read(&pixel_data, sizeof(pixel_data));

			data[j + 0] = (pixel_data & 0x7c) >> 10;
			data[j + 1] = (pixel_data & 0x3e) >> 5;
			data[j + 2] = (pixel_data & 0x1f);

			j += 3;
		}
	}
	else
	{
		stream->read(data, (size_t)(size * channels));

		swap_red_blue(data, size * channels, channels);
	}
}

//-----------------------------------------------------------------------------
void load_compressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels)
{
	uint8_t rle_id = 0;
	uint32_t i = 0;
	uint32_t colors_read = 0;
	uint64_t size = width * height;

	uint8_t* data = (uint8_t*)dest;

	uint8_t* colors = new uint8_t[channels];

	while (i < size)
	{
		stream->read(&rle_id, sizeof(uint8_t));

		// If MSB == 1
		if (rle_id & 0x80)
		{
			rle_id -= 127;

			stream->read(colors, channels);

			while (rle_id)
			{
				data[colors_read + 0] = colors[2];
				data[colors_read + 1] = colors[1];
				data[colors_read + 2] = colors[0];

				if (channels == 4)
				{
					data[colors_read + 3] = colors[3];
				}

				rle_id--;
				colors_read += channels;
				i++;
			}
		}
		else
		{
			rle_id++;

			while (rle_id)
			{
				stream->read(colors, channels);

				data[colors_read + 0] = colors[2];
				data[colors_read + 1] = colors[1];
				data[colors_read + 2] = colors[0];

				if (channels == 4)
				{
					data[colors_read + 3] = colors[3];
				}

				rle_id--;
				colors_read += channels;
				i++;
			}
		}
	}

	delete[] colors;
}

//-----------------------------------------------------------------------------
void swap_red_blue(uint8_t* data, uint64_t size, uint32_t channels)
{
	for (uint64_t i = 0; i < size; i += channels)
	{
		data[i] ^= data[i+2];
		data[i+2] ^= data[i];
		data[i] ^= data[i+2];
	}
}

<commit_msg>Improve CLI of tga-compiler<commit_after>#include <stdio.h>
#include <stdlib.h>

#include "Crown.h"

const char* root_path = NULL;
const char* resource_in = NULL;
const char* resource_out = NULL;

void print_help_message(const char* program_name);
void parse_command_line(int argc, char** argv);

using namespace crown;

struct TGAHeader
{

	char		id_length;			// 00h  Size of Image ID field
	char		color_map_type;		// 01h  Color map type
	char		image_type;			// 02h  Image type code
	char		c_map_spec[5];		// 03h  Color map origin 05h Color map length 07h Depth of color map entries
	uint16_t	x_offset;			// 08h  X origin of image
	uint16_t	y_offset;			// 0Ah  Y origin of image
	uint16_t	width;				// 0Ch  Width of image
	uint16_t	height;				// 0Eh  Height of image
	char		pixel_depth;     	// 10h  Image pixel size
	char		image_descriptor;	// 11h  Image descriptor byte
};

void print_help_message(const char* program_name);
void parse_command_line(int argc, char** argv);

void load_uncompressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels);
void load_compressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels);
void swap_red_blue(uint8_t* data, uint64_t size, uint32_t channels);

/// TGA compiler for "tga" resource type
/// TODO: Explain supported formats, usage etc.
int main(int argc, char** argv)
{
	parse_command_line(argc, argv);

	// FIXME: validate input

	Filesystem fs_root(root_path);

	if (!fs_root.exists(resource_in))
	{
		printf("%s: ERROR: %s does not exist. Aborting.\n", argv[0], resource_in);
		return -1;
	}

	char resource_basename[256];
	char resource_extension[256];

	path::filename_without_extension(resource_in, resource_basename, 256);
	path::extension(resource_in, resource_extension, 256);

	uint32_t resource_basename_hash = hash::fnv1a_32(resource_basename, string::strlen(resource_basename));
	uint32_t resource_extension_hash = hash::fnv1a_32(resource_extension, string::strlen(resource_extension));

	FileStream* src_file = (FileStream*)fs_root.open(resource_in, SOM_READ);

	//-------------------------------------------------------------------------
	// Read TGA Header
	//-------------------------------------------------------------------------

	// The TGA header used throughout the code
	TGAHeader header;
	memset(&header, 0, sizeof(TGAHeader));

	// Read the header
	src_file->read(&header, sizeof(TGAHeader));

	// Skip TGA ID
	src_file->skip(header.id_length);

	// Pixel format currently unknown
	PixelFormat format = PF_UNKNOWN;

	// Compute color channels
	uint32_t channels = header.pixel_depth / 8;

	// Compute image size
	uint64_t image_size = header.width * header.height;

	uint8_t* image_data = NULL;

	// Select the appropriate pixel format and allocate resource data based on tga size and channels
	switch (channels)
	{
		case 2:
		case 3:
		{
			format = PF_RGB_8;
			image_data = new uint8_t[(uint32_t)(image_size * 3)];

			break;
		}
		case 4:
		{
			format = PF_RGBA_8;
			image_data = new uint8_t[(uint32_t)(image_size * channels)];

			break;
		}
		default:
		{
			printf("Fatal: Unable to determine TGA channels. Aborting.\n");
			return -1;
		}
	}

	printf("Debug: w = %d, h = %d, channels = %d\n", header.width, header.height, channels);

	// Determine image type (compressed/uncompressed) and call proper function to load TGA
	switch (header.image_type)
	{
		case 0:
		{
			printf("Fatal: The resource does not contain image data. Aborting.");
			return -1;
		}
		case 2:
		{
			printf("Debug: loading uncompressed...\n");
			load_uncompressed(image_data, src_file, header.width, header.height, channels);
			break;
		}

		case 10:
		{
			printf("Debug: loading compressed...\n");
			load_compressed(image_data, src_file, header.width, header.height, channels);
			break;
		}

		default:
		{
			printf("Fatal: Image type not supported. Aborting.");
			return -1;
		}
	}

	// FIXME Fixed options for now until proper settings management implemented
	TextureMode		mode = TM_MODULATE;
	TextureFilter	filter = TF_BILINEAR;
	TextureWrap		wrap = TW_REPEAT;

	// Open output file
	FileStream* dest_file = (FileStream*)fs_root.open(resource_out, SOM_WRITE);

	ArchiveEntry archive_entry;
	archive_entry.name = resource_basename_hash;
	archive_entry.type = resource_extension_hash;
	archive_entry.offset = sizeof(ArchiveEntry);
	archive_entry.size = image_size * channels + sizeof(PixelFormat) + sizeof(uint16_t) * 2 +
							sizeof(TextureMode) + sizeof(TextureFilter) + sizeof(TextureWrap);

	// Write out the archive entry
	dest_file->write(&archive_entry, sizeof(ArchiveEntry));

	// Write out the data
	dest_file->write(&format, sizeof(PixelFormat));
	dest_file->write(&header.width, sizeof(uint16_t));
	dest_file->write(&header.height, sizeof(uint16_t));

	dest_file->write(&mode, sizeof(TextureMode));
	dest_file->write(&filter, sizeof(TextureFilter));
	dest_file->write(&wrap, sizeof(TextureWrap));

	dest_file->write(image_data, image_size * channels);

	// Done, free the resources and exit
	if (image_data != NULL)
	{
		delete[] image_data;
	}

	fs_root.close(dest_file);

	return 0;
}

//-----------------------------------------------------------------------------
void parse_command_line(int argc, char** argv)
{
	// Parse arguments
	ArgsOption options[] =
	{
		"help",         AOA_NO_ARGUMENT,       NULL,        'h',
		"root-path",    AOA_REQUIRED_ARGUMENT, NULL,        'r',
		"resource-in",  AOA_REQUIRED_ARGUMENT, NULL,        'i',
		"resource-out", AOA_REQUIRED_ARGUMENT, NULL,        'o',
		NULL, 0, NULL, 0
	};

	Args args(argc, argv, "", options);

	while (1)
	{
		int32_t ret = args.next_option();

		switch (ret)
		{
			case -1:
			{
				return;
			}
			// Help message
			case 'h':
			{
				print_help_message(argv[0]);
				exit(0);
			}
			// Root path
			case 'r':
			{
				if (args.option_argument() == NULL)
				{
					printf("%s: ERROR: missing path after `--root-path`\n", argv[0]);
					exit(-1);
				}

				root_path = args.option_argument();

				break;
			}
			// Resource in
			case 'i':
			{
				if (args.option_argument() == NULL)
				{
					printf("%s: ERROR: missing path after `--resource-in`\n", argv[0]);
					exit(-1);
				}

				resource_in = args.option_argument();

				break;
			}
			// Resource out
			case 'o':
			{
				if (args.option_argument() == NULL)
				{
					printf("%s: ERROR: missing path after `--resource-out`\n", argv[0]);
					exit(-1);
				}

				resource_out = args.option_argument();

				break;
			}
			default:
			{
				break;
			}
		}
	}
}

//-----------------------------------------------------------------------------
void print_help_message(const char* program_name)
{
	printf("Usage: %s [options]\n", program_name);
	printf("Options:\n\n");

	printf("  --help                  Show this help.\n");
	printf("  --root-path <path>      The _absolute_ <path> whether to look for the input resource.\n");
	printf("  --resource-in <path>    The _relative_ <path> of the input resource.\n");
	printf("  --resource-out <width>  The _relative_ <path> of the output resource.\n");
}

//-----------------------------------------------------------------------------
void load_uncompressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels)
{
	uint64_t size = width * height;

	uint8_t* data = (uint8_t*)dest;

	if (channels == 2)
	{
		int32_t j = 0;

		for (uint64_t i = 0; i < size * channels; i++)
		{
			uint16_t pixel_data;

			stream->read(&pixel_data, sizeof(pixel_data));

			data[j + 0] = (pixel_data & 0x7c) >> 10;
			data[j + 1] = (pixel_data & 0x3e) >> 5;
			data[j + 2] = (pixel_data & 0x1f);

			j += 3;
		}
	}
	else
	{
		stream->read(data, (size_t)(size * channels));

		swap_red_blue(data, size * channels, channels);
	}
}

//-----------------------------------------------------------------------------
void load_compressed(void* dest, Stream* stream, uint32_t width, uint32_t height, uint32_t channels)
{
	uint8_t rle_id = 0;
	uint32_t i = 0;
	uint32_t colors_read = 0;
	uint64_t size = width * height;

	uint8_t* data = (uint8_t*)dest;

	uint8_t* colors = new uint8_t[channels];

	while (i < size)
	{
		stream->read(&rle_id, sizeof(uint8_t));

		// If MSB == 1
		if (rle_id & 0x80)
		{
			rle_id -= 127;

			stream->read(colors, channels);

			while (rle_id)
			{
				data[colors_read + 0] = colors[2];
				data[colors_read + 1] = colors[1];
				data[colors_read + 2] = colors[0];

				if (channels == 4)
				{
					data[colors_read + 3] = colors[3];
				}

				rle_id--;
				colors_read += channels;
				i++;
			}
		}
		else
		{
			rle_id++;

			while (rle_id)
			{
				stream->read(colors, channels);

				data[colors_read + 0] = colors[2];
				data[colors_read + 1] = colors[1];
				data[colors_read + 2] = colors[0];

				if (channels == 4)
				{
					data[colors_read + 3] = colors[3];
				}

				rle_id--;
				colors_read += channels;
				i++;
			}
		}
	}

	delete[] colors;
}

//-----------------------------------------------------------------------------
void swap_red_blue(uint8_t* data, uint64_t size, uint32_t channels)
{
	for (uint64_t i = 0; i < size; i += channels)
	{
		data[i] ^= data[i+2];
		data[i+2] ^= data[i];
		data[i] ^= data[i+2];
	}
}

<|endoftext|>


<commit_before>#include "femeoc.hh"

namespace Dune {
namespace Stuff {
namespace Fem {

FemEoc::FemEoc()
  : outputFile_()
    , level_(0)
    , prevError_(0)
    , error_(0)
    , description_(0)
    , prevh_(0)
    , initial_(true)
    , pos_(0)
{}

FemEoc::~FemEoc() {
  outputFile_.close();
}

void FemEoc::init(const std::string& path,
          const std::string& name, const std::string& descript, const std::string& inputFile) {
  if ( !Dune::directoryExists(path) && !Dune::createDirectory(path) )
    DUNE_THROW( Dune::IOError, (boost::format("couldn't create directory") % path).str() );
  init(path + "/" + name, descript, path + "/" + inputFile);
}

void FemEoc::init(const std::string& name, const std::string& descript, const std::string& inputFile) {
  if ( !outputFile_.is_open() )
  {
    std::ofstream main( (name + "_main.tex").c_str() );
    std::ifstream input( inputFile.c_str() );
    if (!main)
    {
      std::cerr << "Could not open file : "
                << (name + "_main.tex").c_str()
                << " ... ABORTING" << std::endl;
      abort();
    }

    std::ostringstream filestreamBody;
    filestreamBody << name << "_body.tex";
    outputFile_.open(filestreamBody.str().c_str(), std::ios::out);
    std::string bodyfile = filestreamBody.str().substr(filestreamBody.str().find(
                                                         '/') != std::string::npos ? filestreamBody.str().find(
                                                         '/') + 1 : 0);

    if (!input)
    {
      std::cerr << "Could not open file : "
                << inputFile
                << " ... using default template" << std::endl;
      main << "\\documentclass[10pt,english]{article}\n"
           << "\\usepackage{fontenc}\n"
           << "\\usepackage{vmargin}\n"
           << "\\usepackage{longtable}\n"
           << "\\setpapersize[landscape]{A4}\n"
           << "\\usepackage[latin1]{inputenc}\n"
           << "\\usepackage{setspace}\n"
           << "\\onehalfspacing\n"
           << "\\makeatletter\n"
           << "\\providecommand{\\boldsymbol}[1]{\\mbox{\\boldmath $#1$}}\n"
           << "\\providecommand{\\tabularnewline}{\\\\}\n"
           << "\\usepackage{babel}\n"
           << "\\makeatother\n"
           << "\\begin{document}\n"
           << "\\begin{center}\\large\n"
           << descript
           << "\n\\end{center}\n\n"
           << "\\input{"
           << bodyfile
           << "}\n"
           << "\\end{document}\n" << std::endl;
    } else {
      std::stringstream inputTex;
      while ( input.good() )
      {
        inputTex << (char) input.get();
      }
      std::string input_str = inputTex.str();
      int pos = input_str.find("DESCRIPTION", 0);
      input_str.replace(pos, 11, "");
      input_str.insert(pos, descript);

      pos = input_str.find("BODYFILE", 0);
      input_str.replace(pos, 8, "");
      input_str.insert(pos, bodyfile);

      main << input_str;
    }
    main.close();
  } else {
    DUNE_THROW(Dune::InvalidStateException, "");
  }
} // init

size_t FemEoc::addentry(const std::string& descript) {
  if (!initial_)
    DUNE_THROW(Dune::InvalidStateException, "");
  pos_.push_back( error_.size() );
  error_.push_back(0);
  prevError_.push_back(0);
  description_.push_back(descript);
  return pos_.size() - 1;
} // addentry

void FemEoc::seterrors(size_t id, const double& err) {
  int pos = pos_[id];

  error_[pos] = err;
}

void FemEoc::writeerr(double h, double size, double time, int counter) {
  if (initial_)
  {
    outputFile_ << "\\begin{tabular}{|c|c|c|c|c|";
    for (unsigned int i = 0; i < error_.size(); i++)
    {
      outputFile_ << "|cc|";
    }
    outputFile_ << "}\n"
                << "\\hline \n"
                << "level & h & size & CPU-time & counter";
    for (unsigned int i = 0; i < error_.size(); i++)
    {
      outputFile_ << " & " << description_[i]
                  << " & EOC ";
    }
    outputFile_ << "\n \\tabularnewline\n"
                << "\\hline\n"
                << "\\hline\n";
  }
  outputFile_ << "\\hline \n"
              << level_ << " & "
              << h << " & "
              << size << " & "
              << time << " & "
              << counter;
  for (unsigned int i = 0; i < error_.size(); ++i)
  {
    outputFile_ << " & " << error_[i] << " & ";
    if (initial_)
    {
      outputFile_ << " --- ";
    } else {
      double factor = prevh_ / h;
      outputFile_ << log(prevError_[i] / error_[i]) / log(factor);
    }
    prevError_[i] = error_[i];
    error_[i] = -1;  // uninitialized
  }
  outputFile_ << "\n"
              << "\\tabularnewline\n"
              << "\\hline \n";
  outputFile_.flush();
  prevh_ = h;
  level_++;
  initial_ = false;
} // writeerr

} // namespace Stuff
} // namespace Fem
} // namespace Dune
<commit_msg>[fem.femeoc.cc] added HAVE_DUNE_FEM guard<commit_after>#include "femeoc.hh"

#ifdef HAVE_DUNE_FEM

namespace Dune {
namespace Stuff {
namespace Fem {

FemEoc::FemEoc()
  : outputFile_()
    , level_(0)
    , prevError_(0)
    , error_(0)
    , description_(0)
    , prevh_(0)
    , initial_(true)
    , pos_(0)
{}

FemEoc::~FemEoc() {
  outputFile_.close();
}

void FemEoc::init(const std::string& path,
          const std::string& name, const std::string& descript, const std::string& inputFile) {
  if ( !Dune::directoryExists(path) && !Dune::createDirectory(path) )
    DUNE_THROW( Dune::IOError, (boost::format("couldn't create directory") % path).str() );
  init(path + "/" + name, descript, path + "/" + inputFile);
}

void FemEoc::init(const std::string& name, const std::string& descript, const std::string& inputFile) {
  if ( !outputFile_.is_open() )
  {
    std::ofstream main( (name + "_main.tex").c_str() );
    std::ifstream input( inputFile.c_str() );
    if (!main)
    {
      std::cerr << "Could not open file : "
                << (name + "_main.tex").c_str()
                << " ... ABORTING" << std::endl;
      abort();
    }

    std::ostringstream filestreamBody;
    filestreamBody << name << "_body.tex";
    outputFile_.open(filestreamBody.str().c_str(), std::ios::out);
    std::string bodyfile = filestreamBody.str().substr(filestreamBody.str().find(
                                                         '/') != std::string::npos ? filestreamBody.str().find(
                                                         '/') + 1 : 0);

    if (!input)
    {
      std::cerr << "Could not open file : "
                << inputFile
                << " ... using default template" << std::endl;
      main << "\\documentclass[10pt,english]{article}\n"
           << "\\usepackage{fontenc}\n"
           << "\\usepackage{vmargin}\n"
           << "\\usepackage{longtable}\n"
           << "\\setpapersize[landscape]{A4}\n"
           << "\\usepackage[latin1]{inputenc}\n"
           << "\\usepackage{setspace}\n"
           << "\\onehalfspacing\n"
           << "\\makeatletter\n"
           << "\\providecommand{\\boldsymbol}[1]{\\mbox{\\boldmath $#1$}}\n"
           << "\\providecommand{\\tabularnewline}{\\\\}\n"
           << "\\usepackage{babel}\n"
           << "\\makeatother\n"
           << "\\begin{document}\n"
           << "\\begin{center}\\large\n"
           << descript
           << "\n\\end{center}\n\n"
           << "\\input{"
           << bodyfile
           << "}\n"
           << "\\end{document}\n" << std::endl;
    } else {
      std::stringstream inputTex;
      while ( input.good() )
      {
        inputTex << (char) input.get();
      }
      std::string input_str = inputTex.str();
      int pos = input_str.find("DESCRIPTION", 0);
      input_str.replace(pos, 11, "");
      input_str.insert(pos, descript);

      pos = input_str.find("BODYFILE", 0);
      input_str.replace(pos, 8, "");
      input_str.insert(pos, bodyfile);

      main << input_str;
    }
    main.close();
  } else {
    DUNE_THROW(Dune::InvalidStateException, "");
  }
} // init

size_t FemEoc::addentry(const std::string& descript) {
  if (!initial_)
    DUNE_THROW(Dune::InvalidStateException, "");
  pos_.push_back( error_.size() );
  error_.push_back(0);
  prevError_.push_back(0);
  description_.push_back(descript);
  return pos_.size() - 1;
} // addentry

void FemEoc::seterrors(size_t id, const double& err) {
  int pos = pos_[id];

  error_[pos] = err;
}

void FemEoc::writeerr(double h, double size, double time, int counter) {
  if (initial_)
  {
    outputFile_ << "\\begin{tabular}{|c|c|c|c|c|";
    for (unsigned int i = 0; i < error_.size(); i++)
    {
      outputFile_ << "|cc|";
    }
    outputFile_ << "}\n"
                << "\\hline \n"
                << "level & h & size & CPU-time & counter";
    for (unsigned int i = 0; i < error_.size(); i++)
    {
      outputFile_ << " & " << description_[i]
                  << " & EOC ";
    }
    outputFile_ << "\n \\tabularnewline\n"
                << "\\hline\n"
                << "\\hline\n";
  }
  outputFile_ << "\\hline \n"
              << level_ << " & "
              << h << " & "
              << size << " & "
              << time << " & "
              << counter;
  for (unsigned int i = 0; i < error_.size(); ++i)
  {
    outputFile_ << " & " << error_[i] << " & ";
    if (initial_)
    {
      outputFile_ << " --- ";
    } else {
      double factor = prevh_ / h;
      outputFile_ << log(prevError_[i] / error_[i]) / log(factor);
    }
    prevError_[i] = error_[i];
    error_[i] = -1;  // uninitialized
  }
  outputFile_ << "\n"
              << "\\tabularnewline\n"
              << "\\hline \n";
  outputFile_.flush();
  prevh_ = h;
  level_++;
  initial_ = false;
} // writeerr

} // namespace Stuff
} // namespace Fem
} // namespace Dune

#endif // HAVE_DUNE_FEM
<|endoftext|>