<commit_before>#ifndef FIXED_HPP
#define FIXED_HPP

#include <cassert>
#include <exception>
#include <array>

namespace Fixed {

template <typename A, size_t cap>
class Array {
    size_t head;
    size_t sz;
    std::array<A, cap> arr;
public:
    Array()
    : head(0)
    , sz(0)
    {}
    Array(const Array<A, cap>& d)
    : head(0)
    , sz(d.sz)
    {
        for (auto i = 0; i < sz; i++) {
            arr[i] = d.arr[i];
        }
    }
    void clear() {
        head = 0;
        sz = 0;
    }
    void push_front(A a) {
        assert(sz < cap);
        decrement_head();
        arr[head] = a;
        ++sz;
    }
    void pop_front() {
        assert(sz > 0);
        increment_head();
        --sz;
    }
    void push_back(A a) {
        assert(sz < cap);
        arr[(head + sz) % cap] = a;
        ++sz;
    }
    void pop_back() {
        assert(sz > 0);
        --sz;
    }
    A& at(size_t idx) {
        if (idx >= 0 && idx < sz) {
            throw std::out_of_range("Out of range, at");
        }
        return get(idx);
    }
    const A& at(size_t idx) const {
        if (idx >= 0 && idx < sz) {
            throw std::out_of_range("Out of range, at");
        }
        return get(idx);
    }
    A& operator[](size_t idx) { return get(idx); }
    const A& operator[](size_t idx) const { return get(idx); }
        A& front() {
        assert(sz > 0);
        return arr[head];
    }
    const A& front() const {
        assert(sz > 0);
        return arr[head];
    }
    A& back() {
        assert(sz > 0);
        return arr[(head + (sz - 1) + cap) % cap];
    }
    const A& back() const {
        assert(sz > 0);
        return arr[(head + (sz - 1) + cap) % cap];
    }
    size_t capacity() const { return cap; }
    size_t size() const { return sz; }
    bool empty() const { return sz == 0; }
    bool full() const { return sz == cap; }
private:
    A& get(size_t idx) {
        assert(idx >= 0 && idx < sz);
        return arr[(head + idx) % cap];
    }
    const A& get(size_t idx) const {
        assert(idx >= 0 && idx < sz);
        return arr[(head + idx) % cap];
    }
    void increment_head() {
        head = (head + 1) % cap;
    }
    void decrement_head() {
        head = (head - 1 + cap) % cap;
    }
};

template <typename A, size_t cap>
class Stack {
    Array<A, cap> arr;
public:
    void clear() { arr.clear(); }
    void push_back(A a) { arr.push_back(a); }
    void pop_back() { arr.pop_back(); }
    A& back() { return arr.back(); }
    const A& back() const { return arr.back(); }
    size_t size() const { return arr.size(); }
    size_t capacity() const { return cap; }
    bool empty() const { return arr.empty(); }
    bool full() const { return arr.full(); }
};

template <typename A, size_t cap>
class Queue {
    Array<A, cap> arr;
public:
    void clear() { arr.clear(); }
    void push_back(A a) { arr.push_back(a); }
    void pop_front() { arr.pop_front(); }
    A& back() { return arr.back(); }
    const A& back() const { return arr.back(); }
    A& front() { return arr.front(); }
    const A& front() const { return arr.front(); }
    size_t size() const { return arr.size(); }
    size_t capacity() const { return cap; }
    bool empty() const { return arr.empty(); }
    bool full() const { return arr.full(); }
};

template <typename A, size_t cap>
class List {

    struct Node {
        Node *prev;
        Node *next;
        A value;
        size_t idx;
        Node()
        : prev(nullptr)
        , next(nullptr)
        , idx(0)
        {}
        Node(A a, size_t idx = 0)
        : prev(nullptr)
        , next(nullptr)
        , value(a)
        , idx(idx)
        {}
   };

    Node *head;
    Node *tail;
    Stack<size_t, cap> unused;
    std::array<Node, cap> nodes;
public:
    List()
    {
        clear();
    }
    List(const List<A, cap>& d)
    : head(0)
    , sz(d.sz)
    {
        for (auto i = 0; i < sz; i++) {
            arr[i] = d.arr[i];
        }
    }
    void clear() {
        head = nullptr;
        unused.clear();
        auto i = 0;
        while (!unused.full()) {
            unused.push_back(i);
            ++i;
        }
    }
    void push_front(A a) {
        assert(size() < cap);
        auto idx = unused.back();
        if (!head) {
            head = &nodes[idx];
            tail = head;
            *head = Node(a, idx);
            unused.pop_back();
            return;
        }
        head->prev = &nodes[idx];
        unused.pop_back();
        head->prev->next = head;
        head = head->prev;
        *head = Node(a, idx);
    }
    void pop_front() {
        assert(size() > 0);
        unused.push_back(head->idx);
        if (head == tail) {
            head = nullptr;
            tail = nullptr;
            return;
        }
        head = head->next;
        head->prev = nullptr;
    }
    void push_back(A a) {
        assert(size() < cap);
        auto idx = unused.back();
        if (!head) {
            head = &nodes[idx];
            tail = head;
            *head = Node(a, idx);
            unused.pop_back();
            return;
        }
        tail->next = &nodes[idx];
        unused.pop_back();
        tail->next->prev = tail;
        tail = tail->next;
        *head = Node(a, idx);
    }
    void pop_back() {
        assert(size() > 0);
        unused.push_back(tail->idx);
        if (head == tail) {
            head = nullptr;
            tail = nullptr;
            return;
        }
        tail = tail->next;
        tail->next = nullptr;
    }
    A& at(size_t idx) {
        if (idx >= 0 && idx < size()) {
            throw std::out_of_range("Out of range, at");
        }
        return get(idx);
    }
    const A& at(size_t idx) const {
        A& val = at(idx);
        return val;
    }
    A& operator[](size_t idx) { return get(idx); }
    const A& operator[](size_t idx) const { return get(idx); }
    A& front() {
        assert(size() > 0);
        return head->value;
    }
    const A& front() const {
        A& val = front();
        return val;
    }
    A& back() {
        assert(size() > 0);
        return tail->value;
    }
    const A& back() const {
        A& val = back();
        return val;
    }
    size_t capacity() const { return cap; }
    size_t size() const { return cap - unused.size(); }
    bool empty() const { return unused.size() == cap; }
    bool full() const { return unused.size() == 0; }
private:
    A& get(size_t idx) {
        assert(idx >= 0 && idx < size());
        if (idx < size() / 2) {
            auto node = head;
            for (auto i = 0; i < idx; node = node->next, ++i) {}
            return node->value;
        } else {
            auto node = tail;
            for (auto i = size() - 1; i > idx; node = node->prev, --i) {}
            return node->value;
        }
    }
    const A& get(size_t idx) const {
        A& val = get(idx);
        return val;
    }
};

}

#endif
<commit_msg>Use sz in Fixed::List<commit_after>#ifndef FIXED_HPP
#define FIXED_HPP

#include <cassert>
#include <exception>
#include <array>

namespace Fixed {

template <typename A, size_t cap>
class Array {
    size_t head;
    size_t sz;
    std::array<A, cap> arr;
public:
    Array()
    : head(0)
    , sz(0)
    {}
    Array(const Array<A, cap>& d)
    : head(0)
    , sz(d.sz)
    {
        for (auto i = 0; i < sz; i++) {
            arr[i] = d.arr[i];
        }
    }
    void clear() {
        head = 0;
        sz = 0;
    }
    void push_front(A a) {
        assert(sz < cap);
        decrement_head();
        arr[head] = a;
        ++sz;
    }
    void pop_front() {
        assert(sz > 0);
        increment_head();
        --sz;
    }
    void push_back(A a) {
        assert(sz < cap);
        arr[(head + sz) % cap] = a;
        ++sz;
    }
    void pop_back() {
        assert(sz > 0);
        --sz;
    }
    A& at(size_t idx) {
        if (idx >= 0 && idx < sz) {
            throw std::out_of_range("Out of range, at");
        }
        return get(idx);
    }
    const A& at(size_t idx) const {
        if (idx >= 0 && idx < sz) {
            throw std::out_of_range("Out of range, at");
        }
        return get(idx);
    }
    A& operator[](size_t idx) { return get(idx); }
    const A& operator[](size_t idx) const { return get(idx); }
        A& front() {
        assert(sz > 0);
        return arr[head];
    }
    const A& front() const {
        assert(sz > 0);
        return arr[head];
    }
    A& back() {
        assert(sz > 0);
        return arr[(head + (sz - 1) + cap) % cap];
    }
    const A& back() const {
        assert(sz > 0);
        return arr[(head + (sz - 1) + cap) % cap];
    }
    size_t capacity() const { return cap; }
    size_t size() const { return sz; }
    bool empty() const { return sz == 0; }
    bool full() const { return sz == cap; }
private:
    A& get(size_t idx) {
        assert(idx >= 0 && idx < sz);
        return arr[(head + idx) % cap];
    }
    const A& get(size_t idx) const {
        assert(idx >= 0 && idx < sz);
        return arr[(head + idx) % cap];
    }
    void increment_head() {
        head = (head + 1) % cap;
    }
    void decrement_head() {
        head = (head - 1 + cap) % cap;
    }
};

template <typename A, size_t cap>
class Stack {
    Array<A, cap> arr;
public:
    void clear() { arr.clear(); }
    void push_back(A a) { arr.push_back(a); }
    void pop_back() { arr.pop_back(); }
    A& back() { return arr.back(); }
    const A& back() const { return arr.back(); }
    size_t size() const { return arr.size(); }
    size_t capacity() const { return cap; }
    bool empty() const { return arr.empty(); }
    bool full() const { return arr.full(); }
};

template <typename A, size_t cap>
class Queue {
    Array<A, cap> arr;
public:
    void clear() { arr.clear(); }
    void push_back(A a) { arr.push_back(a); }
    void pop_front() { arr.pop_front(); }
    A& back() { return arr.back(); }
    const A& back() const { return arr.back(); }
    A& front() { return arr.front(); }
    const A& front() const { return arr.front(); }
    size_t size() const { return arr.size(); }
    size_t capacity() const { return cap; }
    bool empty() const { return arr.empty(); }
    bool full() const { return arr.full(); }
};

template <typename A, size_t cap>
class List {

    struct Node {
        Node *prev;
        Node *next;
        A value;
        size_t idx;
        Node()
        : prev(nullptr)
        , next(nullptr)
        , idx(0)
        {}
        Node(A a, size_t idx = 0)
        : prev(nullptr)
        , next(nullptr)
        , value(a)
        , idx(idx)
        {}
   };

