<commit_before>
/* FmtTextDecor.cpp
 *
 * Copyright (C) 2013 Michael Imamura
 *
 * 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 "StdAfx.h"

#include "utf8/utf8.h"

#include "Exception.h"
#include "ResStr.h"

#include "FmtTextDecor.h"

namespace AISDL {

namespace {
	const SDL_Color FMT_COLORS[] = {
		{ 0x00, 0x00, 0x00, 0xff },  // 0   ^0  black
		{ 0xff, 0x00, 0x00, 0xff },  // 1   ^1  red
		{ 0x00, 0xff, 0x00, 0xff },  // 2   ^2  green
		{ 0xff, 0xff, 0x00, 0xff },  // 3   ^3  yellow
		{ 0x00, 0x00, 0xff, 0xff },  // 4   ^4  blue
		{ 0x00, 0xff, 0xff, 0xff },  // 5   ^5  cyan
		{ 0xff, 0x00, 0xff, 0xff },  // 6   ^6  magenta
		{ 0xff, 0xff, 0xff, 0xff },  // 7   ^7  [default] white
		{ 0xff, 0x7f, 0x00, 0xff },  // 8   ^8  orange
		{ 0x7f, 0x7f, 0x7f, 0xff },  // 9   ^9  dark gray
		{ 0xbf, 0xbf, 0xbf, 0xff },  // 10  ^:  light gray
		{ 0xbf, 0xbf, 0xbf, 0xff },  // 11  ^;  light gray
		{ 0x00, 0x7f, 0x00, 0xff },  // 12  ^<  dark green
		{ 0x7f, 0x7f, 0x00, 0xff },  // 13  ^=  dark yellow
		{ 0x00, 0x00, 0x7f, 0xff },  // 14  ^>  dark blue
		{ 0x7f, 0x00, 0x00, 0xff },  // 15  ^?  dark red
		{ 0x7f, 0x3f, 0x00, 0xff },  // 16  ^@  brown
		{ 0xff, 0x99, 0x19, 0xff },  // 17  ^a  pumpkin
		{ 0x00, 0x7f, 0x7f, 0xff },  // 18  ^b  dark cyan
		{ 0x7f, 0x00, 0x7f, 0xff },  // 19  ^c  dark magenta
		{ 0x00, 0x7f, 0xff, 0xff },  // 20  ^d  azure
		{ 0x7f, 0x00, 0xff, 0xff },  // 21  ^e  violet
		{ 0x33, 0x99, 0xcc, 0xff },  // 22  ^f  [external link]
		{ 0xcc, 0xff, 0xcc, 0xff },  // 23  ^g  mint green
		{ 0x00, 0x66, 0x33, 0xff },  // 24  ^h  forest green
		{ 0xff, 0x00, 0x33, 0xff },  // 25  ^i
		{ 0xb2, 0x19, 0x19, 0xff },  // 26  ^j
		{ 0x99, 0x33, 0x00, 0xff },  // 27  ^k
		{ 0xcc, 0x99, 0x33, 0xff },  // 28  ^l
		{ 0x99, 0x99, 0x33, 0xff },  // 29  ^m
		{ 0xff, 0xff, 0xbf, 0xff },  // 30  ^n
		{ 0xff, 0xff, 0x7f, 0xff },  // 31  ^o  [keyword link]
	};
}

/**
 * Constructor when using static string.
 * @param display The target display.
 * @param font The font to use to render the text.
 * @param s The text itself.
 * @param width The maximum width of the text area (currently unused).
 */
FmtTextDecor::FmtTextDecor(Display &display, std::shared_ptr<Ttf> font,
	const std::string &s, int width) :
	display(display), font(std::move(font)), s(s),
	width(width),
	sizeWidth(0), sizeHeight(0)
{
	Reformat();
}

/**
 * Constructor when using resource string.
 * @param display The target display.
 * @param font The font to use to render the text.
 * @param text The text itself.
 * @param width The maximum width of the text area (currently unused).
 */
FmtTextDecor::FmtTextDecor(Display &display, std::shared_ptr<Ttf> font,
	std::shared_ptr<ResStr> text, int width) :
	display(display), font(std::move(font)), text(std::move(text)),
	width(width),
	sizeWidth(0), sizeHeight(0)
{
	Reformat();

	// Automatically trigger Reformat() when the text changes.
	this->text->SetOnReload([&]() {
		Reformat();
	});
}

/**
 * Process the text and generate the list of formatted renderables.
 */
void FmtTextDecor::Reformat()
{
	int lineHeight = TTF_FontLineSkip(**font);
	int spaceWidth = font->spaceLayoutWidth;
	if (text) s = **text;
	int x = 0, y = 0;
	int fmtColor = 7;

	sizeWidth = 0;
	sizeHeight = 0;

	rends.clear();
	rends.reserve(s.length());

	uint32_t ch = 0;
	for (auto iter = s.cbegin(), iend = s.cend(); iter != iend; ) {
		ch = utf8::next(iter, iend);

		// Only handle characters which we have included in the type case.
		if (ch > font->glyphs.size()) {
			SDL_Log("Unrenderable code point: %d", ch);
			continue;
		}

		switch (ch) {
			case '\n':  // Newlines.
				x = 0;
				y += lineHeight;
				break;

			case '^':  // Color codes.
				if (iter == iend) {
					return;
				}
				else {
					uint32_t idx = utf8::next(iter, iend);

					// Allow "^^" as an escape sequence for "^".
					if (idx == '^') break;

					fmtColor = (idx + 16) & 31;
				}
				break;

			case '\r':  // Ignore CRs.
				break;

			case ' ':
				x += spaceWidth;
				break;

			default: {
				const Ttf::Glyph &glyph = font->glyphs[ch];
				if (!glyph.avail) continue;

				rends.push_back(Rend(&glyph, x, y, fmtColor));

				x += glyph.layoutW;
			}
		}

		if (x >= sizeWidth) {
			sizeWidth = x;
		}
	}

	// If the last char wasn't a newline, adjust the height otherwise we'll
	// cut off the bottom line of text.
	if (ch != '\n') {
		y += lineHeight;
	}
	sizeHeight = y;
}

/**
 * Change the text to a static string.
 * @param s The static string.
 */
void FmtTextDecor::SetText(const std::string &s)
{
	if (text) {
		text.reset();
	}
	if (this->s != s) {
		this->s = s;
		Reformat();
	}
}

/**
 * Render the text at the specified coordinates.
 * @param x The X coordinate.
 * @param y The Y coordinate.
 * @param alpha The opacity (0 is fully transparent, 255 is fully opaque).
 * @param cursor @c true to draw a cursor at the end of the text.
 * @param limit The maximum number of characters to render.
 */
void FmtTextDecor::Render(int x, int y, int alpha, bool cursor,
	unsigned int limit) const
{
	// If completely transparent, do nothing.
	if (alpha == 0) return;

	int fmtColor = 7;

	SDL_SetTextureAlphaMod(font->typeCase, alpha);

	// Reset default color to white.
	SDL_SetTextureColorMod(font->typeCase, 0xff, 0xff, 0xff);

	unsigned int count = 0;
	int cursorX = x, cursorY = y;
	for (auto iter = rends.cbegin(); iter != rends.cend(); ++iter) {
		if (fmtColor != iter->fmtColor) {
			fmtColor = iter->fmtColor;
			const SDL_Color &color = FMT_COLORS[fmtColor];
			SDL_SetTextureColorMod(font->typeCase, color.r, color.g, color.b);
		}

		SDL_Rect destRect = {
			iter->x + x,
			iter->y + y,
			iter->glyph->texRect.w,
			iter->glyph->texRect.h,
		};
		if (SDL_RenderCopy(display.renderer, font->typeCase,
			&iter->glyph->texRect, &destRect) < 0)
		{
			throw Exception(SDL_GetError());
		}
		cursorX = destRect.x + iter->glyph->layoutW;
		cursorY = destRect.y;

		count++;
		if (count >= limit) {
			break;
		}
	}

	if (cursor) {
		const Ttf::Glyph &glyph = font->glyphs['_'];
		if (glyph.avail) {
			SDL_Rect destRect = {
				cursorX, cursorY,
				glyph.texRect.w, glyph.texRect.h
			};
			if (SDL_RenderCopy(display.renderer, font->typeCase,
				&glyph.texRect, &destRect) < 0)
			{
				throw Exception(SDL_GetError());
			}
		}
	}
}

}
<commit_msg>Fix "^^" as an escape for "^".<commit_after>
/* FmtTextDecor.cpp
 *
 * Copyright (C) 2013 Michael Imamura
 *
 * 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 "StdAfx.h"

#include "utf8/utf8.h"

#include "Exception.h"
#include "ResStr.h"

#include "FmtTextDecor.h"

namespace AISDL {

namespace {
	const SDL_Color FMT_COLORS[] = {
		{ 0x00, 0x00, 0x00, 0xff },  // 0   ^0  black
		{ 0xff, 0x00, 0x00, 0xff },  // 1   ^1  red
		{ 0x00, 0xff, 0x00, 0xff },  // 2   ^2  green
		{ 0xff, 0xff, 0x00, 0xff },  // 3   ^3  yellow
		{ 0x00, 0x00, 0xff, 0xff },  // 4   ^4  blue
		{ 0x00, 0xff, 0xff, 0xff },  // 5   ^5  cyan
		{ 0xff, 0x00, 0xff, 0xff },  // 6   ^6  magenta
		{ 0xff, 0xff, 0xff, 0xff },  // 7   ^7  [default] white
		{ 0xff, 0x7f, 0x00, 0xff },  // 8   ^8  orange
		{ 0x7f, 0x7f, 0x7f, 0xff },  // 9   ^9  dark gray
		{ 0xbf, 0xbf, 0xbf, 0xff },  // 10  ^:  light gray
		{ 0xbf, 0xbf, 0xbf, 0xff },  // 11  ^;  light gray
		{ 0x00, 0x7f, 0x00, 0xff },  // 12  ^<  dark green
		{ 0x7f, 0x7f, 0x00, 0xff },  // 13  ^=  dark yellow
		{ 0x00, 0x00, 0x7f, 0xff },  // 14  ^>  dark blue
		{ 0x7f, 0x00, 0x00, 0xff },  // 15  ^?  dark red
		{ 0x7f, 0x3f, 0x00, 0xff },  // 16  ^@  brown
		{ 0xff, 0x99, 0x19, 0xff },  // 17  ^a  pumpkin
		{ 0x00, 0x7f, 0x7f, 0xff },  // 18  ^b  dark cyan
		{ 0x7f, 0x00, 0x7f, 0xff },  // 19  ^c  dark magenta
		{ 0x00, 0x7f, 0xff, 0xff },  // 20  ^d  azure
		{ 0x7f, 0x00, 0xff, 0xff },  // 21  ^e  violet
		{ 0x33, 0x99, 0xcc, 0xff },  // 22  ^f  [external link]
		{ 0xcc, 0xff, 0xcc, 0xff },  // 23  ^g  mint green
		{ 0x00, 0x66, 0x33, 0xff },  // 24  ^h  forest green
		{ 0xff, 0x00, 0x33, 0xff },  // 25  ^i
		{ 0xb2, 0x19, 0x19, 0xff },  // 26  ^j
		{ 0x99, 0x33, 0x00, 0xff },  // 27  ^k
		{ 0xcc, 0x99, 0x33, 0xff },  // 28  ^l
		{ 0x99, 0x99, 0x33, 0xff },  // 29  ^m
		{ 0xff, 0xff, 0xbf, 0xff },  // 30  ^n
		{ 0xff, 0xff, 0x7f, 0xff },  // 31  ^o  [keyword link]
	};
}

/**
 * Constructor when using static string.
 * @param display The target display.
 * @param font The font to use to render the text.
 * @param s The text itself.
 * @param width The maximum width of the text area (currently unused).
 */
