<commit_before>// Best-first Utility-Guided Search Yes! From:
// "Best-first Utility-Guided Search," Wheeler Ruml and Minh B. Do,
// Proceedings of the Twentieth International Joint Conference on
// Artificial Intelligence (IJCAI-07), 2007

#include "../search/search.hpp"
#include "../structs/binheap.hpp"
#include "../utils/pool.hpp"
#include <cstring>

template <class D> struct Bugsy : public SearchAlgorithm<D> {
	typedef typename D::State State;
	typedef typename D::PackedState PackedState;
	typedef typename D::Cost Cost;
	typedef typename D::Oper Oper;

	struct Node : SearchNode<D> {
		typename D::Cost f, h, d;
		double u, t;

		// The expansion count when this node was
		// generated.
		unsigned long expct;

		// path-based mean expansion delay.
		double avgdelay;
		unsigned long depth;

		static bool pred(Node *a, Node *b) {
			if (a->u != b->u)
				return a->u > b->u;
			if (a->t != b->t)
				return a->t < b->t;
			if (a->f != b->f)
				return a->f < b->f;
			return a->g > b->g;
		}
	};

	enum {
		// Resort1 is the number of expansions to perform
		// before the 1st open list resort.
		Resort1 = 128,
	};

	Bugsy(int argc, const char *argv[]) :
			SearchAlgorithm<D>(argc, argv),
			uselms(false),
			usehhat(false),
			usedhat(false),
			navg(0),
			herror(0),
			derror(0),
			useexpdelay(false),
			avgdelay(0),
			dropdups(false),
			timeper(0.0),
			nextresort(Resort1),
			nresort(0),
			closed(30000001) {
		wf = wt = -1;
		for (int i = 0; i < argc; i++) {
			if (i < argc - 1 && strcmp(argv[i], "-wf") == 0)
				wf = strtod(argv[++i], NULL);
			else if (i < argc - 1 && strcmp(argv[i], "-wt") == 0)
				wt = strtod(argv[++i], NULL);
			else if (i < argc - 1 && strcmp(argv[i], "-expdelay") == 0)
				useexpdelay = true;
			else if (i < argc - 1 && strcmp(argv[i], "-hhat") == 0)
				usehhat = true;
			else if (i < argc - 1 && strcmp(argv[i], "-dhat") == 0)
				usedhat = true;
			else if (i < argc - 1 && strcmp(argv[i], "-dropdups") == 0)
				dropdups = true;
			else if (i < argc - 1 && strcmp(argv[i], "-interph") == 0)
				interph = usehhat = true;
			else if (i < argc - 1 && strcmp(argv[i], "-hlms") == 0)
				initlms(argv[++i]);
		}

		if (wf < 0)
			fatal("Must specify non-negative f-weight using -wf");
		if (wt < 0)
			fatal("Must specify non-negative t-weight using -wt");

		nodes = new Pool<Node>();
	}

	~Bugsy() {
		delete nodes;
	}

	void search(D &d, typename D::State &s0) {
		this->start();
		last = walltime();
		closed.init(d);
		Node *n0 = init(d, s0);
		closed.add(n0);
		open.push(n0);

		while (!open.empty() && !SearchAlgorithm<D>::limit()) {
			Node* n = *open.pop();
			State buf, &state = d.unpack(buf, n->packed);
			if (d.isgoal(state)) {
				SearchAlgorithm<D>::res.goal(d, n);
				break;
			}
			expand(d, n, state);
			updatetime();
			updateopen();
		}

		this->finish();
	}

	virtual void reset() {
		SearchAlgorithm<D>::reset();
		open.clear();
		closed.clear();
		delete nodes;
		timeper = 0.0;
		nresort = 0;
		nextresort = Resort1;
		navg = 0;
		herror = derror = 0;
		nodes = new Pool<Node>();
	}

	virtual void output(FILE *out) {
		SearchAlgorithm<D>::output(out);
		closed.prstats(stdout, "closed ");
		dfpair(stdout, "open list type", "%s", "binary heap");
		dfpair(stdout, "node size", "%u", sizeof(Node));
		dfpair(stdout, "wf", "%g", wf);
		dfpair(stdout, "wt", "%g", wt);
		dfpair(stdout, "final time per expand", "%g", timeper);
		dfpair(stdout, "number of resorts", "%lu", nresort);
		if (usehhat)
			dfpair(stdout, "mean single-step h error", "%g", herror);
		if (usedhat)
			dfpair(stdout, "mean single-step d error", "%g", derror);
		if (useexpdelay)
			dfpair(stdout, "mean expansion delay", "%g", avgdelay);
	}

private:

	// Kidinfo holds information about a node used for
	// correcting the heuristic estimates.
	struct Kidinfo {
		Kidinfo() : f(-1), h(-1), d(-1) { }

		Kidinfo(Cost gval, Cost hval, Cost dval) : f(gval + hval), h(hval), d(dval) { }

		Cost f, h, d;
	};

	// expand expands the node, adding its children to the
	// open and closed lists as appropriate.
	void expand(D &d, Node *n, State &state) {
		this->res.expd++;

		if (useexpdelay) {
			unsigned long delay = this->res.expd - n->expct;
			avgdelay = avgdelay + (delay - avgdelay)/this->res.expd;
		}

		Kidinfo bestinfo;
		typename D::Operators ops(d, state);
		for (unsigned int i = 0; i < ops.size(); i++) {
			if (ops[i] == n->pop)
				continue;

			this->res.gend++;

			Kidinfo kinfo = considerkid(d, n, state, ops[i]);
			if (bestinfo.f < Cost(0) || kinfo.f < bestinfo.f)
				bestinfo = kinfo;
		}

		if (bestinfo.f < Cost(0))
			return;

		navg++;
		if (usehhat) {
			double herr = bestinfo.f - n->f;
			if (herr < 0)	// floating point rounding
				herr = 0;
			herror = herror + (herr - herror)/navg;
		}

		if (usedhat) {
			double derr = bestinfo.d + 1 - n->d;
			if (derr < 0)	// floating point rounding
				derr = 0;
			derror = derror + (derr - derror)/navg;
		}
	}

	// considers adding the child to the open and closed lists.
	Kidinfo considerkid(D &d, Node *parent, State &state, Oper op) {
		Node *kid = nodes->construct();
		typename D::Edge e(d, state, op);
		kid->g = parent->g + e.cost;
		kid->depth = parent->depth + 1;
		kid->avgdelay = parent->avgdelay;

		// single step path-max on d
		kid->d = d.d(e.state);
		if (kid->d < parent->d - Cost(1))
			kid->d = parent->d - Cost(1);

		// single step path-max on h
		kid->h = d.h(e.state);
		if (kid->h < parent->h - e.cost)
			kid->h = parent->h - e.cost;

		kid->f = kid->g + kid->h;

		if (useexpdelay)
			kid->expct = this->res.expd;

		Kidinfo kinfo(kid->g, kid->h, kid->d);

		d.pack(kid->packed, e.state);

		unsigned long hash = d.hash(kid->packed);
		Node *dup = static_cast<Node*>(closed.find(kid->packed, hash));
		if (dup) {
			this->res.dups++;
			if (!dropdups && kid->g < dup->g) {
				if (dup->ind < 0)
					this->res.reopnd++;
				dup->f = dup->f - dup->g + kid->g;
				dup->update(kid->g, parent, op, e.revop);
				computeutil(dup);
				open.pushupdate(dup, dup->ind);
			}
			nodes->destruct(kid);
		} else {
			kid->update(kid->g, parent, op, e.revop);
			computeutil(kid);
			closed.add(kid, hash);
			open.push(kid);
		}
		return kinfo;
	}

	Node *init(D &d, State &s0) {
		Node *n0 = nodes->construct();
		d.pack(n0->packed, s0);
		n0->g = Cost(0);
		n0->h = n0->f = d.h(s0);
		n0->d = d.d(s0);
		n0->depth = 0;
		n0->avgdelay = 0;
		computeutil(n0);
		n0->op = n0->pop = D::Nop;
		n0->parent = NULL;
		n0->expct = 0;
		return n0;
	}

	// compututil computes the utility value of the given node
	// using corrected estimates of d and h.
	void computeutil(Node *n) {
		double d = n->d;
		if (usedhat)
			d /= (1 - derror);

		double h = uselms ? hlms(n) : n->h;
		if (usehhat) {
			if (interph) {
				double hhat = h + d*herror;
				double w = wf/(wf+wt);
				h = n->h*w + hhat*(1-w);
			} else {
				h += d * herror;
			}
		}

		if (useexpdelay && avgdelay > 0)
			d *= avgdelay;

		double f = h + n->g;
		n->t = timeper * d;
		n->u = -(wf * f + wt * n->t);
	}

	// updatetime runs a simple state machine (from Wheeler's BUGSY
	// implementation) that estimates the node expansion rate.
	void updatetime() {
		double t = walltime() - last;
		timeper = timeper + (t - timeper)/this->res.expd;
		last = walltime();
	}

	// updateopen updates the utilities of all nodes on open and
	// reinitializes the heap every 2^i expansions.
	void updateopen() {
		if (this->res.expd < nextresort)
			return;
		nextresort *= 2;
		nresort++;
		for (int i = 0; i < open.size(); i++)
			computeutil(open.at(i));
		open.reinit();
	}

	void initlms(const char *wts) {
		uselms = true;
		char *cpy = new char[strlen(wts)+1];
		memcpy(cpy, wts, strlen(wts)+1);

		char *tok = strtok(cpy, ",");
		int n = sizeof(coeffs)/sizeof(coeffs[0]);
		for (int i = 0; i < n; i++) {
			if (!tok)
				fatal("Expected %d coefficients", n);
			char *end = NULL;
			coeffs[i] = strtod(tok, &end);
			if (end == tok)
				fatal("Coefficient %d (%s) is invalid", i, tok);
			tok = strtok(NULL, ",");
		}

		delete []cpy;
	}

	double hlms(Node *n) const {
		return n->h*coeffs[0] +
			n->g*coeffs[1] +
			n->d*coeffs[2] +
			n->depth*coeffs[3];
	}

	bool uselms;
	// h, g, d, and D coefficients for LMS-based heuristic;
	double coeffs[4];

	// wf and wt are the cost and time weight respectively.
	double wf, wt;

	// heuristic correction
	bool usehhat, usedhat;
	unsigned long navg;
	double herror, derror;

	// interph — when using heuristic correction,
	// interpolate between h and hhat depending
	// on the ratio of wf to wt.
	bool interph;

	// expansion delay
	bool useexpdelay;
	double avgdelay;

	bool dropdups;

	// for nodes-per-second estimation
	double timeper, last;

	// for resorting the open list
	unsigned long nextresort;
	unsigned int nresort;

	BinHeap<Node, Node*> open;
 	ClosedList<SearchNode<D>, SearchNode<D>, D> closed;
	Pool<Node> *nodes;
};
<commit_msg>search: bugsy -dlms.<commit_after>// Best-first Utility-Guided Search Yes! From:
// "Best-first Utility-Guided Search," Wheeler Ruml and Minh B. Do,
// Proceedings of the Twentieth International Joint Conference on
// Artificial Intelligence (IJCAI-07), 2007

#include "../search/search.hpp"
#include "../structs/binheap.hpp"
#include "../utils/pool.hpp"
#include <cstring>