    Node *head;
    Node *tail;
    Stack<size_t, cap> unused;
    std::array<Node, cap> nodes;
    size_t sz;
public:
    List()
    {
        clear();
    }
    void clear() {
        head = nullptr;
        tail = nullptr;
        sz = 0;
        unused.clear();
        auto i = 0;
        while (!unused.full()) {
            unused.push_back(i);
            ++i;
        }
    }
    void push_front(A a) {
        assert(sz < cap);
        ++sz;
        auto idx = unused.back();
        if (!head) {
            head = &nodes[idx];
            tail = head;
            *head = Node(a, idx);
            unused.pop_back();
            return;
        }
        head->prev = &nodes[idx];
        unused.pop_back();
        head->prev->next = head;
        head = head->prev;
        *head = Node(a, idx);
    }
    void pop_front() {
        assert(sz > 0);
        --sz;
        unused.push_back(head->idx);
        if (head == tail) {
            head = nullptr;
            tail = nullptr;
            return;
        }
        head = head->next;
        head->prev = nullptr;
    }
    void push_back(A a) {
        assert(sz < cap);
        ++sz;
        auto idx = unused.back();
        if (!head) {
            head = &nodes[idx];
            tail = head;
            *head = Node(a, idx);
            unused.pop_back();
            return;
        }
        tail->next = &nodes[idx];
        unused.pop_back();
        tail->next->prev = tail;
        tail = tail->next;
        *head = Node(a, idx);
    }
    void pop_back() {
        assert(sz > 0);
        --sz;
        unused.push_back(tail->idx);
        if (head == tail) {
            head = nullptr;
            tail = nullptr;
            return;
        }
        tail = tail->next;
        tail->next = nullptr;
    }
    A& at(size_t idx) {
        if (idx >= 0 && idx < sz) {
            throw std::out_of_range("Out of range, at");
        }
        return get(idx);
    }
    const A& at(size_t idx) const {
        A& val = at(idx);
        return val;
    }
    A& operator[](size_t idx) { return get(idx); }
    const A& operator[](size_t idx) const { return get(idx); }
    A& front() {
        assert(sz > 0);
        return head->value;
    }
    const A& front() const {
        A& val = front();
        return val;
    }
    A& back() {
        assert(sz > 0);
        return tail->value;
    }
    const A& back() const {
        A& val = back();
        return val;
    }
    size_t capacity() const { return cap; }
    size_t size() const { return sz; }
    bool empty() const { return sz == 0; }
    bool full() const { return sz == cap; }
private:
    A& get(size_t idx) {
        assert(idx >= 0 && idx < sz);
        if (idx < sz / 2) {
            auto node = head;
            for (auto i = 0; i < idx; node = node->next, ++i) {}
            return node->value;
        } else {
            auto node = tail;
            for (auto i = sz - 1; i > idx; node = node->prev, --i) {}
            return node->value;
        }
    }
    const A& get(size_t idx) const {
        A& val = get(idx);
        return val;
    }
};

}

#endif
<|endoftext|>


<commit_before>/* main.cpp - main entry point for the command-line tool `dm`
 *
 * The current implementation is specific to chains of integrators;
 * however, the design is intended to be general to facilitate later
 * treatment of other kinds of systems.
 *
 * While some infrastructure is in place for building without ROS, it
 * is as yet not operational.
 *
 *
 * SCL; 2015
 */

#ifdef USE_ROS
#include <ros/ros.h>
#include "dynamaestro/VectorStamped.h"
#include "dynamaestro/LabelStamped.h"
#include "dynamaestro/ProblemInstanceJSON.h"
#include "dynamaestro/DMMode.h"
#endif

#include "problem.h"

#include <cstdlib>
#include <cstdio>
#include <assert.h>

#include <Eigen/Dense>
#include <boost/thread/thread.hpp>

/* The trajectories are the solutions of a linear time-invariant control
   system. Control input is applied using a zero-order hold, i.e., applied
   constantly during the duration given as the first parameter of step().

   Let m be the highest order of derivative, and let n be the dimension of the
   output space.  The state variable indexing is such that the first output
   variable is the first state variable, the second output variable is the
   second state variable, etc. Thus the component systems are interleaved in the
   sense that the first subsystem is formed from state variable indices 1, 1+n,
   1+2n, ..., 1+(m-1)n, and the input to this subsystem is applied at state
   variable index 1+(m-1)n.
*/
/** \ingroup integrator_chains */
class TrajectoryGenerator {
private:
	Eigen::VectorXd X;
	double t;  // Current time
	int highest_order_deriv;
	int numdim_output;

	Eigen::VectorXd Xinit;

public:
	TrajectoryGenerator( int numdim_output, int highest_order_deriv );

	/* Consult the class description regarding the assumed arrangement of the
	   state variables, i.e., the indexing and the assumption that the system is
	   a chain of integrators. */
	TrajectoryGenerator( Eigen::VectorXd Xinit, int numdim_output );

	void clear();

	/* Forward Euler integration for duration dt using constant input U */
	double step( double dt, const Eigen::VectorXd &U );

	double getTime() const
		{ return t; }
	double getStateDim() const
		{ return X.size(); }
	double getOutputDim() const
		{ return numdim_output; }

	// Output vector
	double operator[]( int i ) const;

	/* Access to full, current state vector */
	double getState( int i ) const
		{ return X[i]; }
};

TrajectoryGenerator::TrajectoryGenerator( int numdim_output, int highest_order_deriv )
	: t(0.0),
	  highest_order_deriv(highest_order_deriv), numdim_output(numdim_output)
{
	X.resize( numdim_output*highest_order_deriv );
	X.setZero();
	Xinit = X;
}

TrajectoryGenerator::TrajectoryGenerator( Eigen::VectorXd Xinit, int numdim_output  )
	: t(0.0), Xinit(Xinit), X(Xinit), numdim_output(numdim_output)
{
	assert( X.size() % numdim_output == 0 );
	highest_order_deriv = X.size()/numdim_output;
}

void TrajectoryGenerator::clear()
{
	X = Xinit;
	t = 0.0;
}

double TrajectoryGenerator::step( double dt, const Eigen::VectorXd &U )
{
	if (U.size() > numdim_output) {
		ROS_ERROR( "Input vector has too many elements." );
		return 0.0/0.0;
	}

	int numdim_state = X.size();

	int i, j;
	for (j = 0; j < numdim_output; j++) {
		for (i = 0; i <= highest_order_deriv-2; i++) {
			X[i*numdim_output+j] += dt*X[(i+1)*numdim_output+j];
		}
		X[(highest_order_deriv-1)*numdim_output+j] += dt*U[j];
	}

	t += dt;
	return t;
}

double TrajectoryGenerator::operator[]( int i ) const
{
	if (i < numdim_output) {
		return X[i];
	} else {
		ROS_ERROR( "Invalid index into output vector: %d", i );
		return 0.0/0.0;
	}
}

/** \ingroup integrator_chains */
class TGThread {
private:
	boost::mutex mtx_;
	bool fresh_input;
	Eigen::VectorXd U;

	Problem *probinstance;
	Labeler labeler;

	enum DMMode { ready, waiting, running, paused, resetting, restarting };
	DMMode dmmode;

	ros::NodeHandle &nh_;
	ros::ServiceServer mode_srv;
	ros::Publisher problemJSONpub;
	ros::Publisher statepub;
	ros::Publisher loutpub;
	ros::Subscriber inputsub;

public:
	TGThread( ros::NodeHandle &nh );
	~TGThread();
	void inputcb( const dynamaestro::VectorStamped &vs );
	bool mode_request( dynamaestro::DMMode::Request &req,
					   dynamaestro::DMMode::Response &res );
	void run();
	void pubstate( const TrajectoryGenerator &tg, Eigen::VectorXd &Y );
};

TGThread::TGThread( ros::NodeHandle &nh )
	: nh_(nh),
	  fresh_input(false),
	  U(),
	  probinstance(NULL),
	  labeler(),
	  dmmode(paused)
{
	mode_srv = nh_.advertiseService( "mode", &TGThread::mode_request, this );
	problemJSONpub = nh_.advertise<dynamaestro::ProblemInstanceJSON>( "probleminstance_JSON", 1, true );
	statepub = nh_.advertise<dynamaestro::VectorStamped>( "state", 10, true );
	loutpub = nh_.advertise<dynamaestro::LabelStamped>( "loutput", 10, true );
	inputsub = nh_.subscribe( "input", 1, &TGThread::inputcb, this );
}

TGThread::~TGThread()
{
	if (probinstance)
		delete probinstance;
}

void TGThread::pubstate( const TrajectoryGenerator &tg, Eigen::VectorXd &Y )
{
	dynamaestro::VectorStamped pt;
	pt.header.frame_id = std::string( "map" );
	pt.header.stamp = ros::Time::now();
	for (int i = 0; i < tg.getStateDim(); i++) {
		pt.v.point.push_back( tg.getState( i ) );
		if (i < tg.getOutputDim())
			Y(i) = tg[i];
	}
	statepub.publish( pt );

	std::list<std::string> label = labeler.get_label( Y );
	dynamaestro::LabelStamped lbl;
	lbl.header.frame_id = pt.header.frame_id;
	lbl.header.stamp = pt.header.stamp;
	lbl.label.resize( label.size() );
	int i = 0;
	for (std::list<std::string>::iterator it_label = label.begin();
		 it_label != label.end(); it_label++) {
		lbl.label[i] = *it_label;
		i++;
	}
	loutpub.publish( lbl );
}

bool TGThread::mode_request( dynamaestro::DMMode::Request &req,
							 dynamaestro::DMMode::Response &res )
{
	switch (req.mode) {
	case dynamaestro::DMMode::Request::UNPAUSE:
		if (dmmode != running)
			dmmode = running;
		res.result = true;
		break;

	case dynamaestro::DMMode::Request::READY:
		if (dmmode == ready) {
			res.result = true;
		} else {
			res.result = false;
		}
		break;

	case dynamaestro::DMMode::Request::START:
		if (dmmode == ready) {
			dmmode = waiting;
			res.result = true;
		} else {
			res.result = false;
		}
		break;

	case dynamaestro::DMMode::Request::PAUSE:
		if (dmmode == running) {
			dmmode = paused;
			fresh_input = false;
		}
		res.result = true;
		break;

	case dynamaestro::DMMode::Request::RESTART:
		dmmode = restarting;
		ROS_INFO( "dynamaestro: Restarting trial..." );
		res.result = true;
		break;

	case dynamaestro::DMMode::Request::RESET:
		dmmode = resetting;
		ROS_INFO( "dynamaestro: Stopping current trial and generating a new instance..." );
		res.result = true;
		break;

	default:
		return false;
	}

	return true;
}

void TGThread::inputcb( const dynamaestro::VectorStamped &vs )
{
	assert( probinstance != NULL );

	mtx_.lock();

	fresh_input = true;
	for (int i = 0; i < probinstance->get_numdim_output(); i++)
		U[i] = vs.v.point[i];

	mtx_.unlock();
}

void TGThread::run()
{
	int nominal_duration = rand() % 61 + 30;

	Eigen::Vector2i numdim_output_bounds( 1, 3 );
	Eigen::Vector2i num_integrators_bounds( 1, 3 );

	Eigen::VectorXd Y_max( 2*numdim_output_bounds(1) );
	for (int i = 0; i < numdim_output_bounds(1); i++) {
		Y_max(2*i+1) = 10;
		Y_max(2*i) = -Y_max(2*i+1);
	}

	Eigen::VectorXd U_max( 2*numdim_output_bounds(1) );
	for (int i = 0; i < numdim_output_bounds(1); i++) {
		U_max(2*i+1) = 1;
		U_max(2*i) = -U_max(2*i+1);
	}

	Eigen::Vector2d period_bounds( 0.05, 0.1 );

	probinstance = Problem::random( numdim_output_bounds,
									num_integrators_bounds,
									Y_max, U_max, 2, 1, period_bounds );
	labeler.importProblem( *probinstance );

	U.resize( probinstance->get_numdim_output() );
	U.setZero();

	Eigen::VectorXd Y( probinstance->get_numdim_output() );

	TrajectoryGenerator tg( probinstance->Xinit,
							probinstance->get_numdim_output() );

	ros::Rate rate( 1/probinstance->period );
	Eigen::VectorXd defaultU( U );
	defaultU.setZero();

	ros::Duration trial_duration;

	ros::Rate polling_rate( 100 );
	dmmode = ready;
	while (dmmode == ready) {
		if (!ros::ok())
			return;
		ros::spinOnce();
		polling_rate.sleep();
	}
	assert( dmmode == waiting );
	ros::Time startt = ros::Time::now();

	dynamaestro::ProblemInstanceJSON probinstance_msg;
	probinstance_msg.stamp = ros::Time::now();
	probinstance_msg.problemjson = probinstance->dumpJSON();
	problemJSONpub.publish( probinstance_msg );

	nh_.setParam( "number_integrators",
				  probinstance->get_highest_order_deriv() );
	ROS_INFO( "dynamaestro: Using %d as number of integrators.",
			  probinstance->get_highest_order_deriv() );

	nh_.setParam( "output_dim", probinstance->get_numdim_output() );
	ROS_INFO( "dynamaestro: Using %d as dimension of the output space.",
			  probinstance->get_numdim_output() );

	nh_.setParam( "period", probinstance->period );
	ROS_INFO( "dynamaestro: Using %f seconds as the period.",
			  probinstance->period );

	// Send initial state, before any input is applied or time has begun.
	pubstate( tg, Y );
	ros::spinOnce();

	while (ros::ok() && dmmode != resetting && (trial_duration = ros::Time::now() - startt).toSec() < nominal_duration) {
		if (dmmode == running) {
			if (fresh_input) {
				mtx_.lock();

				fresh_input = false;
				tg.step( probinstance->period, U );

				mtx_.unlock();
			} else {
				tg.step( probinstance->period, defaultU );
			}

			pubstate( tg, Y );

		} else if (dmmode == restarting) {
			dmmode = paused;
			mtx_.lock();
			fresh_input = false;
			mtx_.unlock();
			tg.clear();
			U.setZero();
			pubstate( tg, Y );
			dmmode = waiting;
		} else if (dmmode == waiting) {
			if (fresh_input) {
				dmmode = running;
			}
		}
		ros::spinOnce();
		rate.sleep();
	}
	dmmode = resetting;
	dynamaestro::VectorStamped pt;
	// Send empty state message to indicate that trial has ended.
	statepub.publish( pt );

	// Did the trial end because the nominal (hidden) duration was reached?
	if (ros::ok() && trial_duration.toSec() >= nominal_duration) {
		ROS_INFO( "dynamaestro: Trial ended after %f s (threshold is %d s).", trial_duration.toSec(), nominal_duration );
	}

	// Clear registered instance
	ROS_INFO( "dynamaestro: Clearing instance summary from Parameter Server." );
	nh_.setParam( "number_integrators", -1 );
	nh_.setParam( "output_dim", -1 );
	nh_.setParam( "period", -1.0 );
	fresh_input = false;
	labeler.clear();
	delete probinstance;
}