FmtTextDecor::FmtTextDecor(Display &display, std::shared_ptr<Ttf> font,
	const std::string &s, int width) :
	display(display), font(std::move(font)), s(s),
	width(width),
	sizeWidth(0), sizeHeight(0)
{
	Reformat();
}

/**
 * Constructor when using resource string.
 * @param display The target display.
 * @param font The font to use to render the text.
 * @param text The text itself.
 * @param width The maximum width of the text area (currently unused).
 */
FmtTextDecor::FmtTextDecor(Display &display, std::shared_ptr<Ttf> font,
	std::shared_ptr<ResStr> text, int width) :
	display(display), font(std::move(font)), text(std::move(text)),
	width(width),
	sizeWidth(0), sizeHeight(0)
{
	Reformat();

	// Automatically trigger Reformat() when the text changes.
	this->text->SetOnReload([&]() {
		Reformat();
	});
}

/**
 * Process the text and generate the list of formatted renderables.
 */
void FmtTextDecor::Reformat()
{
	int lineHeight = TTF_FontLineSkip(**font);
	int spaceWidth = font->spaceLayoutWidth;
	if (text) s = **text;
	int x = 0, y = 0;
	int fmtColor = 7;

	sizeWidth = 0;
	sizeHeight = 0;

	rends.clear();
	rends.reserve(s.length());

	uint32_t ch = 0;
	for (auto iter = s.cbegin(), iend = s.cend(); iter != iend; ) {
		ch = utf8::next(iter, iend);

		// Only handle characters which we have included in the type case.
		if (ch > font->glyphs.size()) {
			SDL_Log("Unrenderable code point: %d", ch);
			continue;
		}

		switch (ch) {
			case '\n':  // Newlines.
				x = 0;
				y += lineHeight;
				break;

			case '^':  // Color codes.
				if (iter == iend) {
					return;
				}
				else {
					uint32_t idx = utf8::next(iter, iend);

					// Allow "^^" as an escape sequence for "^".
					if (idx == '^') {
						const Ttf::Glyph &glyph = font->glyphs['^'];
						if (glyph.avail) {
							rends.emplace_back(Rend(&glyph, x, y, fmtColor));
							x += glyph.layoutW;
						}
						break;
					}

					fmtColor = (idx + 16) & 31;
				}
				break;

			case '\r':  // Ignore CRs.
				break;

			case ' ':
				x += spaceWidth;
				break;

			default: {
				const Ttf::Glyph &glyph = font->glyphs[ch];
				if (!glyph.avail) continue;

				rends.emplace_back(Rend(&glyph, x, y, fmtColor));

				x += glyph.layoutW;
			}
		}

		if (x >= sizeWidth) {
			sizeWidth = x;
		}
	}

	// If the last char wasn't a newline, adjust the height otherwise we'll
	// cut off the bottom line of text.
	if (ch != '\n') {
		y += lineHeight;
	}
	sizeHeight = y;
}

/**
 * Change the text to a static string.
 * @param s The static string.
 */
void FmtTextDecor::SetText(const std::string &s)
{
	if (text) {
		text.reset();
	}
	if (this->s != s) {
		this->s = s;
		Reformat();
	}
}

/**
 * Render the text at the specified coordinates.
 * @param x The X coordinate.
 * @param y The Y coordinate.
 * @param alpha The opacity (0 is fully transparent, 255 is fully opaque).
 * @param cursor @c true to draw a cursor at the end of the text.
 * @param limit The maximum number of characters to render.
 */
void FmtTextDecor::Render(int x, int y, int alpha, bool cursor,
	unsigned int limit) const
{
	// If completely transparent, do nothing.
	if (alpha == 0) return;

	int fmtColor = 7;

	SDL_SetTextureAlphaMod(font->typeCase, alpha);

	// Reset default color to white.
	SDL_SetTextureColorMod(font->typeCase, 0xff, 0xff, 0xff);

	unsigned int count = 0;
	int cursorX = x, cursorY = y;
	for (auto iter = rends.cbegin(); iter != rends.cend(); ++iter) {
		if (fmtColor != iter->fmtColor) {
			fmtColor = iter->fmtColor;
			const SDL_Color &color = FMT_COLORS[fmtColor];
			SDL_SetTextureColorMod(font->typeCase, color.r, color.g, color.b);
		}

		SDL_Rect destRect = {
			iter->x + x,
			iter->y + y,
			iter->glyph->texRect.w,
			iter->glyph->texRect.h,
		};
		if (SDL_RenderCopy(display.renderer, font->typeCase,
			&iter->glyph->texRect, &destRect) < 0)
		{
			throw Exception(SDL_GetError());
		}
		cursorX = destRect.x + iter->glyph->layoutW;
		cursorY = destRect.y;

		count++;
		if (count >= limit) {
			break;
		}
	}

	if (cursor) {
		const Ttf::Glyph &glyph = font->glyphs['_'];
		if (glyph.avail) {
			SDL_Rect destRect = {
				cursorX, cursorY,
				glyph.texRect.w, glyph.texRect.h
			};
			if (SDL_RenderCopy(display.renderer, font->typeCase,
				&glyph.texRect, &destRect) < 0)
			{
				throw Exception(SDL_GetError());
			}
		}
	}
}

}
<|endoftext|>


<commit_before>/*
 * jcom.delta (previously names tl.delta)
 * External for Jamoma: calculate 1st order difference
 * By Trond Lossius, Copyright  2001-06
 * 20031227 initial port to OSX compiled by jasch <jasch@kat.ch>
 * 20060813 ported to Jamoma
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

/*
	<---MAXREF

		/maxref/object/name
			jcom.delta

		/maxref/object/digest
			Calculate difference between incomming numbers

		/maxref/object/description
			<o>jcom.delta</o> calculates the difference between the last incomming value x[n]
			and the previous value received:

			delta = x[n]-x[n-1]

		/maxref/metadata/author
			Trond Lossius

		/maxref/metadata/tag
			Jamoma Max Math

		/maxref/inletlist/0
			Calculate Difference, int, float

		/maxref/outletlist/0
			Delta Value

		/maxref/outletlist/1
			Dumpout

		/maxref/argument/
			None

		/maxref/message/float
			Caculate difference using between this and the previous number received.

		/maxref/message/int
			Converted to float

		/maxref/example/image
			jcom.delta.gif

		/maxref/example/caption
			Calculate difference between the last two numbers received.

		/maxref/seealso/object/name
			jcom.delta2

		/maxref/seealso/object/description
			Calculate the 2nd order difference of incomming numbers.

		/maxref/seealso/object/name
			jcom.velocity

		/maxref/seealso/object/description
			Calculate velocity (rate of change per second) for incomming values.

	MAXREF--->
*/

#include "Jamoma.h";

t_symbol	*ps_delta,
			*ps_delta2,
			*ps_velocity;

#define nonzero(x)				((x > 0) ? x : 1.)

typedef struct _delta{			///< Data structure for this object
	t_object	ob;				///< Must always be the first field; used by Max
	float		x0;				///< Most recerntly received value
	float		x1;				///< Previous value
	float		x2;				///< 2nd last value received
	float		delta;			///< 1st order differential
	float		delta2;			///< 2nd order differential
	long		lasttime;		///< Time code for previous value received
	char		clearflag;		///< Flag indicating that history has been cleared
	t_symbol	*attr_mode;		///< ATTRIBUTE: What mode is the object running in?
	void		*outlet;		///< Pointer to outlet. Need one for each outlet
} t_delta;

// Prototypes for methods: need a method for each incoming message
void *delta_new(t_symbol *s, long argc, t_atom *argv);
void delta_bang(t_delta *x);
void delta_int(t_delta *x, long n);
void delta_float(t_delta *x, double f);
void delta_clear(t_delta *x);
void delta_set(t_delta *x, Symbol *s, long ac, Atom *setval);
void delta_assist(t_delta *x, void *b, long msg, long arg, char *dst);
void delta_attr_setmode(t_delta *x, void *attr, long argc, t_atom *argv);

// Globals
t_class		*this_class;				// Required. Global pointing to this class

/************************************************************************************/
// Main() Function

int main(void)
{
	t_class *c;

	jamoma_init();

	ps_delta	= gensym("delta");
	ps_delta2	= gensym("delta2");
	ps_velocity = gensym("velocity");

	// Define our class
	c = class_new("jcom.delta",(method)delta_new, (method)0L, sizeof(t_delta), (method)0L, 0, 0);

	// Make methods accessible for our class:
	class_addmethod(c, (method)delta_bang,				"bang",		A_CANT,		0);
	class_addmethod(c, (method)delta_int,				"int",		A_LONG,		0);
 	class_addmethod(c, (method)delta_float, 			"float",	A_FLOAT,	0);
	class_addmethod(c, (method)delta_assist, 			"assist",	A_CANT,		0);
    class_addmethod(c, (method)delta_set,				"set",		A_GIMME,	0);
    class_addmethod(c, (method)delta_clear,				"clear",	0);
	class_addmethod(c, (method)object_obex_dumpout, 	"dumpout",	A_CANT,		0);

	// ATTRIBUTE: mode
	CLASS_ATTR_SYM(c, "mode", 0, t_delta, attr_mode);			// create attribute
	CLASS_ATTR_ACCESSORS(c, "mode", delta_attr_setmode, 0L);	// need custom setter method
	CLASS_ATTR_ENUM(c, "mode", 0, "delta delta2 velocity");		// options for inspector

	// Finalize our class
	class_register(CLASS_BOX, c);
	this_class = c;
	return 0;
}

#pragma mark -
#pragma mark Object life
/************************************************************************************/
// Object Life

void *delta_new(t_symbol *s, long argc, t_atom *argv)
{
	long attrstart = attr_args_offset(argc, argv);
	t_delta *x;

	x = (t_delta *)object_alloc(this_class);	// create the new instance and return a pointer to it
	if(x){
		// create inlets and outlets
    	object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL));	// dumpout
		x->outlet = floatout(x);				// create the outlet

		x->attr_mode = ps_delta;				// set default attribute
		attr_args_process(x, argc, argv);		// handle attribute args

		delta_clear(x);							// initilaize instance
	}
	return (x);
}