template <class D> struct Bugsy : public SearchAlgorithm<D> {
	typedef typename D::State State;
	typedef typename D::PackedState PackedState;
	typedef typename D::Cost Cost;
	typedef typename D::Oper Oper;

	struct Node : SearchNode<D> {
		typename D::Cost f, h, d;
		double u, t;

		// The expansion count when this node was
		// generated.
		unsigned long expct;

		// path-based mean expansion delay.
		double avgdelay;
		unsigned long depth;

		static bool pred(Node *a, Node *b) {
			if (a->u != b->u)
				return a->u > b->u;
			if (a->t != b->t)
				return a->t < b->t;
			if (a->f != b->f)
				return a->f < b->f;
			return a->g > b->g;
		}
	};

	enum {
		// Resort1 is the number of expansions to perform
		// before the 1st open list resort.
		Resort1 = 128,
	};

	Bugsy(int argc, const char *argv[]) :
			SearchAlgorithm<D>(argc, argv),
			usehlms(false),
			usehhat(false),
			usedhat(false),
			navg(0),
			herror(0),
			derror(0),
			useexpdelay(false),
			avgdelay(0),
			dropdups(false),
			timeper(0.0),
			nextresort(Resort1),
			nresort(0),
			closed(30000001) {
		wf = wt = -1;
		for (int i = 0; i < argc; i++) {
			if (i < argc - 1 && strcmp(argv[i], "-wf") == 0)
				wf = strtod(argv[++i], NULL);
			else if (i < argc - 1 && strcmp(argv[i], "-wt") == 0)
				wt = strtod(argv[++i], NULL);
			else if (i < argc - 1 && strcmp(argv[i], "-expdelay") == 0)
				useexpdelay = true;
			else if (i < argc - 1 && strcmp(argv[i], "-hhat") == 0)
				usehhat = true;
			else if (i < argc - 1 && strcmp(argv[i], "-dhat") == 0)
				usedhat = true;
			else if (i < argc - 1 && strcmp(argv[i], "-dropdups") == 0)
				dropdups = true;
			else if (i < argc - 1 && strcmp(argv[i], "-interph") == 0)
				interph = usehhat = true;
			else if (i < argc - 1 && strcmp(argv[i], "-hlms") == 0) {
				usehlms = true;
				initlms(sizeof(hcoeffs)/sizeof(hcoeffs[0]), argv[++i], hcoeffs);
			} else if (i < argc - 1 && strcmp(argv[i], "-dlms") == 0) {
				usedlms = true;
				initlms(sizeof(dcoeffs)/sizeof(dcoeffs[0]), argv[++i], dcoeffs);
			}
		}

		if (wf < 0)
			fatal("Must specify non-negative f-weight using -wf");
		if (wt < 0)
			fatal("Must specify non-negative t-weight using -wt");

		nodes = new Pool<Node>();
	}

	~Bugsy() {
		delete nodes;
	}

	void search(D &d, typename D::State &s0) {
		this->start();
		last = walltime();
		closed.init(d);
		Node *n0 = init(d, s0);
		closed.add(n0);
		open.push(n0);

		while (!open.empty() && !SearchAlgorithm<D>::limit()) {
			Node* n = *open.pop();
			State buf, &state = d.unpack(buf, n->packed);
			if (d.isgoal(state)) {
				SearchAlgorithm<D>::res.goal(d, n);
				break;
			}
			expand(d, n, state);
			updatetime();
			updateopen();
		}

		this->finish();
	}

	virtual void reset() {
		SearchAlgorithm<D>::reset();
		open.clear();
		closed.clear();
		delete nodes;
		timeper = 0.0;
		nresort = 0;
		nextresort = Resort1;
		navg = 0;
		herror = derror = 0;
		nodes = new Pool<Node>();
	}

	virtual void output(FILE *out) {
		SearchAlgorithm<D>::output(out);
		closed.prstats(stdout, "closed ");
		dfpair(stdout, "open list type", "%s", "binary heap");
		dfpair(stdout, "node size", "%u", sizeof(Node));
		dfpair(stdout, "wf", "%g", wf);
		dfpair(stdout, "wt", "%g", wt);
		dfpair(stdout, "final time per expand", "%g", timeper);
		dfpair(stdout, "number of resorts", "%lu", nresort);
		if (usehhat)
			dfpair(stdout, "mean single-step h error", "%g", herror);
		if (usedhat)
			dfpair(stdout, "mean single-step d error", "%g", derror);
		if (useexpdelay)
			dfpair(stdout, "mean expansion delay", "%g", avgdelay);
	}

private:

	// Kidinfo holds information about a node used for
	// correcting the heuristic estimates.
	struct Kidinfo {
		Kidinfo() : f(-1), h(-1), d(-1) { }

		Kidinfo(Cost gval, Cost hval, Cost dval) : f(gval + hval), h(hval), d(dval) { }

		Cost f, h, d;
	};

	// expand expands the node, adding its children to the
	// open and closed lists as appropriate.
	void expand(D &d, Node *n, State &state) {
		this->res.expd++;

		if (useexpdelay) {
			unsigned long delay = this->res.expd - n->expct;
			avgdelay = avgdelay + (delay - avgdelay)/this->res.expd;
		}

		Kidinfo bestinfo;
		typename D::Operators ops(d, state);
		for (unsigned int i = 0; i < ops.size(); i++) {
			if (ops[i] == n->pop)
				continue;

			this->res.gend++;

			Kidinfo kinfo = considerkid(d, n, state, ops[i]);
			if (bestinfo.f < Cost(0) || kinfo.f < bestinfo.f)
				bestinfo = kinfo;
		}

		if (bestinfo.f < Cost(0))
			return;

		navg++;
		if (usehhat) {
			double herr = bestinfo.f - n->f;
			if (herr < 0)	// floating point rounding
				herr = 0;
			herror = herror + (herr - herror)/navg;
		}

		if (usedhat) {
			double derr = bestinfo.d + 1 - n->d;
			if (derr < 0)	// floating point rounding
				derr = 0;
			derror = derror + (derr - derror)/navg;
		}
	}

	// considers adding the child to the open and closed lists.
	Kidinfo considerkid(D &d, Node *parent, State &state, Oper op) {
		Node *kid = nodes->construct();
		typename D::Edge e(d, state, op);
		kid->g = parent->g + e.cost;
		kid->depth = parent->depth + 1;
		kid->avgdelay = parent->avgdelay;

		// single step path-max on d
		kid->d = d.d(e.state);
		if (kid->d < parent->d - Cost(1))
			kid->d = parent->d - Cost(1);

		// single step path-max on h
		kid->h = d.h(e.state);
		if (kid->h < parent->h - e.cost)
			kid->h = parent->h - e.cost;

		kid->f = kid->g + kid->h;

		if (useexpdelay)
			kid->expct = this->res.expd;

		Kidinfo kinfo(kid->g, kid->h, kid->d);

		d.pack(kid->packed, e.state);

		unsigned long hash = d.hash(kid->packed);
		Node *dup = static_cast<Node*>(closed.find(kid->packed, hash));
		if (dup) {
			this->res.dups++;
			if (!dropdups && kid->g < dup->g) {
				if (dup->ind < 0)
					this->res.reopnd++;
				dup->f = dup->f - dup->g + kid->g;
				dup->update(kid->g, parent, op, e.revop);
				computeutil(dup);
				open.pushupdate(dup, dup->ind);
			}
			nodes->destruct(kid);
		} else {
			kid->update(kid->g, parent, op, e.revop);
			computeutil(kid);
			closed.add(kid, hash);
			open.push(kid);
		}
		return kinfo;
	}

	Node *init(D &d, State &s0) {
		Node *n0 = nodes->construct();
		d.pack(n0->packed, s0);
		n0->g = Cost(0);
		n0->h = n0->f = d.h(s0);
		n0->d = d.d(s0);
		n0->depth = 0;
		n0->avgdelay = 0;
		computeutil(n0);
		n0->op = n0->pop = D::Nop;
		n0->parent = NULL;
		n0->expct = 0;
		return n0;
	}

	// compututil computes the utility value of the given node
	// using corrected estimates of d and h.
	void computeutil(Node *n) {
		double d = usedlms ? evallms(n, dcoeffs) : n->d;
		if (usedhat)
			d /= (1 - derror);

		double h = usehlms ? evallms(n, hcoeffs) : n->h;
		if (usehhat) {
			if (interph) {
				double hhat = h + d*herror;
				double w = wf/(wf+wt);
				h = n->h*w + hhat*(1-w);
			} else {
				h += d * herror;
			}
		}

		if (useexpdelay && avgdelay > 0)
			d *= avgdelay;

		double f = h + n->g;
		n->t = timeper * d;
		n->u = -(wf * f + wt * n->t);
	}

	// updatetime runs a simple state machine (from Wheeler's BUGSY
	// implementation) that estimates the node expansion rate.
	void updatetime() {
		double t = walltime() - last;
		timeper = timeper + (t - timeper)/this->res.expd;
		last = walltime();
	}

	// updateopen updates the utilities of all nodes on open and
	// reinitializes the heap every 2^i expansions.
	void updateopen() {
		if (this->res.expd < nextresort)
			return;
		nextresort *= 2;
		nresort++;
		for (int i = 0; i < open.size(); i++)
			computeutil(open.at(i));
		open.reinit();
	}

	void initlms(unsigned int n, const char *wts, double coeffs[]) {
		char *cpy = new char[strlen(wts)+1];
		memcpy(cpy, wts, strlen(wts)+1);

		char *tok = strtok(cpy, ",");
		for (unsigned int i = 0; i < n; i++) {
			if (!tok)
				fatal("Expected %u coefficients", n);
			char *end = NULL;
			coeffs[i] = strtod(tok, &end);
			if (end == tok)
				fatal("Coefficient %u (%s) is invalid", i, tok);
			tok = strtok(NULL, ",");
		}

		delete []cpy;
	}

	double evallms(Node *n, double coeffs[]) const {
		return n->h*coeffs[0] +
			n->g*coeffs[1] +
			n->d*coeffs[2] +
			n->depth*coeffs[3];
	}

	bool usehlms;
	// h, g, d, and D coefficients for LMS-based heuristic;
	double hcoeffs[4];

	bool usedlms;
	// h, g, d, and D coefficients for LMS-based heuristic;
	double dcoeffs[4];

	// wf and wt are the cost and time weight respectively.
	double wf, wt;

	// heuristic correction
	bool usehhat, usedhat;
	unsigned long navg;
	double herror, derror;

	// interph — when using heuristic correction,
	// interpolate between h and hhat depending
	// on the ratio of wf to wt.
	bool interph;

	// expansion delay
	bool useexpdelay;
	double avgdelay;

	bool dropdups;

	// for nodes-per-second estimation
	double timeper, last;

	// for resorting the open list
	unsigned long nextresort;
	unsigned int nresort;

	BinHeap<Node, Node*> open;
 	ClosedList<SearchNode<D>, SearchNode<D>, D> closed;
	Pool<Node> *nodes;
};
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: convdiclist.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 19:49:07 $
 *
 *  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 _LINGUISTIC_CONVDICLIST_HXX_
#define _LINGUISTIC_CONVDICLIST_HXX_

#ifndef _COM_SUN_STAR_LINGUISTIC2_XCONVERSIONDICTIONARYLIST_HPP_
#include <com/sun/star/linguistic2/XConversionDictionaryList.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase3.hxx>
#endif
#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX //autogen wg. DBG_ASSERT
#include <tools/debug.hxx>
#endif

#include "misc.hxx"
#include "lngopt.hxx"

class ConvDicNameContainer;

///////////////////////////////////////////////////////////////////////////