void tgthread( ros::NodeHandle &nhp )
{
	TGThread tgt( nhp );
	while (ros::ok()) {
		tgt.run();
	}
}

int main( int argc, char **argv )
{
#ifdef USE_ROS
	ros::init( argc, argv, "dynamaestro" );
	ros::NodeHandle nh( "~" );

	time_t seed = time( NULL );
	srand( seed );
	ROS_INFO( "dynamaestro: Using %ld as the PRNG seed.", seed );

	boost::thread *tgmain = NULL;
	tgmain = new boost::thread( tgthread, nh );
	tgmain->join();
	delete tgmain;

	ros::spin();

#endif
	return 0;
}
<commit_msg>TRIV: Prefer style of placing public items at top of class def<commit_after>/* main.cpp - main entry point for the command-line tool `dm`
 *
 * The current implementation is specific to chains of integrators;
 * however, the design is intended to be general to facilitate later
 * treatment of other kinds of systems.
 *
 * While some infrastructure is in place for building without ROS, it
 * is as yet not operational.
 *
 *
 * SCL; 2015
 */

#ifdef USE_ROS
#include <ros/ros.h>
#include "dynamaestro/VectorStamped.h"
#include "dynamaestro/LabelStamped.h"
#include "dynamaestro/ProblemInstanceJSON.h"
#include "dynamaestro/DMMode.h"
#endif

#include "problem.h"

#include <cstdlib>
#include <cstdio>
#include <assert.h>

#include <Eigen/Dense>
#include <boost/thread/thread.hpp>

/* The trajectories are the solutions of a linear time-invariant control
   system. Control input is applied using a zero-order hold, i.e., applied
   constantly during the duration given as the first parameter of step().

   Let m be the highest order of derivative, and let n be the dimension of the
   output space.  The state variable indexing is such that the first output
   variable is the first state variable, the second output variable is the
   second state variable, etc. Thus the component systems are interleaved in the
   sense that the first subsystem is formed from state variable indices 1, 1+n,
   1+2n, ..., 1+(m-1)n, and the input to this subsystem is applied at state
   variable index 1+(m-1)n.
*/
/** \ingroup integrator_chains */
class TrajectoryGenerator {
public:
	TrajectoryGenerator( int numdim_output, int highest_order_deriv );

	/* Consult the class description regarding the assumed arrangement of the
	   state variables, i.e., the indexing and the assumption that the system is
	   a chain of integrators. */
	TrajectoryGenerator( Eigen::VectorXd Xinit, int numdim_output );

	void clear();

	/* Forward Euler integration for duration dt using constant input U */
	double step( double dt, const Eigen::VectorXd &U );

	double getTime() const
		{ return t; }
	double getStateDim() const
		{ return X.size(); }
	double getOutputDim() const
		{ return numdim_output; }

	// Output vector
	double operator[]( int i ) const;

	/* Access to full, current state vector */
	double getState( int i ) const
		{ return X[i]; }

private:
	Eigen::VectorXd X;
	double t;  // Current time
	int highest_order_deriv;
	int numdim_output;

	Eigen::VectorXd Xinit;
};

TrajectoryGenerator::TrajectoryGenerator( int numdim_output, int highest_order_deriv )
	: t(0.0),
	  highest_order_deriv(highest_order_deriv), numdim_output(numdim_output)
{
	X.resize( numdim_output*highest_order_deriv );
	X.setZero();
	Xinit = X;
}

TrajectoryGenerator::TrajectoryGenerator( Eigen::VectorXd Xinit, int numdim_output  )
	: t(0.0), Xinit(Xinit), X(Xinit), numdim_output(numdim_output)
{
	assert( X.size() % numdim_output == 0 );
	highest_order_deriv = X.size()/numdim_output;
}

void TrajectoryGenerator::clear()
{
	X = Xinit;
	t = 0.0;
}

double TrajectoryGenerator::step( double dt, const Eigen::VectorXd &U )
{
	if (U.size() > numdim_output) {
		ROS_ERROR( "Input vector has too many elements." );
		return 0.0/0.0;
	}

	int numdim_state = X.size();

	int i, j;
	for (j = 0; j < numdim_output; j++) {
		for (i = 0; i <= highest_order_deriv-2; i++) {
			X[i*numdim_output+j] += dt*X[(i+1)*numdim_output+j];
		}
		X[(highest_order_deriv-1)*numdim_output+j] += dt*U[j];
	}

	t += dt;
	return t;
}

double TrajectoryGenerator::operator[]( int i ) const
{
	if (i < numdim_output) {
		return X[i];
	} else {
		ROS_ERROR( "Invalid index into output vector: %d", i );
		return 0.0/0.0;
	}
}

/** \ingroup integrator_chains */
class TGThread {
public:
	TGThread( ros::NodeHandle &nh );
	~TGThread();
	void inputcb( const dynamaestro::VectorStamped &vs );
	bool mode_request( dynamaestro::DMMode::Request &req,
					   dynamaestro::DMMode::Response &res );
	void run();
	void pubstate( const TrajectoryGenerator &tg, Eigen::VectorXd &Y );

private:
	boost::mutex mtx_;
	bool fresh_input;
	Eigen::VectorXd U;

	Problem *probinstance;
	Labeler labeler;

	enum DMMode { ready, waiting, running, paused, resetting, restarting };
	DMMode dmmode;

	ros::NodeHandle &nh_;
	ros::ServiceServer mode_srv;
	ros::Publisher problemJSONpub;
	ros::Publisher statepub;
	ros::Publisher loutpub;
	ros::Subscriber inputsub;
};

TGThread::TGThread( ros::NodeHandle &nh )
	: nh_(nh),
	  fresh_input(false),
	  U(),
	  probinstance(NULL),
	  labeler(),
	  dmmode(paused)
{
	mode_srv = nh_.advertiseService( "mode", &TGThread::mode_request, this );
	problemJSONpub = nh_.advertise<dynamaestro::ProblemInstanceJSON>( "probleminstance_JSON", 1, true );
	statepub = nh_.advertise<dynamaestro::VectorStamped>( "state", 10, true );
	loutpub = nh_.advertise<dynamaestro::LabelStamped>( "loutput", 10, true );
	inputsub = nh_.subscribe( "input", 1, &TGThread::inputcb, this );
}

TGThread::~TGThread()
{
	if (probinstance)
		delete probinstance;
}

void TGThread::pubstate( const TrajectoryGenerator &tg, Eigen::VectorXd &Y )
{
	dynamaestro::VectorStamped pt;
	pt.header.frame_id = std::string( "map" );
	pt.header.stamp = ros::Time::now();
	for (int i = 0; i < tg.getStateDim(); i++) {
		pt.v.point.push_back( tg.getState( i ) );
		if (i < tg.getOutputDim())
			Y(i) = tg[i];
	}
	statepub.publish( pt );

	std::list<std::string> label = labeler.get_label( Y );
	dynamaestro::LabelStamped lbl;
	lbl.header.frame_id = pt.header.frame_id;
	lbl.header.stamp = pt.header.stamp;
	lbl.label.resize( label.size() );
	int i = 0;
	for (std::list<std::string>::iterator it_label = label.begin();
		 it_label != label.end(); it_label++) {
		lbl.label[i] = *it_label;
		i++;
	}
	loutpub.publish( lbl );
}

bool TGThread::mode_request( dynamaestro::DMMode::Request &req,
							 dynamaestro::DMMode::Response &res )
{
	switch (req.mode) {
	case dynamaestro::DMMode::Request::UNPAUSE:
		if (dmmode != running)
			dmmode = running;
		res.result = true;
		break;

	case dynamaestro::DMMode::Request::READY:
		if (dmmode == ready) {
			res.result = true;
		} else {
			res.result = false;
		}
		break;

	case dynamaestro::DMMode::Request::START:
		if (dmmode == ready) {
			dmmode = waiting;
			res.result = true;
		} else {
			res.result = false;
		}
		break;

	case dynamaestro::DMMode::Request::PAUSE:
		if (dmmode == running) {
			dmmode = paused;
			fresh_input = false;
		}
		res.result = true;
		break;

	case dynamaestro::DMMode::Request::RESTART:
		dmmode = restarting;
		ROS_INFO( "dynamaestro: Restarting trial..." );
		res.result = true;
		break;

	case dynamaestro::DMMode::Request::RESET:
		dmmode = resetting;
		ROS_INFO( "dynamaestro: Stopping current trial and generating a new instance..." );
		res.result = true;
		break;

	default:
		return false;
	}

	return true;
}

void TGThread::inputcb( const dynamaestro::VectorStamped &vs )
{
	assert( probinstance != NULL );

	mtx_.lock();

	fresh_input = true;
	for (int i = 0; i < probinstance->get_numdim_output(); i++)
		U[i] = vs.v.point[i];

	mtx_.unlock();
}