#pragma mark -
#pragma mark methods
/************************************************************************************/
// Methods bound to input/inlets

void delta_attr_setmode(t_delta *x, void *attr, long argc, t_atom *argv)
{
	t_symbol *arg = atom_getsym(argv);

	if (arg == ps_delta)
		x->attr_mode = ps_delta;
	else if (arg == ps_velocity)
		x->attr_mode = ps_velocity;
	else if (arg == ps_delta2)
		x->attr_mode = ps_delta2;
	else {
		object_error((t_object *)x, "wrong argument for the mode attribute. Set to delta");
		x->attr_mode = ps_delta;
	}
}

// BANG input
void delta_bang(t_delta *x)
{
	long thistime;
	float vel;

	// mode: 1st order difference
	if (x->attr_mode==ps_delta)
		outlet_float(x->outlet, x->delta);
	// mode: 2nd order difference
	else if (x->attr_mode==ps_delta2)
		outlet_float(x->outlet, x->delta2);
	// mode: velocity
	else if (x->attr_mode==ps_velocity)
	{
		thistime = gettime();
		vel = (1000 * (x->x0 - x->x1) ) / (nonzero(thistime - x->lasttime));
		x->lasttime = thistime;
		outlet_float(x->outlet, vel);
	}
}

// INT input
void delta_int(t_delta *x, long n)
{
	double f;

	f = (double)n;
	delta_float(x,f);
}

// FLOAT input
void delta_float(t_delta *x, double f)
{
	if (x->clearflag) {
		x->x1 = f;
		x->x2 = f;
		x->clearflag = 0;
	}

	// mode: 1st order difference
	if (x->attr_mode==ps_delta)
	{
		x->delta = f - x->x1;
		x->x1 = f;
	}
	// mode: 2nd order difference
	else if (x->attr_mode==ps_delta2)
	{
		x->delta2 = f - 2*x->x1 + x->x2;
		x->x2 = x->x1;
		x->x1 = f;
	}
	// mode: velocity
	else if (x->attr_mode==ps_velocity)
	{
		x->x1 = x->x0;
		x->x0 = f;
	}
	delta_bang(x);
}

// SET input
void delta_set(t_delta *x, Symbol *s, long ac, Atom *setval)
{
	float f;

	if (ac) {
		if (setval->a_type==A_LONG)
			f = (float)setval->a_w.w_long;
		else if (setval->a_type==A_FLOAT)
			f = setval->a_w.w_float;
		else goto err;
	}
	else
		f=0;
	if (x->clearflag) {
		x->x1 = f;
		x->delta = 0;
		x->clearflag = 0;
	}
	else {
		x->delta = f - x->x1;
		x->x1 = f;
	}
	return;

	err:
		error("jcom.delta: Wrong argument for set");
}

// CLEAR input
void delta_clear(t_delta *x)
{
	x->clearflag = 1;
	x->delta = 0;
	x->delta2 = 0;
	x->lasttime = gettime();
}

// Method for Assistance Messages
void delta_assist(t_delta *x, void *b, long msg, long arg, char *dst)	// Display assistance messages
{
	if(msg==1)
	{
		switch(arg)
		{
			case 0: sprintf(dst, "(int/float) function value");
			break;
		}
	}
	else if(msg==2)
	{
		sprintf(dst, "(float) delta value");
	}
}
<commit_msg>Commiting before changing it all again... Will instead go for three outlets that are alway there.<commit_after>/*
 * jcom.delta (previously names tl.delta)
 * External for Jamoma: calculate 1st order difference
 * By Trond Lossius, Copyright  2001-06
 * 20031227 initial port to OSX compiled by jasch <jasch@kat.ch>
 * 20060813 ported to Jamoma
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

/*
	<---MAXREF

		/maxref/object/name
			jcom.delta

		/maxref/object/digest
			Calculate difference between incomming numbers

		/maxref/object/description
			<o>jcom.delta</o> calculates the difference between the last incomming value x[n]
			and the previous value received:

			delta = x[n]-x[n-1]

		/maxref/metadata/author
			Trond Lossius

		/maxref/metadata/tag
			Jamoma Max Math

		/maxref/inletlist/0
			Calculate Difference, int, float

		/maxref/outletlist/0
			Delta Value

		/maxref/outletlist/1
			Dumpout

		/maxref/argument/
			None

		/maxref/message/float
			Caculate difference using between this and the previous number received.

		/maxref/message/int
			Converted to float

		/maxref/example/image
			jcom.delta.gif

		/maxref/example/caption
			Calculate difference between the last two numbers received.

		/maxref/seealso/object/name
			jcom.delta2

		/maxref/seealso/object/description
			Calculate the 2nd order difference of incomming numbers.

		/maxref/seealso/object/name
			jcom.velocity

		/maxref/seealso/object/description
			Calculate velocity (rate of change per second) for incomming values.

	MAXREF--->
*/

#include "Jamoma.h";

t_symbol	*ps_delta,
			*ps_delta2,
			*ps_velocity;

#define nonzero(x)				((x > 0) ? x : 1.)

typedef struct _delta{			///< Data structure for this object
	t_object	ob;				///< Must always be the first field; used by Max
	float		x0;				///< Most recerntly received value
	float		x1;				///< Previous value
	float		x2;				///< 2nd last value received
	float		delta;			///< 1st order differential
	float		delta2;			///< 2nd order differential
	long		lasttime;		///< Time code for previous value received
	char		clearflag;		///< Flag indicating that history has been cleared
	t_symbol	*attr_mode;		///< ATTRIBUTE: What mode is the object running in?
	void		*outlet;		///< Pointer to outlet. Need one for each outlet
} t_delta;

// Prototypes for methods: need a method for each incoming message
void *delta_new(t_symbol *s, long argc, t_atom *argv);
void delta_bang(t_delta *x);
void delta_int(t_delta *x, long n);
void delta_float(t_delta *x, double f);
void delta_clear(t_delta *x);
void delta_set(t_delta *x, Symbol *s, long ac, Atom *setval);
void delta_assist(t_delta *x, void *b, long msg, long arg, char *dst);
void delta_attr_setmode(t_delta *x, void *attr, long argc, t_atom *argv);

// Globals
t_class		*this_class;				// Required. Global pointing to this class

/************************************************************************************/
// Main() Function

int main(void)
{
	t_class *c;

	jamoma_init();

	ps_delta	= gensym("delta");
	ps_delta2	= gensym("delta2");
	ps_velocity = gensym("velocity");

	// Define our class
	c = class_new("jcom.delta",(method)delta_new, (method)0L, sizeof(t_delta), (method)0L, A_GIMME, 0);

	// Make methods accessible for our class:
	class_addmethod(c, (method)delta_bang,				"bang",		A_CANT,		0);
	class_addmethod(c, (method)delta_int,				"int",		A_LONG,		0);
 	class_addmethod(c, (method)delta_float, 			"float",	A_FLOAT,	0);
	class_addmethod(c, (method)delta_assist, 			"assist",	A_CANT,		0);
    class_addmethod(c, (method)delta_set,				"set",		A_GIMME,	0);
    class_addmethod(c, (method)delta_clear,				"clear",	0);
	class_addmethod(c, (method)object_obex_dumpout, 	"dumpout",	A_CANT,		0);

	// ATTRIBUTE: mode
	CLASS_ATTR_SYM(c,		"mode", 0, t_delta, attr_mode);				// create attribute
	CLASS_ATTR_ENUM(c,		"mode", 0, "delta delta2 velocity");		// options for inspector
	CLASS_ATTR_ACCESSORS(c, "mode", 0L, delta_attr_setmode);			// need custom setter method

	// Finalize our class
	class_register(CLASS_BOX, c);
	this_class = c;
	return 0;
}

#pragma mark -
#pragma mark Object life
/************************************************************************************/
// Object Life

void *delta_new(t_symbol *s, long argc, t_atom *argv)
{
	t_delta *x;
	x = (t_delta *)object_alloc(this_class);	// create the new instance and return a pointer to it
	if(x){
		// create inlets and outlets
    	object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL));	// dumpout
		x->outlet = floatout(x);				// create the outlet

		x->attr_mode = ps_delta;				// set default attribute
		attr_args_process(x, argc, argv);		// handle attribute args

		delta_clear(x);							// initilaize instance
	}
	return (x);
}

#pragma mark -
#pragma mark methods
/************************************************************************************/
// Methods bound to input/inlets

void delta_attr_setmode(t_delta *x, void *attr, long argc, t_atom *argv)
{
	t_symbol *arg = atom_getsym(argv);

	if (arg == ps_delta)
		x->attr_mode = ps_delta;
	else if (arg == ps_velocity)
		x->attr_mode = ps_velocity;
	else if (arg == ps_delta2)
		x->attr_mode = ps_delta2;
	else {
		object_error((t_object *)x, "wrong argument for the mode attribute. Set to delta");
		x->attr_mode = ps_delta;
	}
}

// BANG input
void delta_bang(t_delta *x)
{
	long thistime;
	float vel;

	// mode: 1st order difference
	if (x->attr_mode==ps_delta)
		outlet_float(x->outlet, x->delta);
	// mode: 2nd order difference
	else if (x->attr_mode==ps_delta2)
		outlet_float(x->outlet, x->delta2);
	// mode: velocity
	else if (x->attr_mode==ps_velocity)
	{
		thistime = gettime();
		vel = (1000 * (x->x0 - x->x1) ) / (nonzero(thistime - x->lasttime));
		x->lasttime = thistime;
		outlet_float(x->outlet, vel);
	}
}

// INT input
void delta_int(t_delta *x, long n)
{
	double f;

	f = (double)n;
	delta_float(x,f);
}

// FLOAT input
void delta_float(t_delta *x, double f)
{
	if (x->clearflag) {
		x->x1 = f;
		x->x2 = f;
		x->clearflag = 0;
	}

	// mode: 1st order difference
	if (x->attr_mode==ps_delta)
	{
		x->delta = f - x->x1;
		x->x1 = f;
	}
	// mode: 2nd order difference
	else if (x->attr_mode==ps_delta2)
	{
		x->delta2 = f - 2*x->x1 + x->x2;
		x->x2 = x->x1;
		x->x1 = f;
	}
	// mode: velocity
	else if (x->attr_mode==ps_velocity)
	{
		x->x1 = x->x0;
		x->x0 = f;
	}
	delta_bang(x);
}

// SET input
void delta_set(t_delta *x, Symbol *s, long ac, Atom *setval)
{
	float f;

	if (ac) {
		if (setval->a_type==A_LONG)
			f = (float)setval->a_w.w_long;
		else if (setval->a_type==A_FLOAT)
			f = setval->a_w.w_float;
		else goto err;
	}
	else
		f=0;
	if (x->clearflag) {
		x->x1 = f;
		x->delta = 0;
		x->clearflag = 0;
	}
	else {
		x->delta = f - x->x1;
		x->x1 = f;
	}
	return;

	err:
		error("jcom.delta: Wrong argument for set");
}