class ConvDicList :
    public cppu::WeakImplHelper3
    <
        ::com::sun::star::linguistic2::XConversionDictionaryList,
        ::com::sun::star::lang::XComponent,
        ::com::sun::star::lang::XServiceInfo
    >
{

    class MyAppExitListener : public linguistic::AppExitListener
    {
        ConvDicList & rMyDicList;

    public:
        MyAppExitListener( ConvDicList &rDicList ) : rMyDicList( rDicList ) {}
        virtual void    AtExit();
    };

    ::cppu::OInterfaceContainerHelper       aEvtListeners;

    ConvDicNameContainer                   *pNameContainer;
    ::com::sun::star::uno::Reference<
        ::com::sun::star::container::XNameContainer >   xNameContainer;

    MyAppExitListener                      *pExitListener;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::
                XTerminateListener >        xExitListener;

    BOOL                                    bDisposing;

    // disallow copy-constructor and assignment-operator for now
    ConvDicList( const ConvDicList & );
    ConvDicList & operator = (const ConvDicList &);

    ConvDicNameContainer &  GetNameContainer();

public:
    ConvDicList();
    virtual ~ConvDicList();

    // XConversionDictionaryList
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > SAL_CALL getDictionaryContainer(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XConversionDictionary > SAL_CALL addNewDictionary( const ::rtl::OUString& aName, const ::com::sun::star::lang::Locale& aLocale, sal_Int16 nConversionDictionaryType ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL queryConversions( const ::rtl::OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength, const ::com::sun::star::lang::Locale& aLocale, sal_Int16 nConversionDictionaryType, ::com::sun::star::linguistic2::ConversionDirection eDirection, sal_Int32 nTextConversionOptions ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL queryMaxCharCount( const ::com::sun::star::lang::Locale& aLocale, sal_Int16 nConversionDictionaryType, ::com::sun::star::linguistic2::ConversionDirection eDirection ) throw (::com::sun::star::uno::RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

    static inline ::rtl::OUString
        getImplementationName_Static() throw();
    static com::sun::star::uno::Sequence< ::rtl::OUString >
        getSupportedServiceNames_Static() throw();

    // non UNO-specific
    void                    FlushDics();
};

inline ::rtl::OUString ConvDicList::getImplementationName_Static() throw()
{
    return A2OU( "com.sun.star.lingu2.ConvDicList" );
}

///////////////////////////////////////////////////////////////////////////

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.3.114); FILE MERGED 2008/04/01 15:21:26 thb 1.3.114.3: #i85898# Stripping all external header guards 2008/04/01 12:31:45 thb 1.3.114.2: #i85898# Stripping all external header guards 2008/03/31 16:25:37 rt 1.3.114.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: convdiclist.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _LINGUISTIC_CONVDICLIST_HXX_
#define _LINGUISTIC_CONVDICLIST_HXX_

#include <com/sun/star/linguistic2/XConversionDictionaryList.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/interfacecontainer.h>
#include <svtools/svarray.hxx>
#include <tools/debug.hxx>

#include "misc.hxx"
#include "lngopt.hxx"

class ConvDicNameContainer;

///////////////////////////////////////////////////////////////////////////

class ConvDicList :
    public cppu::WeakImplHelper3
    <
        ::com::sun::star::linguistic2::XConversionDictionaryList,
        ::com::sun::star::lang::XComponent,
        ::com::sun::star::lang::XServiceInfo
    >
{

    class MyAppExitListener : public linguistic::AppExitListener
    {
        ConvDicList & rMyDicList;

    public:
        MyAppExitListener( ConvDicList &rDicList ) : rMyDicList( rDicList ) {}
        virtual void    AtExit();
    };

    ::cppu::OInterfaceContainerHelper       aEvtListeners;

    ConvDicNameContainer                   *pNameContainer;
    ::com::sun::star::uno::Reference<
        ::com::sun::star::container::XNameContainer >   xNameContainer;

    MyAppExitListener                      *pExitListener;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::
                XTerminateListener >        xExitListener;

    BOOL                                    bDisposing;

    // disallow copy-constructor and assignment-operator for now
    ConvDicList( const ConvDicList & );
    ConvDicList & operator = (const ConvDicList &);

    ConvDicNameContainer &  GetNameContainer();

public:
    ConvDicList();
    virtual ~ConvDicList();

    // XConversionDictionaryList
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > SAL_CALL getDictionaryContainer(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XConversionDictionary > SAL_CALL addNewDictionary( const ::rtl::OUString& aName, const ::com::sun::star::lang::Locale& aLocale, sal_Int16 nConversionDictionaryType ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL queryConversions( const ::rtl::OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength, const ::com::sun::star::lang::Locale& aLocale, sal_Int16 nConversionDictionaryType, ::com::sun::star::linguistic2::ConversionDirection eDirection, sal_Int32 nTextConversionOptions ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL queryMaxCharCount( const ::com::sun::star::lang::Locale& aLocale, sal_Int16 nConversionDictionaryType, ::com::sun::star::linguistic2::ConversionDirection eDirection ) throw (::com::sun::star::uno::RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

    static inline ::rtl::OUString
        getImplementationName_Static() throw();
    static com::sun::star::uno::Sequence< ::rtl::OUString >
        getSupportedServiceNames_Static() throw();

    // non UNO-specific
    void                    FlushDics();
};

inline ::rtl::OUString ConvDicList::getImplementationName_Static() throw()
{
    return A2OU( "com.sun.star.lingu2.ConvDicList" );
}

///////////////////////////////////////////////////////////////////////////

#endif

<|endoftext|>


<commit_before>#include <mos/graphics/batch.hpp>
namespace mos {
Batch::Batch() {}

Batch::Batch(const std::initializer_list<Model> &models, const glm::mat4 &view,
             const glm::mat4 &projection, const glm::vec2 &resolution,
             const Light &light, const Fog &fog, const Shader &shader,
             const Draw &draw)
    : Batch(models.begin(), models.end(), view, projection, resolution, light,
            fog, shader, draw) {}
}
<commit_msg>FogExp rename.<commit_after>#include <mos/graphics/batch.hpp>
namespace mos {
Batch::Batch() {}

Batch::Batch(const std::initializer_list<Model> &models, const glm::mat4 &view,
             const glm::mat4 &projection, const glm::vec2 &resolution,
             const Light &light, const FogExp &fog, const Shader &shader,
             const Draw &draw)
    : Batch(models.begin(), models.end(), view, projection, resolution, light,
            fog, shader, draw) {}
}
<|endoftext|>


<commit_before>#include "integration_tests/routing_test_tools.hpp"

#include "testing/testing.hpp"

#include "map/feature_vec_model.hpp"

#include "geometry/distance_on_sphere.hpp"
#include "geometry/latlon.hpp"

#include "routing/online_absent_fetcher.hpp"
#include "routing/online_cross_fetcher.hpp"
#include "routing/road_graph_router.hpp"
#include "routing/route.hpp"
#include "routing/router_delegate.hpp"

#include "search/search_engine.hpp"

#include "indexer/index.hpp"

#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"

#include "geometry/distance_on_sphere.hpp"

#include "search/search_engine.hpp"
#include "search/search_query_factory.hpp"

#include <sys/resource.h>

using namespace routing;
using platform::LocalCountryFile;

namespace
{
  void ChangeMaxNumberOfOpenFiles(size_t n)
  {
    struct rlimit rlp;
    getrlimit(RLIMIT_NOFILE, &rlp);
    rlp.rlim_cur = n;
    setrlimit(RLIMIT_NOFILE, &rlp);
  }
}

namespace integration
{
  shared_ptr<model::FeaturesFetcher> CreateFeaturesFetcher(vector<LocalCountryFile> const & localFiles)
  {
    size_t const maxOpenFileNumber = 1024;
    ChangeMaxNumberOfOpenFiles(maxOpenFileNumber);
    shared_ptr<model::FeaturesFetcher> featuresFetcher(new model::FeaturesFetcher);
    featuresFetcher->InitClassificator();

    for (LocalCountryFile const & localFile : localFiles)
    {
      auto p = featuresFetcher->RegisterMap(localFile);
      if (p.second != MwmSet::RegResult::Success)
      {
        ASSERT(false, ("Can't register", localFile));
        return nullptr;
      }
    }
    return featuresFetcher;
  }

  shared_ptr<search::Engine> CreateSearchEngine(shared_ptr<model::FeaturesFetcher> featuresFetcher)
  {
    ASSERT(featuresFetcher, ());
    search::Engine::IndexType const & index = featuresFetcher->GetIndex();

    Platform const & pl = GetPlatform();
    try
    {
      shared_ptr<search::Engine> searchEngine(new search::Engine(
          &index, pl.GetReader(SEARCH_CATEGORIES_FILE_NAME), pl.GetReader(PACKED_POLYGONS_FILE),
          pl.GetReader(COUNTRIES_FILE), languages::GetCurrentOrig(),
          make_unique<search::SearchQueryFactory>()));
      return searchEngine;
    }
    catch (RootException const &e)
    {
      LOG(LCRITICAL, ("Error:", e.what(), " while creating searchEngine."));
      return nullptr;
    }
  }

  shared_ptr<OsrmRouter> CreateOsrmRouter(Index & index, search::Engine & searchEngine)
  {
    shared_ptr<OsrmRouter> osrmRouter(new OsrmRouter(
        &index, [&searchEngine](m2::PointD const & pt)
        {
          return searchEngine.GetCountryFile(pt);
        }
        ));
    return osrmRouter;
  }

  shared_ptr<IRouter> CreatePedestrianRouter(Index & index, search::Engine & searchEngine)
  {
    auto countryFileGetter = [&searchEngine](m2::PointD const & pt)
    {
      return searchEngine.GetCountryFile(pt);
    };
    unique_ptr<IRouter> router = CreatePedestrianAStarBidirectionalRouter(index, countryFileGetter);
    return shared_ptr<IRouter>(move(router));
  }

  class IRouterComponents
  {
  public:
    virtual IRouter * GetRouter() const = 0;
    virtual search::Engine * GetSearchEngine() const = 0;
    virtual ~IRouterComponents() = default;
  };

  class OsrmRouterComponents : public IRouterComponents
  {
  public:
    OsrmRouterComponents(vector<LocalCountryFile> const & localFiles)
        : m_featuresFetcher(CreateFeaturesFetcher(localFiles)),
          m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
          m_osrmRouter(CreateOsrmRouter(m_featuresFetcher->GetIndex(), *m_searchEngine.get()))
    {
    }
    IRouter * GetRouter() const override { return m_osrmRouter.get(); }
    search::Engine * GetSearchEngine() const override { return m_searchEngine.get(); }

  private:
    shared_ptr<model::FeaturesFetcher> m_featuresFetcher;
    shared_ptr<search::Engine> m_searchEngine;
    shared_ptr<OsrmRouter> m_osrmRouter;
  };

  class PedestrianRouterComponents : public IRouterComponents
  {
  public:
    PedestrianRouterComponents(vector<LocalCountryFile> const & localFiles)
        : m_featuresFetcher(CreateFeaturesFetcher(localFiles)),
          m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
          m_router(CreatePedestrianRouter(m_featuresFetcher->GetIndex(), *m_searchEngine))
    {
    }
    IRouter * GetRouter() const override { return m_router.get(); }
    search::Engine * GetSearchEngine() const override { return m_searchEngine.get(); }

  private:
    shared_ptr<model::FeaturesFetcher> m_featuresFetcher;
    shared_ptr<search::Engine> m_searchEngine;
    shared_ptr<IRouter> m_router;
  };

  template <typename TRouterComponents>
  shared_ptr<TRouterComponents> CreateAllMapsComponents()
  {
    // Setting stored paths from testingmain.cpp
    Platform & pl = GetPlatform();
    CommandLineOptions const & options = GetTestingOptions();
    if (options.m_dataPath)
      pl.SetWritableDirForTests(options.m_dataPath);
    if (options.m_resourcePath)
      pl.SetResourceDir(options.m_resourcePath);

    vector<LocalCountryFile> localFiles;
    platform::FindAllLocalMaps(localFiles);
    for (auto & file : localFiles)
      file.SyncWithDisk();
    ASSERT(!localFiles.empty(), ());
    return shared_ptr<TRouterComponents>(new TRouterComponents(localFiles));
  }

  shared_ptr<IRouterComponents> GetOsrmComponents(vector<platform::LocalCountryFile> const & localFiles)
  {
    return shared_ptr<IRouterComponents>(new OsrmRouterComponents(localFiles));
  }

  IRouterComponents & GetOsrmComponents()
  {
    static shared_ptr<IRouterComponents> const inst = CreateAllMapsComponents<OsrmRouterComponents>();
    ASSERT(inst, ());
    return *inst;
  }

  shared_ptr<IRouterComponents> GetPedestrianComponents(vector<platform::LocalCountryFile> const & localFiles)
  {
    return shared_ptr<IRouterComponents>(new PedestrianRouterComponents(localFiles));
  }

  IRouterComponents & GetPedestrianComponents()
  {
    static shared_ptr<IRouterComponents> const inst = CreateAllMapsComponents<PedestrianRouterComponents>();
    ASSERT(inst, ());
    return *inst;
  }

  TRouteResult CalculateRoute(IRouterComponents const & routerComponents,
                              m2::PointD const & startPoint, m2::PointD const & startDirection,
                              m2::PointD const & finalPoint)
  {
    RouterDelegate delegate;
    IRouter * router = routerComponents.GetRouter();
    ASSERT(router, ());
    shared_ptr<Route> route(new Route("mapsme"));
    IRouter::ResultCode result =
        router->CalculateRoute(startPoint, startDirection, finalPoint, delegate, *route.get());
    ASSERT(route, ());
    return TRouteResult(route, result);
  }

  void TestTurnCount(routing::Route const & route, uint32_t expectedTurnCount)
  {
    TEST_EQUAL(route.GetTurns().size(), expectedTurnCount, ());
  }

  void TestRouteLength(Route const & route, double expectedRouteMeters,
                       double relativeError)
  {
    double const delta = expectedRouteMeters * relativeError;
    double const routeMeters = route.GetTotalDistanceMeters();
    TEST(my::AlmostEqualAbs(routeMeters, expectedRouteMeters, delta),
        ("Route time test failed. Expected:", expectedRouteMeters, "have:", routeMeters, "delta:", delta));
  }

  void TestRouteTime(Route const & route, double expectedRouteSeconds, double relativeError)
  {
    double const delta = expectedRouteSeconds * relativeError;
    double const routeSeconds = route.GetTotalTimeSec();
    TEST(my::AlmostEqualAbs(routeSeconds, expectedRouteSeconds, delta),
        ("Route time test failed. Expected:", expectedRouteSeconds, "have:", routeSeconds, "delta:", delta));
  }

  void CalculateRouteAndTestRouteLength(IRouterComponents const & routerComponents,
                                        m2::PointD const & startPoint,
                                        m2::PointD const & startDirection,
                                        m2::PointD const & finalPoint, double expectedRouteMeters,
                                        double relativeError)
  {
    TRouteResult routeResult =
        CalculateRoute(routerComponents, startPoint, startDirection, finalPoint);
    IRouter::ResultCode const result = routeResult.second;
    TEST_EQUAL(result, IRouter::NoError, ());
    TestRouteLength(*routeResult.first, expectedRouteMeters, relativeError);
  }

  const TestTurn & TestTurn::TestValid() const
  {
    TEST(m_isValid, ());
    return *this;
  }

  const TestTurn & TestTurn::TestNotValid() const
  {
    TEST(!m_isValid, ());
    return *this;
  }

  const TestTurn & TestTurn::TestPoint(m2::PointD const & expectedPoint, double inaccuracyMeters) const
  {
    double const distanceMeters = ms::DistanceOnEarth(expectedPoint.y, expectedPoint.x, m_point.y, m_point.x);
    TEST_LESS(distanceMeters, inaccuracyMeters, ());
    return *this;
  }

  const TestTurn & TestTurn::TestDirection(routing::turns::TurnDirection expectedDirection) const
  {
    TEST_EQUAL(m_direction, expectedDirection, ());
    return *this;
  }

  const TestTurn & TestTurn::TestOneOfDirections(
      set<routing::turns::TurnDirection> const & expectedDirections) const
  {
    TEST(expectedDirections.find(m_direction) != expectedDirections.cend(), ());
    return *this;
  }

  const TestTurn & TestTurn::TestRoundAboutExitNum(uint32_t expectedRoundAboutExitNum) const
  {
    TEST_EQUAL(m_roundAboutExitNum, expectedRoundAboutExitNum, ());
    return *this;
  }

  TestTurn GetNthTurn(routing::Route const & route, uint32_t turnNumber)
  {
    Route::TTurns const & turns = route.GetTurns();
    if (turnNumber >= turns.size())
      return TestTurn();

    TurnItem const & turn = turns[turnNumber];
    return TestTurn(route.GetPoly().GetPoint(turn.m_index), turn.m_turn, turn.m_exitNum);
  }

  void TestOnlineFetcher(ms::LatLon const & startPoint, ms::LatLon const & finalPoint,
                         vector<string> const & expected, IRouterComponents & routerComponents)
  {
    auto countryFileGetter = [&routerComponents](m2::PointD const & p) -> string
    {
      return routerComponents.GetSearchEngine()->GetCountryFile(p);
    };
    auto localFileGetter = [&routerComponents](string const & countryFile) -> shared_ptr<LocalCountryFile>
    {
      //Always returns empty LocalFile
      return make_shared<LocalCountryFile>();
    };
    routing::OnlineAbsentCountriesFetcher fetcher(countryFileGetter, localFileGetter);
    fetcher.GenerateRequest(MercatorBounds::FromLatLon(startPoint),
                            MercatorBounds::FromLatLon(finalPoint));
    vector<string> absent;
    fetcher.GetAbsentCountries(absent);
    if (expected.size() < 2)
    {
      // Single MWM case. Do not use online routing.
      TEST(absent.empty(), ());
      return;
    }
    TEST_EQUAL(absent.size(), expected.size(), ());
    for (string const & name : expected)
    {
      TEST(find(absent.begin(), absent.end(), name) != absent.end(), ("Can't find ", name));
    }
  }

  void TestOnlineCrosses(ms::LatLon const & startPoint, ms::LatLon const & finalPoint,
                         vector<string> const & expected,
                         IRouterComponents & routerComponents)
  {
    routing::OnlineCrossFetcher fetcher(OSRM_ONLINE_SERVER_URL, startPoint, finalPoint);
    fetcher.Do();
    vector<m2::PointD> const & points = fetcher.GetMwmPoints();
    TEST_EQUAL(points.size(), expected.size(), ());
    for (m2::PointD const & point : points)
    {
      string const mwmName = routerComponents.GetSearchEngine()->GetCountryFile(point);
      TEST(find(expected.begin(), expected.end(), mwmName) != expected.end(), ("Can't find ", mwmName));
    }
    TestOnlineFetcher(startPoint, finalPoint, expected, routerComponents);
  }
}
<commit_msg>[routing] Itegration tests bad turns counter fix.<commit_after>#include "integration_tests/routing_test_tools.hpp"

#include "testing/testing.hpp"

#include "map/feature_vec_model.hpp"

#include "geometry/distance_on_sphere.hpp"
#include "geometry/latlon.hpp"

#include "routing/online_absent_fetcher.hpp"
#include "routing/online_cross_fetcher.hpp"
#include "routing/road_graph_router.hpp"
#include "routing/route.hpp"
#include "routing/router_delegate.hpp"

#include "search/search_engine.hpp"

#include "indexer/index.hpp"

#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"

#include "geometry/distance_on_sphere.hpp"

#include "search/search_engine.hpp"
#include "search/search_query_factory.hpp"

#include <sys/resource.h>

using namespace routing;
using platform::LocalCountryFile;

namespace
{
  void ChangeMaxNumberOfOpenFiles(size_t n)
  {
    struct rlimit rlp;
    getrlimit(RLIMIT_NOFILE, &rlp);
    rlp.rlim_cur = n;
    setrlimit(RLIMIT_NOFILE, &rlp);
  }
}

namespace integration
{
  shared_ptr<model::FeaturesFetcher> CreateFeaturesFetcher(vector<LocalCountryFile> const & localFiles)
  {
    size_t const maxOpenFileNumber = 1024;
    ChangeMaxNumberOfOpenFiles(maxOpenFileNumber);
    shared_ptr<model::FeaturesFetcher> featuresFetcher(new model::FeaturesFetcher);
    featuresFetcher->InitClassificator();

    for (LocalCountryFile const & localFile : localFiles)
    {
      auto p = featuresFetcher->RegisterMap(localFile);
      if (p.second != MwmSet::RegResult::Success)
      {
        ASSERT(false, ("Can't register", localFile));
        return nullptr;
      }
    }
    return featuresFetcher;
  }

  shared_ptr<search::Engine> CreateSearchEngine(shared_ptr<model::FeaturesFetcher> featuresFetcher)
  {
    ASSERT(featuresFetcher, ());
    search::Engine::IndexType const & index = featuresFetcher->GetIndex();

    Platform const & pl = GetPlatform();
    try
    {
      shared_ptr<search::Engine> searchEngine(new search::Engine(
          &index, pl.GetReader(SEARCH_CATEGORIES_FILE_NAME), pl.GetReader(PACKED_POLYGONS_FILE),
          pl.GetReader(COUNTRIES_FILE), languages::GetCurrentOrig(),
          make_unique<search::SearchQueryFactory>()));
      return searchEngine;
    }
    catch (RootException const &e)
    {
      LOG(LCRITICAL, ("Error:", e.what(), " while creating searchEngine."));
      return nullptr;
    }
  }

  shared_ptr<OsrmRouter> CreateOsrmRouter(Index & index, search::Engine & searchEngine)
  {
    shared_ptr<OsrmRouter> osrmRouter(new OsrmRouter(
        &index, [&searchEngine](m2::PointD const & pt)
        {
          return searchEngine.GetCountryFile(pt);
        }
        ));
    return osrmRouter;
  }

  shared_ptr<IRouter> CreatePedestrianRouter(Index & index, search::Engine & searchEngine)
  {
    auto countryFileGetter = [&searchEngine](m2::PointD const & pt)
    {
      return searchEngine.GetCountryFile(pt);
    };
    unique_ptr<IRouter> router = CreatePedestrianAStarBidirectionalRouter(index, countryFileGetter);
    return shared_ptr<IRouter>(move(router));
  }

  class IRouterComponents
  {
  public:
    virtual IRouter * GetRouter() const = 0;
    virtual search::Engine * GetSearchEngine() const = 0;
    virtual ~IRouterComponents() = default;
  };

  class OsrmRouterComponents : public IRouterComponents
  {
  public:
    OsrmRouterComponents(vector<LocalCountryFile> const & localFiles)
        : m_featuresFetcher(CreateFeaturesFetcher(localFiles)),
          m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
          m_osrmRouter(CreateOsrmRouter(m_featuresFetcher->GetIndex(), *m_searchEngine.get()))
    {
    }
    IRouter * GetRouter() const override { return m_osrmRouter.get(); }
    search::Engine * GetSearchEngine() const override { return m_searchEngine.get(); }

  private:
    shared_ptr<model::FeaturesFetcher> m_featuresFetcher;
    shared_ptr<search::Engine> m_searchEngine;
    shared_ptr<OsrmRouter> m_osrmRouter;
  };

  class PedestrianRouterComponents : public IRouterComponents
  {
  public:
    PedestrianRouterComponents(vector<LocalCountryFile> const & localFiles)
        : m_featuresFetcher(CreateFeaturesFetcher(localFiles)),
          m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
          m_router(CreatePedestrianRouter(m_featuresFetcher->GetIndex(), *m_searchEngine))
    {
    }
    IRouter * GetRouter() const override { return m_router.get(); }
    search::Engine * GetSearchEngine() const override { return m_searchEngine.get(); }

  private:
    shared_ptr<model::FeaturesFetcher> m_featuresFetcher;
    shared_ptr<search::Engine> m_searchEngine;
    shared_ptr<IRouter> m_router;
  };

  template <typename TRouterComponents>
  shared_ptr<TRouterComponents> CreateAllMapsComponents()
  {
    // Setting stored paths from testingmain.cpp
    Platform & pl = GetPlatform();
    CommandLineOptions const & options = GetTestingOptions();
    if (options.m_dataPath)
      pl.SetWritableDirForTests(options.m_dataPath);
    if (options.m_resourcePath)
      pl.SetResourceDir(options.m_resourcePath);

    vector<LocalCountryFile> localFiles;
    platform::FindAllLocalMaps(localFiles);
    for (auto & file : localFiles)
      file.SyncWithDisk();
    ASSERT(!localFiles.empty(), ());
    return shared_ptr<TRouterComponents>(new TRouterComponents(localFiles));
  }

  shared_ptr<IRouterComponents> GetOsrmComponents(vector<platform::LocalCountryFile> const & localFiles)
  {
    return shared_ptr<IRouterComponents>(new OsrmRouterComponents(localFiles));
  }

  IRouterComponents & GetOsrmComponents()
  {
    static shared_ptr<IRouterComponents> const inst = CreateAllMapsComponents<OsrmRouterComponents>();
    ASSERT(inst, ());
    return *inst;
  }

  shared_ptr<IRouterComponents> GetPedestrianComponents(vector<platform::LocalCountryFile> const & localFiles)
  {
    return shared_ptr<IRouterComponents>(new PedestrianRouterComponents(localFiles));
  }

  IRouterComponents & GetPedestrianComponents()
  {
    static shared_ptr<IRouterComponents> const inst = CreateAllMapsComponents<PedestrianRouterComponents>();
    ASSERT(inst, ());
    return *inst;
  }

  TRouteResult CalculateRoute(IRouterComponents const & routerComponents,
                              m2::PointD const & startPoint, m2::PointD const & startDirection,
                              m2::PointD const & finalPoint)
  {
    RouterDelegate delegate;
    IRouter * router = routerComponents.GetRouter();
    ASSERT(router, ());
    shared_ptr<Route> route(new Route("mapsme"));
    IRouter::ResultCode result =
        router->CalculateRoute(startPoint, startDirection, finalPoint, delegate, *route.get());
    ASSERT(route, ());
    return TRouteResult(route, result);
  }

  void TestTurnCount(routing::Route const & route, uint32_t expectedTurnCount)
  {
    // We use -1 for ignoring the "ReachedYourDestination" turn record.
    TEST_EQUAL(route.GetTurns().size() - 1, expectedTurnCount, ());
  }

  void TestRouteLength(Route const & route, double expectedRouteMeters,
                       double relativeError)
  {
    double const delta = expectedRouteMeters * relativeError;
    double const routeMeters = route.GetTotalDistanceMeters();
    TEST(my::AlmostEqualAbs(routeMeters, expectedRouteMeters, delta),
        ("Route time test failed. Expected:", expectedRouteMeters, "have:", routeMeters, "delta:", delta));
  }

  void TestRouteTime(Route const & route, double expectedRouteSeconds, double relativeError)
  {
    double const delta = expectedRouteSeconds * relativeError;
    double const routeSeconds = route.GetTotalTimeSec();
    TEST(my::AlmostEqualAbs(routeSeconds, expectedRouteSeconds, delta),
        ("Route time test failed. Expected:", expectedRouteSeconds, "have:", routeSeconds, "delta:", delta));
  }

  void CalculateRouteAndTestRouteLength(IRouterComponents const & routerComponents,
                                        m2::PointD const & startPoint,
                                        m2::PointD const & startDirection,
                                        m2::PointD const & finalPoint, double expectedRouteMeters,
                                        double relativeError)
  {
    TRouteResult routeResult =
        CalculateRoute(routerComponents, startPoint, startDirection, finalPoint);
    IRouter::ResultCode const result = routeResult.second;
    TEST_EQUAL(result, IRouter::NoError, ());
    TestRouteLength(*routeResult.first, expectedRouteMeters, relativeError);
  }

  const TestTurn & TestTurn::TestValid() const
  {
    TEST(m_isValid, ());
    return *this;
  }

  const TestTurn & TestTurn::TestNotValid() const
  {
    TEST(!m_isValid, ());
    return *this;
  }

  const TestTurn & TestTurn::TestPoint(m2::PointD const & expectedPoint, double inaccuracyMeters) const
  {
    double const distanceMeters = ms::DistanceOnEarth(expectedPoint.y, expectedPoint.x, m_point.y, m_point.x);
    TEST_LESS(distanceMeters, inaccuracyMeters, ());
    return *this;
  }

  const TestTurn & TestTurn::TestDirection(routing::turns::TurnDirection expectedDirection) const
  {
    TEST_EQUAL(m_direction, expectedDirection, ());
    return *this;
  }

  const TestTurn & TestTurn::TestOneOfDirections(
      set<routing::turns::TurnDirection> const & expectedDirections) const
  {
    TEST(expectedDirections.find(m_direction) != expectedDirections.cend(), ());
    return *this;
  }

  const TestTurn & TestTurn::TestRoundAboutExitNum(uint32_t expectedRoundAboutExitNum) const
  {
    TEST_EQUAL(m_roundAboutExitNum, expectedRoundAboutExitNum, ());
    return *this;
  }

  TestTurn GetNthTurn(routing::Route const & route, uint32_t turnNumber)
  {
    Route::TTurns const & turns = route.GetTurns();
    if (turnNumber >= turns.size())
      return TestTurn();

    TurnItem const & turn = turns[turnNumber];
    return TestTurn(route.GetPoly().GetPoint(turn.m_index), turn.m_turn, turn.m_exitNum);
  }

  void TestOnlineFetcher(ms::LatLon const & startPoint, ms::LatLon const & finalPoint,
                         vector<string> const & expected, IRouterComponents & routerComponents)
  {
    auto countryFileGetter = [&routerComponents](m2::PointD const & p) -> string
    {
      return routerComponents.GetSearchEngine()->GetCountryFile(p);
    };
    auto localFileGetter = [&routerComponents](string const & countryFile) -> shared_ptr<LocalCountryFile>
    {
      //Always returns empty LocalFile
      return make_shared<LocalCountryFile>();
    };
    routing::OnlineAbsentCountriesFetcher fetcher(countryFileGetter, localFileGetter);
    fetcher.GenerateRequest(MercatorBounds::FromLatLon(startPoint),
                            MercatorBounds::FromLatLon(finalPoint));
    vector<string> absent;
    fetcher.GetAbsentCountries(absent);
    if (expected.size() < 2)
    {
      // Single MWM case. Do not use online routing.
      TEST(absent.empty(), ());
      return;
    }
    TEST_EQUAL(absent.size(), expected.size(), ());
    for (string const & name : expected)
    {
      TEST(find(absent.begin(), absent.end(), name) != absent.end(), ("Can't find ", name));
    }
  }

  void TestOnlineCrosses(ms::LatLon const & startPoint, ms::LatLon const & finalPoint,
                         vector<string> const & expected,
                         IRouterComponents & routerComponents)
  {
    routing::OnlineCrossFetcher fetcher(OSRM_ONLINE_SERVER_URL, startPoint, finalPoint);
    fetcher.Do();
    vector<m2::PointD> const & points = fetcher.GetMwmPoints();
    TEST_EQUAL(points.size(), expected.size(), ());
    for (m2::PointD const & point : points)
    {
      string const mwmName = routerComponents.GetSearchEngine()->GetCountryFile(point);
      TEST(find(expected.begin(), expected.end(), mwmName) != expected.end(), ("Can't find ", mwmName));
    }
    TestOnlineFetcher(startPoint, finalPoint, expected, routerComponents);
  }
}
<|endoftext|>


<commit_before><commit_msg>Fix up some unit tests for HostResolver:<commit_after><|endoftext|>


<commit_before>#pragma once

#include <type_traits>

namespace agency
{
namespace detail
{

template<class _Tp, _Tp... _Ip>
struct integer_sequence
{
  typedef _Tp value_type;
  static_assert(std::is_integral<_Tp>::value,
                "std::integer_sequence can only be instantiated with an integral type" );
  static constexpr size_t size() noexcept { return sizeof...(_Ip); }
};

template<size_t... _Ip>
using index_sequence = integer_sequence<size_t, _Ip...>;

namespace integer_sequence_detail
{

template <class _Tp, _Tp _Sp, _Tp _Ep, class _IntSequence>
struct make_integer_sequence_unchecked;

template <class _Tp, _Tp _Sp, _Tp _Ep, _Tp ..._Indices>
struct make_integer_sequence_unchecked<_Tp, _Sp, _Ep,
                                       integer_sequence<_Tp, _Indices...>>
{
  typedef typename make_integer_sequence_unchecked<
    _Tp, _Sp+1, _Ep,
    integer_sequence<_Tp, _Indices..., _Sp>
  >::type type;
};

template <class _Tp, _Tp _Ep, _Tp ..._Indices>
struct make_integer_sequence_unchecked<_Tp, _Ep, _Ep,
                                       integer_sequence<_Tp, _Indices...>>
{
  typedef integer_sequence<_Tp, _Indices...> type;
};

template <class _Tp, _Tp _Ep>
struct make_integer_sequence
{
  static_assert(std::is_integral<_Tp>::value,
                "std::make_integer_sequence can only be instantiated with an integral type" );
  static_assert(0 <= _Ep, "std::make_integer_sequence input shall not be negative");
  typedef typename make_integer_sequence_unchecked
                   <
                      _Tp, 0, _Ep, integer_sequence<_Tp>
                   >::type type;
};

} // end integer_sequence_detail

template<class _Tp, _Tp _Np>
using make_integer_sequence = typename integer_sequence_detail::make_integer_sequence<_Tp, _Np>::type;

template<size_t _Np>
using make_index_sequence = make_integer_sequence<size_t, _Np>;

template<class... _Tp>
using index_sequence_for = make_index_sequence<sizeof...(_Tp)>;

} // end detail
} // end agency

<commit_msg>Add map_index_sequence, exclusive_scan_index_sequence, and transform_exclusive_scan_index_sequence<commit_after>#pragma once

#include <type_traits>
#include <stddef.h> // for size_t

namespace agency
{
namespace detail
{

template<class _Tp, _Tp... _Ip>
struct integer_sequence
{
  typedef _Tp value_type;
  static_assert(std::is_integral<_Tp>::value,
                "std::integer_sequence can only be instantiated with an integral type" );
  static constexpr size_t size() noexcept { return sizeof...(_Ip); }
};

template<size_t... _Ip>
using index_sequence = integer_sequence<size_t, _Ip...>;

namespace integer_sequence_detail
{

template <class _Tp, _Tp _Sp, _Tp _Ep, class _IntSequence>
struct make_integer_sequence_unchecked;

template <class _Tp, _Tp _Sp, _Tp _Ep, _Tp ..._Indices>
struct make_integer_sequence_unchecked<_Tp, _Sp, _Ep,
                                       integer_sequence<_Tp, _Indices...>>
{
  typedef typename make_integer_sequence_unchecked<
    _Tp, _Sp+1, _Ep,
    integer_sequence<_Tp, _Indices..., _Sp>
  >::type type;
};

template <class _Tp, _Tp _Ep, _Tp ..._Indices>
struct make_integer_sequence_unchecked<_Tp, _Ep, _Ep,
                                       integer_sequence<_Tp, _Indices...>>
{
  typedef integer_sequence<_Tp, _Indices...> type;
};

template <class _Tp, _Tp _Ep>
struct make_integer_sequence
{
  static_assert(std::is_integral<_Tp>::value,
                "std::make_integer_sequence can only be instantiated with an integral type" );
  static_assert(0 <= _Ep, "std::make_integer_sequence input shall not be negative");
  typedef typename make_integer_sequence_unchecked
                   <
                      _Tp, 0, _Ep, integer_sequence<_Tp>
                   >::type type;
};

template<template<size_t> class MetaFunction, class IndexSeqence>
struct map_index_sequence;

template<template<size_t> class MetaFunction, size_t... Indices>
struct map_index_sequence<MetaFunction, index_sequence<Indices...>>
{
  using type = index_sequence<MetaFunction<Indices>::value...>;
};

template<class IndexSequence1, class IndexSequence2>
struct index_sequence_cat_impl;

template<size_t... Indices1, size_t... Indices2>
struct index_sequence_cat_impl<index_sequence<Indices1...>,index_sequence<Indices2...>>
{
  using type = index_sequence<Indices1...,Indices2...>;
};

template<class IndexSequence1, class IndexSequence2>
using index_sequence_cat = typename index_sequence_cat_impl<IndexSequence1,IndexSequence2>::type;

// compute the exclusive scan of IndexSequence
// initializing the first value in the sequence to Init
template<size_t Init, class IndexSequence>
struct exclusive_scan_index_sequence;

template<size_t Init, size_t Index0, size_t... Indices>
struct exclusive_scan_index_sequence<Init,index_sequence<Index0, Indices...>>
{
  using rest = typename exclusive_scan_index_sequence<Init + Index0, index_sequence<Indices...>>::type;

  using type = index_sequence_cat<index_sequence<Init>, rest>;
};

template<size_t Init, size_t Index0>
struct exclusive_scan_index_sequence<Init,index_sequence<Index0>>
{
  using type = index_sequence<Init>;
};

} // end integer_sequence_detail

template<class _Tp, _Tp _Np>
using make_integer_sequence = typename integer_sequence_detail::make_integer_sequence<_Tp, _Np>::type;

template<size_t _Np>
using make_index_sequence = make_integer_sequence<size_t, _Np>;

template<class... _Tp>
using index_sequence_for = make_index_sequence<sizeof...(_Tp)>;

template<template<size_t> class MetaFunction, class IndexSequence>
using map_index_sequence = typename integer_sequence_detail::map_index_sequence<MetaFunction,IndexSequence>::type;

template<size_t Init, class IndexSequence>
using exclusive_scan_index_sequence = typename integer_sequence_detail::exclusive_scan_index_sequence<Init,IndexSequence>::type;

template<template<size_t> class MetaFunction, size_t Init, class IndexSequence>
using transform_exclusive_scan_index_sequence = exclusive_scan_index_sequence<Init, map_index_sequence<MetaFunction,IndexSequence>>;

} // end detail
} // end agency

<|endoftext|>


<commit_before>/*
 * DIPlib 3.0
 * This file contains definitions of functions that implement the Kuwahara-Nagao operator.
 *
 * (c)2017, Cris Luengo.
 * Based on original DIPlib code: (c)1995-2014, Delft University of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diplib.h"
#include "diplib/nonlinear.h"
#include "diplib/linear.h"
#include "diplib/framework.h"
#include "diplib/generic_iterators.h"
#include "diplib/pixel_table.h"
#include "diplib/overload.h"

namespace dip {

namespace {

struct SelectionLineFilterParameters {
   void const* inBuffer;
   dfloat const* controlBuffer;
   void* outBuffer;
   dip::sint inStride;
   dip::sint inTensorStride; // == 1
   dip::sint controlStride;
   dip::sint outStride;
   dip::sint outTensorStride;
   dip::uint tensorLength;
   dip::uint bufferLength;
   PixelTableOffsets const& pixelTable;
   dfloat threshold;
   bool minimum;
};

class SelectionLineFilterBase {
   public:
      virtual void Filter( SelectionLineFilterParameters const& params ) = 0;
};

template< typename TPI >
class SelectionLineFilter : public SelectionLineFilterBase {
   public:
      virtual void Filter( SelectionLineFilterParameters const& params ) override {
         TPI const* in = static_cast< TPI const* >( params.inBuffer );
         dfloat const* control = params.controlBuffer;
         TPI* out = static_cast< TPI* >( params.outBuffer );
         auto const& distance = params.pixelTable.Weights();
         // For each pixel on the line:
         for( dip::uint ii = 0; ii < params.bufferLength; ++ii ) {
            // Iterate over the pixel table and find optimal offset
            auto it = params.pixelTable.begin();
            auto d = distance.begin();
            dfloat centerValue = *control;
            dfloat bestValue = params.minimum ? std::numeric_limits< dfloat >::max() : std::numeric_limits< dfloat >::lowest();
            dfloat bestDistance = std::numeric_limits< dfloat >::max();
            dip::sint bestOffset = 0;
            do {
               dfloat value = control[ *it ];
               if(( params.minimum ? ( value < bestValue ) : ( value > bestValue )) ||
                     (( value == bestValue ) && ( *d < bestDistance ))) {
                  bestValue = value;
                  bestDistance = *d;
                  bestOffset = *it;
               }
            } while( ++d, ++it );
            if( params.minimum ? bestValue + params.threshold < centerValue
                               : bestValue - params.threshold > centerValue ) {
               bestOffset *= params.tensorLength;
            } else {
               bestOffset = 0;
            }
            // Copy the tensor at that offset over the the output
            out[ 0 ] = in[ bestOffset ];
            for( dip::sint jj = 1; jj < static_cast< dip::sint >( params.tensorLength ); ++jj ) {
               out[ jj * params.outTensorStride ] = in[ bestOffset + jj * params.inTensorStride ];
            }
            // Next pixel
            in += params.inStride;
            control += params.controlStride;
            out += params.outStride;
         }
      }
};

} // namespace

void SelectionFilter(
      Image const& c_in,
      Image const& c_control,
      Image& out,
      Kernel const& kernel,
      dfloat threshold,
      String const& mode,
      StringArray const& boundaryCondition
) {
   // We are not using a framework here, because this is the only pixel table filter that uses two input images.
   // So we've copied things over from Framework::Full, and changed (simplified) them a bit. There's no multi-threading
   // here yet.
   // TODO: add multithreading.

   DIP_THROW_IF( !c_in.IsForged() || !c_control.IsForged(), E::IMAGE_NOT_FORGED );
   DIP_THROW_IF( c_in.Sizes() != c_control.Sizes(), E::SIZES_DONT_MATCH );
   DIP_THROW_IF( !c_control.IsScalar(), E::IMAGE_NOT_SCALAR );
   DIP_THROW_IF( !c_control.DataType().IsReal(), E::DATA_TYPE_NOT_SUPPORTED );
   DIP_THROW_IF( kernel.HasWeights(), E::KERNEL_NOT_BINARY );
   bool minimum = BooleanFromString( mode, "minimum", "maximum" );

   // Determine boundary sizes
   UnsignedArray kernelSizes;
   DIP_START_STACK_TRACE
      kernelSizes = kernel.Sizes( c_in.Sizes() );
   DIP_END_STACK_TRACE
   UnsignedArray boundary = kernelSizes;
   for( dip::uint& b : boundary ) {
      b /= 2;
   }
   IntegerArray shift = kernel.Shift();
   if( !shift.empty() ) {
      dip::uint n = std::min( shift.size(), boundary.size() );
      for( dip::uint ii = 0; ii < n; ++ii ) {
         boundary[ ii ] += static_cast< dip::uint >( std::abs( shift[ ii ] ));
      }
   }

   // Copy input images with boundary extension
   Image in;
   Image control;
   control.SetDataType( DT_DFLOAT );
   control.Protect();
   DIP_START_STACK_TRACE
      BoundaryConditionArray bc = StringArrayToBoundaryConditionArray( boundaryCondition );
      ExtendImageLowLevel( c_in, in, boundary, bc, Option::ExtendImage_Masked );
      ExtendImageLowLevel( c_control, control, boundary, bc, Option::ExtendImage_Masked );
   DIP_END_STACK_TRACE
#ifdef DIP__ENABLE_ASSERT
   // We have created a new `in` and `control`, so we expect normal strides here. Let's make sure this is the case!
   DIP_ASSERT( in.TensorStride() == 1 );
   for( dip::uint ii = 0; ii < in.Dimensionality(); ++ii ) {
      DIP_ASSERT( in.Stride( ii ) == control.Stride( ii ) * static_cast< dip::sint >( in.TensorElements() ));
   }
#endif

   // Adjust output if necessary (and possible)
   // NOTE: Don't use c_in any more from here on. It has possibly been reforged!
   DIP_START_STACK_TRACE
      out.ReForge( in.Sizes(), in.TensorElements(), in.DataType(), Option::AcceptDataTypeChange::DONT_ALLOW );
      out.ReshapeTensor( in.Tensor() );
      out.SetPixelSize( in.PixelSize() );
      if( !in.IsColor() ) {
         out.SetColorSpace( in.ColorSpace() );
      }
   DIP_END_STACK_TRACE
   DIP_ASSERT( in.DataType() == out.DataType() );

   // Create a pixel table suitable to be applied to `input`
   dip::uint processingDim = Framework::OptimalProcessingDim( in, kernelSizes );
   PixelTable pixelTable;
   DIP_START_STACK_TRACE
      pixelTable = kernel.PixelTable( in.Sizes(), processingDim );
   DIP_END_STACK_TRACE
   pixelTable.AddDistanceToOriginAsWeights();
   PixelTableOffsets pixelTableOffsets = pixelTable.Prepare( control ); // offsets are for the `control` image, multiply by `in.TensorElements()` to get offsets into `in`.

   // Get the line filter of the right type
   std::unique_ptr< SelectionLineFilterBase > lineFilter;
   DIP_OVL_NEW_ALL( lineFilter, SelectionLineFilter, (), in.DataType() );

   // Loop over all image lines
   SelectionLineFilterParameters params = {
         nullptr,
         nullptr,
         nullptr,
         in.Stride( processingDim ),
         in.TensorStride(),
         control.Stride( processingDim ),
         out.Stride( processingDim ),
         out.TensorStride(),
         in.TensorElements(),
         in.Size( processingDim ),
         pixelTableOffsets,
         threshold,
         minimum
   };
   GenericJointImageIterator< 3 > it( { in, control, out }, processingDim );
   do {
      params.inBuffer = in.Pointer( it.Offset< 0 >() );
      params.controlBuffer = static_cast< dfloat* >( control.Pointer( it.Offset< 1 >() ));
      params.outBuffer = out.Pointer( it.Offset< 2 >() );
      DIP_START_STACK_TRACE
         lineFilter->Filter( params );
      DIP_END_STACK_TRACE
   } while( ++it );
}

void Kuwahara(
      Image const& in,
      Image& out,
      Kernel kernel,
      dfloat threshold,
      StringArray const& boundaryCondition
) {
   DIP_START_STACK_TRACE
      Image value = dip::Uniform( in, kernel, boundaryCondition );
      Image control = dip::VarianceFilter( in, kernel, boundaryCondition );
      kernel.Mirror();
      SelectionFilter( value, control, out, kernel, threshold, "minimum", boundaryCondition );
   DIP_END_STACK_TRACE
}

} // namespace dip
<commit_msg>Fix GCC compiler warning.<commit_after>/*
 * DIPlib 3.0
 * This file contains definitions of functions that implement the Kuwahara-Nagao operator.
 *
 * (c)2017, Cris Luengo.
 * Based on original DIPlib code: (c)1995-2014, Delft University of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diplib.h"
#include "diplib/nonlinear.h"
#include "diplib/linear.h"
#include "diplib/framework.h"
#include "diplib/generic_iterators.h"
#include "diplib/pixel_table.h"
#include "diplib/overload.h"

namespace dip {

namespace {

struct SelectionLineFilterParameters {
   void const* inBuffer;
   dfloat const* controlBuffer;
   void* outBuffer;
   dip::sint inStride;
   dip::sint inTensorStride; // == 1
   dip::sint controlStride;
   dip::sint outStride;
   dip::sint outTensorStride;
   dip::uint tensorLength;
   dip::uint bufferLength;
   PixelTableOffsets const& pixelTable;
   dfloat threshold;
   bool minimum;
};

class SelectionLineFilterBase {
   public:
      virtual void Filter( SelectionLineFilterParameters const& params ) = 0;
};

template< typename TPI >
class SelectionLineFilter : public SelectionLineFilterBase {
   public:
      virtual void Filter( SelectionLineFilterParameters const& params ) override {
         TPI const* in = static_cast< TPI const* >( params.inBuffer );
         dfloat const* control = params.controlBuffer;
         TPI* out = static_cast< TPI* >( params.outBuffer );
         auto const& distance = params.pixelTable.Weights();
         // For each pixel on the line:
         for( dip::uint ii = 0; ii < params.bufferLength; ++ii ) {
            // Iterate over the pixel table and find optimal offset
            auto it = params.pixelTable.begin();
            auto d = distance.begin();
            dfloat centerValue = *control;
            dfloat bestValue = params.minimum ? std::numeric_limits< dfloat >::max() : std::numeric_limits< dfloat >::lowest();
            dfloat bestDistance = std::numeric_limits< dfloat >::max();
            dip::sint bestOffset = 0;
            do {
               dfloat value = control[ *it ];
               if(( params.minimum ? ( value < bestValue ) : ( value > bestValue )) ||
                     (( value == bestValue ) && ( *d < bestDistance ))) {
                  bestValue = value;
                  bestDistance = *d;
                  bestOffset = *it;
               }
            } while( ++d, ++it );
            if( params.minimum ? bestValue + params.threshold < centerValue
                               : bestValue - params.threshold > centerValue ) {
               bestOffset *= static_cast< dip::sint >( params.tensorLength );
            } else {
               bestOffset = 0;
            }
            // Copy the tensor at that offset over the the output
            out[ 0 ] = in[ bestOffset ];
            for( dip::sint jj = 1; jj < static_cast< dip::sint >( params.tensorLength ); ++jj ) {
               out[ jj * params.outTensorStride ] = in[ bestOffset + jj * params.inTensorStride ];
            }
            // Next pixel
            in += params.inStride;
            control += params.controlStride;
            out += params.outStride;
         }
      }
};

} // namespace

void SelectionFilter(
      Image const& c_in,
      Image const& c_control,
      Image& out,
      Kernel const& kernel,
      dfloat threshold,
      String const& mode,
      StringArray const& boundaryCondition
) {
   // We are not using a framework here, because this is the only pixel table filter that uses two input images.
   // So we've copied things over from Framework::Full, and changed (simplified) them a bit. There's no multi-threading
   // here yet.
   // TODO: add multithreading.

   DIP_THROW_IF( !c_in.IsForged() || !c_control.IsForged(), E::IMAGE_NOT_FORGED );
   DIP_THROW_IF( c_in.Sizes() != c_control.Sizes(), E::SIZES_DONT_MATCH );
   DIP_THROW_IF( !c_control.IsScalar(), E::IMAGE_NOT_SCALAR );
   DIP_THROW_IF( !c_control.DataType().IsReal(), E::DATA_TYPE_NOT_SUPPORTED );
   DIP_THROW_IF( kernel.HasWeights(), E::KERNEL_NOT_BINARY );
   bool minimum = BooleanFromString( mode, "minimum", "maximum" );

   // Determine boundary sizes
   UnsignedArray kernelSizes;
   DIP_START_STACK_TRACE
      kernelSizes = kernel.Sizes( c_in.Sizes() );
   DIP_END_STACK_TRACE
   UnsignedArray boundary = kernelSizes;
   for( dip::uint& b : boundary ) {
      b /= 2;
   }
   IntegerArray shift = kernel.Shift();
   if( !shift.empty() ) {
      dip::uint n = std::min( shift.size(), boundary.size() );
      for( dip::uint ii = 0; ii < n; ++ii ) {
         boundary[ ii ] += static_cast< dip::uint >( std::abs( shift[ ii ] ));
      }
   }

   // Copy input images with boundary extension
   Image in;
   Image control;
   control.SetDataType( DT_DFLOAT );
   control.Protect();
   DIP_START_STACK_TRACE
      BoundaryConditionArray bc = StringArrayToBoundaryConditionArray( boundaryCondition );
      ExtendImageLowLevel( c_in, in, boundary, bc, Option::ExtendImage_Masked );
      ExtendImageLowLevel( c_control, control, boundary, bc, Option::ExtendImage_Masked );
   DIP_END_STACK_TRACE
#ifdef DIP__ENABLE_ASSERT
   // We have created a new `in` and `control`, so we expect normal strides here. Let's make sure this is the case!
   DIP_ASSERT( in.TensorStride() == 1 );
   for( dip::uint ii = 0; ii < in.Dimensionality(); ++ii ) {
      DIP_ASSERT( in.Stride( ii ) == control.Stride( ii ) * static_cast< dip::sint >( in.TensorElements() ));
   }
#endif

   // Adjust output if necessary (and possible)
   // NOTE: Don't use c_in any more from here on. It has possibly been reforged!
   DIP_START_STACK_TRACE
      out.ReForge( in.Sizes(), in.TensorElements(), in.DataType(), Option::AcceptDataTypeChange::DONT_ALLOW );
      out.ReshapeTensor( in.Tensor() );
      out.SetPixelSize( in.PixelSize() );
      if( !in.IsColor() ) {
         out.SetColorSpace( in.ColorSpace() );
      }
   DIP_END_STACK_TRACE
   DIP_ASSERT( in.DataType() == out.DataType() );

   // Create a pixel table suitable to be applied to `input`
   dip::uint processingDim = Framework::OptimalProcessingDim( in, kernelSizes );
   PixelTable pixelTable;
   DIP_START_STACK_TRACE
      pixelTable = kernel.PixelTable( in.Sizes(), processingDim );
   DIP_END_STACK_TRACE
   pixelTable.AddDistanceToOriginAsWeights();
   PixelTableOffsets pixelTableOffsets = pixelTable.Prepare( control ); // offsets are for the `control` image, multiply by `in.TensorElements()` to get offsets into `in`.

   // Get the line filter of the right type
   std::unique_ptr< SelectionLineFilterBase > lineFilter;
   DIP_OVL_NEW_ALL( lineFilter, SelectionLineFilter, (), in.DataType() );

   // Loop over all image lines
   SelectionLineFilterParameters params = {
         nullptr,
         nullptr,
         nullptr,
         in.Stride( processingDim ),
         in.TensorStride(),
         control.Stride( processingDim ),
         out.Stride( processingDim ),
         out.TensorStride(),
         in.TensorElements(),
         in.Size( processingDim ),
         pixelTableOffsets,
         threshold,
         minimum
   };
   GenericJointImageIterator< 3 > it( { in, control, out }, processingDim );
   do {
      params.inBuffer = in.Pointer( it.Offset< 0 >() );
      params.controlBuffer = static_cast< dfloat* >( control.Pointer( it.Offset< 1 >() ));
      params.outBuffer = out.Pointer( it.Offset< 2 >() );
      DIP_START_STACK_TRACE
         lineFilter->Filter( params );
      DIP_END_STACK_TRACE
   } while( ++it );
}

void Kuwahara(
      Image const& in,
      Image& out,
      Kernel kernel,
      dfloat threshold,
      StringArray const& boundaryCondition
) {
   DIP_START_STACK_TRACE
      Image value = dip::Uniform( in, kernel, boundaryCondition );
      Image control = dip::VarianceFilter( in, kernel, boundaryCondition );
      kernel.Mirror();
      SelectionFilter( value, control, out, kernel, threshold, "minimum", boundaryCondition );
   DIP_END_STACK_TRACE
}

} // namespace dip
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file object/root-classes.cc
 ** \brief Creation of the root Objects.
 */

#include <urbi/object/global.hh>
#include <object/object-class.hh>
#include <object/output-stream.hh>
#include <object/root-classes.hh>
#include <object/semaphore.hh>
#include <object/symbols.hh>
#include <object/system.hh>
#include <object/uvar.hh>
#include <urbi/object/barrier.hh>
#include <urbi/object/code.hh>
#include <urbi/object/cxx-object.hh>
#include <urbi/object/date.hh>
#include <urbi/object/dictionary.hh>
#include <urbi/object/directory.hh>
#include <urbi/object/duration.hh>
#include <urbi/object/file.hh>
#include <urbi/object/float.hh>
#include <urbi/object/list.hh>
#include <urbi/object/lobby.hh>
#include <urbi/object/object.hh>
#include <urbi/object/path.hh>
#include <urbi/object/primitive.hh>
#include <urbi/object/string.hh>
#include <urbi/object/tag.hh>
#include <urbi/object/task.hh>

namespace urbi
{
  namespace object
  {

#define CLASS_INITIALIZE(What)					\
    rObject What ## _class;					\
    namespace { static void What ## _class_initialize (); }

// Classes with nothing to initialize
#define CLASS_EMPTY_INITIALIZE(What)                            \
    rObject What ## _class;					\
    namespace { static void What ## _class_initialize () { } }

    /* Help the generation of symbols.

       SYMBOL(Dictionary);
       SYMBOL(Global);
       SYMBOL(System);
       SYMBOL(Tag);
       SYMBOL(acceptedVoid);
       SYMBOL(asCode);
       SYMBOL(asDictionary);
       SYMBOL(asFloat);
       SYMBOL(asGlobal);
       SYMBOL(asInteger);
       SYMBOL(asList);
       SYMBOL(asLobby);
       SYMBOL(asObject);
       SYMBOL(asPrimitive);
       SYMBOL(asSystem);
       SYMBOL(asTag);
       SYMBOL(asTask);
       SYMBOL(asfalse);
       SYMBOL(asnil);
       SYMBOL(astrue);
       SYMBOL(asvoid);
       SYMBOL(false);
       SYMBOL(nil);
       SYMBOL(true);
       SYMBOL(void);

    */

    CLASS_INITIALIZE(accepted_void);
    CLASS_EMPTY_INITIALIZE(false);
    CLASS_EMPTY_INITIALIZE(nil);
    CLASS_EMPTY_INITIALIZE(true);
    CLASS_INITIALIZE(void);

#undef CLASS_INITIALIZE

    /*------------------------.
    | Global initialization.  |
    `------------------------*/

    /// Whether the root classes where initialized.
    bool root_classes_initialized = false;

    static rObject
    id(objects_type args)
    {
      check_arg_count(args.size() - 1, 0);
      return args.front();
    }

    /// Initialize the root classes.  There are some dependency issues.
    /// For instance, String is a clone of Object, but Object.type is a
    /// String.  So we need to control the initialization sequence.
    void
    root_classes_initialize()
    {
      if (root_classes_initialized)
        return;
      root_classes_initialized = true;

      // The construction of the primitive classes goes in several
      // steps.
      //
      // 1. Construct the (empty) objects for the base classes.  They
      // all derive from Object... except Object.
      //
      // 2. Initialize the "type" field for all of them, including
      // Object (requires that these classes exists, in particular
      // string_class from which any String is a clone).
      //
      // 3. Finalize the construction for each base class: bind some
      // initial methods.
      //
      // 4. Register all these classes in Global, to make them
      // accessible from anywhere.
      //
      // CLASS_CREATE does 1, CLASS_INIT does 2, CLASS_REGISTER does 3
      // and 4.  CLASS_SETUP runs 1 to 4.

#define CLASS_CREATE(What, Name)                \
      What = Object::proto->clone()

#define CLASS_INIT(What, Name)                  \
      What->slot_set(SYMBOL(DOLLAR_type),       \
                     new String(SYMBOL(Name))); \
      What->slot_set(SYMBOL(as ## Name),        \
                     new Primitive(id))

#define CLASS_REGISTER(What, Name)                      \
      What ## _initialize();                            \
      global_class->slot_set(SYMBOL(Name), What, true)

#define CLASS_SETUP(What, Name)                 \
      CLASS_CREATE(What, Name);                 \
      CLASS_INIT(What, Name);                   \
      CLASS_REGISTER(What, Name)

#define ANONYMOUS_CLASS_SETUP(What, Name)       \
      CLASS_CREATE(What, Name);                 \
      CLASS_REGISTER(What, Name)

#define EXISTING_CLASS_SETUP(What, Name)        \
      CLASS_INIT(What, Name);                   \
      CLASS_REGISTER(What, Name)

      // Object is a special case: it is not built as a clone of itself.
      Object::proto = new Object();

      // These guys are used in the property system, we need them
      // early.  But completing their initialization requires String
      // support.  So this is performed below.
      true_class = new Object();
      true_class->proto_add(Object::proto);
      false_class = new Object();
      false_class->proto_add(Object::proto);

      // Our current initialization system does not track
      // dependencies, we have to address them by hand until some
      // better scheme is found.
#define INIT(Class)                                     \
      CxxObject::push_initializer_to_back<Class>()

      // Primitive derives from Executable.
      INIT(Executable);
      INIT(Primitive);
      INIT(Code);

      INIT(UVar);

      INIT(Path);
      INIT(Directory);
      INIT(OutputStream);

      // Duration derives from Float.
      INIT(Float);
      INIT(Duration);

      // Events use Lists.
      INIT(List);
      INIT(Event);
#undef INIT

      CxxObject::create();

      // The other primitives.  Because primitive initialization depend
      // a lot on one another (e.g., String is used everywhere for slot
      // names, and Primitive is used for... all the primitive methods
      // in the primitive classes), first create them all, then bind
      // them all.
      // Setup boolean entities.
      global_class = Object::proto->clone();
      CLASS_INIT(global_class, Global);
      CLASS_INIT(Object::proto, Object);
      global_class_initialize();
      global_class->slot_set(SYMBOL(Global), global_class, true);
      object_class_initialize();
      global_class->slot_set(SYMBOL(Object), Object::proto, true);
      CxxObject::initialize(global_class);

      // Completion cannot be done before String is complete.
      EXISTING_CLASS_SETUP(true_class, true);
      EXISTING_CLASS_SETUP(false_class, false);

      CLASS_SETUP(nil_class, nil);
      CLASS_SETUP(system_class, System);
      CLASS_SETUP(void_class, void);

      ANONYMOUS_CLASS_SETUP(accepted_void_class, acceptedVoid);

#undef SYMBOL_

      // Object.addProto(Global)
      Object::proto->proto_add(global_class);

      CxxObject::cleanup();
    }

    // This is only used to created references on unused classes, so
    // they get initialized anyway.
    void
    dummy_references()
    {
      Barrier     *b;
      (void)b;
      Date        date;
      Directory   d;
      File        f;
      Path        p;
      Semaphore   s;
      UVar        v;
    }

    namespace
    {
      template <typename T>
      static inline void
      cleanup_object(libport::intrusive_ptr<T>& o)
      {
        o->protos_set(new object::List(object::List::value_type()));
        o.reset();
      }
    }

    void
    cleanup_existing_objects()
    {
      cleanup_object(Barrier::proto);
      cleanup_object(Code::proto);
      cleanup_object(Dictionary::proto);
      cleanup_object(false_class);
      cleanup_object(Float::proto);
      cleanup_object(global_class);
      cleanup_object(Lobby::proto);
      cleanup_object(Object::proto); // FIXME
      cleanup_object(Primitive::proto);
      cleanup_object(Semaphore::proto);
      cleanup_object(String::proto);
      cleanup_object(system_class);
      cleanup_object(Tag::proto);
      cleanup_object(Task::proto);
      cleanup_object(true_class);
      cleanup_object(void_class);
      // List must be last, because it is used in cleanup_object.
      cleanup_object(List::proto);
    }

    /*-------.
    | void.  |
    `-------*/
    namespace
    {
      static rObject
      void_class_acceptVoid(objects_type args)
      {
        check_arg_count(args.size() - 1, 0);

        return accepted_void_class;
      }

      static void
      void_class_initialize()
      {
        void_class->slot_set(SYMBOL(asString), new String(SYMBOL(void)));
        void_class->slot_set(SYMBOL(DOLLAR_id), new String(SYMBOL(void)));
        // void prints nothing in the toplevel
        void_class->slot_set(SYMBOL(asToplevelPrintable), new String(""));
        passert("void must be initialized after true", true_class);
        void_class->slot_set(SYMBOL(isVoid), true_class);
        void_class->slot_set
          (SYMBOL(acceptVoid), new Primitive(void_class_acceptVoid));
      }

      static void
      accepted_void_class_initialize()
      {
        accepted_void_class->proto_remove(Object::proto);
        passert("void must be initialized before acceptedVoid", void_class);
        accepted_void_class->proto_add(void_class);
      }
    }

  } // namespace object
}
<commit_msg>build: fix.<commit_after>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file object/root-classes.cc
 ** \brief Creation of the root Objects.
 */

#include <urbi/object/global.hh>
#include <object/object-class.hh>
#include <object/output-stream.hh>
#include <object/root-classes.hh>
#include <object/semaphore.hh>
#include <object/symbols.hh>
#include <object/system.hh>
#include <object/uvar.hh>
#include <urbi/object/barrier.hh>
#include <urbi/object/code.hh>
#include <urbi/object/cxx-object.hh>
#include <urbi/object/date.hh>
#include <urbi/object/dictionary.hh>
#include <urbi/object/directory.hh>
#include <urbi/object/duration.hh>
#include <urbi/object/event.hh>
#include <urbi/object/file.hh>
#include <urbi/object/float.hh>
#include <urbi/object/list.hh>
#include <urbi/object/lobby.hh>
#include <urbi/object/object.hh>
#include <urbi/object/path.hh>
#include <urbi/object/primitive.hh>
#include <urbi/object/string.hh>
#include <urbi/object/tag.hh>
#include <urbi/object/task.hh>

namespace urbi
{
  namespace object
  {

#define CLASS_INITIALIZE(What)					\
    rObject What ## _class;					\
    namespace { static void What ## _class_initialize (); }

// Classes with nothing to initialize
#define CLASS_EMPTY_INITIALIZE(What)                            \
    rObject What ## _class;					\
    namespace { static void What ## _class_initialize () { } }

    /* Help the generation of symbols.

       SYMBOL(Dictionary);
       SYMBOL(Global);
       SYMBOL(System);
       SYMBOL(Tag);
       SYMBOL(acceptedVoid);
       SYMBOL(asCode);
       SYMBOL(asDictionary);
       SYMBOL(asFloat);
       SYMBOL(asGlobal);
       SYMBOL(asInteger);
       SYMBOL(asList);
       SYMBOL(asLobby);
       SYMBOL(asObject);
       SYMBOL(asPrimitive);
       SYMBOL(asSystem);
       SYMBOL(asTag);
       SYMBOL(asTask);
       SYMBOL(asfalse);
       SYMBOL(asnil);
       SYMBOL(astrue);
       SYMBOL(asvoid);
       SYMBOL(false);
       SYMBOL(nil);
       SYMBOL(true);
       SYMBOL(void);

    */

    CLASS_INITIALIZE(accepted_void);
    CLASS_EMPTY_INITIALIZE(false);
    CLASS_EMPTY_INITIALIZE(nil);
    CLASS_EMPTY_INITIALIZE(true);
    CLASS_INITIALIZE(void);

#undef CLASS_INITIALIZE

    /*------------------------.
    | Global initialization.  |
    `------------------------*/

    /// Whether the root classes where initialized.
    bool root_classes_initialized = false;

    static rObject
    id(objects_type args)
    {
      check_arg_count(args.size() - 1, 0);
      return args.front();
    }

    /// Initialize the root classes.  There are some dependency issues.
    /// For instance, String is a clone of Object, but Object.type is a
    /// String.  So we need to control the initialization sequence.
    void
    root_classes_initialize()
    {
      if (root_classes_initialized)
        return;
      root_classes_initialized = true;

      // The construction of the primitive classes goes in several
      // steps.
      //
      // 1. Construct the (empty) objects for the base classes.  They
      // all derive from Object... except Object.
      //
      // 2. Initialize the "type" field for all of them, including
      // Object (requires that these classes exists, in particular
      // string_class from which any String is a clone).
      //
      // 3. Finalize the construction for each base class: bind some
      // initial methods.
      //
      // 4. Register all these classes in Global, to make them
      // accessible from anywhere.
      //
      // CLASS_CREATE does 1, CLASS_INIT does 2, CLASS_REGISTER does 3
      // and 4.  CLASS_SETUP runs 1 to 4.

#define CLASS_CREATE(What, Name)                \
      What = Object::proto->clone()

#define CLASS_INIT(What, Name)                  \
      What->slot_set(SYMBOL(DOLLAR_type),       \
                     new String(SYMBOL(Name))); \
      What->slot_set(SYMBOL(as ## Name),        \
                     new Primitive(id))

#define CLASS_REGISTER(What, Name)                      \
      What ## _initialize();                            \
      global_class->slot_set(SYMBOL(Name), What, true)

#define CLASS_SETUP(What, Name)                 \
      CLASS_CREATE(What, Name);                 \
      CLASS_INIT(What, Name);                   \
      CLASS_REGISTER(What, Name)

#define ANONYMOUS_CLASS_SETUP(What, Name)       \
      CLASS_CREATE(What, Name);                 \
      CLASS_REGISTER(What, Name)

#define EXISTING_CLASS_SETUP(What, Name)        \
      CLASS_INIT(What, Name);                   \
      CLASS_REGISTER(What, Name)

      // Object is a special case: it is not built as a clone of itself.
      Object::proto = new Object();

      // These guys are used in the property system, we need them
      // early.  But completing their initialization requires String
      // support.  So this is performed below.
      true_class = new Object();
      true_class->proto_add(Object::proto);
      false_class = new Object();
      false_class->proto_add(Object::proto);

      // Our current initialization system does not track
      // dependencies, we have to address them by hand until some
      // better scheme is found.
#define INIT(Class)                                     \
      CxxObject::push_initializer_to_back<Class>()

      // Primitive derives from Executable.
      INIT(Executable);
      INIT(Primitive);
      INIT(Code);

      INIT(UVar);

      INIT(Path);
      INIT(Directory);
      INIT(OutputStream);

      // Duration derives from Float.
      INIT(Float);
      INIT(Duration);

      // Events use Lists.
      INIT(List);
      INIT(Event);
#undef INIT

      CxxObject::create();

      // The other primitives.  Because primitive initialization depend
      // a lot on one another (e.g., String is used everywhere for slot
      // names, and Primitive is used for... all the primitive methods
      // in the primitive classes), first create them all, then bind
      // them all.
      // Setup boolean entities.
      global_class = Object::proto->clone();
      CLASS_INIT(global_class, Global);
      CLASS_INIT(Object::proto, Object);
      global_class_initialize();
      global_class->slot_set(SYMBOL(Global), global_class, true);
      object_class_initialize();
      global_class->slot_set(SYMBOL(Object), Object::proto, true);
      CxxObject::initialize(global_class);

      // Completion cannot be done before String is complete.
      EXISTING_CLASS_SETUP(true_class, true);
      EXISTING_CLASS_SETUP(false_class, false);

      CLASS_SETUP(nil_class, nil);
      CLASS_SETUP(system_class, System);
      CLASS_SETUP(void_class, void);

      ANONYMOUS_CLASS_SETUP(accepted_void_class, acceptedVoid);

#undef SYMBOL_

      // Object.addProto(Global)
      Object::proto->proto_add(global_class);

      CxxObject::cleanup();
    }

    // This is only used to created references on unused classes, so
    // they get initialized anyway.
    void
    dummy_references()
    {
      Barrier     *b;
      (void)b;
      Date        date;
      Directory   d;
      File        f;
      Path        p;
      Semaphore   s;
      UVar        v;
    }

    namespace
    {
      template <typename T>
      static inline void
      cleanup_object(libport::intrusive_ptr<T>& o)
      {
        o->protos_set(new object::List(object::List::value_type()));
        o.reset();
      }
    }

    void
    cleanup_existing_objects()
    {
      cleanup_object(Barrier::proto);
      cleanup_object(Code::proto);
      cleanup_object(Dictionary::proto);
      cleanup_object(false_class);
      cleanup_object(Float::proto);
      cleanup_object(global_class);
      cleanup_object(Lobby::proto);
      cleanup_object(Object::proto); // FIXME
      cleanup_object(Primitive::proto);
      cleanup_object(Semaphore::proto);
      cleanup_object(String::proto);
      cleanup_object(system_class);
      cleanup_object(Tag::proto);
      cleanup_object(Task::proto);
      cleanup_object(true_class);
      cleanup_object(void_class);
      // List must be last, because it is used in cleanup_object.
      cleanup_object(List::proto);
    }

    /*-------.
    | void.  |
    `-------*/
    namespace
    {
      static rObject
      void_class_acceptVoid(objects_type args)
      {
        check_arg_count(args.size() - 1, 0);

        return accepted_void_class;
      }

      static void
      void_class_initialize()
      {
        void_class->slot_set(SYMBOL(asString), new String(SYMBOL(void)));
        void_class->slot_set(SYMBOL(DOLLAR_id), new String(SYMBOL(void)));
        // void prints nothing in the toplevel
        void_class->slot_set(SYMBOL(asToplevelPrintable), new String(""));
        passert("void must be initialized after true", true_class);
        void_class->slot_set(SYMBOL(isVoid), true_class);
        void_class->slot_set
          (SYMBOL(acceptVoid), new Primitive(void_class_acceptVoid));
      }

      static void
      accepted_void_class_initialize()
      {
        accepted_void_class->proto_remove(Object::proto);
        passert("void must be initialized before acceptedVoid", void_class);
        accepted_void_class->proto_add(void_class);
      }
    }

  } // namespace object
}
<|endoftext|>