void TGThread::run()
{
	int nominal_duration = rand() % 61 + 30;

	Eigen::Vector2i numdim_output_bounds( 1, 3 );
	Eigen::Vector2i num_integrators_bounds( 1, 3 );

	Eigen::VectorXd Y_max( 2*numdim_output_bounds(1) );
	for (int i = 0; i < numdim_output_bounds(1); i++) {
		Y_max(2*i+1) = 10;
		Y_max(2*i) = -Y_max(2*i+1);
	}

	Eigen::VectorXd U_max( 2*numdim_output_bounds(1) );
	for (int i = 0; i < numdim_output_bounds(1); i++) {
		U_max(2*i+1) = 1;
		U_max(2*i) = -U_max(2*i+1);
	}

	Eigen::Vector2d period_bounds( 0.05, 0.1 );

	probinstance = Problem::random( numdim_output_bounds,
									num_integrators_bounds,
									Y_max, U_max, 2, 1, period_bounds );
	labeler.importProblem( *probinstance );

	U.resize( probinstance->get_numdim_output() );
	U.setZero();

	Eigen::VectorXd Y( probinstance->get_numdim_output() );

	TrajectoryGenerator tg( probinstance->Xinit,
							probinstance->get_numdim_output() );

	ros::Rate rate( 1/probinstance->period );
	Eigen::VectorXd defaultU( U );
	defaultU.setZero();

	ros::Duration trial_duration;

	ros::Rate polling_rate( 100 );
	dmmode = ready;
	while (dmmode == ready) {
		if (!ros::ok())
			return;
		ros::spinOnce();
		polling_rate.sleep();
	}
	assert( dmmode == waiting );
	ros::Time startt = ros::Time::now();

	dynamaestro::ProblemInstanceJSON probinstance_msg;
	probinstance_msg.stamp = ros::Time::now();
	probinstance_msg.problemjson = probinstance->dumpJSON();
	problemJSONpub.publish( probinstance_msg );

	nh_.setParam( "number_integrators",
				  probinstance->get_highest_order_deriv() );
	ROS_INFO( "dynamaestro: Using %d as number of integrators.",
			  probinstance->get_highest_order_deriv() );

	nh_.setParam( "output_dim", probinstance->get_numdim_output() );
	ROS_INFO( "dynamaestro: Using %d as dimension of the output space.",
			  probinstance->get_numdim_output() );

	nh_.setParam( "period", probinstance->period );
	ROS_INFO( "dynamaestro: Using %f seconds as the period.",
			  probinstance->period );

	// Send initial state, before any input is applied or time has begun.
	pubstate( tg, Y );
	ros::spinOnce();

	while (ros::ok() && dmmode != resetting && (trial_duration = ros::Time::now() - startt).toSec() < nominal_duration) {
		if (dmmode == running) {
			if (fresh_input) {
				mtx_.lock();

				fresh_input = false;
				tg.step( probinstance->period, U );

				mtx_.unlock();
			} else {
				tg.step( probinstance->period, defaultU );
			}

			pubstate( tg, Y );

		} else if (dmmode == restarting) {
			dmmode = paused;
			mtx_.lock();
			fresh_input = false;
			mtx_.unlock();
			tg.clear();
			U.setZero();
			pubstate( tg, Y );
			dmmode = waiting;
		} else if (dmmode == waiting) {
			if (fresh_input) {
				dmmode = running;
			}
		}
		ros::spinOnce();
		rate.sleep();
	}
	dmmode = resetting;
	dynamaestro::VectorStamped pt;
	// Send empty state message to indicate that trial has ended.
	statepub.publish( pt );

	// Did the trial end because the nominal (hidden) duration was reached?
	if (ros::ok() && trial_duration.toSec() >= nominal_duration) {
		ROS_INFO( "dynamaestro: Trial ended after %f s (threshold is %d s).", trial_duration.toSec(), nominal_duration );
	}

	// Clear registered instance
	ROS_INFO( "dynamaestro: Clearing instance summary from Parameter Server." );
	nh_.setParam( "number_integrators", -1 );
	nh_.setParam( "output_dim", -1 );
	nh_.setParam( "period", -1.0 );
	fresh_input = false;
	labeler.clear();
	delete probinstance;
}

void tgthread( ros::NodeHandle &nhp )
{
	TGThread tgt( nhp );
	while (ros::ok()) {
		tgt.run();
	}
}

int main( int argc, char **argv )
{
#ifdef USE_ROS
	ros::init( argc, argv, "dynamaestro" );
	ros::NodeHandle nh( "~" );

	time_t seed = time( NULL );
	srand( seed );
	ROS_INFO( "dynamaestro: Using %ld as the PRNG seed.", seed );

	boost::thread *tgmain = NULL;
	tgmain = new boost::thread( tgthread, nh );
	tgmain->join();
	delete tgmain;

	ros::spin();

#endif
	return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ComponentDefinition.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-04 13:56:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX
#include "ComponentDefinition.hxx"
#endif
#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef DBACCESS_SHARED_DBASTRINGS_HRC
#include "dbastrings.hrc"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _COMPHELPER_SEQUENCE_HXX_
#include <comphelper/sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _COMPHELPER_PROPERTY_HXX_
#include <comphelper/property.hxx>
#endif
#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_
#include "definitioncolumn.hxx"
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::lang;

using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::osl;
using namespace ::comphelper;
using namespace ::cppu;

extern "C" void SAL_CALL createRegistryInfo_OComponentDefinition()
{
    static ::dbaccess::OMultiInstanceAutoRegistration< ::dbaccess::OComponentDefinition > aAutoRegistration;
}

//........................................................................
namespace dbaccess
{
//........................................................................
DBG_NAME(OComponentDefinition_Impl)
OComponentDefinition_Impl::OComponentDefinition_Impl()
{
    DBG_CTOR(OComponentDefinition_Impl,NULL);
}
// -----------------------------------------------------------------------------
OComponentDefinition_Impl::~OComponentDefinition_Impl()
{
    DBG_DTOR(OComponentDefinition_Impl,NULL);
}
//==========================================================================
//= OComponentDefinition
//==========================================================================
//--------------------------------------------------------------------------
DBG_NAME(OComponentDefinition)
//--------------------------------------------------------------------------
void OComponentDefinition::registerProperties()
{
    OComponentDefinition_Impl& rDefinition( getDefinition() );
    ODataSettings::registerPropertiesFor( &rDefinition );

    registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY|PropertyAttribute::CONSTRAINED,
                    &rDefinition.m_aProps.aTitle, ::getCppuType(&rDefinition.m_aProps.aTitle));

    if ( m_bTable )
    {
        registerProperty(PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, PropertyAttribute::BOUND,
                        &rDefinition.m_sSchemaName, ::getCppuType(&rDefinition.m_sSchemaName));

        registerProperty(PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, PropertyAttribute::BOUND,
                        &rDefinition.m_sCatalogName, ::getCppuType(&rDefinition.m_sCatalogName));
    }
}

//--------------------------------------------------------------------------
OComponentDefinition::OComponentDefinition(const Reference< XMultiServiceFactory >& _xORB
                                           ,const Reference< XInterface >&  _xParentContainer
                                           ,const TContentPtr& _pImpl
                                           ,sal_Bool _bTable)
    :OContentHelper(_xORB,_xParentContainer,_pImpl)
    ,ODataSettings(m_aBHelper,!_bTable)
    ,m_bTable(_bTable)
{
    DBG_CTOR(OComponentDefinition, NULL);
    registerProperties();
}
//--------------------------------------------------------------------------
OComponentDefinition::~OComponentDefinition()
{
    DBG_DTOR(OComponentDefinition, NULL);
}

//--------------------------------------------------------------------------
OComponentDefinition::OComponentDefinition( const Reference< XInterface >& _rxContainer
                                       ,const ::rtl::OUString& _rElementName
                                       ,const Reference< XMultiServiceFactory >& _xORB
                                       ,const TContentPtr& _pImpl
                                       ,sal_Bool _bTable)
    :OContentHelper(_xORB,_rxContainer,_pImpl)
    ,ODataSettings(m_aBHelper)
    ,m_bTable(_bTable)
{
    DBG_CTOR(OComponentDefinition, NULL);

    registerProperties();

    m_pImpl->m_aProps.aTitle = _rElementName;

    DBG_ASSERT(m_pImpl->m_aProps.aTitle.getLength() != 0, "OComponentDefinition::OComponentDefinition : invalid name !");
}

//--------------------------------------------------------------------------
IMPLEMENT_IMPLEMENTATION_ID(OComponentDefinition);
IMPLEMENT_GETTYPES3(OComponentDefinition,ODataSettings,OContentHelper,OComponentDefinition_BASE);
IMPLEMENT_FORWARD_XINTERFACE3( OComponentDefinition,OContentHelper,ODataSettings,OComponentDefinition_BASE)
//--------------------------------------------------------------------------
::rtl::OUString OComponentDefinition::getImplementationName_Static(  ) throw(RuntimeException)
{
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.OComponentDefinition"));
}

//--------------------------------------------------------------------------
::rtl::OUString SAL_CALL OComponentDefinition::getImplementationName(  ) throw(RuntimeException)
{
    return getImplementationName_Static();
}

//--------------------------------------------------------------------------
Sequence< ::rtl::OUString > OComponentDefinition::getSupportedServiceNames_Static(  ) throw(RuntimeException)
{
    Sequence< ::rtl::OUString > aServices(2);
    aServices.getArray()[0] = SERVICE_SDB_TABLEDEFINITION;
    aServices.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content"));

    return aServices;
}

//--------------------------------------------------------------------------
Sequence< ::rtl::OUString > SAL_CALL OComponentDefinition::getSupportedServiceNames(  ) throw(RuntimeException)
{
    return getSupportedServiceNames_Static();
}
//------------------------------------------------------------------------------
Reference< XInterface > OComponentDefinition::Create(const Reference< XMultiServiceFactory >& _rxFactory)
{
    return *(new OComponentDefinition(_rxFactory,NULL,TContentPtr(new OComponentDefinition_Impl)));
}
// -----------------------------------------------------------------------------
void SAL_CALL OComponentDefinition::disposing()
{
    OContentHelper::disposing();
    if ( m_pColumns.get() )
        m_pColumns->disposing();
}
// -----------------------------------------------------------------------------
IPropertyArrayHelper& OComponentDefinition::getInfoHelper()
{
    return *getArrayHelper();
}
//--------------------------------------------------------------------------
IPropertyArrayHelper* OComponentDefinition::createArrayHelper( ) const
{
    Sequence< Property > aProps;
    describeProperties(aProps);
    return new OPropertyArrayHelper(aProps);
}
//--------------------------------------------------------------------------
Reference< XPropertySetInfo > SAL_CALL OComponentDefinition::getPropertySetInfo(  ) throw(RuntimeException)
{
    Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
    return xInfo;
}
// -----------------------------------------------------------------------------
Reference< XNameAccess> OComponentDefinition::getColumns() throw (RuntimeException)
{
    ::osl::MutexGuard aGuard(m_aMutex);
    ::connectivity::checkDisposed(OContentHelper::rBHelper.bDisposed);

    if ( !m_pColumns.get() )
    {
        ::std::vector< ::rtl::OUString> aNames;

        const OComponentDefinition_Impl& rDefinition( getDefinition() );
        aNames.reserve( rDefinition.size() );

        OComponentDefinition_Impl::const_iterator aIter = rDefinition.begin();
        OComponentDefinition_Impl::const_iterator aEnd = rDefinition.end();
        for ( ; aIter != aEnd; ++aIter )
            aNames.push_back( aIter->first );

        m_pColumns.reset( new OColumns( *this, m_aMutex, sal_True, aNames, this, NULL, sal_True, sal_False, sal_False ) );
        m_pColumns->setParent( *this );
    }
    return m_pColumns.get();
}
// -----------------------------------------------------------------------------
OColumn* OComponentDefinition::createColumn(const ::rtl::OUString& _rName) const
{
    const OComponentDefinition_Impl& rDefinition( getDefinition() );
    OComponentDefinition_Impl::const_iterator aFind = rDefinition.find( _rName );
    if ( aFind != rDefinition.end() )
        return new OTableColumnWrapper( aFind->second, aFind->second, sal_True );
    return new OTableColumn( _rName );
}
// -----------------------------------------------------------------------------
Reference< ::com::sun::star::beans::XPropertySet > OComponentDefinition::createColumnDescriptor()
{
    return new OTableColumnDescriptor();
}
// -----------------------------------------------------------------------------
void OComponentDefinition::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
{
    ODataSettings::setFastPropertyValue_NoBroadcast(nHandle,rValue);
    notifyDataSourceModified();
}
// -----------------------------------------------------------------------------
void OComponentDefinition::columnDropped(const ::rtl::OUString& _sName)
{
    getDefinition().erase( _sName );
    notifyDataSourceModified();
}
// -----------------------------------------------------------------------------
void OComponentDefinition::columnAppended( const Reference< XPropertySet >& _rxSourceDescriptor )
{
    ::rtl::OUString sName;
    _rxSourceDescriptor->getPropertyValue( PROPERTY_NAME ) >>= sName;

    Reference<XPropertySet> xColDesc = new OTableColumnDescriptor();
    ::comphelper::copyProperties( _rxSourceDescriptor, xColDesc );
    getDefinition().insert( sName, xColDesc );

    // formerly, here was a setParent at the xColDesc. The parent used was an adapter (ChildHelper_Impl)
    // which held another XChild weak, and forwarded all getParent requests to this other XChild.
    // m_pColumns was used for this. This was nonsense, since m_pColumns dies when our instance dies,
    // but xColDesc will live longer than this. So effectively, the setParent call was pretty useless.
    //
    // The intention for this parenting was that the column descriptor is able to find the data source,
    // by traveling up the parent hierachy until there's an XDataSource. This didn't work (which
    // for instance causes #i65023#). We need another way to properly ensure this.

    notifyDataSourceModified();
}

//........................................................................
}   // namespace dbaccess
//........................................................................