// CLEAR input
void delta_clear(t_delta *x)
{
	x->clearflag = 1;
	x->delta = 0;
	x->delta2 = 0;
	x->lasttime = gettime();
}

// Method for Assistance Messages
void delta_assist(t_delta *x, void *b, long msg, long arg, char *dst)	// Display assistance messages
{
	if(msg==1)
	{
		switch(arg)
		{
			case 0: sprintf(dst, "(int/float) function value");
			break;
		}
	}
	else if(msg==2)
	{
		sprintf(dst, "(float) delta value");
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 Thomas Moulard.
//
// This file is part of sot-core.
// sot-core is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// sot-core 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 sot-core.  If not, see <http://www.gnu.org/licenses/>.

#include <sstream>

#define BOOST_TEST_MODULE matrix_twist

#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/output_test_stream.hpp>

#include <jrl/mal/boost.hh>
#include <sot/core/matrix-homogeneous.hh>
#include "sot/core/matrix-twist.hh"

using boost::test_tools::output_test_stream;

namespace ml = maal::boost;

#define MATRIX_BOOST_REQUIRE_CLOSE(N, M, LEFT, RIGHT, TOLERANCE)	\
  for (unsigned i = 0; i < N; ++i)					\
    for (unsigned j = 0; j < M; ++j)					\
      BOOST_REQUIRE_CLOSE(LEFT (i, j), RIGHT (i, j), TOLERANCE)

#define MATRIX_6x6_BOOST_REQUIRE_CLOSE(LEFT, RIGHT, TOLERANCE)	\
  MATRIX_BOOST_REQUIRE_CLOSE (6, 6, LEFT, RIGHT, TOLERANCE)

#define MATRIX_4x4_INIT(M,					  \
			A00, A01, A02, A03,			  \
			A10, A11, A12, A13,			  \
			A20, A21, A22, A23,			  \
			A30, A31, A32, A33)			  \
  M (0, 0) = A00, M (0, 1) = A01, M (0, 2) = A02, M (0, 3) = A03; \
  M (1, 0) = A10, M (1, 1) = A11, M (1, 2) = A12, M (1, 3) = A13; \
  M (2, 0) = A20, M (2, 1) = A21, M (2, 2) = A22, M (2, 3) = A23; \
  M (3, 0) = A30, M (3, 1) = A31, M (3, 2) = A32, M (3, 3) = A33  \

#define MATRIX_6x6_INIT(M,						\
			A00, A01, A02, A03, A04, A05,			\
			A10, A11, A12, A13, A14, A15,			\
			A20, A21, A22, A23, A24, A25,			\
			A30, A31, A32, A33, A34, A35,			\
			A40, A41, A42, A43, A44, A45,			\
			A50, A51, A52, A53, A54, A55)			\
  M (0, 0) = A00, M (0, 1) = A01, M (0, 2) = A02, M (0, 3) = A03,	\
    M (0, 4) = A04, M (0, 5) = A05;					\
  M (1, 0) = A10, M (1, 1) = A11, M (1, 2) = A12, M (1, 3) = A13,	\
    M (1, 4) = A14, M (1, 5) = A15;					\
  M (2, 0) = A20, M (2, 1) = A21, M (2, 2) = A22, M (2, 3) = A23,	\
    M (2, 4) = A24, M (2, 5) = A25;					\
  M (3, 0) = A30, M (3, 1) = A31, M (3, 2) = A32, M (3, 3) = A33,	\
    M (3, 4) = A34, M (3, 5) = A35;					\
  M (4, 0) = A40, M (4, 1) = A41, M (4, 2) = A42, M (4, 3) = A43,	\
    M (4, 4) = A44, M (4, 5) = A45;					\
  M (5, 0) = A50, M (5, 1) = A51, M (5, 2) = A52, M (5, 3) = A53,	\
    M (5, 4) = A54, M (5, 5) = A55

BOOST_AUTO_TEST_CASE (constructor_trivial)
{
  sot::MatrixHomogeneous M;
  sot::MatrixTwist twist (M);

  ml::Matrix twistRef (6, 6);

  for (unsigned i = 0; i < 6; ++i)
    for (unsigned j = 0; j < 6; ++j)
      twistRef (i, j) = (i == j) ? 1. : 0.;

  MATRIX_6x6_BOOST_REQUIRE_CLOSE (twist, twistRef, 0.001);
}

BOOST_AUTO_TEST_CASE (constructor_rotation_only)
{
  sot::MatrixHomogeneous M;

  MATRIX_4x4_INIT (M,
		   0.,  0.,  1., 0.,
		   1.,  0.,  0., 0.,
		   0., -1.,  0., 0.,
		   0.,  0.,  0., 1.);
  sot::MatrixTwist twist (M);

  ml::Matrix twistRef (6, 6);
  MATRIX_6x6_INIT (twistRef,
		   0.,  0.,  1., 0.,  0., 0.,
		   1.,  0.,  0., 0.,  0., 0.,
		   0., -1.,  0., 0.,  0., 0.,
		   0.,  0.,  0., 0.,  0., 1.,
		   0.,  0.,  0., 1.,  0., 0.,
		   0.,  0.,  0., 0., -1., 0.);

  MATRIX_6x6_BOOST_REQUIRE_CLOSE (twist, twistRef, 0.001);
}

BOOST_AUTO_TEST_CASE (constructor_translation_only)
{
  sot::MatrixHomogeneous M;

  MATRIX_4x4_INIT (M,
		   1., 0.,  0., 11.,
		   0., 1.,  0., 22.,
		   0., 0.,  1., 33.,
		   0., 0.,  0., 1.);
  sot::MatrixTwist twist (M);

  //FIXME: to be checked.
  ml::Matrix twistRef (6, 6);
  MATRIX_6x6_INIT (twistRef,
		   1., 0., 0.,   0., -33.,  22.,
		   0., 1., 0.,  33.,   0., -11.,
		   0., 0., 1., -22.,  11.,   0.,
		   0., 0., 0.,   1.,   0.,   0.,
		   0., 0., 0.,   0.,   1.,   0.,
		   0., 0., 0.,   0.,   0.,   1.);

  MATRIX_6x6_BOOST_REQUIRE_CLOSE (twist, twistRef, 0.001);
}

//FIXME: rotation+translation test case.
<commit_msg>Upgrade to previous changes.<commit_after>// Copyright 2011 Thomas Moulard.
//
// This file is part of sot-core.
// sot-core is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// sot-core 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 sot-core.  If not, see <http://www.gnu.org/licenses/>.

#include <sstream>

#define BOOST_TEST_MODULE matrix_twist

#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/output_test_stream.hpp>

#include <jrl/mal/boost.hh>
#include <sot/core/matrix-homogeneous.hh>
#include "sot/core/matrix-twist.hh"

using boost::test_tools::output_test_stream;

namespace ml = maal::boost;

#define MATRIX_BOOST_REQUIRE_CLOSE(N, M, LEFT, RIGHT, TOLERANCE)	\
  for (unsigned i = 0; i < N; ++i)					\
    for (unsigned j = 0; j < M; ++j)					\
      BOOST_REQUIRE_CLOSE(LEFT (i, j), RIGHT (i, j), TOLERANCE)

#define MATRIX_6x6_BOOST_REQUIRE_CLOSE(LEFT, RIGHT, TOLERANCE)	\
  MATRIX_BOOST_REQUIRE_CLOSE (6, 6, LEFT, RIGHT, TOLERANCE)

#define MATRIX_4x4_INIT(M,					  \
			A00, A01, A02, A03,			  \
			A10, A11, A12, A13,			  \
			A20, A21, A22, A23,			  \
			A30, A31, A32, A33)			  \
  M (0, 0) = A00, M (0, 1) = A01, M (0, 2) = A02, M (0, 3) = A03; \
  M (1, 0) = A10, M (1, 1) = A11, M (1, 2) = A12, M (1, 3) = A13; \
  M (2, 0) = A20, M (2, 1) = A21, M (2, 2) = A22, M (2, 3) = A23; \
  M (3, 0) = A30, M (3, 1) = A31, M (3, 2) = A32, M (3, 3) = A33  \

#define MATRIX_6x6_INIT(M,						\
			A00, A01, A02, A03, A04, A05,			\
			A10, A11, A12, A13, A14, A15,			\
			A20, A21, A22, A23, A24, A25,			\
			A30, A31, A32, A33, A34, A35,			\
			A40, A41, A42, A43, A44, A45,			\
			A50, A51, A52, A53, A54, A55)			\
  M (0, 0) = A00, M (0, 1) = A01, M (0, 2) = A02, M (0, 3) = A03,	\
    M (0, 4) = A04, M (0, 5) = A05;					\
  M (1, 0) = A10, M (1, 1) = A11, M (1, 2) = A12, M (1, 3) = A13,	\
    M (1, 4) = A14, M (1, 5) = A15;					\
  M (2, 0) = A20, M (2, 1) = A21, M (2, 2) = A22, M (2, 3) = A23,	\
    M (2, 4) = A24, M (2, 5) = A25;					\
  M (3, 0) = A30, M (3, 1) = A31, M (3, 2) = A32, M (3, 3) = A33,	\
    M (3, 4) = A34, M (3, 5) = A35;					\
  M (4, 0) = A40, M (4, 1) = A41, M (4, 2) = A42, M (4, 3) = A43,	\
    M (4, 4) = A44, M (4, 5) = A45;					\
  M (5, 0) = A50, M (5, 1) = A51, M (5, 2) = A52, M (5, 3) = A53,	\
    M (5, 4) = A54, M (5, 5) = A55

BOOST_AUTO_TEST_CASE (constructor_trivial)
{
  dynamicgraph::sot::MatrixHomogeneous M;
  dynamicgraph::sot::MatrixTwist twist (M);

  ml::Matrix twistRef (6, 6);

  for (unsigned i = 0; i < 6; ++i)
    for (unsigned j = 0; j < 6; ++j)
      twistRef (i, j) = (i == j) ? 1. : 0.;

  MATRIX_6x6_BOOST_REQUIRE_CLOSE (twist, twistRef, 0.001);
}

BOOST_AUTO_TEST_CASE (constructor_rotation_only)
{
  dynamicgraph::sot::MatrixHomogeneous M;

  MATRIX_4x4_INIT (M,
		   0.,  0.,  1., 0.,
		   1.,  0.,  0., 0.,
		   0., -1.,  0., 0.,
		   0.,  0.,  0., 1.);
  dynamicgraph::sot::MatrixTwist twist (M);

  ml::Matrix twistRef (6, 6);
  MATRIX_6x6_INIT (twistRef,
		   0.,  0.,  1., 0.,  0., 0.,
		   1.,  0.,  0., 0.,  0., 0.,
		   0., -1.,  0., 0.,  0., 0.,
		   0.,  0.,  0., 0.,  0., 1.,
		   0.,  0.,  0., 1.,  0., 0.,
		   0.,  0.,  0., 0., -1., 0.);

  MATRIX_6x6_BOOST_REQUIRE_CLOSE (twist, twistRef, 0.001);
}

BOOST_AUTO_TEST_CASE (constructor_translation_only)
{
  dynamicgraph::sot::MatrixHomogeneous M;

  MATRIX_4x4_INIT (M,
		   1., 0.,  0., 11.,
		   0., 1.,  0., 22.,
		   0., 0.,  1., 33.,
		   0., 0.,  0., 1.);
  dynamicgraph::sot::MatrixTwist twist (M);

  //FIXME: to be checked.
  ml::Matrix twistRef (6, 6);
  MATRIX_6x6_INIT (twistRef,
		   1., 0., 0.,   0., -33.,  22.,
		   0., 1., 0.,  33.,   0., -11.,
		   0., 0., 1., -22.,  11.,   0.,
		   0., 0., 0.,   1.,   0.,   0.,
		   0., 0., 0.,   0.,   1.,   0.,
		   0., 0., 0.,   0.,   0.,   1.);

  MATRIX_6x6_BOOST_REQUIRE_CLOSE (twist, twistRef, 0.001);
}

//FIXME: rotation+translation test case.
<|endoftext|>


<commit_before>#include "GibbsSampler.h"
#include "math/SIMD.h"

/******************** AmplitudeGibbsSampler Implementation ********************/

void AmplitudeGibbsSampler::sync(PatternGibbsSampler &sampler)
{
    mOtherMatrix = &(sampler.mMatrix);
    mAPMatrix = sampler.mAPMatrix;
}

unsigned AmplitudeGibbsSampler::getRow(uint64_t pos) const
{
    return pos / (mBinSize * mNumCols);
}

unsigned AmplitudeGibbsSampler::getCol(uint64_t pos) const
{
    return (pos / mBinSize) % mNumCols;
}

bool AmplitudeGibbsSampler::canUseGibbs(unsigned row, unsigned col) const // NOLINT(misc-unused-parameters)
{
    return !gaps::algo::isVectorZero(mOtherMatrix->colPtr(col),
        mOtherMatrix->nRow());
}

bool AmplitudeGibbsSampler::canUseGibbs(unsigned r1, unsigned c1, unsigned r2, unsigned c2) const
{
    return canUseGibbs(r1, c1) || canUseGibbs(r2, c2);
}

void AmplitudeGibbsSampler::updateAPMatrix(unsigned row, unsigned col, float delta)
{
    const float *other = mOtherMatrix->colPtr(col);
    float *ap = mAPMatrix.rowPtr(row);
    unsigned size = mAPMatrix.nCol();

    gaps::simd::packedFloat pOther, pAP;
    gaps::simd::Index i(0);
    gaps::simd::packedFloat pDelta(delta);
    for (; i <= size - i.increment(); ++i)
    {
        pOther.load(other + i);
        pAP.load(ap + i);
        pAP += pDelta * pOther;
        pAP.store(ap + i);
    }

    for (unsigned j = i.value(); j < size; ++j)
    {
        ap[j] += delta * other[j];
    }
}

AlphaParameters AmplitudeGibbsSampler::alphaParameters(unsigned row, unsigned col)
{
    return gaps::algo::alphaParameters(mDMatrix.nCol(), mDMatrix.rowPtr(row),
        mSMatrix.rowPtr(row), mAPMatrix.rowPtr(row), mOtherMatrix->colPtr(col));
}

AlphaParameters AmplitudeGibbsSampler::alphaParameters(unsigned r1, unsigned c1,
unsigned r2, unsigned c2)
{
    if (r1 == r2)
    {
        return gaps::algo::alphaParameters(mDMatrix.nCol(), mDMatrix.rowPtr(r1),
            mSMatrix.rowPtr(r1), mAPMatrix.rowPtr(r1), mOtherMatrix->colPtr(c1),
            mOtherMatrix->colPtr(c2));
    }
    return alphaParameters(r1, c1) + alphaParameters(r2, c2);
}

float AmplitudeGibbsSampler::computeDeltaLL(unsigned row, unsigned col, float mass)
{
    return gaps::algo::deltaLL(mDMatrix.nCol(), mDMatrix.rowPtr(row),
        mSMatrix.rowPtr(row), mAPMatrix.rowPtr(row), mOtherMatrix->colPtr(col),
        mass);
}

float AmplitudeGibbsSampler::computeDeltaLL(unsigned r1, unsigned c1, float m1,
unsigned r2, unsigned c2, float m2)
{
    if (r1 == r2)
    {
        return gaps::algo::deltaLL(mDMatrix.nCol(), mDMatrix.rowPtr(r1),
            mSMatrix.rowPtr(r1), mAPMatrix.rowPtr(r1), mOtherMatrix->colPtr(c1),
            m1, mOtherMatrix->colPtr(c2), m2);
    }
    return computeDeltaLL(r1, c1, m1) + computeDeltaLL(r2, c2, m2);
}

/********************* PatternGibbsSampler Implementation *********************/

void PatternGibbsSampler::sync(AmplitudeGibbsSampler &sampler)
{
    mOtherMatrix = &(sampler.mMatrix);
    mAPMatrix = sampler.mAPMatrix;
}

unsigned PatternGibbsSampler::getRow(uint64_t pos) const
{
    return pos / (mBinSize * mNumCols);
}

unsigned PatternGibbsSampler::getCol(uint64_t pos) const
{
    return (pos / mBinSize) % mNumCols;
}

bool PatternGibbsSampler::canUseGibbs(unsigned row, unsigned col) const // NOLINT(misc-unused-parameters)
{
    return !gaps::algo::isVectorZero(mOtherMatrix->colPtr(col),
        mOtherMatrix->nRow());
}

bool PatternGibbsSampler::canUseGibbs(unsigned r1, unsigned c1, unsigned r2, unsigned c2) const
{
    return canUseGibbs(r1, c1) || canUseGibbs(r2, c2);
}

void PatternGibbsSampler::updateAPMatrix(unsigned row, unsigned col, float delta)
{
    const float *other = mOtherMatrix->colPtr(col);
    float *ap = mAPMatrix.colPtr(row);
    unsigned size = mAPMatrix.nRow();

    gaps::simd::packedFloat pOther, pAP;
    gaps::simd::Index i(0);
    gaps::simd::packedFloat pDelta(delta);
    for (; i <= size - i.increment(); ++i)
    {
        pOther.load(other + i);
        pAP.load(ap + i);
        pAP += pDelta * pOther;
        pAP.store(ap + i);
    }

    for (unsigned j = i.value(); j < size; ++j)
    {
        ap[j] += delta * other[j];
    }
}

AlphaParameters PatternGibbsSampler::alphaParameters(unsigned row, unsigned col)
{
    return gaps::algo::alphaParameters(mDMatrix.nRow(), mDMatrix.colPtr(row),
        mSMatrix.colPtr(row), mAPMatrix.colPtr(row), mOtherMatrix->colPtr(col));
}

AlphaParameters PatternGibbsSampler::alphaParameters(unsigned r1, unsigned c1,
unsigned r2, unsigned c2)
{
    if (c1 == c2)
    {
        return gaps::algo::alphaParameters(mDMatrix.nRow(), mDMatrix.colPtr(r1),
            mSMatrix.colPtr(r1), mAPMatrix.colPtr(r1), mOtherMatrix->colPtr(c1),
            mOtherMatrix->colPtr(c2));
    }
    return alphaParameters(r1, c1) + alphaParameters(r2, c2);
}

float PatternGibbsSampler::computeDeltaLL(unsigned row, unsigned col, float mass)
{
    return gaps::algo::deltaLL(mDMatrix.nRow(), mDMatrix.colPtr(row),
        mSMatrix.colPtr(row), mAPMatrix.colPtr(row), mOtherMatrix->colPtr(col),
        mass);
}

float PatternGibbsSampler::computeDeltaLL(unsigned r1, unsigned c1, float m1,
unsigned r2, unsigned c2, float m2)
{
    if (c1 == c2)
    {
        return gaps::algo::deltaLL(mDMatrix.nRow(), mDMatrix.colPtr(r1),
            mSMatrix.colPtr(r1), mAPMatrix.colPtr(r1), mOtherMatrix->colPtr(c1),
            m1, mOtherMatrix->colPtr(c2), m2);
    }
    return computeDeltaLL(r1, c1, m1) + computeDeltaLL(r2, c2, m2);
}<commit_msg>consistent with old version<commit_after>#include "GibbsSampler.h"
#include "math/SIMD.h"

/******************** AmplitudeGibbsSampler Implementation ********************/

void AmplitudeGibbsSampler::sync(PatternGibbsSampler &sampler)
{
    mOtherMatrix = &(sampler.mMatrix);
    mAPMatrix = sampler.mAPMatrix;
}

unsigned AmplitudeGibbsSampler::getRow(uint64_t pos) const
{
    return pos / (mBinSize * mNumCols);
}

unsigned AmplitudeGibbsSampler::getCol(uint64_t pos) const
{
    return (pos / mBinSize) % mNumCols;
}

bool AmplitudeGibbsSampler::canUseGibbs(unsigned row, unsigned col) const // NOLINT(misc-unused-parameters)
{
    return !gaps::algo::isVectorZero(mOtherMatrix->colPtr(col),
        mOtherMatrix->nRow());
}

bool AmplitudeGibbsSampler::canUseGibbs(unsigned r1, unsigned c1, unsigned r2, unsigned c2) const
{
    return canUseGibbs(r1, c1) || canUseGibbs(r2, c2);
}

void AmplitudeGibbsSampler::updateAPMatrix(unsigned row, unsigned col, float delta)
{
    const float *other = mOtherMatrix->colPtr(col);
    float *ap = mAPMatrix.rowPtr(row);
    unsigned size = mAPMatrix.nCol();

    gaps::simd::packedFloat pOther, pAP;
    gaps::simd::Index i(0);
    gaps::simd::packedFloat pDelta(delta);
    for (; i <= size - i.increment(); ++i)
    {
        pOther.load(other + i);
        pAP.load(ap + i);
        pAP += pDelta * pOther;
        pAP.store(ap + i);
    }

    for (unsigned j = i.value(); j < size; ++j)
    {
        ap[j] += delta * other[j];
    }
}

AlphaParameters AmplitudeGibbsSampler::alphaParameters(unsigned row, unsigned col)
{
    return gaps::algo::alphaParameters(mDMatrix.nCol(), mDMatrix.rowPtr(row),
        mSMatrix.rowPtr(row), mAPMatrix.rowPtr(row), mOtherMatrix->colPtr(col));
}