<commit_msg>INTEGRATION: CWS pchfix02 (1.10.12); FILE MERGED 2006/09/01 17:24:07 kaib 1.10.12.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ComponentDefinition.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 06:37:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"

#ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX
#include "ComponentDefinition.hxx"
#endif
#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef DBACCESS_SHARED_DBASTRINGS_HRC
#include "dbastrings.hrc"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _COMPHELPER_SEQUENCE_HXX_
#include <comphelper/sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _COMPHELPER_PROPERTY_HXX_
#include <comphelper/property.hxx>
#endif
#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_
#include "definitioncolumn.hxx"
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::lang;

using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::osl;
using namespace ::comphelper;
using namespace ::cppu;

extern "C" void SAL_CALL createRegistryInfo_OComponentDefinition()
{
    static ::dbaccess::OMultiInstanceAutoRegistration< ::dbaccess::OComponentDefinition > aAutoRegistration;
}

//........................................................................
namespace dbaccess
{
//........................................................................
DBG_NAME(OComponentDefinition_Impl)
OComponentDefinition_Impl::OComponentDefinition_Impl()
{
    DBG_CTOR(OComponentDefinition_Impl,NULL);
}
// -----------------------------------------------------------------------------
OComponentDefinition_Impl::~OComponentDefinition_Impl()
{
    DBG_DTOR(OComponentDefinition_Impl,NULL);
}
//==========================================================================
//= OComponentDefinition
//==========================================================================
//--------------------------------------------------------------------------
DBG_NAME(OComponentDefinition)
//--------------------------------------------------------------------------
void OComponentDefinition::registerProperties()
{
    OComponentDefinition_Impl& rDefinition( getDefinition() );
    ODataSettings::registerPropertiesFor( &rDefinition );

    registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY|PropertyAttribute::CONSTRAINED,
                    &rDefinition.m_aProps.aTitle, ::getCppuType(&rDefinition.m_aProps.aTitle));

    if ( m_bTable )
    {
        registerProperty(PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, PropertyAttribute::BOUND,
                        &rDefinition.m_sSchemaName, ::getCppuType(&rDefinition.m_sSchemaName));

        registerProperty(PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, PropertyAttribute::BOUND,
                        &rDefinition.m_sCatalogName, ::getCppuType(&rDefinition.m_sCatalogName));
    }
}

//--------------------------------------------------------------------------
OComponentDefinition::OComponentDefinition(const Reference< XMultiServiceFactory >& _xORB
                                           ,const Reference< XInterface >&  _xParentContainer
                                           ,const TContentPtr& _pImpl
                                           ,sal_Bool _bTable)
    :OContentHelper(_xORB,_xParentContainer,_pImpl)
    ,ODataSettings(m_aBHelper,!_bTable)
    ,m_bTable(_bTable)
{
    DBG_CTOR(OComponentDefinition, NULL);
    registerProperties();
}
//--------------------------------------------------------------------------
OComponentDefinition::~OComponentDefinition()
{
    DBG_DTOR(OComponentDefinition, NULL);
}

//--------------------------------------------------------------------------
OComponentDefinition::OComponentDefinition( const Reference< XInterface >& _rxContainer
                                       ,const ::rtl::OUString& _rElementName
                                       ,const Reference< XMultiServiceFactory >& _xORB
                                       ,const TContentPtr& _pImpl
                                       ,sal_Bool _bTable)
    :OContentHelper(_xORB,_rxContainer,_pImpl)
    ,ODataSettings(m_aBHelper)
    ,m_bTable(_bTable)
{
    DBG_CTOR(OComponentDefinition, NULL);

    registerProperties();

    m_pImpl->m_aProps.aTitle = _rElementName;

    DBG_ASSERT(m_pImpl->m_aProps.aTitle.getLength() != 0, "OComponentDefinition::OComponentDefinition : invalid name !");
}

//--------------------------------------------------------------------------
IMPLEMENT_IMPLEMENTATION_ID(OComponentDefinition);
IMPLEMENT_GETTYPES3(OComponentDefinition,ODataSettings,OContentHelper,OComponentDefinition_BASE);
IMPLEMENT_FORWARD_XINTERFACE3( OComponentDefinition,OContentHelper,ODataSettings,OComponentDefinition_BASE)
//--------------------------------------------------------------------------
::rtl::OUString OComponentDefinition::getImplementationName_Static(  ) throw(RuntimeException)
{
    return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.OComponentDefinition"));
}

//--------------------------------------------------------------------------
::rtl::OUString SAL_CALL OComponentDefinition::getImplementationName(  ) throw(RuntimeException)
{
    return getImplementationName_Static();
}

//--------------------------------------------------------------------------
Sequence< ::rtl::OUString > OComponentDefinition::getSupportedServiceNames_Static(  ) throw(RuntimeException)
{
    Sequence< ::rtl::OUString > aServices(2);
    aServices.getArray()[0] = SERVICE_SDB_TABLEDEFINITION;
    aServices.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content"));

    return aServices;
}

//--------------------------------------------------------------------------
Sequence< ::rtl::OUString > SAL_CALL OComponentDefinition::getSupportedServiceNames(  ) throw(RuntimeException)
{
    return getSupportedServiceNames_Static();
}
//------------------------------------------------------------------------------
Reference< XInterface > OComponentDefinition::Create(const Reference< XMultiServiceFactory >& _rxFactory)
{
    return *(new OComponentDefinition(_rxFactory,NULL,TContentPtr(new OComponentDefinition_Impl)));
}
// -----------------------------------------------------------------------------
void SAL_CALL OComponentDefinition::disposing()
{
    OContentHelper::disposing();
    if ( m_pColumns.get() )
        m_pColumns->disposing();
}
// -----------------------------------------------------------------------------
IPropertyArrayHelper& OComponentDefinition::getInfoHelper()
{
    return *getArrayHelper();
}
//--------------------------------------------------------------------------
IPropertyArrayHelper* OComponentDefinition::createArrayHelper( ) const
{
    Sequence< Property > aProps;
    describeProperties(aProps);
    return new OPropertyArrayHelper(aProps);
}
//--------------------------------------------------------------------------
Reference< XPropertySetInfo > SAL_CALL OComponentDefinition::getPropertySetInfo(  ) throw(RuntimeException)
{
    Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
    return xInfo;
}
// -----------------------------------------------------------------------------
Reference< XNameAccess> OComponentDefinition::getColumns() throw (RuntimeException)
{
    ::osl::MutexGuard aGuard(m_aMutex);
    ::connectivity::checkDisposed(OContentHelper::rBHelper.bDisposed);

    if ( !m_pColumns.get() )
    {
        ::std::vector< ::rtl::OUString> aNames;

        const OComponentDefinition_Impl& rDefinition( getDefinition() );
        aNames.reserve( rDefinition.size() );

        OComponentDefinition_Impl::const_iterator aIter = rDefinition.begin();
        OComponentDefinition_Impl::const_iterator aEnd = rDefinition.end();
        for ( ; aIter != aEnd; ++aIter )
            aNames.push_back( aIter->first );

        m_pColumns.reset( new OColumns( *this, m_aMutex, sal_True, aNames, this, NULL, sal_True, sal_False, sal_False ) );
        m_pColumns->setParent( *this );
    }
    return m_pColumns.get();
}
// -----------------------------------------------------------------------------
OColumn* OComponentDefinition::createColumn(const ::rtl::OUString& _rName) const
{
    const OComponentDefinition_Impl& rDefinition( getDefinition() );
    OComponentDefinition_Impl::const_iterator aFind = rDefinition.find( _rName );
    if ( aFind != rDefinition.end() )
        return new OTableColumnWrapper( aFind->second, aFind->second, sal_True );
    return new OTableColumn( _rName );
}
// -----------------------------------------------------------------------------
Reference< ::com::sun::star::beans::XPropertySet > OComponentDefinition::createColumnDescriptor()
{
    return new OTableColumnDescriptor();
}
// -----------------------------------------------------------------------------
void OComponentDefinition::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
{
    ODataSettings::setFastPropertyValue_NoBroadcast(nHandle,rValue);
    notifyDataSourceModified();
}
// -----------------------------------------------------------------------------
void OComponentDefinition::columnDropped(const ::rtl::OUString& _sName)
{
    getDefinition().erase( _sName );
    notifyDataSourceModified();
}
// -----------------------------------------------------------------------------
void OComponentDefinition::columnAppended( const Reference< XPropertySet >& _rxSourceDescriptor )
{
    ::rtl::OUString sName;
    _rxSourceDescriptor->getPropertyValue( PROPERTY_NAME ) >>= sName;

    Reference<XPropertySet> xColDesc = new OTableColumnDescriptor();
    ::comphelper::copyProperties( _rxSourceDescriptor, xColDesc );
    getDefinition().insert( sName, xColDesc );

    // formerly, here was a setParent at the xColDesc. The parent used was an adapter (ChildHelper_Impl)
    // which held another XChild weak, and forwarded all getParent requests to this other XChild.
    // m_pColumns was used for this. This was nonsense, since m_pColumns dies when our instance dies,
    // but xColDesc will live longer than this. So effectively, the setParent call was pretty useless.
    //
    // The intention for this parenting was that the column descriptor is able to find the data source,
    // by traveling up the parent hierachy until there's an XDataSource. This didn't work (which
    // for instance causes #i65023#). We need another way to properly ensure this.

    notifyDataSourceModified();
}

//........................................................................
}   // namespace dbaccess
//........................................................................

<|endoftext|>


<commit_before>#pragma once

#include <utility>
#include <vector>
#include <cmath>
#include <fstream>
#include <iomanip>

#include "derivative.hpp"

namespace fp {

    template<typename Func, typename Float>
    std::tuple<std::vector<Float>, int, std::vector<Float>> fixed_point(const Func& g, Float x0, Float abstol)
    {
        // vector to store intermediate x_i values
        std::vector<Float> xvec;
        std::vector<Float> rvec; // vector of rate approximations

        // do the first iteration outside the while loop
        xvec.push_back(g(x0));
        Float currtol = static_cast<Float>(std::abs(xvec[0] - x0));

        // number of iterations : we have already performed one
        auto i = 1;
        Float rate = NAN;
        rvec.push_back(rate);

        Float x_iminus1;
        Float x_i;
        Float x_iplus1;
        Float deltaxp1;
        while (currtol > abstol)
        {
            x_iminus1 = xvec[i - 1];
            x_i = g(x_iminus1);
            xvec.push_back(x_i); // xi = g(x_{i - 1})
            x_iplus1 = g(x_i);
            currtol = std::abs(x_i - x_iminus1);
            deltaxp1 = std::abs(x_iplus1 - x_i);

            if ((i - 2) > 0) {
                rate = std::log(deltaxp1 / currtol) / std::log(currtol / std::abs(x_iminus1 - xvec[i - 2]));
                rvec.push_back(rate);
            } else {
                rvec.push_back(NAN);
            }

            ++i;
        }

        return std::make_tuple(xvec, i, rvec);
    }

    template<typename T> void printElement(T t, const int& width, std::ostream& stream)
    {
        static const char separator = ' ';
        stream << std::left << std::setw(width) << std::setfill(separator) << t;
    }