AlphaParameters AmplitudeGibbsSampler::alphaParameters(unsigned r1, unsigned c1,
unsigned r2, unsigned c2)
{
    if (r1 == r2)
    {
        return gaps::algo::alphaParameters(mDMatrix.nCol(), mDMatrix.rowPtr(r1),
            mSMatrix.rowPtr(r1), mAPMatrix.rowPtr(r1), mOtherMatrix->colPtr(c1),
            mOtherMatrix->colPtr(c2));
    }
    return alphaParameters(r1, c1) + alphaParameters(r2, c2);
}

float AmplitudeGibbsSampler::computeDeltaLL(unsigned row, unsigned col, float mass)
{
    return gaps::algo::deltaLL(mDMatrix.nCol(), mDMatrix.rowPtr(row),
        mSMatrix.rowPtr(row), mAPMatrix.rowPtr(row), mOtherMatrix->colPtr(col),
        mass);
}

float AmplitudeGibbsSampler::computeDeltaLL(unsigned r1, unsigned c1, float m1,
unsigned r2, unsigned c2, float m2)
{
    if (r1 == r2)
    {
        return gaps::algo::deltaLL(mDMatrix.nCol(), mDMatrix.rowPtr(r1),
            mSMatrix.rowPtr(r1), mAPMatrix.rowPtr(r1), mOtherMatrix->colPtr(c1),
            m1, mOtherMatrix->colPtr(c2), m2);
    }
    return computeDeltaLL(r1, c1, m1) + computeDeltaLL(r2, c2, m2);
}

/********************* PatternGibbsSampler Implementation *********************/

void PatternGibbsSampler::sync(AmplitudeGibbsSampler &sampler)
{
    mOtherMatrix = &(sampler.mMatrix);
    mAPMatrix = sampler.mAPMatrix;
}

unsigned PatternGibbsSampler::getRow(uint64_t pos) const
{
    return pos / (mBinSize * mNumCols);
}

unsigned PatternGibbsSampler::getCol(uint64_t pos) const
{
    return (pos / mBinSize) % mNumCols;
}

bool PatternGibbsSampler::canUseGibbs(unsigned row, unsigned col) const // NOLINT(misc-unused-parameters)
{
    return !gaps::algo::isVectorZero(mOtherMatrix->colPtr(col),
        mOtherMatrix->nRow());
}

bool PatternGibbsSampler::canUseGibbs(unsigned r1, unsigned c1, unsigned r2, unsigned c2) const
{
    return canUseGibbs(r1, c1) || canUseGibbs(r2, c2);
}

void PatternGibbsSampler::updateAPMatrix(unsigned row, unsigned col, float delta)
{
    const float *other = mOtherMatrix->colPtr(col);
    float *ap = mAPMatrix.colPtr(row);
    unsigned size = mAPMatrix.nRow();

    gaps::simd::packedFloat pOther, pAP;
    gaps::simd::Index i(0);
    gaps::simd::packedFloat pDelta(delta);
    for (; i <= size - i.increment(); ++i)
    {
        pOther.load(other + i);
        pAP.load(ap + i);
        pAP += pDelta * pOther;
        pAP.store(ap + i);
    }

    for (unsigned j = i.value(); j < size; ++j)
    {
        ap[j] += delta * other[j];
    }
}

AlphaParameters PatternGibbsSampler::alphaParameters(unsigned row, unsigned col)
{
    return gaps::algo::alphaParameters(mDMatrix.nRow(), mDMatrix.colPtr(row),
        mSMatrix.colPtr(row), mAPMatrix.colPtr(row), mOtherMatrix->colPtr(col));
}

AlphaParameters PatternGibbsSampler::alphaParameters(unsigned r1, unsigned c1,
unsigned r2, unsigned c2)
{
    if (r1 == r2)
    {
        return gaps::algo::alphaParameters(mDMatrix.nRow(), mDMatrix.colPtr(r1),
            mSMatrix.colPtr(r1), mAPMatrix.colPtr(r1), mOtherMatrix->colPtr(c1),
            mOtherMatrix->colPtr(c2));
    }
    return alphaParameters(r1, c1) + alphaParameters(r2, c2);
}

float PatternGibbsSampler::computeDeltaLL(unsigned row, unsigned col, float mass)
{
    return gaps::algo::deltaLL(mDMatrix.nRow(), mDMatrix.colPtr(row),
        mSMatrix.colPtr(row), mAPMatrix.colPtr(row), mOtherMatrix->colPtr(col),
        mass);
}

float PatternGibbsSampler::computeDeltaLL(unsigned r1, unsigned c1, float m1,
unsigned r2, unsigned c2, float m2)
{
    if (r1 == r2)
    {
        return gaps::algo::deltaLL(mDMatrix.nRow(), mDMatrix.colPtr(r1),
            mSMatrix.colPtr(r1), mAPMatrix.colPtr(r1), mOtherMatrix->colPtr(c1),
            m1, mOtherMatrix->colPtr(c2), m2);
    }
    return computeDeltaLL(r1, c1, m1) + computeDeltaLL(r2, c2, m2);
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <cuda.h>
#include <check.h>
#include <map>
#include <gdrapi.h>

namespace gdrcopy {
    namespace test {
        extern std::map<CUdeviceptr, CUdeviceptr> _allocations;

        static inline CUresult gpuMemAlloc(CUdeviceptr *pptr, size_t psize, bool align_to_gpu_page = true, bool set_sync_memops = true)
        {
            CUresult ret = CUDA_SUCCESS;
            CUdeviceptr ptr;
            size_t size;

            if (align_to_gpu_page)
                size = psize + GPU_PAGE_SIZE - 1;
            else
                size = psize;

            ret = cuMemAlloc(&ptr, size);
            if (ret != CUDA_SUCCESS)
                return ret;

            if (set_sync_memops) {
                unsigned int flag = 1;
                ret = cuPointerSetAttribute(&flag, CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, ptr);
                if (ret != CUDA_SUCCESS) {
                    cuMemFree(ptr);
                    return ret;
                }
            }

            if (align_to_gpu_page)
                *pptr = (ptr + GPU_PAGE_SIZE - 1) & GPU_PAGE_MASK;
            else
                *pptr = ptr;

            // Record the actual pointer for doing gpuMemFree later.
            _allocations[*pptr] = ptr;

            return CUDA_SUCCESS;
        }

        static inline CUresult gpuMemFree(CUdeviceptr pptr)
        {
            CUresult ret = CUDA_SUCCESS;
            CUdeviceptr ptr;

            if (_allocations.count(pptr) > 0) {
                ptr = _allocations[pptr];
                ret = cuMemFree(ptr);
                if (ret == CUDA_SUCCESS)
                    _allocations.erase(ptr);
                return ret;
            }
            else
                return CUDA_ERROR_INVALID_VALUE;
        }

        extern bool print_dbg_msg;

        void print_dbg(const char* fmt, ...);

        #define EXIT_WAIVED 2

        extern const char *testname;

        #define BEGIN_GDRCOPY_TEST(__testname)                                  \
        START_TEST(__testname)                                                  \
        testname = #__testname;                                                 \
        print_dbg("&&&& RUNNING " # __testname "\n");                           \
        fflush(stdout);                                                         \
        fflush(stderr);                                                         \
        pid_t __pid = fork();                                                   \
        if (__pid < 0) {                                                        \
            print_dbg("Cannot fork\n");                                         \
            print_dbg("&&&& FAILED " # __testname "\n");                        \
            exit(EXIT_FAILURE);                                                 \
        }                                                                       \
        if (__pid == 0)

        #define END_GDRCOPY_TEST                                                \
        if (__pid) {                                                            \
            int __child_exit_status = -EINVAL;                                  \
            if (waitpid(__pid, &__child_exit_status, 0) == -1) {                \
                print_dbg("waitpid returned an error\n");                       \
                print_dbg("&&&& FAILED %s\n", gdrcopy::test::testname);         \
                exit(EXIT_FAILURE);                                             \
            }                                                                   \
            if (__child_exit_status == EXIT_SUCCESS)                            \
                print_dbg("&&&& PASSED %s\n", gdrcopy::test::testname);         \
            else if (__child_exit_status == EXIT_WAIVED)                        \
                print_dbg("&&&& WAIVED %s\n", gdrcopy::test::testname);         \
            else                                                                \
                print_dbg("&&&& FAILED %s\n", gdrcopy::test::testname);         \
        }                                                                       \
        END_TEST

        #define ASSERT(x)                                                       \
            do                                                                  \
                {                                                               \
                    if (!(x))                                                   \
                        {                                                       \
                            fprintf(stderr, "Assertion \"%s\" failed at %s:%d\n", #x, __FILE__, __LINE__); \
                            exit(EXIT_FAILURE);                                 \
                        }                                                       \
                } while (0)

        #define ASSERTDRV(stmt)				\
            do                                          \
                {                                       \
                    CUresult result = (stmt);           \
                    if (result != CUDA_SUCCESS) {       \
                        const char *_err_name;          \
                        cuGetErrorName(result, &_err_name); \
                        fprintf(stderr, "CUDA error: %s\n", _err_name);   \
                    }                                   \
                    ASSERT(CUDA_SUCCESS == result);     \
                } while (0)

        static inline bool operator==(const gdr_mh_t &a, const gdr_mh_t &b) {
            return a.h == b.h;
        }

        static const gdr_mh_t null_mh = {0};

        #define ASSERT_EQ(P, V) ASSERT((P) == (V))
        #define CHECK_EQ(P, V) ASSERT((P) == (V))
        #define ASSERT_NEQ(P, V) ASSERT(!((P) == (V)))
        #define BREAK_IF_NEQ(P, V) if((P) != (V)) break
        #define BEGIN_CHECK do
        #define END_CHECK while(0)

        int compare_buf(uint32_t *ref_buf, uint32_t *buf, size_t size);

        void init_hbuf_walking_bit(uint32_t *h_buf, size_t size);

        void init_hbuf_linear_ramp(uint32_t *h_buf, size_t size);
    }
}
<commit_msg>Fixed compilation bug with libcheck-0.13<commit_after>/*
 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <cuda.h>
#include <check.h>
#include <map>
#include <gdrapi.h>

namespace gdrcopy {
    namespace test {
        extern std::map<CUdeviceptr, CUdeviceptr> _allocations;

        static inline CUresult gpuMemAlloc(CUdeviceptr *pptr, size_t psize, bool align_to_gpu_page = true, bool set_sync_memops = true)
        {
            CUresult ret = CUDA_SUCCESS;
            CUdeviceptr ptr;
            size_t size;

            if (align_to_gpu_page)
                size = psize + GPU_PAGE_SIZE - 1;
            else
                size = psize;

            ret = cuMemAlloc(&ptr, size);
            if (ret != CUDA_SUCCESS)
                return ret;

            if (set_sync_memops) {
                unsigned int flag = 1;
                ret = cuPointerSetAttribute(&flag, CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, ptr);
                if (ret != CUDA_SUCCESS) {
                    cuMemFree(ptr);
                    return ret;
                }
            }

            if (align_to_gpu_page)
                *pptr = (ptr + GPU_PAGE_SIZE - 1) & GPU_PAGE_MASK;
            else
                *pptr = ptr;

            // Record the actual pointer for doing gpuMemFree later.
            _allocations[*pptr] = ptr;

            return CUDA_SUCCESS;
        }

        static inline CUresult gpuMemFree(CUdeviceptr pptr)
        {
            CUresult ret = CUDA_SUCCESS;
            CUdeviceptr ptr;

            if (_allocations.count(pptr) > 0) {
                ptr = _allocations[pptr];
                ret = cuMemFree(ptr);
                if (ret == CUDA_SUCCESS)
                    _allocations.erase(ptr);
                return ret;
            }
            else
                return CUDA_ERROR_INVALID_VALUE;
        }

        extern bool print_dbg_msg;

        void print_dbg(const char* fmt, ...);

        #define EXIT_WAIVED 2

        extern const char *testname;

        #define BEGIN_GDRCOPY_TEST(__testname)                                  \
        START_TEST(__testname) {                                                \
            testname = #__testname;                                             \
            print_dbg("&&&& RUNNING " # __testname "\n");                       \
            fflush(stdout);                                                     \
            fflush(stderr);                                                     \
            pid_t __pid = fork();                                               \
            if (__pid < 0) {                                                    \
                print_dbg("Cannot fork\n");                                     \
                print_dbg("&&&& FAILED " # __testname "\n");                    \
                exit(EXIT_FAILURE);                                             \
            }                                                                   \
            if (__pid == 0) {

        #define END_GDRCOPY_TEST }                                              \
            if (__pid) {                                                        \
                int __child_exit_status = -EINVAL;                              \
                if (waitpid(__pid, &__child_exit_status, 0) == -1) {            \
                    print_dbg("waitpid returned an error\n");                   \
                    print_dbg("&&&& FAILED %s\n", gdrcopy::test::testname);     \
                    exit(EXIT_FAILURE);                                         \
                }                                                               \
                if (__child_exit_status == EXIT_SUCCESS)                        \
                    print_dbg("&&&& PASSED %s\n", gdrcopy::test::testname);     \
                else if (__child_exit_status == EXIT_WAIVED)                    \
                    print_dbg("&&&& WAIVED %s\n", gdrcopy::test::testname);     \
                else                                                            \
                    print_dbg("&&&& FAILED %s\n", gdrcopy::test::testname);     \
            }                                                                   \
        } END_TEST

        #define ASSERT(x)                                                       \
            do                                                                  \
                {                                                               \
                    if (!(x))                                                   \
                        {                                                       \
                            fprintf(stderr, "Assertion \"%s\" failed at %s:%d\n", #x, __FILE__, __LINE__); \
                            exit(EXIT_FAILURE);                                 \
                        }                                                       \
                } while (0)

        #define ASSERTDRV(stmt)				\
            do                                          \
                {                                       \
                    CUresult result = (stmt);           \
                    if (result != CUDA_SUCCESS) {       \
                        const char *_err_name;          \
                        cuGetErrorName(result, &_err_name); \
                        fprintf(stderr, "CUDA error: %s\n", _err_name);   \
                    }                                   \
                    ASSERT(CUDA_SUCCESS == result);     \
                } while (0)

        static inline bool operator==(const gdr_mh_t &a, const gdr_mh_t &b) {
            return a.h == b.h;
        }

        static const gdr_mh_t null_mh = {0};

        #define ASSERT_EQ(P, V) ASSERT((P) == (V))
        #define CHECK_EQ(P, V) ASSERT((P) == (V))
        #define ASSERT_NEQ(P, V) ASSERT(!((P) == (V)))
        #define BREAK_IF_NEQ(P, V) if((P) != (V)) break
        #define BEGIN_CHECK do
        #define END_CHECK while(0)

        int compare_buf(uint32_t *ref_buf, uint32_t *buf, size_t size);

        void init_hbuf_walking_bit(uint32_t *h_buf, size_t size);

        void init_hbuf_linear_ramp(uint32_t *h_buf, size_t size);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *   Email: russ@q12.org   Web: www.q12.org                              *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * 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 (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

/*

@@@ WORK IN PROGRESS @@@

TODO
  * ALIGN allocations to dEFFICIENT_SIZE

*/

#include <string.h>
#include <errno.h>
#include "obstack.h"
#include "ode/error.h"
#include "ode/config.h"
#include "ode/memory.h"

//****************************************************************************
// constants

// each Arena pointer points to a block of this many bytes
#define ARENA_SIZE 4096

//****************************************************************************
// dObStack

dObStack::dObStack()
{
  first = 0;
  last = 0;
  current_arena = 0;
  current_ofs = 0;
}

dObStack::~dObStack()
{
  // free all arenas
  Arena *a,*nexta;
  a = first;
  while (a) {
    nexta = a->next;
    dFree (a,ARENA_SIZE);
    a = nexta;
  }
}

void *dObStack::alloc (int num_bytes)
{
  // @@@ assumes num_bytes is not too large.

  // allocate or move to a new arena if necessary
  if (!first) {
    // allocate the first arena if necessary
    first = last = (Arena *) dAlloc (ARENA_SIZE);
    first->next = 0;
    first->used = sizeof (Arena);
  }
  else {
    // we already have one or more arenas, see if a new arena must be used
    if ((last->used + num_bytes) > ARENA_SIZE) {
      if (!last->next) {
	last->next = (Arena *) dAlloc (ARENA_SIZE);
	last->next->next = 0;
      }
      last = last->next;
      last->used = sizeof (Arena);
    }
  }

  // allocate an area in the arena
  char *c = ((char*) last) + last->used;
  last->used += num_bytes;
  return c;
}

void dObStack::freeAll()
{
  last = first;
  first->used = sizeof(Arena);
}

void *dObStack::rewind()
{
  current_arena = first;
  current_ofs = sizeof (Arena);
  if (current_arena)
    return ((char*) current_arena) + current_ofs;
  else return 0;
}

void *dObStack::next (int num_bytes)
{
  // this functions exactly like alloc, except that no new storage is ever
  // allocated

  // @@@ assumes num_bytes is not too large.

  if (!current_arena) return 0;
  if ((current_ofs + num_bytes) > ARENA_SIZE) {
    current_arena = current_arena->next;
    if (!current_arena) return 0;
    current_ofs = sizeof (Arena);
  }
  char *c = ((char*) current_arena) + current_ofs;
  current_arena += num_bytes;
  return c;
}
<commit_msg>work in progress<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *   Email: russ@q12.org   Web: www.q12.org                              *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * 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 (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

/*

@@@ WORK IN PROGRESS @@@

TODO
  * ALIGN allocations to dEFFICIENT_SIZE

*/

#include <string.h>
#include <errno.h>
#include "obstack.h"
#include "ode/error.h"
#include "ode/config.h"
#include "ode/memory.h"

typedef unsigned int intP;

//****************************************************************************
// constants and macros

// each Arena pointer points to a block of this many bytes
#define ARENA_SIZE 4096

#define ROUND_UP_OFFSET_TO_EFFICIENT_SIZE(arena,ofs) \
  ofs = (int) dEFFICIENT_SIZE( ((intP)(arena)) + ofs ); \

@@@@@@@@

//****************************************************************************
// dObStack

dObStack::dObStack()
{
  first = 0;
  last = 0;
  current_arena = 0;
  current_ofs = 0;
}

dObStack::~dObStack()
{
  // free all arenas
  Arena *a,*nexta;
  a = first;
  while (a) {
    nexta = a->next;
    dFree (a,ARENA_SIZE);
    a = nexta;
  }
}

void *dObStack::alloc (int num_bytes)
{
  // @@@ assumes num_bytes is not too large.

  // allocate or move to a new arena if necessary
  if (!first) {
    // allocate the first arena if necessary
    first = last = (Arena *) dAlloc (ARENA_SIZE);
    first->next = 0;
    first->used = sizeof (Arena);
  }
  else {
    // we already have one or more arenas, see if a new arena must be used
    if ((last->used + num_bytes) > ARENA_SIZE) {
      if (!last->next) {
	last->next = (Arena *) dAlloc (ARENA_SIZE);
	last->next->next = 0;
      }
      last = last->next;
      last->used = sizeof (Arena);
    }
  }

  // allocate an area in the arena
  char *c = ((char*) last) + last->used;
  last->used += num_bytes;
  return c;
}

void dObStack::freeAll()
{
  last = first;
  first->used = sizeof(Arena);
}

void *dObStack::rewind()
{
  current_arena = first;
  current_ofs = sizeof (Arena);
  if (current_arena)
    return ((char*) current_arena) + current_ofs;
  else return 0;
}

void *dObStack::next (int num_bytes)
{
  // this functions exactly like alloc, except that no new storage is ever
  // allocated

  // @@@ assumes num_bytes is not too large.

  if (!current_arena) return 0;
  if ((current_ofs + num_bytes) > ARENA_SIZE) {
    current_arena = current_arena->next;
    if (!current_arena) return 0;
    current_ofs = sizeof (Arena);
  }
  char *c = ((char*) current_arena) + current_ofs;
  current_arena += num_bytes;
  return c;
}
<|endoftext|>


<commit_before>#include "unit_tests/tests.hpp"
#include "grune-json/grune-json.hpp"

#include "grune/non_terminal.hpp"
#include "grune/production.hpp"
#include "grune/symbol.hpp"
#include "grune/grammars/anbncn.hpp"
#include "grune/grammars/turtle.hpp"
#include "grune/grammars/tom_dick_and_harry.hpp"

#include <iostream>

using namespace grune;

namespace
{

#define ASSERT_EQUAL_END_TO_END(value) \
    do { \
        std::string err; \
        auto first_pass = \
            json11::Json::parse( \
                json11::Json(value).dump(), \
                err\
            ).as<decltype(value)>(); \
        BOOST_CHECK_EQUAL(err, std::string()); \
        BOOST_CHECK_EQUAL(first_pass, value); \
        auto second_pass = \
            json11::Json::parse( \
                json11::Json(first_pass).dump(), \
                err\
            ).as<decltype(value)>(); \
        BOOST_CHECK_EQUAL(err, std::string()); \
        BOOST_CHECK_EQUAL(second_pass, value); \
    } while (0)

#define ASSERT_LOAD_EQUAL(document, value) \
    do { \
        std::string err; \
        auto new_value = \
            json11::Json::parse(document, err).as<decltype(value)>(); \
        BOOST_CHECK_EQUAL(err, std::string()); \
        BOOST_CHECK_EQUAL(value, new_value); \
    } while (0)

}

BOOST_AUTO_TEST_SUITE(json_tests)

BOOST_AUTO_TEST_CASE(symbol_test)
{
    symbol empty;
    symbol asdf("asdf");
    non_terminal A("A");

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"\" }", empty);

    ASSERT_EQUAL_END_TO_END(asdf);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"asdf\" }", asdf);

    ASSERT_EQUAL_END_TO_END(A);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": false, \"text\": \"A\" }", A);
}

BOOST_AUTO_TEST_CASE(sequence_test)
{
    sequence empty { };
    sequence asdf { "a", "s", "d", "f" };
    sequence nts
    {
        non_terminal("A"),
        non_terminal("B"),
        non_terminal("C"),
    };

    sequence mixed
    {
        "(", non_terminal("expr"), ")"
    };

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_EQUAL_END_TO_END(asdf);
    ASSERT_EQUAL_END_TO_END(nts);
    ASSERT_EQUAL_END_TO_END(mixed);
}

BOOST_AUTO_TEST_CASE(sequence_list_test)
{
    sequence_list empty { };
    sequence_list asdf { { "a" }, { "s" }, { "d" }, { "f" } };
    sequence_list bits
    {
        { 0, 0 },
        { 0, 1 },
        { 1, 0 },
        { 1, 1 },
    };
    sequence_list nested_empty
    {
        { },
        { },
        { },
    };
    sequence_list mixed
    {
        { "a", "s" },
        { non_terminal("D"), non_terminal("F") },
        { },
        { "q", non_terminal("W"), "erty" },
    };

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_EQUAL_END_TO_END(asdf);
    ASSERT_EQUAL_END_TO_END(bits);
    ASSERT_EQUAL_END_TO_END(nested_empty);
    ASSERT_EQUAL_END_TO_END(mixed);
}

BOOST_AUTO_TEST_CASE(production_test)
{
    non_terminal A("A");
    non_terminal B("B");

    production empty;
    production p1_1 { A, { "x" } };
    production p1_2 { A, { "y" } };
    production p1_3 { A, { "z" } };
    production_list p1 { p1_1, p1_2, p1_3 };
    production p2_1 { { A, B }, { "x", "y", "z" } };
    production p2_2 { { A, B }, { "z", "y", "x" } };
    production_list p2 { p2_1, p2_2 };
    production p3 { { B, A }, { } };
    production_list all { p1_1, p1_2, p1_3, p2_1, p2_2, p3 };

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_EQUAL_END_TO_END(p1);
    ASSERT_EQUAL_END_TO_END(p1_1);
    ASSERT_EQUAL_END_TO_END(p1_2);
    ASSERT_EQUAL_END_TO_END(p1_3);
    ASSERT_EQUAL_END_TO_END(p2);
    ASSERT_EQUAL_END_TO_END(p2_1);
    ASSERT_EQUAL_END_TO_END(p2_2);
    ASSERT_EQUAL_END_TO_END(p3);
    ASSERT_EQUAL_END_TO_END(all);
}

BOOST_AUTO_TEST_CASE(grammar_test)
{
    auto anbncn = grune::grammars::anbncn();
    auto turtle = grune::grammars::cyclic_manhattan_turtle();
    auto tdh = grune::grammars::tom_dick_and_harry();

    ASSERT_EQUAL_END_TO_END(anbncn);
    ASSERT_EQUAL_END_TO_END(turtle);
    ASSERT_EQUAL_END_TO_END(tdh);
}

BOOST_AUTO_TEST_CASE(simple_format_test)
{
    std::string json_doc = "[a, b, c, d]";
    sequence expected = { "a", "b", "c", "d" };

    ASSERT_LOAD_EQUAL(json_doc, expected);
}

BOOST_AUTO_TEST_CASE(simple_nonterms)
{
    symbol t("_t");
    non_terminal nt("_nt");
    symbol empty_term("");
    non_terminal empty_nonterm("");

    ASSERT_EQUAL_END_TO_END(t);
    ASSERT_EQUAL_END_TO_END(nt);
    ASSERT_EQUAL_END_TO_END(empty_term);
    ASSERT_EQUAL_END_TO_END(empty_nonterm);

    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"_t\" }", t);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": false, \"text\": \"_nt\" }", nt);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"\" }", empty_term);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": false, \"text\": \"\" }", empty_nonterm);

    ASSERT_LOAD_EQUAL("\\_t", t);
    ASSERT_LOAD_EQUAL("__nt", nt);
    ASSERT_LOAD_EQUAL("\"\"", empty_term);
    ASSERT_LOAD_EQUAL("_", empty_nonterm);
}