    template<typename Func, typename Float>
    void test_fixed_point(const Func& g, Float x0, Float abstol,
                          const std::string& funcname = "g", const std::string& filename = "test_g.txt")
    {
        const int nameWidth     = 24;
        const int numWidth      = 25;

        std::ofstream file;
        file.open(filename.c_str(), std::ios::out | std::ios::app);
        file << std::scientific << std::setprecision(15);
        file << "Getting the fixed points of '" << funcname
            << "' given x_0 = " << x0 << " and abstol = " << abstol << std::endl;

        auto tuple = fixed_point(g, x0, abstol);

        auto xvec = std::get<0>(tuple);
        auto iters = std::get<1>(tuple);
        auto rvec = std::get<2>(tuple);

        printElement("i", nameWidth, file);
        printElement("x_i", nameWidth, file);
        printElement("|x_i - x_{i - 1}|", nameWidth, file);
        printElement("rate", nameWidth, file);
        file << '\n';

        for (auto i = 0; i < xvec.size(); ++i)
        {
            printElement(i, numWidth, file);
            printElement(xvec[i], numWidth, file);
            if ((i - 1) >= 0) {
                printElement(std::abs(xvec[i] - xvec[i - 1]), numWidth, file);
            }
            printElement(rvec[i], numWidth, file);
            file << '\n';
        }

        file << "END" << std::endl;
    }

    void test_fp(double x0, double abstol)
    {
        const auto g1 = [](double x) -> double {
            return (x * x + 2) / 3;
        };

        // will result in NaNs because the value under the square root
        // will become negative at some point.
        const auto g2 = [](double x) -> double {
            return std::sqrt(3 * x - 2);
        };

        const auto g3 = [](double x) -> double {
            return 3 - (2 / x);
        };

        const auto g4 = [](double x) -> double {
            return (x * x  - 2) / (2 * x - 3);
        };

        std::vector<std::function<double(double)>> vec {g1, g2, g3, g4};
        std::vector<std::string> filenames {"g1.txt", "g2.txt", "g3.txt", "g4.txt"};
        std::vector<std::string> funcnames {"g1", "g2", "g3", "g4"};

        for (auto i = 0; i < vec.size(); ++i) {
            fp::test_fixed_point(vec[i], x0, abstol, funcnames[i], filenames[i]);
        }
    }

    template<typename Func, typename Float>
    std::tuple<std::vector<Float>, int, std::vector<Float>> newton_method(const Func& f, Float x0, Float abstol)
    {
        // vector to store intermediate x_i values
        std::vector<Float> xvec;
        std::vector<Float> rvec; // vector of rate approximations

        // do the first iteration outside the while loop
        auto x1 = x0 - (f(x0) / derivative(f, x0));
        xvec.push_back(x1);
        Float currtol = static_cast<Float>(std::abs(xvec[0] - x0));

        // number of iterations : we have already performed one
        auto i = 1;
        Float rate = NAN;
        rvec.push_back(rate);

        Float x_iminus1;
        Float x_i;
        Float x_iplus1;
        Float deltaxp1;
        while (currtol > abstol)
        {
            x_iminus1 = xvec[i - 1];
            x_i = x_iminus1 - (f(x_iminus1) / derivative(f, x_iminus1));
            xvec.push_back(x_i);
            x_iplus1 = x_i - (f(x_i) / derivative(f, x_i));
            currtol = std::abs(x_i - x_iminus1);
            deltaxp1 = std::abs(x_iplus1 - x_i);

            if ((i - 2) > 0) {
                rate = std::log(deltaxp1 / currtol) / std::log(currtol / std::abs(x_iminus1 - xvec[i - 2]));
                rvec.push_back(rate);
            } else {
                rvec.push_back(NAN);
            }

            ++i;
        }

        return std::make_tuple(xvec, i, rvec);
    }

    template<typename Func, typename Float>
    void test_newton_method(const Func& f, Float x0, Float abstol,
                            const std::string& funcname = "f", const std::string& filename = "test_f.txt")
    {
        const int nameWidth     = 24;
        const int numWidth      = 25;

        std::ofstream file;
        file.open(filename.c_str(), std::ios::out | std::ios::app);
        file << std::scientific << std::setprecision(15);
        file << "Getting the fixed points of '" << funcname
        << "' given x_0 = " << x0 << " and abstol = " << abstol << std::endl;

        auto tuple = newton_method(f, x0, abstol);

        auto xvec = std::get<0>(tuple);
        auto iters = std::get<1>(tuple);
        auto rvec = std::get<2>(tuple);

        printElement("i", nameWidth, file);
        printElement("x_i", nameWidth, file);
        printElement("|x_i - x_{i - 1}|", nameWidth, file);
        printElement("rate", nameWidth, file);
        file << '\n';

        for (auto i = 0; i < xvec.size(); ++i)
        {
            printElement(i, numWidth, file);
            printElement(xvec[i], numWidth, file);
            if ((i - 1) >= 0) {
                printElement(std::abs(xvec[i] - xvec[i - 1]), numWidth, file);
            }
            printElement(rvec[i], numWidth, file);
            file << '\n';
        }

        file << "END" << std::endl;
    }

    namespace newton {
        // we can't use functors with the derivative function
        // so we have to stick to traditional functions
        double f1(double x)
        {
            return x * x - 3 * x + 2;
        }

        double f2(double x)
        {
            return x * x * x - 2 * x - 5;
        }

        double f3(double x)
        {
            return std::exp(-x) - x;
        }

        double f4(double x)
        {
            return std::sin(x) * x - 1;
        }

        double f5(double x)
        {
            return x * x * x - 3 * x * x + 3 * x - 1;
        }
    }

    void test_newton(double abstol)
    {
        using namespace newton; // for functions f1 to f5

        std::vector<double (*)(double)> vec {f1, f2, f3, f4, f5};
        std::vector<std::string> filenames {"f1.txt", "f2.txt", "f3.txt", "f4.txt", "f5.txt"};
        std::vector<std::string> funcnames {"f1", "f2", "f3", "f4", "f5"};
        std::vector<double> xnaughts {2.1, 2.5, 0.6, 0.9, 0.5};

        for (auto i = 0; i < vec.size(); ++i) {
            test_newton_method(*vec[i], xnaughts[i], abstol, funcnames[i], filenames[i]);
        }
    }

    template<typename Func, typename Float>
    std::tuple<std::vector<Float>,
            int,
            std::vector<Float>>
    secant_method(const Func& f, Float x0, Float x1, Float abstol)
    {

    }
}<commit_msg>Adding the secant method routine. Still need to add tests.<commit_after>#pragma once

#include <utility>
#include <vector>
#include <cmath>
#include <fstream>
#include <iomanip>

#include "derivative.hpp"

namespace fp {

    template<typename Func, typename Float>
    std::tuple<std::vector<Float>, int, std::vector<Float>> fixed_point(const Func& g, Float x0, Float abstol)
    {
        // vector to store intermediate x_i values
        std::vector<Float> xvec;
        std::vector<Float> rvec; // vector of rate approximations

        // do the first iteration outside the while loop
        xvec.push_back(g(x0));
        Float currtol = static_cast<Float>(std::abs(xvec[0] - x0));

        // number of iterations : we have already performed one
        auto i = 1;
        Float rate = NAN;
        rvec.push_back(rate);

        Float x_iminus1;
        Float x_i;
        Float x_iplus1;
        Float deltaxp1;
        while (currtol > abstol)
        {
            x_iminus1 = xvec[i - 1];
            x_i = g(x_iminus1);
            xvec.push_back(x_i); // xi = g(x_{i - 1})
            x_iplus1 = g(x_i);
            currtol = std::abs(x_i - x_iminus1);
            deltaxp1 = std::abs(x_iplus1 - x_i);

            if ((i - 2) > 0) {
                rate = std::log(deltaxp1 / currtol) / std::log(currtol / std::abs(x_iminus1 - xvec[i - 2]));
                rvec.push_back(rate);
            } else {
                rvec.push_back(NAN);
            }

            ++i;
        }

        return std::make_tuple(xvec, i, rvec);
    }

    template<typename T> void printElement(T t, const int& width, std::ostream& stream)
    {
        static const char separator = ' ';
        stream << std::left << std::setw(width) << std::setfill(separator) << t;
    }

    template<typename Func, typename Float>
    void test_fixed_point(const Func& g, Float x0, Float abstol,
                          const std::string& funcname = "g", const std::string& filename = "test_g.txt")
    {
        const int nameWidth     = 24;
        const int numWidth      = 25;

        std::ofstream file;
        file.open(filename.c_str(), std::ios::out | std::ios::app);
        file << std::scientific << std::setprecision(15);
        file << "Getting the fixed points of '" << funcname
            << "' given x_0 = " << x0 << " and abstol = " << abstol << std::endl;

        auto tuple = fixed_point(g, x0, abstol);

        auto xvec = std::get<0>(tuple);
        auto iters = std::get<1>(tuple);
        auto rvec = std::get<2>(tuple);

        printElement("i", nameWidth, file);
        printElement("x_i", nameWidth, file);
        printElement("|x_i - x_{i - 1}|", nameWidth, file);
        printElement("rate", nameWidth, file);
        file << '\n';

        for (auto i = 0; i < xvec.size(); ++i)
        {
            printElement(i, numWidth, file);
            printElement(xvec[i], numWidth, file);
            if ((i - 1) >= 0) {
                printElement(std::abs(xvec[i] - xvec[i - 1]), numWidth, file);
            }
            printElement(rvec[i], numWidth, file);
            file << '\n';
        }

        file << "END" << std::endl;
    }

    void test_fp(double x0, double abstol)
    {
        const auto g1 = [](double x) -> double {
            return (x * x + 2) / 3;
        };

        // will result in NaNs because the value under the square root
        // will become negative at some point.
        const auto g2 = [](double x) -> double {
            return std::sqrt(3 * x - 2);
        };

        const auto g3 = [](double x) -> double {
            return 3 - (2 / x);
        };

        const auto g4 = [](double x) -> double {
            return (x * x  - 2) / (2 * x - 3);
        };

        std::vector<std::function<double(double)>> vec {g1, g2, g3, g4};
        std::vector<std::string> filenames {"g1.txt", "g2.txt", "g3.txt", "g4.txt"};
        std::vector<std::string> funcnames {"g1", "g2", "g3", "g4"};

        for (auto i = 0; i < vec.size(); ++i) {
            fp::test_fixed_point(vec[i], x0, abstol, funcnames[i], filenames[i]);
        }
    }

    template<typename Func, typename Float>
    std::tuple<std::vector<Float>, int, std::vector<Float>> newton_method(const Func& f, Float x0, Float abstol)
    {
        // vector to store intermediate x_i values
        std::vector<Float> xvec;
        std::vector<Float> rvec; // vector of rate approximations

        // do the first iteration outside the while loop
        auto x1 = x0 - (f(x0) / derivative(f, x0));
        xvec.push_back(x1);
        Float currtol = static_cast<Float>(std::abs(xvec[0] - x0));

        // number of iterations : we have already performed one
        auto i = 1;
        Float rate = NAN;
        rvec.push_back(rate);

        Float x_iminus1;
        Float x_i;
        Float x_iplus1;
        Float deltaxp1;
        while (currtol > abstol)
        {
            x_iminus1 = xvec[i - 1];
            x_i = x_iminus1 - (f(x_iminus1) / derivative(f, x_iminus1));
            xvec.push_back(x_i);
            x_iplus1 = x_i - (f(x_i) / derivative(f, x_i));
            currtol = std::abs(x_i - x_iminus1);
            deltaxp1 = std::abs(x_iplus1 - x_i);

            if ((i - 2) > 0) {
                rate = std::log(deltaxp1 / currtol) / std::log(currtol / std::abs(x_iminus1 - xvec[i - 2]));
                rvec.push_back(rate);
            } else {
                rvec.push_back(NAN);
            }

            ++i;
        }

        return std::make_tuple(xvec, i, rvec);
    }