BOOST_AUTO_TEST_CASE(short_production)
{
    non_terminal A("A");
    symbol a("a");

    production p
    {
        A, { a }
    };

    ASSERT_EQUAL_END_TO_END(p);
    ASSERT_LOAD_EQUAL("{ \"lhs\": \"_A\", \"rhs\": \"a\" }", p);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fixup another json error in the unit tests<commit_after>#include "unit_tests/tests.hpp"
#include "grune-json/grune-json.hpp"

#include "grune/non_terminal.hpp"
#include "grune/production.hpp"
#include "grune/symbol.hpp"
#include "grune/grammars/anbncn.hpp"
#include "grune/grammars/turtle.hpp"
#include "grune/grammars/tom_dick_and_harry.hpp"

#include <iostream>

using namespace grune;

namespace
{

#define ASSERT_EQUAL_END_TO_END(value) \
    do { \
        std::string err; \
        auto first_pass = \
            json11::Json::parse( \
                json11::Json(value).dump(), \
                err\
            ).as<decltype(value)>(); \
        BOOST_CHECK_EQUAL(err, std::string()); \
        BOOST_CHECK_EQUAL(first_pass, value); \
        auto second_pass = \
            json11::Json::parse( \
                json11::Json(first_pass).dump(), \
                err\
            ).as<decltype(value)>(); \
        BOOST_CHECK_EQUAL(err, std::string()); \
        BOOST_CHECK_EQUAL(second_pass, value); \
    } while (0)

#define ASSERT_LOAD_EQUAL(document, value) \
    do { \
        std::string err; \
        auto new_value = \
            json11::Json::parse(document, err).as<decltype(value)>(); \
        BOOST_CHECK_EQUAL(err, std::string()); \
        BOOST_CHECK_EQUAL(value, new_value); \
    } while (0)

}

BOOST_AUTO_TEST_SUITE(json_tests)

BOOST_AUTO_TEST_CASE(symbol_test)
{
    symbol empty;
    symbol asdf("asdf");
    non_terminal A("A");

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"\" }", empty);

    ASSERT_EQUAL_END_TO_END(asdf);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"asdf\" }", asdf);

    ASSERT_EQUAL_END_TO_END(A);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": false, \"text\": \"A\" }", A);
}

BOOST_AUTO_TEST_CASE(sequence_test)
{
    sequence empty { };
    sequence asdf { "a", "s", "d", "f" };
    sequence nts
    {
        non_terminal("A"),
        non_terminal("B"),
        non_terminal("C"),
    };

    sequence mixed
    {
        "(", non_terminal("expr"), ")"
    };

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_EQUAL_END_TO_END(asdf);
    ASSERT_EQUAL_END_TO_END(nts);
    ASSERT_EQUAL_END_TO_END(mixed);
}

BOOST_AUTO_TEST_CASE(sequence_list_test)
{
    sequence_list empty { };
    sequence_list asdf { { "a" }, { "s" }, { "d" }, { "f" } };
    sequence_list bits
    {
        { 0, 0 },
        { 0, 1 },
        { 1, 0 },
        { 1, 1 },
    };
    sequence_list nested_empty
    {
        { },
        { },
        { },
    };
    sequence_list mixed
    {
        { "a", "s" },
        { non_terminal("D"), non_terminal("F") },
        { },
        { "q", non_terminal("W"), "erty" },
    };

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_EQUAL_END_TO_END(asdf);
    ASSERT_EQUAL_END_TO_END(bits);
    ASSERT_EQUAL_END_TO_END(nested_empty);
    ASSERT_EQUAL_END_TO_END(mixed);
}

BOOST_AUTO_TEST_CASE(production_test)
{
    non_terminal A("A");
    non_terminal B("B");

    production empty;
    production p1_1 { A, { "x" } };
    production p1_2 { A, { "y" } };
    production p1_3 { A, { "z" } };
    production_list p1 { p1_1, p1_2, p1_3 };
    production p2_1 { { A, B }, { "x", "y", "z" } };
    production p2_2 { { A, B }, { "z", "y", "x" } };
    production_list p2 { p2_1, p2_2 };
    production p3 { { B, A }, { } };
    production_list all { p1_1, p1_2, p1_3, p2_1, p2_2, p3 };

    ASSERT_EQUAL_END_TO_END(empty);
    ASSERT_EQUAL_END_TO_END(p1);
    ASSERT_EQUAL_END_TO_END(p1_1);
    ASSERT_EQUAL_END_TO_END(p1_2);
    ASSERT_EQUAL_END_TO_END(p1_3);
    ASSERT_EQUAL_END_TO_END(p2);
    ASSERT_EQUAL_END_TO_END(p2_1);
    ASSERT_EQUAL_END_TO_END(p2_2);
    ASSERT_EQUAL_END_TO_END(p3);
    ASSERT_EQUAL_END_TO_END(all);
}

BOOST_AUTO_TEST_CASE(grammar_test)
{
    auto anbncn = grune::grammars::anbncn();
    auto turtle = grune::grammars::cyclic_manhattan_turtle();
    auto tdh = grune::grammars::tom_dick_and_harry();

    ASSERT_EQUAL_END_TO_END(anbncn);
    ASSERT_EQUAL_END_TO_END(turtle);
    ASSERT_EQUAL_END_TO_END(tdh);
}

BOOST_AUTO_TEST_CASE(simple_format_test)
{
    std::string json_doc = "[\"a\",\"b\", \"c\", \"d\"]";
    sequence expected = { "a", "b", "c", "d" };

    ASSERT_LOAD_EQUAL(json_doc, expected);
}

BOOST_AUTO_TEST_CASE(simple_nonterms)
{
    symbol t("_t");
    non_terminal nt("_nt");
    symbol empty_term("");
    non_terminal empty_nonterm("");

    ASSERT_EQUAL_END_TO_END(t);
    ASSERT_EQUAL_END_TO_END(nt);
    ASSERT_EQUAL_END_TO_END(empty_term);
    ASSERT_EQUAL_END_TO_END(empty_nonterm);

    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"_t\" }", t);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": false, \"text\": \"_nt\" }", nt);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": true, \"text\": \"\" }", empty_term);
    ASSERT_LOAD_EQUAL("{ \"is_terminal\": false, \"text\": \"\" }", empty_nonterm);

    ASSERT_LOAD_EQUAL("\"\\\\_t\"", t);
    ASSERT_LOAD_EQUAL("\"__nt\"", nt);
    ASSERT_LOAD_EQUAL("\"\"", empty_term);
    ASSERT_LOAD_EQUAL("\"_\"", empty_nonterm);
}

BOOST_AUTO_TEST_CASE(short_production)
{
    non_terminal A("A");
    symbol a("a");

    production p
    {
        A, { a }
    };

    ASSERT_EQUAL_END_TO_END(p);
    ASSERT_LOAD_EQUAL("{ \"lhs\": \"_A\", \"rhs\": \"a\" }", p);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>