    template<typename Func, typename Float>
    void test_newton_method(const Func& f, Float x0, Float abstol,
                            const std::string& funcname = "f", const std::string& filename = "test_f.txt")
    {
        const int nameWidth     = 24;
        const int numWidth      = 25;

        std::ofstream file;
        file.open(filename.c_str(), std::ios::out | std::ios::app);
        file << std::scientific << std::setprecision(15);
        file << "Getting the fixed points of '" << funcname
        << "' given x_0 = " << x0 << " and abstol = " << abstol << std::endl;

        auto tuple = newton_method(f, x0, abstol);

        auto xvec = std::get<0>(tuple);
        auto iters = std::get<1>(tuple);
        auto rvec = std::get<2>(tuple);

        printElement("i", nameWidth, file);
        printElement("x_i", nameWidth, file);
        printElement("|x_i - x_{i - 1}|", nameWidth, file);
        printElement("rate", nameWidth, file);
        file << '\n';

        for (auto i = 0; i < xvec.size(); ++i)
        {
            printElement(i, numWidth, file);
            printElement(xvec[i], numWidth, file);
            if ((i - 1) >= 0) {
                printElement(std::abs(xvec[i] - xvec[i - 1]), numWidth, file);
            }
            printElement(rvec[i], numWidth, file);
            file << '\n';
        }

        file << "END" << std::endl;
    }

    namespace newton {
        // we can't use functors with the derivative function
        // so we have to stick to traditional functions
        double f1(double x)
        {
            return x * x - 3 * x + 2;
        }

        double f2(double x)
        {
            return x * x * x - 2 * x - 5;
        }

        double f3(double x)
        {
            return std::exp(-x) - x;
        }

        double f4(double x)
        {
            return std::sin(x) * x - 1;
        }

        double f5(double x)
        {
            return x * x * x - 3 * x * x + 3 * x - 1;
        }
    }

    void test_newton(double abstol)
    {
        using namespace newton; // for functions f1 to f5

        std::vector<double (*)(double)> vec {f1, f2, f3, f4, f5};
        std::vector<std::string> filenames {"f1.txt", "f2.txt", "f3.txt", "f4.txt", "f5.txt"};
        std::vector<std::string> funcnames {"f1", "f2", "f3", "f4", "f5"};
        std::vector<double> xnaughts {2.1, 2.5, 0.6, 0.9, 0.5};

        for (auto i = 0; i < vec.size(); ++i) {
            test_newton_method(*vec[i], xnaughts[i], abstol, funcnames[i], filenames[i]);
        }
    }

    template<typename Func, typename Float>
    std::tuple<std::vector<Float>,
            int,
            std::vector<Float>>
    secant_method(const Func& f, Float x0, Float x1, Float abstol)
    {
        // vector to store intermediate x_i values
        std::vector<Float> xvec;
        std::vector<Float> rvec; // vector of rate approximations

        // do the first iteration outside the while loop
        xvec.push_back(x1);
        auto x2 = x1 - f(x1) * ((x1 - x0) / (f(x1) - f(x0)));
        xvec.push_back(x2);
        Float currtol = static_cast<Float>(std::abs(xvec[0] - x1));

        // number of iterations : we have already performed one
        auto i = 2;
        Float rate = NAN;
        rvec.push_back(rate);

        Float x_iminus2;
        Float x_iminus1;
        Float x_i;
        Float x_iplus1;
        Float deltaxp1;
        while (currtol > abstol)
        {
            x_iminus2 = xvec[i - 2];
            x_iminus1 = xvec[i - 1];
            x_i = x_iminus1 - f(x_iminus1) * ((x_iminus1 - x_iminus2) / (f(x_iminus1) - f(x_iminus2)));
            xvec.push_back(x_i);
            x_iplus1 = x_i - f(x_i) * ((x_i - x_iminus1) / (f(x_i) - f(x_iminus1)));
            currtol = std::abs(x_i - x_iminus1);
            deltaxp1 = std::abs(x_iplus1 - x_i);

            if ((i - 2) > 0) {
                rate = std::log(deltaxp1 / currtol) / std::log(currtol / std::abs(x_iminus1 - xvec[i - 2]));
                rvec.push_back(rate);
            } else {
                rvec.push_back(NAN);
            }

            ++i;
        }

        return std::make_tuple(xvec, i, rvec);
    }

    template<typename Float, typename = std::enable_if<std::is_arithmetic<Float>::value>::type>
    Float midpoint(Float a, Float b)
    {
        return a + (b - a) / 2;
    }

    template<typename Float, typename = std::enable_if<std::is_arithmetic<Float>::value>::type>
    int sign(Float a)
    {
        return a > 0 ? 1 : -1;
    }

    template<typename Func, typename Float>
    Float
    bisection_method(const Func& f, Float a, Float b, Float abstol, int numiters)
    {
        auto n = 1;
        Float c;
        Float l = a;
        Float u = b;
        while (n <= numiters)
        {
            c = midpoint(l, u);
            if ((u - l) < abstol) {
                break;
            }
            if (sign(f(c)) = sign(f(l))) {
                l = c;
            } else {
                b = c;
            }
            n++;
        }

        return c;
    }
}<|endoftext|>


<commit_before>#include <julia.h>
#include "JMain.h"

using namespace std;

shared_ptr<nj::Expr> JMain::eval(const shared_ptr<nj::Expr> &expr)
{
   shared_ptr<nj::Expr> result;

   return result;
}

JMain::JMain()
{
   initialized = false;
   deactivated = false;
}

void JMain::initialize(int argc,const char *argv[]) throw(nj::InitializationException)
{
   unique_lock<mutex> lock(m_state);

   if(argc >= 1) install_directory = argv[0];
   initialized = true;
}

shared_ptr<nj::Expr> JMain::de_queue(list<shared_ptr<nj::Expr>> &queue)
{
   bool done = false;
   shared_ptr<nj::Expr> expr;

   while(!done)
   {
      {
         unique_lock<mutex> lock(m_state);

         while(eval_queue.empty() && !done)
         {
printf("Waiting for an expression\n");
            c_state.wait(lock);
            if(deactivated) done = true;
         }

         if(!deactivated)
         {
printf("Checking end of queue\n");
            expr = queue.back();
printf("Got expr\n");
printf("Expr text = %s\n",expr->getText().c_str());
            queue.pop_back();
printf("Poped end of queue\n");
            if(expr.get()) done = true;
         }
         else done = true;
      }
   }
   return expr;
}

void JMain::operator()()
{
   bool done = false;

   while(!done)
   {
      unique_lock<mutex> lock(m_state);

      if(!initialized) c_state.wait(lock);
      if(initialized || deactivated) done = true;
   }

   if(!deactivated)
   {
      if(install_directory == "") jl_init(0);
      else jl_init((char*)install_directory.c_str());
      JL_SET_STACK_BASE;

      done = false;
      shared_ptr<nj::Expr> expr;

      while(!done)
      {
printf("entering de_queue\n");
         expr = de_queue(eval_queue);

printf("got an expr\n");

         if(expr.get())
         {
printf("expr text = %s\n",expr->getText().c_str());
            shared_ptr<nj::Expr> result = eval(expr);

printf("Got a result\n");
            if(result.get())
            {
printf("Expr result = %s\n",result->getText().c_str());
              unique_lock<mutex> lock(m_state);

              if(!deactivated)
              {
printf("Pushing result\n");
                 result_queue.push_front(result);
                 c_state.notify_all();
              }
              else done = true;
            }
         }
         else done = true;
      }
   }
}

void JMain::evalQueuePut(const string &expressionText)
{
   unique_lock<mutex> lock(m_state);
   shared_ptr<nj::Expr> expr(new nj::Expr(expressionText));
printf("Received an expr %s\n",expressionText.c_str());
   eval_queue.push_front(expr);
   c_state.notify_all();
}

string JMain::resultQueueGet()
{
   shared_ptr<nj::Expr> expr = de_queue(result_queue);
printf("Got Result\n");
   if(expr.get())
   {
printf("Result text = %s\n",expr->getText().c_str());
    return expr->getText();
   }
printf("Result text = ""\n");
   return "";
}

void JMain::stop()
{
   unique_lock<mutex> lock(m_state);

   deactivated = true;
   c_state.notify_all();
}

JMain::~JMain() {}
<commit_msg>Debugging...<commit_after>#include <julia.h>
#include "JMain.h"

using namespace std;

shared_ptr<nj::Expr> JMain::eval(const shared_ptr<nj::Expr> &expr)
{
   shared_ptr<nj::Expr> result;

   return result;
}

JMain::JMain()
{
   initialized = false;
   deactivated = false;
}

void JMain::initialize(int argc,const char *argv[]) throw(nj::InitializationException)
{
   unique_lock<mutex> lock(m_state);

   if(argc >= 1) install_directory = argv[0];
   initialized = true;
}

shared_ptr<nj::Expr> JMain::de_queue(list<shared_ptr<nj::Expr>> &queue)
{
   bool done = false;
   shared_ptr<nj::Expr> expr;

   while(!done)
   {
      {
         unique_lock<mutex> lock(m_state);

         while(eval_queue.empty() && !done)
         {
printf("Waiting for an expression\n");
            c_state.wait(lock);
            if(deactivated) done = true;
         }

         if(!deactivated)
         {
printf("Checking end of queue\n");
            expr = queue.back();
printf("Got expr\n");
printf("Expr text = %s\n",expr->getText().c_str());
            queue.pop_back();
printf("Poped end of queue\n");
            if(expr.get()) done = true;
         }
         else done = true;
      }
   }
   return expr;
}

void JMain::operator()()
{
   bool done = false;

   while(!done)
   {
      unique_lock<mutex> lock(m_state);

      if(!initialized) c_state.wait(lock);
      if(initialized || deactivated) done = true;
   }

   if(!deactivated)
   {
      if(install_directory == "") jl_init(0);
      else jl_init((char*)install_directory.c_str());
      JL_SET_STACK_BASE;

      done = false;

      while(!done)
      {
printf("entering de_queue\n");
         shared_ptr<nj::Expr> expr = de_queue(eval_queue);

printf("got an expr\n");

         if(expr.get())
         {
printf("expr text = %s\n",expr->getText().c_str());
            shared_ptr<nj::Expr> result = eval(expr);

printf("Got a result\n");
            if(result.get())
            {
printf("Expr result = %s\n",result->getText().c_str());
              unique_lock<mutex> lock(m_state);

              if(!deactivated)
              {
printf("Pushing result\n");
                 result_queue.push_front(result);
                 c_state.notify_all();
              }
              else done = true;
            }
         }
         else printf("Expr was null\n");
      }
   }
}

void JMain::evalQueuePut(const string &expressionText)
{
   unique_lock<mutex> lock(m_state);
   shared_ptr<nj::Expr> expr(new nj::Expr(expressionText));
printf("Received an expr %s\n",expressionText.c_str());
   eval_queue.push_front(expr);
   c_state.notify_all();
}

string JMain::resultQueueGet()
{
   shared_ptr<nj::Expr> expr = de_queue(result_queue);
printf("Got Result\n");
   if(expr.get())
   {
printf("Result text = %s\n",expr->getText().c_str());
    return expr->getText();
   }
printf("Result text = ""\n");
   return "";
}

void JMain::stop()
{
   unique_lock<mutex> lock(m_state);

   deactivated = true;
   c_state.notify_all();
}

JMain::~JMain() {}
<|endoftext|>


<commit_before>#include <cassert>
#include <cmath>
#include <string>

#include "fixfmt/text.hh"
#include "py.hh"

using namespace py;
using std::string;

//------------------------------------------------------------------------------

// FIXME: Add docstrings.

namespace {

template<typename TYPE>
ref<Object> analyze_float(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {"buf", "max_precision", nullptr};
  PyObject* array_obj;
  int max_precision;
  Arg::ParseTupleAndKeywords(
    args, kw_args, "Oi", arg_names, &array_obj, &max_precision);

  BufferRef buffer(array_obj, PyBUF_ND);
  if (buffer->ndim != 1)
    throw TypeError("not a one-dimensional array");
  if (buffer->itemsize != sizeof(TYPE))
    throw TypeError("wrong itemsize");
  TYPE const* const array = (TYPE const* const) buffer->buf;
  size_t const length = buffer->shape[0];

  bool has_nan = false;
  bool has_pos_inf = false;
  bool has_neg_inf = false;
  size_t num = 0;
  TYPE min = std::numeric_limits<TYPE>::max();
  TYPE max = std::numeric_limits<TYPE>::min();

  // Estimate precision truncating 'precision' digits to the right of the
  // decimal point, and comparing the result to 'tolerance'.
  // FIXME: Might not be correct for long double.
  int precision = 0;
  TYPE precision_scale = 1;
  TYPE tolerance = fixfmt::pow10(-max_precision) / 2;

  for (size_t i = 0; i < length; ++i) {
    TYPE const val = array[i];
    // Flag NaN.
    if (std::isnan(val)) {
      has_nan = true;
      continue;
    }
    // Flag positive and negative infinity.
    if (std::isinf(val)) {
      if (val > 0)
        has_pos_inf = true;
      else
        has_neg_inf = true;
      continue;
    }
    // Keep count of non-NaN/infinity values.
    ++num;
    // Compute min and max, excluding NaN and infinity.
    if (val < min)
      min = val;
    if (val > max)
      max = val;
    // Expand precision if necessary to accommodate additional fractional
    // digits, up to the maximum specified precision.
    while (precision < max_precision) {
      TYPE const scaled = std::abs(val) * precision_scale;
      TYPE const remainder = scaled - (long) (scaled + tolerance);
      if (remainder < tolerance)
        break;
      else {
        ++precision;
        precision_scale *= 10;
        tolerance *= 10;
      }
    }
  }

  // FIXME: Wrap this better.
  PyObject* result = PyTuple_New(7);
  PyTuple_SET_ITEM(result, 0, Bool::from(has_nan).release());
  PyTuple_SET_ITEM(result, 1, Bool::from(has_pos_inf).release());
  PyTuple_SET_ITEM(result, 2, Bool::from(has_neg_inf).release());
  PyTuple_SET_ITEM(result, 3, Long::FromLong(num).release());
  PyTuple_SET_ITEM(result, 4, Float::FromDouble(min).release());
  PyTuple_SET_ITEM(result, 5, Float::FromDouble(max).release());
  PyTuple_SET_ITEM(result, 6, Long::FromLong(precision).release());
  return ref<Tuple>::take(result);
}

ref<Object> center(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "pad", "position", nullptr};
  char const* str;
  int length;
  char const* pad = " ";
  float position = 0.5;
  Arg::ParseTupleAndKeywords(
      args, kw_args, "sI|sd", arg_names, &str, &length, &pad, &position);

  // FIXME: Validate args.
  if (strlen(pad) == 0)
    throw ValueError("empty pad");
  if (position < 0 or position > 1)
    throw ValueError("position out of range");

  return Unicode::from(fixfmt::center(string(str), length, pad, position));
}

ref<Object> pad(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "pad", "left", nullptr};
  char const* str;
  int length;
  char const* pad = " ";
  int left = false;
  Arg::ParseTupleAndKeywords(
      args, kw_args, "sI|sp", arg_names, &str, &length, &pad, &left);

  // FIXME: Validate args.
  if (strlen(pad) == 0)
    throw ValueError("empty pad");

  return Unicode::from(fixfmt::pad(string(str), length, pad, (bool) left));
}

ref<Object> elide(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "ellipsis", "position", nullptr};
  char const* str;
  int length;
  char const* ellipsis = fixfmt::ELLIPSIS;
  float position = 1.0;
  Arg::ParseTupleAndKeywords(
    args, kw_args, "sI|sf", arg_names, &str, &length, &ellipsis, &position);

  string r = fixfmt::elide(string(str), length, string(ellipsis), position);
  return Unicode::from(r);
}

ref<Object> palide(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "ellipsis", "pad", "position", "left", nullptr };
  char const* str;
  int length;
  char const* ellipsis = fixfmt::ELLIPSIS;
  char const* pad = " ";
  float position = 1.0;
  int left = false;
  Arg::ParseTupleAndKeywords(
    args, kw_args, "sI|ssfp", arg_names,
    &str, &length, &ellipsis, &pad, &position, &left);

  // FIXME: Validate args.
  if (strlen(pad) == 0)
    throw ValueError("empty pad");

  string r = fixfmt::palide(
    string(str), length, string(ellipsis), pad, position, (bool) left);
  return Unicode::from(r);
}

ref<Object> string_length(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = { "string", nullptr };
  char const* str;
  Arg::ParseTupleAndKeywords(args, kw_args, "s", arg_names, &str);

  return Long::FromLong(fixfmt::string_length(str));
}

}  // anonymous namespace

//------------------------------------------------------------------------------

Methods<Module>& add_functions(Methods<Module>& methods)
{
  methods
    .add<analyze_float<double>> ("analyze_double")
    .add<analyze_float<float>>  ("analyze_float")
    .add<center>                ("center")
    .add<elide>                 ("elide")
    .add<pad>                   ("pad")
    .add<palide>                ("palide")
    .add<string_length>         ("string_length")
    ;
  return methods;
}

<commit_msg>Note about compiler optimization.<commit_after>#include <cassert>
#include <cmath>
#include <string>

#include "fixfmt/text.hh"
#include "py.hh"

using namespace py;
using std::string;

//------------------------------------------------------------------------------

// FIXME: Add docstrings.

namespace {

template<typename TYPE>
ref<Object> analyze_float(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {"buf", "max_precision", nullptr};
  PyObject* array_obj;
  int max_precision;
  Arg::ParseTupleAndKeywords(
    args, kw_args, "Oi", arg_names, &array_obj, &max_precision);

  BufferRef buffer(array_obj, PyBUF_ND);
  if (buffer->ndim != 1)
    throw TypeError("not a one-dimensional array");
  if (buffer->itemsize != sizeof(TYPE))
    throw TypeError("wrong itemsize");
  TYPE const* const array = (TYPE const* const) buffer->buf;
  size_t const length = buffer->shape[0];

  bool has_nan = false;
  bool has_pos_inf = false;
  bool has_neg_inf = false;
  size_t num = 0;
  TYPE min = std::numeric_limits<TYPE>::max();
  TYPE max = std::numeric_limits<TYPE>::min();

  // Estimate precision truncating 'precision' digits to the right of the
  // decimal point, and comparing the result to 'tolerance'.
  // FIXME: Might not be correct for long double.
  int precision = 0;
  TYPE precision_scale = 1;
  TYPE tolerance = fixfmt::pow10(-max_precision) / 2;

  // Note: Weird.  LLVM 6.1.0 on OSX vectorizes this loop only if the precision
  // logic is _present_, with the result that it runs _faster_ than without.

  for (size_t i = 0; i < length; ++i) {
    TYPE const val = array[i];
    // Flag NaN.
    if (std::isnan(val)) {
      has_nan = true;
      continue;
    }
    // Flag positive and negative infinity.
    if (std::isinf(val)) {
      if (val > 0)
        has_pos_inf = true;
      else
        has_neg_inf = true;
      continue;
    }
    // Keep count of non-NaN/infinity values.
    ++num;
    // Compute min and max, excluding NaN and infinity.
    if (val < min)
      min = val;
    if (val > max)
      max = val;
    // Expand precision if necessary to accommodate additional fractional
    // digits, up to the maximum specified precision.
    while (precision < max_precision) {
      TYPE const scaled = std::abs(val) * precision_scale;
      TYPE const remainder = scaled - (long) (scaled + tolerance);
      if (remainder < tolerance)
        break;
      else {
        ++precision;
        precision_scale *= 10;
        tolerance *= 10;
      }
    }
  }

  // FIXME: Wrap this better.
  PyObject* result = PyTuple_New(7);
  PyTuple_SET_ITEM(result, 0, Bool::from(has_nan).release());
  PyTuple_SET_ITEM(result, 1, Bool::from(has_pos_inf).release());
  PyTuple_SET_ITEM(result, 2, Bool::from(has_neg_inf).release());
  PyTuple_SET_ITEM(result, 3, Long::FromLong(num).release());
  PyTuple_SET_ITEM(result, 4, Float::FromDouble(min).release());
  PyTuple_SET_ITEM(result, 5, Float::FromDouble(max).release());
  PyTuple_SET_ITEM(result, 6, Long::FromLong(precision).release());
  return ref<Tuple>::take(result);
}

ref<Object> center(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "pad", "position", nullptr};
  char const* str;
  int length;
  char const* pad = " ";
  float position = 0.5;
  Arg::ParseTupleAndKeywords(
      args, kw_args, "sI|sd", arg_names, &str, &length, &pad, &position);

  // FIXME: Validate args.
  if (strlen(pad) == 0)
    throw ValueError("empty pad");
  if (position < 0 or position > 1)
    throw ValueError("position out of range");

  return Unicode::from(fixfmt::center(string(str), length, pad, position));
}

ref<Object> pad(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "pad", "left", nullptr};
  char const* str;
  int length;
  char const* pad = " ";
  int left = false;
  Arg::ParseTupleAndKeywords(
      args, kw_args, "sI|sp", arg_names, &str, &length, &pad, &left);

  // FIXME: Validate args.
  if (strlen(pad) == 0)
    throw ValueError("empty pad");

  return Unicode::from(fixfmt::pad(string(str), length, pad, (bool) left));
}

ref<Object> elide(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "ellipsis", "position", nullptr};
  char const* str;
  int length;
  char const* ellipsis = fixfmt::ELLIPSIS;
  float position = 1.0;
  Arg::ParseTupleAndKeywords(
    args, kw_args, "sI|sf", arg_names, &str, &length, &ellipsis, &position);

  string r = fixfmt::elide(string(str), length, string(ellipsis), position);
  return Unicode::from(r);
}

ref<Object> palide(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = {
    "string", "length", "ellipsis", "pad", "position", "left", nullptr };
  char const* str;
  int length;
  char const* ellipsis = fixfmt::ELLIPSIS;
  char const* pad = " ";
  float position = 1.0;
  int left = false;
  Arg::ParseTupleAndKeywords(
    args, kw_args, "sI|ssfp", arg_names,
    &str, &length, &ellipsis, &pad, &position, &left);

  // FIXME: Validate args.
  if (strlen(pad) == 0)
    throw ValueError("empty pad");

  string r = fixfmt::palide(
    string(str), length, string(ellipsis), pad, position, (bool) left);
  return Unicode::from(r);
}

ref<Object> string_length(Module* module, Tuple* args, Dict* kw_args)
{
  static char const* arg_names[] = { "string", nullptr };
  char const* str;
  Arg::ParseTupleAndKeywords(args, kw_args, "s", arg_names, &str);

  return Long::FromLong(fixfmt::string_length(str));
}

}  // anonymous namespace

//------------------------------------------------------------------------------

Methods<Module>& add_functions(Methods<Module>& methods)
{
  methods
    .add<analyze_float<double>> ("analyze_double")
    .add<analyze_float<float>>  ("analyze_float")
    .add<center>                ("center")
    .add<elide>                 ("elide")
    .add<pad>                   ("pad")
    .add<palide>                ("palide")
    .add<string_length>         ("string_length")
    ;
  return methods;
}

<|endoftext|>


<commit_before>/***************************************************************************
COSC 501
Elliott Plack
Lab 10
6 NOV 2013
***************************************************************************/

<commit_msg>Define problem<commit_after>/***************************************************************************
COSC 501
Elliott Plack
Lab 10
6 NOV 2013                                                  Due 11 NOV 2013
Problem:	Use a class to calculate price-change percentage of a given
			stock, like Google (GOOG)
Algorithm:
***************************************************************************/

<|endoftext|>