<commit_before>/*
Copyright 2013, Jernej Kovacic

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.
*/

/**
 * @file
 * @author Jernej Kovacic
 *
 * Implementation of the class PolynomialInterpolationGeneric. The class
 * calculates an interpolation polynomial that goes exactly through
 * entered points.
 *
 * As the class is templated, this file must not be compiled.
 * Instead it must be included after the class declaration in the .h file
 */

// Deliberately there is no #include "PolynomialInterpolationGeneric.hpp"
#include "polynomial/PolynomialGeneric.hpp"
#include "exception/CurveFittingException.hpp"
#include "../settings/omp_settings.h"

#include <vector>
#include <new>
#include <cstddef>

/**
 * Constructor.
 *
 * It initializes all its internal structures.
 */
template<class T>
math::PolynomialInterpolationGeneric<T>::PolynomialInterpolationGeneric()
{
    math::CurveFittingGenericAb<T>::_init();
}

/**
 * Generates an interpolation polynomial that goes exactly
 * through all entered points. The degree of the polynomial is
 * equal to nr. of points - 1.
 *
 * @param degree - ignored as it does not make any sense at this class.
 *
 * @throw CurveFittingException if generation of the curve failed for any reason.
 */
template<class T>
void math::PolynomialInterpolationGeneric<T>::generateCurve(size_t degree) throw (math::CurveFittingException)
{
    // performs necessary checks
    this->_curveGenerationCheck();
    // TODO check value of degree?

    /*
         One possible algorithm would be construction of the so called
         Vandermonde matrix. However, this method is known as computationally
         inefficient and prone to significant computation errors when solving a
         system of linear equations.

         Instead, the Newton's interpolation algorithm will be applied, described at:
         http://en.wikipedia.org/wiki/Newton_polynomial

         Procedure of the algorithm:
         - input: points: (x0,y0), (x1,y1), ..., (xn,yn)
         - create a (n+1)x(n+1) matrix a, fill it with zeros
         - fill the first column of the matrix with y's:
             a(i,0) = y(i)   for i = 0 .. n
         - calculate lower diagonal elements as differential quotients:

                       a(r,c-1) - a(r-1,c-1)
             a(r,c) = ------------------------
                           x(r) - x(r-c)

              for c = 1..n, r=c..n

         - when this procedure is completed, the interpolation polynomial
           is expressed as:

             p(x) = y(0) + a(1,1)*(x-y(0)) + a(2,2)*(x-y(0))*(x-y(1)) + ... +

                          n-1
                         +---+
                         |   |
              + a(n,n) * |   | (x-y(k))
                         |   |
                          k=0
     */

    try
    {
        // As it turns out, the algorithm above can be further optimized.
        // It is sufficient to use a 1D vector (storing just the current "column")
        // instead of a 2D matrix. It is also possible to update polynomials
        // concurrently when updating "columns".

        // number of points
        const size_t N = this->points.size();

        // create vectors to store temporary results:
        std::vector<T> a;
        std::vector<T> x;

        if ( N > a.max_size() )
        {
            throw math::CurveFittingException(math::CurveFittingException::CURVE_GENERATION_FAILED);
        }

        a.resize(N);
        x.resize(N);

        // hiding idx from the rest of the function
        {
            // As iterators are the fastest way to access linked list elements,
            // traverse the list only once and populate appropriate elements of a and b
            size_t idx = 0;
            for (
              typename std::list<typename math::CurveFittingGenericAb<T>::CPoint>::const_iterator it=this->points.begin();
              it!=this->points.end();
              ++it, ++idx )
                {
                    x.at(idx) = it->p_x;
                    a.at(idx) = it->p_y;
                }  // for it
        }  // hiding idx from the rest of the code

        // Polynomials:
        // (x-y0)*(x-y1)*...*(x-yi)
        math::PolynomialGeneric<T> temp(true, 1);
        // partial polynomial sum (sum of temp*a(i,i))
        math::PolynomialGeneric<T> sum(true, 1);
        // 1st degree term (x-y) that will be multiplied by temp
        math::PolynomialGeneric<T> term(true, 2);

        // Initialize the polynomials:

        // term will always be of form (x-xi), hence term(1)
        // is always equal to 1, while term(0) will be set depending on c
        term.set(1, math::NumericUtil<T>::ONE);

        // initial value of temp: 1
        temp.set(0, math::NumericUtil<T>::ONE);
        // initial value of sum: a(0,0)
        sum.set(0, a.at(0));

        // recalculate vector's element as differential quotients:
        // a(i) = (a(i+1)-a(i))/ (appropriate difference of x)

        /*
         * This for loop cannot be parallelized because 'a' at each iteration
         * depends on the same vector at the previous iteration
         */
        for ( size_t c=0; c<(N-1); ++c )
        {
            /*
             * On the other hand, it is possible to parallelize the inner
             * for loop. However it must be ensured that a.at(i) is updated
             * before a.at(i+1). This can be achieved using the OpenMP
             * "ordered" clause.
             */
            #pragma omp parallel for ordered default(none) shared(a, x, c)
            for ( size_t i=0; i<(N-1-c); ++i )
            {
                T el = (a.at(i+1) - a.at(i)) / (x.at(i+c+1) - x.at(i));

                // It is important that this update is performed in the right order!
                #pragma omp ordered
                a.at(i) = el;
            }  // for i

            // finally update the polynomials as described in the last section above
            term.set(0, -x.at(c));
            temp *= term;
            sum += a.at(0) * temp;
        } // for c

        // vectors are not needed anymore
        x.clear();
        a.clear();

        // The algorithm is finished, assign the interpolation polynomial to poly:
        this->poly = sum;

        // the curve can be marked as generated
        this->curveGenerated = true;
    }  // try
    catch ( const math::PolynomialException& pex )
    {
        // the only possible PolynomialException is out of memory
        throw math::CurveFittingException(math::CurveFittingException::OUT_OF_MEMORY);
    }
    catch ( const std::bad_alloc& ba )
    {
        throw math::CurveFittingException(math::CurveFittingException::OUT_OF_MEMORY);
    }

    (void) degree;
}
<commit_msg>corrected description of the algorithm<commit_after>/*
Copyright 2013, Jernej Kovacic

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.
*/

/**
 * @file
 * @author Jernej Kovacic
 *
 * Implementation of the class PolynomialInterpolationGeneric. The class
 * calculates an interpolation polynomial that goes exactly through
 * entered points.
 *
 * As the class is templated, this file must not be compiled.
 * Instead it must be included after the class declaration in the .h file
 */

// Deliberately there is no #include "PolynomialInterpolationGeneric.hpp"
#include "polynomial/PolynomialGeneric.hpp"
#include "exception/CurveFittingException.hpp"
#include "../settings/omp_settings.h"

#include <vector>
#include <new>
#include <cstddef>

/**
 * Constructor.
 *
 * It initializes all its internal structures.
 */
template<class T>
math::PolynomialInterpolationGeneric<T>::PolynomialInterpolationGeneric()
{
    math::CurveFittingGenericAb<T>::_init();
}

/**
 * Generates an interpolation polynomial that goes exactly
 * through all entered points. The degree of the polynomial is
 * equal to nr. of points - 1.
 *
 * @param degree - ignored as it does not make any sense at this class.
 *
 * @throw CurveFittingException if generation of the curve failed for any reason.
 */
template<class T>
void math::PolynomialInterpolationGeneric<T>::generateCurve(size_t degree) throw (math::CurveFittingException)
{
    // performs necessary checks
    this->_curveGenerationCheck();
    // TODO check value of degree?

    /*
         One possible algorithm would be construction of the so called
         Vandermonde matrix. However, this method is known as computationally
         inefficient and prone to significant computation errors when solving a
         system of linear equations.

         Instead, the Newton's interpolation algorithm will be applied, described at:
         http://en.wikipedia.org/wiki/Newton_polynomial

         Procedure of the algorithm:
         - input: points: (x0,y0), (x1,y1), ..., (xn,yn)
         - create a (n+1)x(n+1) matrix a, fill it with zeros
         - fill the first column of the matrix with y's:
             a(i,0) = y(i)   for i = 0 .. n
         - calculate lower diagonal elements as differential quotients:

                       a(r,c-1) - a(r-1,c-1)
             a(r,c) = ------------------------
                           x(r) - x(r-c)

              for c = 1..n, r=c..n

         - when this procedure is completed, the interpolation polynomial
           is expressed as:

             p(x) = y(0) + a(1,1)*(x-x(0)) + a(2,2)*(x-x(0))*(x-x(1)) + ... +

                          n-1
                         +---+
                         |   |
              + a(n,n) * |   | (x-x(k))
                         |   |
                          k=0
     */

    try
    {
        // As it turns out, the algorithm above can be further optimized.
        // It is sufficient to use a 1D vector (storing just the current "column")
        // instead of a 2D matrix. It is also possible to update polynomials
        // concurrently when updating "columns".

        // number of points
        const size_t N = this->points.size();

        // create vectors to store temporary results:
        std::vector<T> a;
        std::vector<T> x;

        if ( N > a.max_size() )
        {
            throw math::CurveFittingException(math::CurveFittingException::CURVE_GENERATION_FAILED);
        }

        a.resize(N);
        x.resize(N);

        // hiding idx from the rest of the function
        {
            // As iterators are the fastest way to access linked list elements,
            // traverse the list only once and populate appropriate elements of a and b
            size_t idx = 0;
            for (
              typename std::list<typename math::CurveFittingGenericAb<T>::CPoint>::const_iterator it=this->points.begin();
              it!=this->points.end();
              ++it, ++idx )
                {
                    x.at(idx) = it->p_x;
                    a.at(idx) = it->p_y;
                }  // for it
        }  // hiding idx from the rest of the code

        // Polynomials:
        // (x-y0)*(x-y1)*...*(x-yi)
        math::PolynomialGeneric<T> temp(true, 1);
        // partial polynomial sum (sum of temp*a(i,i))
        math::PolynomialGeneric<T> sum(true, 1);
        // 1st degree term (x-y) that will be multiplied by temp
        math::PolynomialGeneric<T> term(true, 2);

        // Initialize the polynomials:

        // term will always be of form (x-xi), hence term(1)
        // is always equal to 1, while term(0) will be set depending on c
        term.set(1, math::NumericUtil<T>::ONE);

        // initial value of temp: 1
        temp.set(0, math::NumericUtil<T>::ONE);
        // initial value of sum: a(0,0)
        sum.set(0, a.at(0));

        // recalculate vector's element as differential quotients:
        // a(i) = (a(i+1)-a(i))/ (appropriate difference of x)

        /*
         * This for loop cannot be parallelized because 'a' at each iteration
         * depends on the same vector at the previous iteration
         */
        for ( size_t c=0; c<(N-1); ++c )
        {
            /*
             * On the other hand, it is possible to parallelize the inner
             * for loop. However it must be ensured that a.at(i) is updated
             * before a.at(i+1). This can be achieved using the OpenMP
             * "ordered" clause.
             */
            #pragma omp parallel for ordered default(none) shared(a, x, c)
            for ( size_t i=0; i<(N-1-c); ++i )
            {
                T el = (a.at(i+1) - a.at(i)) / (x.at(i+c+1) - x.at(i));

                // It is important that this update is performed in the right order!
                #pragma omp ordered
                a.at(i) = el;
            }  // for i

            // finally update the polynomials as described in the last section above
            term.set(0, -x.at(c));
            temp *= term;
            sum += a.at(0) * temp;
        } // for c

        // vectors are not needed anymore
        x.clear();
        a.clear();

        // The algorithm is finished, assign the interpolation polynomial to poly:
        this->poly = sum;

        // the curve can be marked as generated
        this->curveGenerated = true;
    }  // try
    catch ( const math::PolynomialException& pex )
    {
        // the only possible PolynomialException is out of memory
        throw math::CurveFittingException(math::CurveFittingException::OUT_OF_MEMORY);
    }
    catch ( const std::bad_alloc& ba )
    {
        throw math::CurveFittingException(math::CurveFittingException::OUT_OF_MEMORY);
    }

    (void) degree;
}
<|endoftext|>


<commit_before>#ifndef __lxarray__
#define __lxarray__

#include "lxalloc.hpp"
#include "lxstore.hpp"
#include "lxstack.hpp"
#include "lxbuffs.hpp"
#include "lxchars.hpp"
#include "lxerror.hpp"

// Emulate C arrays/pointers in Lua

template <class User> struct lux_Array
{
	// Pointer storage implementation
	typedef lux_Store<User*> Type;

	// Array allocation function
	static int __new(lua_State *state)
	{
		lux_Chars shift;
		const char *string;
		ssize_t length;
		size_t size;
		User *data;
		// Constructor arguments
		switch (lua_type(state, 1))
		{
		  case LUA_TNIL:
		  case LUA_TNONE:
			data = nullptr;
			size = 0;
		  	break;
		  case LUA_TNUMBER:
			size = lux_to<int>(state, 1);
			data = new User [size];
			break;
		  case LUA_TTABLE:
			// Copy table contents
			size = luaL_len(state, 1);
			data = new User [size];
			lua_pushnil(state);
			for (int it = 0; lua_next(state, 1); ++it)
			{
			 data[it] = lux_to<User>(state, 3);
			 lua_pop(state, 1);
			}
			break;
		  case LUA_TSTRING:
			// Get UTF-8 encoded string with length
			string = lua_tolstring(state, 1, &size);
			length = shift.stringsize(string, size);
			// Check the string for encoding errors
			if (length < 0)	return lux_argerror(state, 1);
			else shift.reset();
			// Create and convert
			data = new User [length];
			size = shift.to(data, string, length);
			break;
		  default:
			return luaL_argerror(state, 1, "invalid type");
		};
		// Put the array on the stack
		Type::push(state, data, size);
		luaL_setmetatable(state, Type::name);
		return 1;
	}

	// Garbage collection callback
	static int __gc(lua_State *state)
	{
		Type *user = Type::check(state);
		// Owner's have non-negative sizes
		if (0 < user->size) delete [] user->data;
		return 0;
	}

	// Size of array or zero if pointer
	static int __len(lua_State *state)
	{
		Type *user = Type::check(state);
		lux_push(state, abs(user->size));
		return 1;
	}

	// Read array data at offset
	static int __index(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		lux_push(state, data[offset]);
		return 1;
	}

	// Write array data at offset
	static int __newindex(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		data[offset] = lux_to<User>(state, 3);
		return 0;
	}

	// String conversion for printing
	static int __tostring(lua_State *state)
	{
		Type *user = Type::check(state);
		size_t size = abs(user->size);
		// Build up a string
		lux_Buffer buffer(state);
		// Iterate over each item in the array
		for (auto item = 0; item < size; ++item)
		{
			// Add separator only after first
			if (item) buffer.addstring(", ");
			// Convert each element to string
			lux_push(state, user->data[item]);
			buffer.addvalue();
		}
		buffer.push();
		return 1;
	}

	// Concatenate arrays of same type
	static int __concat(lua_State *state)
	{
		Type *one = Type::check(state, 1);
		Type *two = Type::check(state, 2);
		// Genuine size of arrays
		size_t n = abs(one->size);
		size_t m = abs(two->size);
		// Pointers are valid?
		if (n > 0 and m > 0)
		{
			// Required storage
			size_t size = n + m;
			User *data = new User [size];
			// Push userdata onto stack
			new (state) Type(data, size);
			luaL_setmetatable(state, Type::name);
			// Copy contents of input arrays
			memcpy(data + n, two->data, m * sizeof(User));
			memcpy(data, one->data, n * sizeof(User));
			return 1;
		}
		return 0;
	}

	// Pointer addition arithmetic
	static int __add(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		lux_push(state, data + offset);
		return 1;
	}

	// Pointer subtraction arithmetic
	static int __sub(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		lux_push(state, data - offset);
		return 1;
	}

	// Shift values left by given amount
	static int __shl(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		ssize_t shift = luaL_checkinteger(state, 2);
		// We only accept positive values for shifting
		luaL_argcheck(state, (shift > 0), 2, "shift > 0");
		// Shorthand variables
		size_t t = user->size;
		size_t s = shift;
		size_t n = s % t;
		size_t m = t - n;
		// Copy without overlap
		if (n < m)
		{
		User temp[m];
		memcpy(temp, user->data + n, m * sizeof(User));
		memcpy(user->data + m, user->data, n * sizeof(User));
		memcpy(user->data, temp, m * sizeof(User));
		}
		else
		{
		User temp[n];
		memcpy(temp, user->data, n * sizeof(User));
		memcpy(user->data, user->data + n, m * sizeof(User));
		memcpy(user->data + m, temp, n * sizeof(User));
		}
		lua_pushvalue(state, 1);
		return 1;
	}

	// Shift values right by given amount
	static int __shr(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		ssize_t shift = luaL_checkinteger(state, 2);
		// We only accept positive values for shifting
		luaL_argcheck(state, (shift > 0), 2, "shift > 0");
		// Shorthand variables
		size_t t = user->size;
		size_t s = shift;
		size_t n = s % t;
		size_t m = t - n;
		// Copy without overlap
		if (n < m)
		{
		User temp[m];
		memcpy(temp, user->data, m * sizeof(User));
		memcpy(user->data, user->data + m, n * sizeof(User));
		memcpy(user->data + n, temp, m * sizeof(User));
		}
		else
		{
		User temp[n];
		memcpy(temp, user->data + m, n * sizeof(User));
		memcpy(user->data + m, user->data, m * sizeof(User));
		memcpy(user->data, temp, n * sizeof(User));
		}
		lua_pushvalue(state, 1);
		return 1;
	}

	// Element comparison operator used for qsort
	static int compare(const void *p1, const void *p2)
	{
		User e1 = *(const User *) p1;
		User e2 = *(const User *) p2;
		return e1 < e2 ? -1 : e1 > e2 ? 1 : 0;
	}

	// Quick sort of the array elements
	static int __qsort(lua_State *state)
	{
		Type *user = Type::check(state);
		qsort(user->data, abs(user->size), sizeof(User), compare);
	}

	// Read as string from a file
	static int __fgets(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		// Buffer to store UTF-8 characters
		char data[user->size * MB_CUR_MAX];
		// Read from the file stream
		fgets(data, sizeof(data), file);
		// Conversion
		lux_Chars shift;
		ssize_t size = shift.to(user->data, data, sizeof(data));
		if (size < 0) return lux_perror(state);
		// Return bytes read
		lux_push(state, size);
		return 1;
	}

	// Write as string to a file
	static int __fputs(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		// Buffer to store UTF-8 characters
		char data[user->size * MB_CUR_MAX];
		// Conversion
		lux_Chars shift;
		ssize_t size = shift.from(data, user->data, user->size);
		if (size < 0) return lux_perror(state);
		// Write to the file stream
		data[size] = '\0';
		fputs(data, file);
		return 0;
	}

	// Read binary elements from a file
	static int __fread(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		size_t num = fread(user->data, user->size, sizeof(User), file);
		lux_push(state, num);
		return 1;
	}

	// Write binary elements to a file
	static int __fwrite(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		size_t num = fwrite(user->data, user->size, sizeof(User), file);
		lux_push(state, num);
		return 1;
	}

	// Loader compatible with luaL_requiref
	static int open(lua_State *state)
	{
		Type::name = lua_tostring(state, +1);
		luaL_newmetatable(state, Type::name);
		luaL_Reg regs [] =
		{
		{"new", __new},
		{"qsort", __qsort},
		{"fgets", __fgets},
		{"fputs", __fputs},
		{"fread", __fread},
		{"fwrite", __fwrite},
		{"__tostring", __tostring},
		{"__concat", __concat},
		{"__newindex", __newindex},
		{"__index", __index},
		{"__add", __add},
		{"__sub", __sub},
		{"__shl", __shl},
		{"__shr", __shr},
		{"__len", __len},
		{"__gc", __gc},
		{nullptr}
		};
		luaL_setfuncs(state, regs, 0);
		return 1;
	}
};

#endif // file

<commit_msg>Added operands for wqlexical comparison of arrays<commit_after>#ifndef __lxarray__
#define __lxarray__

#include "lxalloc.hpp"
#include "lxstore.hpp"
#include "lxstack.hpp"
#include "lxbuffs.hpp"
#include "lxchars.hpp"
#include "lxerror.hpp"

// Emulate C arrays/pointers in Lua

template <class User> struct lux_Array
{
	// Pointer storage implementation
	typedef lux_Store<User*> Type;

	// Array allocation function
	static int __new(lua_State *state)
	{
		lux_Chars shift;
		const char *string;
		ssize_t length;
		size_t size;
		User *data;
		// Constructor arguments
		switch (lua_type(state, 1))
		{
		  case LUA_TNIL:
		  case LUA_TNONE:
			data = nullptr;
			size = 0;
		  	break;
		  case LUA_TNUMBER:
			size = lux_to<int>(state, 1);
			data = new User [size];
			break;
		  case LUA_TTABLE:
			// Copy table contents
			size = luaL_len(state, 1);
			data = new User [size];
			lua_pushnil(state);
			for (int it = 0; lua_next(state, 1); ++it)
			{
			 data[it] = lux_to<User>(state, 3);
			 lua_pop(state, 1);
			}
			break;
		  case LUA_TSTRING:
			// Get UTF-8 encoded string with length
			string = lua_tolstring(state, 1, &size);
			length = shift.stringsize(string, size);
			// Check the string for encoding errors
			if (length < 0)	return lux_argerror(state, 1);
			else shift.reset();
			// Create and convert
			data = new User [length];
			size = shift.to(data, string, length);
			break;
		  default:
			return luaL_argerror(state, 1, "invalid type");
		};
		// Put the array on the stack
		Type::push(state, data, size);
		luaL_setmetatable(state, Type::name);
		return 1;
	}

	// Garbage collection callback
	static int __gc(lua_State *state)
	{
		Type *user = Type::check(state);
		// Owner's have non-negative sizes
		if (0 < user->size) delete [] user->data;
		return 0;
	}

	// Size of array or zero if pointer
	static int __len(lua_State *state)
	{
		Type *user = Type::check(state);
		lux_push(state, abs(user->size));
		return 1;
	}

	// Read array data at offset
	static int __index(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		lux_push(state, data[offset]);
		return 1;
	}

	// Write array data at offset
	static int __newindex(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		data[offset] = lux_to<User>(state, 3);
		return 0;
	}

	// String conversion for printing
	static int __tostring(lua_State *state)
	{
		Type *user = Type::check(state);
		size_t size = abs(user->size);
		// Build up a string
		lux_Buffer buffer(state);
		// Iterate over each item in the array
		for (auto item = 0; item < size; ++item)
		{
			// Add separator only after first
			if (item) buffer.addstring(", ");
			// Convert each element to string
			lux_push(state, user->data[item]);
			buffer.addvalue();
		}
		buffer.push();
		return 1;
	}

	// Concatenate arrays of same type
	static int __concat(lua_State *state)
	{
		Type *one = Type::check(state, 1);
		Type *two = Type::check(state, 2);
		// Genuine size of arrays
		size_t n = abs(one->size);
		size_t m = abs(two->size);
		// Pointers are valid?
		if (n > 0 and m > 0)
		{
			// Required storage
			size_t size = n + m;
			User *data = new User [size];
			// Push userdata onto stack
			new (state) Type(data, size);
			luaL_setmetatable(state, Type::name);
			// Copy contents of input arrays
			memcpy(data + n, two->data, m * sizeof(User));
			memcpy(data, one->data, n * sizeof(User));
			return 1;
		}
		return 0;
	}

	// Pointer addition arithmetic
	static int __add(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		lux_push(state, data + offset);
		return 1;
	}

	// Pointer subtraction arithmetic
	static int __sub(lua_State *state)
	{
		User *data = lux_to<User*>(state, 1);
		int offset = lux_to<int>(state, 2);
		lux_push(state, data - offset);
		return 1;
	}

	// Shift values left by given amount
	static int __shl(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		ssize_t shift = luaL_checkinteger(state, 2);
		// We only accept positive values for shifting
		luaL_argcheck(state, (shift > 0), 2, "shift > 0");
		// Proportions used in shift
		size_t size = abs(user->size);
		size_t n = shift % size;
		size_t m = size - n;
		// Copy parts into new array
		User *data = new User [size];
		memcpy(data, user->data + n, m * sizeof(User));
		memcpy(data + m, user->data, n * sizeof(User));
		// Put array onto the stack
		Type::push(state, data, size);
		luaL_setmetatable(state, Type::name);
		return 1;
	}

	// Shift values right by given amount
	static int __shr(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		ssize_t shift = luaL_checkinteger(state, 2);
		// We only accept positive values for shifting
		luaL_argcheck(state, (shift > 0), 2, "shift > 0");
		// Proportions used in shift
		size_t size = abs(user->size);
		size_t n = shift % size;
		size_t m = size - n;
		// Copy part into new array
		User *data = new User [size];
		memcpy(data, user->data + m, n * sizeof(User));
		memcpy(data + n, user->data, m * sizeof(User));
		// Put array onto the stack
		Type::push(state, data, size);
		luaL_setmetatable(state, Type::name);
		return 1;
	}

	// Quick sort of the array elements
	static int __qsort(lua_State *state)
	{
		// Element comparison operator used for quick sort
		auto compare = [](const void *p1, const void *p2)->int
		{
			// Cast to the userdata type
			User a = *(const User *) p1;
			User b = *(const User *) p2;
			// Compare as numeric values
			return a < b ? -1 : a > b ? +1 : 0;
		};
		Type *user = Type::check(state);
		qsort(user->data, abs(user->size), sizeof(User), compare);
	}

	// Check equality of elements
	static int __eq(lua_State *state)
	{
		Type *one = Type::check(state, 1);
		Type *two = Type::check(state, 2);
		// Are equal if pointers are
		if (one->data == two->data)
		{
			lux_push(state, true);
			return 1;
		}
		// Not equal if sizes aren't
		if (one->size != two->size)
		{
			lux_push(state, false);
			return 1;
		}
		size_t size = abs(one->size);
		// Now we check each of the members
		for (int item = 0; item < size; ++item)
		{
			// Not equal if any respective members don't
			if (one->data[item] not_eq two->data[item])
			{
				lux_push(state, false);
				return 1;
			}
		}
		// Must be equal
		lux_push(state, true);
		return 1;
	}

	// Lexical less than comparison
	static int __lt(lua_State *state)
	{
		Type *one = Type::check(state, 1);
		Type *two = Type::check(state, 2);
		// Genuine rray sizes
		size_t n = abs(one->size);
		size_t m = abs(two->size);
		// Find the smaller of them
		size_t size = n < m ? n : m;
		// Compare each respective element
		for (int item = 0; item < size; ++item)
		{
			// Return on first negative result
			if (one->data[item] >= two->data[item])
			{
				lux_push(state, false);
				return 1;
			}
		}
		lux_push(state, true);
		return 1;
	}

	// Lexical less than or equal
	static int __le(lua_State *state)
	{
		Type *one = Type::check(state, 1);
		Type *two = Type::check(state, 2);
		// Genuine rray sizes
		size_t n = abs(one->size);
		size_t m = abs(two->size);
		// Find the smaller of them
		size_t size = n < m ? n : m;
		// Compare each respective element
		for (int item = 0; item < size; ++item)
		{
			// Return on first negative result
			if (one->data[item] > two->data[item])
			{
				lux_push(state, false);
				return 1;
			}
		}
		lux_push(state, true);
		return 1;
	}

	// Read as string from a file
	static int __fgets(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		// Buffer to store UTF-8 characters
		char data[user->size * MB_CUR_MAX];
		// Read from the file stream
		fgets(data, sizeof(data), file);
		// Conversion
		lux_Chars shift;
		ssize_t size = shift.to(user->data, data, sizeof(data));
		if (size < 0) return lux_perror(state);
		// Return bytes read
		lux_push(state, size);
		return 1;
	}

	// Write as string to a file
	static int __fputs(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		// Buffer to store UTF-8 characters
		char data[user->size * MB_CUR_MAX];
		// Conversion
		lux_Chars shift;
		ssize_t size = shift.from(data, user->data, user->size);
		if (size < 0) return lux_perror(state);
		// Write to the file stream
		data[size] = '\0';
		fputs(data, file);
		return 0;
	}

	// Read binary elements from a file
	static int __fread(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		size_t num = fread(user->data, user->size, sizeof(User), file);
		lux_push(state, num);
		return 1;
	}

	// Write binary elements to a file
	static int __fwrite(lua_State *state)
	{
		Type *user = Type::check(state, 1);
		FILE *file = lux_to<FILE*>(state, 2);
		size_t num = fwrite(user->data, user->size, sizeof(User), file);
		lux_push(state, num);
		return 1;
	}

	// Loader compatible with luaL_requiref
	static int open(lua_State *state)
	{
		Type::name = lua_tostring(state, +1);
		luaL_newmetatable(state, Type::name);
		luaL_Reg regs [] =
		{
		{"new", __new},
		{"qsort", __qsort},
		{"fgets", __fgets},
		{"fputs", __fputs},
		{"fread", __fread},
		{"fwrite", __fwrite},
		{"__tostring", __tostring},
		{"__concat", __concat},
		{"__newindex", __newindex},
		{"__index", __index},
		{"__add", __add},
		{"__sub", __sub},
		{"__shl", __shl},
		{"__shr", __shr},
		{"__len", __len},
		{"__eq", __eq},
		{"__lt", __lt},
		{"__le", __le},
		{"__gc", __gc},
		{nullptr}
		};
		luaL_setfuncs(state, regs, 0);
		return 1;
	}
};

#endif // file

<|endoftext|>


<commit_before>/** -*- mode: C++ -*-
 * Copyright (c) 2004 David Faure <faure@kde.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of this program with any edition of
 *  the Qt library by Trolltech AS, Norway (or with modified versions
 *  of Qt that use the same license as Qt), and distribute linked
 *  combinations including the two.  You must obey the GNU General
 *  Public License in all respects for all of the code used other than
 *  Qt.  If you modify this file, you may extend this exception to
 *  your version of the file, but you are not obligated to do so.  If
 *  you do not wish to do so, delete this exception statement from
 *  your version.
 */

#include "accountcombobox.h"
#include "kmkernel.h"
#include "kmfolder.h"
#include "kmfolderdir.h"
#include "kmacctmgr.h"

using namespace KMail;

AccountComboBox::AccountComboBox( bool needsInbox, QWidget* parent, const char* name )
  : QComboBox( parent, name ), mNeedsInbox( needsInbox )
{
  // Currently there's no auto-refresh of the account list,
  // since this combo is only used within the configuration dialog itself
  // OK it could be useful when using Apply - TODO: signal from kmacctmgr
  slotRefreshAccounts();
}

void AccountComboBox::slotRefreshAccounts()
{
  clear();
  // Note that this won't take into account newly-created-in-configuredialog accounts
  // until clicking OK or Apply. This would make this class much more complex
  // (this would have to be different depending on whether this combo is in the
  // configuration dialog or not...)
  QStringList accountNames;
  QValueList<KMAccount *> lst = applicableAccounts();
  QValueList<KMAccount *>::ConstIterator it = lst.begin();
  for ( ; it != lst.end() ; ++it )
    accountNames.append( (*it)->name() );
  insertStringList( accountNames );
}

void AccountComboBox::setCurrentAccount( KMAccount* account )
{
  int i = 0;
  for( KMAccount *a = kmkernel->acctMgr()->first(); a;
       a = kmkernel->acctMgr()->next(), ++i ) {
    if ( a == account ) {
      setCurrentItem( i );
      return;
    }
  }
}

KMAccount* AccountComboBox::currentAccount() const
{
  int i = 0;
  QValueList<KMAccount *> lst = applicableAccounts();
  QValueList<KMAccount *>::ConstIterator it = lst.begin();
  while ( it != lst.end() && i < currentItem() ) {
    ++it;
    ++i;
  }
  return *it;
}

QValueList<KMAccount *> KMail::AccountComboBox::applicableAccounts() const
{
  QValueList<KMAccount *> lst;
  for( KMAccount *a = kmkernel->acctMgr()->first(); a;
       a = kmkernel->acctMgr()->next() ) {
    if ( a && a->folder() ) {
      bool ok = false;
      if ( mNeedsInbox ) {
        KMFolderNode *node;
        for (node = a->folder()->child()->first(); node; node = a->folder()->child()->next())
          if (!node->isDir() && node->name() == "INBOX") {
            ok = true;
            break;
          }
      } else
        ok = true;
      if ( ok )
        lst.append( a );
    }
  }
  return lst;
}

#include "accountcombobox.moc"
<commit_msg>Don't crash<commit_after>/** -*- mode: C++ -*-
 * Copyright (c) 2004 David Faure <faure@kde.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of this program with any edition of
 *  the Qt library by Trolltech AS, Norway (or with modified versions
 *  of Qt that use the same license as Qt), and distribute linked
 *  combinations including the two.  You must obey the GNU General
 *  Public License in all respects for all of the code used other than
 *  Qt.  If you modify this file, you may extend this exception to
 *  your version of the file, but you are not obligated to do so.  If
 *  you do not wish to do so, delete this exception statement from
 *  your version.
 */

#include "accountcombobox.h"
#include "kmkernel.h"
#include "kmfolder.h"
#include "kmfolderdir.h"
#include "kmacctmgr.h"

using namespace KMail;

AccountComboBox::AccountComboBox( bool needsInbox, QWidget* parent, const char* name )
  : QComboBox( parent, name ), mNeedsInbox( needsInbox )
{
  // Currently there's no auto-refresh of the account list,
  // since this combo is only used within the configuration dialog itself
  // OK it could be useful when using Apply - TODO: signal from kmacctmgr
  slotRefreshAccounts();
}

void AccountComboBox::slotRefreshAccounts()
{
  clear();
  // Note that this won't take into account newly-created-in-configuredialog accounts
  // until clicking OK or Apply. This would make this class much more complex
  // (this would have to be different depending on whether this combo is in the
  // configuration dialog or not...)
  QStringList accountNames;
  QValueList<KMAccount *> lst = applicableAccounts();
  QValueList<KMAccount *>::ConstIterator it = lst.begin();
  for ( ; it != lst.end() ; ++it )
    accountNames.append( (*it)->name() );
  insertStringList( accountNames );
}

void AccountComboBox::setCurrentAccount( KMAccount* account )
{
  int i = 0;
  for( KMAccount *a = kmkernel->acctMgr()->first(); a;
       a = kmkernel->acctMgr()->next(), ++i ) {
    if ( a == account ) {
      setCurrentItem( i );
      return;
    }
  }
}

KMAccount* AccountComboBox::currentAccount() const
{
  int i = 0;
  QValueList<KMAccount *> lst = applicableAccounts();
  QValueList<KMAccount *>::ConstIterator it = lst.begin();
  while ( it != lst.end() && i < currentItem() ) {
    ++it;
    ++i;
  }
  return *it;
}

QValueList<KMAccount *> KMail::AccountComboBox::applicableAccounts() const
{
  QValueList<KMAccount *> lst;
  for( KMAccount *a = kmkernel->acctMgr()->first(); a;
       a = kmkernel->acctMgr()->next() ) {
    if ( a && a->folder() ) {
      bool ok = false;
      if ( mNeedsInbox ) {
        KMFolderDir* child = a->folder()->child();
        if ( child ) {
          for (KMFolderNode* node = child->first(); node; node = child->next())
            if (!node->isDir() && node->name() == "INBOX") {
              ok = true;
              break;
            }
        }
      } else
        ok = true;
      if ( ok )
        lst.append( a );
    }
  }
  return lst;
}

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


<commit_before>#include "PriorFactory.h"

#include <Eigen/Core>

#include <SmurffCpp/Priors/NormalPrior.h>
#include <SmurffCpp/Priors/NormalOnePrior.h>
#include <SmurffCpp/Priors/SpikeAndSlabPrior.h>

#include <SmurffCpp/Utils/Error.h>

#include <SmurffCpp/SideInfo/DenseDoubleFeatSideInfo.h>
#include <SmurffCpp/SideInfo/SparseDoubleFeatSideInfo.h>
#include <SmurffCpp/SideInfo/SparseFeatSideInfo.h>

#include <SmurffCpp/Utils/MatrixUtils.h>

using namespace smurff;
using namespace Eigen;

//create macau prior features

std::shared_ptr<ISideInfo> PriorFactory::side_info_config_to_dense_features(std::shared_ptr<MatrixConfig> sideinfoConfig, int mode)
{
   Eigen::MatrixXd sideinfo = matrix_utils::dense_to_eigen(*sideinfoConfig);
   auto side_info_ptr = std::make_shared<Eigen::MatrixXd>(sideinfo);
   return std::make_shared<DenseDoubleFeatSideInfo>(side_info_ptr);
}

std::shared_ptr<ISideInfo> PriorFactory::side_info_config_to_sparse_binary_features(std::shared_ptr<MatrixConfig> sideinfoConfig, int mode)
{
   std::uint64_t nrow = sideinfoConfig->getNRow();
   std::uint64_t ncol = sideinfoConfig->getNCol();
   std::uint64_t nnz = sideinfoConfig->getNNZ();

   std::shared_ptr<std::vector<std::uint32_t> > rows = sideinfoConfig->getRowsPtr();
   std::shared_ptr<std::vector<std::uint32_t> > cols = sideinfoConfig->getColsPtr();

   // Temporary solution. As soon as SparseFeat works with vectors instead of pointers,
   // we will remove these extra memory allocation and manipulation
   int* rowsRawPtr = new int[nnz];
   int* colsRawPtr = new int[nnz];
   for (std::uint64_t i = 0; i < nnz; i++)
   {
      rowsRawPtr[i] = rows->operator[](i);
      colsRawPtr[i] = cols->operator[](i);
   }

   auto side_info_ptr = std::make_shared<SparseFeat>(nrow, ncol, nnz, rowsRawPtr, colsRawPtr);
   return std::make_shared<SparseFeatSideInfo>(side_info_ptr);
}

std::shared_ptr<ISideInfo> PriorFactory::side_info_config_to_sparse_features(std::shared_ptr<MatrixConfig> sideinfoConfig, int mode)
{
   std::uint64_t nrow = sideinfoConfig->getNRow();
   std::uint64_t ncol = sideinfoConfig->getNCol();
   std::uint64_t nnz = sideinfoConfig->getNNZ();

   const auto& rows   = sideinfoConfig->getRows();
   const auto& cols   = sideinfoConfig->getCols();
   const auto& values = sideinfoConfig->getValues();

   // Temporary solution. As soon as SparseDoubleFeat works with vectorsor shared pointers instead of raw pointers,
   // we will remove these extra memory allocation and manipulation
   int* rowsRawPtr = new int[nnz];
   int* colsRawPtr = new int[nnz];
   double* valuesRawPtr = new double[nnz];
   for (size_t i = 0; i < nnz; i++)
   {
      rowsRawPtr[i] = rows[i];
      colsRawPtr[i] = cols[i];
      valuesRawPtr[i] = values[i];
   }

   auto side_info_ptr = std::make_shared<SparseDoubleFeat>(nrow, ncol, nnz, rowsRawPtr, colsRawPtr, valuesRawPtr);
   return std::make_shared<SparseDoubleFeatSideInfo>(side_info_ptr);
}

//-------

std::shared_ptr<ILatentPrior> PriorFactory::create_macau_prior(std::shared_ptr<Session> session, PriorTypes prior_type,
   const std::vector<std::shared_ptr<ISideInfo> >& side_infos,
   const std::vector<std::shared_ptr<SideInfoConfig> >& config_items)
{
   if(prior_type == PriorTypes::macau || prior_type == PriorTypes::default_prior)
   {
      return create_macau_prior<MacauPrior>(session, side_infos, config_items);
   }
   else if(prior_type == PriorTypes::macauone)
   {
      return create_macau_prior<MacauOnePrior>(session, side_infos, config_items);
   }
   else
   {
      THROWERROR("Unknown prior with side info: " + priorTypeToString(prior_type));
   }
}

std::shared_ptr<ILatentPrior> PriorFactory::create_prior(std::shared_ptr<Session> session, int mode)
{
   PriorTypes priorType = session->getConfig().getPriorTypes().at(mode);

   switch(priorType)
   {
   case PriorTypes::normal:
   case PriorTypes::default_prior:
      return std::shared_ptr<NormalPrior>(new NormalPrior(session, -1));
   case PriorTypes::spikeandslab:
      return std::shared_ptr<SpikeAndSlabPrior>(new SpikeAndSlabPrior(session, -1));
   case PriorTypes::normalone:
      return std::shared_ptr<NormalOnePrior>(new NormalOnePrior(session, -1));
   case PriorTypes::macau:
   case PriorTypes::macauone:
      return create_macau_prior<PriorFactory>(session, mode, priorType, session->getConfig().getSideInfoConfigs(mode));
   default:
      {
         THROWERROR("Unknown prior: " + priorTypeToString(priorType));
      }
   }
}
<commit_msg>Don't copy to init sideinfo<commit_after>#include "PriorFactory.h"

#include <Eigen/Core>

#include <SmurffCpp/Priors/NormalPrior.h>
#include <SmurffCpp/Priors/NormalOnePrior.h>
#include <SmurffCpp/Priors/SpikeAndSlabPrior.h>

#include <SmurffCpp/Utils/Error.h>

#include <SmurffCpp/SideInfo/DenseDoubleFeatSideInfo.h>
#include <SmurffCpp/SideInfo/SparseDoubleFeatSideInfo.h>
#include <SmurffCpp/SideInfo/SparseFeatSideInfo.h>

#include <SmurffCpp/Utils/MatrixUtils.h>

using namespace smurff;
using namespace Eigen;

//create macau prior features

std::shared_ptr<ISideInfo> PriorFactory::side_info_config_to_dense_features(std::shared_ptr<MatrixConfig> sideinfoConfig, int mode)
{
   auto side_info_ptr = std::make_shared<Eigen::MatrixXd>(matrix_utils::dense_to_eigen(*sideinfoConfig));
   return std::make_shared<DenseDoubleFeatSideInfo>(side_info_ptr);
}

std::shared_ptr<ISideInfo> PriorFactory::side_info_config_to_sparse_binary_features(std::shared_ptr<MatrixConfig> sideinfoConfig, int mode)
{
   std::uint64_t nrow = sideinfoConfig->getNRow();
   std::uint64_t ncol = sideinfoConfig->getNCol();
   std::uint64_t nnz = sideinfoConfig->getNNZ();

   const std::uint32_t* rows = sideinfoConfig->getRows().data();
   const std::uint32_t* cols = sideinfoConfig->getCols().data();

   auto side_info_ptr = std::make_shared<SparseFeat>(nrow, ncol, nnz, (int *)rows,  (int *)cols);
   return std::make_shared<SparseFeatSideInfo>(side_info_ptr);
}

std::shared_ptr<ISideInfo> PriorFactory::side_info_config_to_sparse_features(std::shared_ptr<MatrixConfig> sideinfoConfig, int mode)
{
   std::uint64_t nrow = sideinfoConfig->getNRow();
   std::uint64_t ncol = sideinfoConfig->getNCol();
   std::uint64_t nnz = sideinfoConfig->getNNZ();

   const std::uint32_t* rows = sideinfoConfig->getRows().data();
   const std::uint32_t* cols = sideinfoConfig->getCols().data();
   const double*        vals = sideinfoConfig->getValues().data();

   auto side_info_ptr = std::make_shared<SparseDoubleFeat>(nrow, ncol, nnz, (int *)rows, (int *)cols, (double *)vals);
   return std::make_shared<SparseDoubleFeatSideInfo>(side_info_ptr);
}

//-------

std::shared_ptr<ILatentPrior> PriorFactory::create_macau_prior(std::shared_ptr<Session> session, PriorTypes prior_type,
   const std::vector<std::shared_ptr<ISideInfo> >& side_infos,
   const std::vector<std::shared_ptr<SideInfoConfig> >& config_items)
{
   if(prior_type == PriorTypes::macau || prior_type == PriorTypes::default_prior)
   {
      return create_macau_prior<MacauPrior>(session, side_infos, config_items);
   }
   else if(prior_type == PriorTypes::macauone)
   {
      return create_macau_prior<MacauOnePrior>(session, side_infos, config_items);
   }
   else
   {
      THROWERROR("Unknown prior with side info: " + priorTypeToString(prior_type));
   }
}

std::shared_ptr<ILatentPrior> PriorFactory::create_prior(std::shared_ptr<Session> session, int mode)
{
   PriorTypes priorType = session->getConfig().getPriorTypes().at(mode);

   switch(priorType)
   {
   case PriorTypes::normal:
   case PriorTypes::default_prior:
      return std::shared_ptr<NormalPrior>(new NormalPrior(session, -1));
   case PriorTypes::spikeandslab:
      return std::shared_ptr<SpikeAndSlabPrior>(new SpikeAndSlabPrior(session, -1));
   case PriorTypes::normalone:
      return std::shared_ptr<NormalOnePrior>(new NormalOnePrior(session, -1));
   case PriorTypes::macau:
   case PriorTypes::macauone:
      return create_macau_prior<PriorFactory>(session, mode, priorType, session->getConfig().getSideInfoConfigs(mode));
   default:
      {
         THROWERROR("Unknown prior: " + priorTypeToString(priorType));
      }
   }
}
<|endoftext|>


<commit_before>/*
    knarticlewindow.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <kwin.h>

#include <kstdaction.h>
#include <kedittoolbar.h>
#include <kkeydialog.h>
#include <kconfig.h>
#include <kaccel.h>
#include <kaction.h>

#include "knarticle.h"
#include "knarticlewidget.h"
#include "utilities.h"
#include "knglobals.h"
#include "knode.h"
#include "knarticlewindow.h"
#include <qpopupmenu.h>

QPtrList<KNArticleWindow> KNArticleWindow::instances;

bool KNArticleWindow::closeAllWindowsForCollection(KNArticleCollection *col, bool force)
{
  QPtrList<KNArticleWindow> list=instances;
  for(KNArticleWindow *i=list.first(); i; i=list.next())
    if(i->artW->article()->collection()==col) {
      if (force)
        i->close();
      else
        return false;
    }
  return true;
}

bool KNArticleWindow::closeAllWindowsForArticle(KNArticle *art, bool force)
{
  QPtrList<KNArticleWindow> list=instances;
  for(KNArticleWindow *i=list.first(); i; i=list.next())
    if(i->artW->article()==art) {
      if (force)
        i->close();
      else
        return false;
    }
  return true;
}

bool KNArticleWindow::raiseWindowForArticle(KNArticle *art)
{
  bool ret=false;
  for(KNArticleWindow *i=instances.first(); i; i=instances.next())
    if(i->artW->article()==art) {
      KWin::setActiveWindow(i->winId());
      ret = true;
      break;
    }
  return ret;
}

bool KNArticleWindow::raiseWindowForArticle(const QCString &mid)
{
  bool ret=false;
  for(KNArticleWindow *i=instances.first(); i; i=instances.next())
    if(i->artW->article()->messageID()->as7BitString(false)==mid) {
      KWin::setActiveWindow(i->winId());
      ret = true;
      break;
    }
  return ret;
}

//==================================================================================

KNArticleWindow::KNArticleWindow(KNArticle *art)
  : KMainWindow(0, "articleWindow")
{
  instances.append(this);

  if(art)
    setCaption(art->subject()->asUnicodeString());

  artW=new KNArticleWidget(actionCollection(),this);
  artW->setArticle(art);
  setCentralWidget(artW);

  // file menu
  KStdAction::close(this, SLOT(slotFileClose()),actionCollection());

  // settings menu
  a_ctShowToolbar = KStdAction::showToolbar(this, SLOT(slotToggleToolBar()), actionCollection());
  KStdAction::keyBindings(this, SLOT(slotConfKeys()), actionCollection());
  KStdAction::configureToolbars(this, SLOT(slotConfToolbar()), actionCollection());
  KStdAction::preferences(knGlobals.top, SLOT(slotSettings()), actionCollection());

  a_ccel=new KAccel(this);
  artW->setCharsetKeyboardAction()->plugAccel(a_ccel);

  createGUI("knreaderui.rc");
  QPopupMenu *pop = static_cast<QPopupMenu *>(factory()->container("body_popup", this));
  if (!pop) pop = new QPopupMenu(this);
  artW->setBodyPopup(pop);

  KConfig *conf = KGlobal::config();
  conf->setGroup("articleWindow_options");
  resize(500,400);    // default optimized for 800x600
  applyMainWindowSettings(conf);
  a_ctShowToolbar->setChecked(!toolBar()->isHidden());
}

KNArticleWindow::~KNArticleWindow()
{
  instances.removeRef(this);
  KConfig *conf = KGlobal::config();
  conf->setGroup("articleWindow_options");
  saveMainWindowSettings(conf);
}

void KNArticleWindow::slotFileClose()
{
  close();
}

void KNArticleWindow::slotToggleToolBar()
{
  if(toolBar()->isVisible())
    toolBar()->hide();
  else
    toolBar()->show();
}

void KNArticleWindow::slotConfKeys()
{
  KKeyDialog::configureKeys(actionCollection(), xmlFile(), true, this);
}

void KNArticleWindow::slotConfToolbar()
{
  KEditToolbar *dlg = new KEditToolbar(guiFactory(),this);
  if (dlg->exec()) {
    createGUI("knreaderui.rc");
    QPopupMenu *pop = static_cast<QPopupMenu *>(factory()->container("body_popup", this));
    if (!pop) pop = new QPopupMenu(this);
    artW->setBodyPopup(pop);
  }
  delete dlg;
}

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

#include "knarticlewindow.moc"
<commit_msg>fix the "random" crashes of knode. Happened after viewing a missing article in an external window. Reviewed by Christian Gebauer<commit_after>// -*- c-basic-offset: 2 -*-
/*
    knarticlewindow.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <kwin.h>

#include <kstdaction.h>
#include <kedittoolbar.h>
#include <kkeydialog.h>
#include <kconfig.h>
#include <kaccel.h>
#include <kaction.h>

#include "knarticle.h"
#include "knarticlewidget.h"
#include "utilities.h"
#include "knglobals.h"
#include "knode.h"
#include "knarticlewindow.h"
#include <qpopupmenu.h>

QPtrList<KNArticleWindow> KNArticleWindow::instances;

bool KNArticleWindow::closeAllWindowsForCollection(KNArticleCollection *col, bool force)
{
  QPtrList<KNArticleWindow> list=instances;
  for(KNArticleWindow *i=list.first(); i; i=list.next())
    if(i->artW->article() && i->artW->article()->collection()==col) {
      if (force)
        i->close();
      else
        return false;
    }
  return true;
}

bool KNArticleWindow::closeAllWindowsForArticle(KNArticle *art, bool force)
{
  QPtrList<KNArticleWindow> list=instances;
  for(KNArticleWindow *i=list.first(); i; i=list.next())
    if(i->artW->article() && i->artW->article() == art) {
      if (force)
        i->close();
      else
        return false;
    }
  return true;
}

bool KNArticleWindow::raiseWindowForArticle(KNArticle *art)
{
  for(KNArticleWindow *i=instances.first(); i; i=instances.next())
    if(i->artW->article() && i->artW->article() ==art) {
      KWin::setActiveWindow(i->winId());
      return true;
    }
  return false;
}

bool KNArticleWindow::raiseWindowForArticle(const QCString &mid)
{
  for(KNArticleWindow *i=instances.first(); i; i=instances.next())
    if(i->artW->article() && i->artW->article()->messageID()->as7BitString(false)==mid) {
      KWin::setActiveWindow(i->winId());
      return true;
    }

  return false;
}

//==================================================================================

KNArticleWindow::KNArticleWindow(KNArticle *art)
  : KMainWindow(0, "articleWindow")
{
  if(art)
    setCaption(art->subject()->asUnicodeString());

  artW=new KNArticleWidget(actionCollection(),this);
  artW->setArticle(art);
  setCentralWidget(artW);

  instances.append(this);

  // file menu
  KStdAction::close(this, SLOT(slotFileClose()),actionCollection());

  // settings menu
  a_ctShowToolbar = KStdAction::showToolbar(this, SLOT(slotToggleToolBar()), actionCollection());
  KStdAction::keyBindings(this, SLOT(slotConfKeys()), actionCollection());
  KStdAction::configureToolbars(this, SLOT(slotConfToolbar()), actionCollection());
  KStdAction::preferences(knGlobals.top, SLOT(slotSettings()), actionCollection());

  a_ccel=new KAccel(this);
  artW->setCharsetKeyboardAction()->plugAccel(a_ccel);

  createGUI("knreaderui.rc");
  QPopupMenu *pop = static_cast<QPopupMenu *>(factory()->container("body_popup", this));
  if (!pop) pop = new QPopupMenu(this);
  artW->setBodyPopup(pop);

  KConfig *conf = KGlobal::config();
  conf->setGroup("articleWindow_options");
  resize(500,400);    // default optimized for 800x600
  applyMainWindowSettings(conf);
  a_ctShowToolbar->setChecked(!toolBar()->isHidden());
}

KNArticleWindow::~KNArticleWindow()
{
  instances.removeRef(this);
  KConfig *conf = KGlobal::config();
  conf->setGroup("articleWindow_options");
  saveMainWindowSettings(conf);
}

void KNArticleWindow::slotFileClose()
{
  close();
}

void KNArticleWindow::slotToggleToolBar()
{
  if(toolBar()->isVisible())
    toolBar()->hide();
  else
    toolBar()->show();
}

void KNArticleWindow::slotConfKeys()
{
  KKeyDialog::configureKeys(actionCollection(), xmlFile(), true, this);
}

void KNArticleWindow::slotConfToolbar()
{
  KEditToolbar *dlg = new KEditToolbar(guiFactory(),this);
  if (dlg->exec()) {
    createGUI("knreaderui.rc");
    QPopupMenu *pop = static_cast<QPopupMenu *>(factory()->container("body_popup", this));
    if (!pop) pop = new QPopupMenu(this);
    artW->setBodyPopup(pop);
  }
  delete dlg;
}

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

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


<commit_before>/*
    This file is part of KOrganizer.

    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
    Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QObject>

#include <libkdepim/kdepimprotocols.h>

#include "urihandler.h"

#ifndef KORG_NODBUS
#include <knodeinterface.h>
#include <kmailinterface.h>
#include <korganizerinterface.h>
#include <coreinterface.h>
#endif

#include <kiconloader.h>
#include <krun.h>
#include <kapplication.h>
#include <kprocess.h>
#include <kdebug.h>
#include <ktoolinvocation.h>

bool UriHandler::process( const QString &uri )
{
  kDebug(5850) << "UriHandler::process(): " << uri << endl;

#ifndef KORG_NODBUS
  if ( uri.startsWith( KDEPIMPROTOCOL_EMAIL ) ) {
    // make sure kmail is running or the part is shown
    KToolInvocation::startServiceByDesktopPath("kmail");

    // parse string, show
    int colon = uri.indexOf( ':' );
    // extract 'number' from 'kmail:<number>/<id>'
    QString serialNumberStr = uri.mid( colon + 1 );
    serialNumberStr = serialNumberStr.left( serialNumberStr.indexOf( '/' ) );

    org::kde::kmail::kmail kmail("org.kde.kmail", "/KMail", QDBusConnection::sessionBus());
    kmail.showMail( serialNumberStr.toUInt(), QString() );
    return true;
  } else if ( uri.startsWith( "mailto:" ) ) {
    KToolInvocation::invokeMailer( uri.mid(7), QString() );
    return true;
  } else if ( uri.startsWith( KDEPIMPROTOCOL_CONTACT ) ) {
    if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kaddressbook") ) {
      kapp->updateRemoteUserTimestamp("kaddressbook");
      org::kde::KAddressbook::Core kaddressbook("org.kde.kaddressbook", "/KAddressBook", QDBusConnection::sessionBus());
      kaddressbook.showContactEditor(uri.mid( ::qstrlen( KDEPIMPROTOCOL_CONTACT ) ) );
      return true;
    } else {
      /*
        KaddressBook is not already running.  Pass it the UID of the contact via the command line while starting it - its neater.
        We start it without its main interface
      */
      KIconLoader *iconLoader = new KIconLoader();
      QString iconPath = KIconLoader::global()->iconPath( "go", K3Icon::Small );
      QString tmpStr = "kaddressbook --editor-only --uid ";
      tmpStr += KProcess::quote( uri.mid( ::qstrlen( KDEPIMPROTOCOL_CONTACT ) )
      );
      KRun::runCommand( tmpStr, "KAddressBook", iconPath );
      return true;
    }
  } else if ( uri.startsWith( KDEPIMPROTOCOL_INCIDENCE ) ) {
    // make sure korganizer is running or the part is shown
    KToolInvocation::startServiceByDesktopPath("korganizer");

    // we must work around KUrl breakage (it doesn't know about URNs)
    QString uid = KUrl::fromPercentEncoding( uri.toLatin1() ).mid( 11 );
    OrgKdeKorganizerKorganizerInterface korganizerIface("org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );

    return korganizerIface.showIncidence( uid );
  } else if ( uri.startsWith( KDEPIMPROTOCOL_NEWSARTICLE ) ) {
    KToolInvocation::startServiceByDesktopPath( "knode" );
    org::kde::knode knode("org.kde.knode", "/KNode", QDBusConnection::sessionBus());
    knode.openURL(uri);
  } else {  // no special URI, let KDE handle it
    new KRun(KUrl( uri ),0L);
  }
#endif /* KORG_NODBUS */

  return false;
}
<commit_msg>don't leak a KIconLoader<commit_after>/*
    This file is part of KOrganizer.

    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
    Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>

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

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QObject>

#include <libkdepim/kdepimprotocols.h>

#include "urihandler.h"

#ifndef KORG_NODBUS
#include <knodeinterface.h>
#include <kmailinterface.h>
#include <korganizerinterface.h>
#include <coreinterface.h>
#endif

#include <kiconloader.h>
#include <krun.h>
#include <kapplication.h>
#include <kprocess.h>
#include <kdebug.h>
#include <ktoolinvocation.h>

bool UriHandler::process( const QString &uri )
{
  kDebug(5850) << "UriHandler::process(): " << uri << endl;

#ifndef KORG_NODBUS
  if ( uri.startsWith( KDEPIMPROTOCOL_EMAIL ) ) {
    // make sure kmail is running or the part is shown
    KToolInvocation::startServiceByDesktopPath("kmail");

    // parse string, show
    int colon = uri.indexOf( ':' );
    // extract 'number' from 'kmail:<number>/<id>'
    QString serialNumberStr = uri.mid( colon + 1 );
    serialNumberStr = serialNumberStr.left( serialNumberStr.indexOf( '/' ) );

    org::kde::kmail::kmail kmail("org.kde.kmail", "/KMail", QDBusConnection::sessionBus());
    kmail.showMail( serialNumberStr.toUInt(), QString() );
    return true;
  } else if ( uri.startsWith( "mailto:" ) ) {
    KToolInvocation::invokeMailer( uri.mid(7), QString() );
    return true;
  } else if ( uri.startsWith( KDEPIMPROTOCOL_CONTACT ) ) {
    if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kaddressbook") ) {
      kapp->updateRemoteUserTimestamp("kaddressbook");
      org::kde::KAddressbook::Core kaddressbook("org.kde.kaddressbook", "/KAddressBook", QDBusConnection::sessionBus());
      kaddressbook.showContactEditor(uri.mid( ::qstrlen( KDEPIMPROTOCOL_CONTACT ) ) );
      return true;
    } else {
      /*
        KaddressBook is not already running.  Pass it the UID of the contact via the command line while starting it - its neater.
        We start it without its main interface
      */
      QString iconPath = KIconLoader::global()->iconPath( "go", K3Icon::Small );
      QString tmpStr = "kaddressbook --editor-only --uid ";
      tmpStr += KProcess::quote( uri.mid( ::qstrlen( KDEPIMPROTOCOL_CONTACT ) )
      );
      KRun::runCommand( tmpStr, "KAddressBook", iconPath );
      return true;
    }
  } else if ( uri.startsWith( KDEPIMPROTOCOL_INCIDENCE ) ) {
    // make sure korganizer is running or the part is shown
    KToolInvocation::startServiceByDesktopPath("korganizer");

    // we must work around KUrl breakage (it doesn't know about URNs)
    QString uid = KUrl::fromPercentEncoding( uri.toLatin1() ).mid( 11 );
    OrgKdeKorganizerKorganizerInterface korganizerIface("org.kde.korganizer", "/Korganizer", QDBusConnection::sessionBus() );

    return korganizerIface.showIncidence( uid );
  } else if ( uri.startsWith( KDEPIMPROTOCOL_NEWSARTICLE ) ) {
    KToolInvocation::startServiceByDesktopPath( "knode" );
    org::kde::knode knode("org.kde.knode", "/KNode", QDBusConnection::sessionBus());
    knode.openURL(uri);
  } else {  // no special URI, let KDE handle it
    new KRun(KUrl( uri ),0L);
  }
#endif /* KORG_NODBUS */

  return false;
}
<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "kinematics-precomp.h"  // Precompiled header

#include <mrpt/kinematics/CVehicleSimulVirtualBase.h>
#include <mrpt/math/wrap2pi.h>
#include <mrpt/random.h>

using namespace mrpt::kinematics;

CVehicleSimulVirtualBase::CVehicleSimulVirtualBase() :
m_firmware_control_period(500e-6), m_use_odo_error(false)
{
}

CVehicleSimulVirtualBase::~CVehicleSimulVirtualBase()
{
}

void CVehicleSimulVirtualBase::setCurrentGTPose(const mrpt::math::TPose2D  &pose)
{
	m_GT_pose=pose;
}

void CVehicleSimulVirtualBase::simulateOneTimeStep(const double dt)
{
	using mrpt::poses::CPose2D;
	const double final_t = m_time + dt;
	while (m_time <= final_t)
	{
		// Simulate movement during At:
		CPose2D nextOdometry(mrpt::poses::UNINITIALIZED_POSE), nextGT(mrpt::poses::UNINITIALIZED_POSE);
		nextOdometry.composeFrom(CPose2D(m_odometry),
			CPose2D (
				m_odometric_vel.vx*m_firmware_control_period,
				m_odometric_vel.vy*m_firmware_control_period,
				m_odometric_vel.omega*m_firmware_control_period
			));
		nextGT.composeFrom(CPose2D(m_GT_pose),
			CPose2D(
				m_GT_vel.vx*m_firmware_control_period,
				m_GT_vel.vy*m_firmware_control_period,
				m_GT_vel.omega*m_firmware_control_period
			));
		nextOdometry.phi(mrpt::math::wrapToPi(nextOdometry.phi()));
		nextGT.phi(mrpt::math::wrapToPi(nextGT.phi()));

		this->internal_simulControlStep(m_firmware_control_period);

		//Now rotate our current Odo velocity into GT coordinates
		m_GT_vel = getCurrentOdometricVelLocal();
		m_GT_vel.rotate(m_GT_pose.phi);

		//Add some errors
		if (m_use_odo_error)
		{
			m_GT_vel.vx    -= m_Ax_err_bias   + m_Ax_err_std * mrpt::random::randomGenerator.drawGaussian1D_normalized();
			m_GT_vel.vy    -= m_Ay_err_bias   + m_Ay_err_std * mrpt::random::randomGenerator.drawGaussian1D_normalized();
			m_GT_vel.omega -= m_Aphi_err_bias + m_Aphi_err_std * mrpt::random::randomGenerator.drawGaussian1D_normalized();
		}

		m_odometry = nextOdometry;
		m_GT_pose = nextGT;

		m_time += m_firmware_control_period; // Move forward

	}
}

void CVehicleSimulVirtualBase::resetStatus()
{
	m_GT_pose= mrpt::math::TPose2D(.0,.0,.0);
	m_GT_vel = mrpt::math::TTwist2D(.0,.0,.0);
	m_odometry = mrpt::math::TPose2D(.0,.0,.0);
	m_odometric_vel = mrpt::math::TTwist2D(.0,.0,.0);
	internal_clear();
}

void CVehicleSimulVirtualBase::resetTime()
{
	m_time = .0;
}

mrpt::math::TTwist2D CVehicleSimulVirtualBase::getCurrentGTVelLocal() const
{
	mrpt::math::TTwist2D tl = this->m_GT_vel;
	tl.rotate(-m_GT_pose.phi);
	return tl;
}

mrpt::math::TTwist2D CVehicleSimulVirtualBase::getCurrentOdometricVelLocal() const
{
	mrpt::math::TTwist2D tl = this->m_odometric_vel;
	tl.rotate(-m_odometry.phi);
	return tl;
}
<commit_msg>apply odometry errors to pose, not velocity<commit_after>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "kinematics-precomp.h"  // Precompiled header

#include <mrpt/kinematics/CVehicleSimulVirtualBase.h>
#include <mrpt/math/wrap2pi.h>
#include <mrpt/random.h>

using namespace mrpt::kinematics;

CVehicleSimulVirtualBase::CVehicleSimulVirtualBase() :
m_firmware_control_period(500e-6), m_use_odo_error(false)
{
}

CVehicleSimulVirtualBase::~CVehicleSimulVirtualBase()
{
}

void CVehicleSimulVirtualBase::setCurrentGTPose(const mrpt::math::TPose2D  &pose)
{
	m_GT_pose=pose;
}

void CVehicleSimulVirtualBase::simulateOneTimeStep(const double dt)
{
	using mrpt::poses::CPose2D;
	const double final_t = m_time + dt;
	while (m_time <= final_t)
	{
		// Simulate movement during At:
		CPose2D nextOdometry(mrpt::poses::UNINITIALIZED_POSE), nextGT(mrpt::poses::UNINITIALIZED_POSE);
		nextOdometry.composeFrom(CPose2D(m_odometry),
			CPose2D (
				m_odometric_vel.vx*m_firmware_control_period,
				m_odometric_vel.vy*m_firmware_control_period,
				m_odometric_vel.omega*m_firmware_control_period
			));
		nextGT.composeFrom(CPose2D(m_GT_pose),
			CPose2D(
				m_GT_vel.vx*m_firmware_control_period,
				m_GT_vel.vy*m_firmware_control_period,
				m_GT_vel.omega*m_firmware_control_period
			));
		nextOdometry.phi(mrpt::math::wrapToPi(nextOdometry.phi()));
		nextGT.phi(mrpt::math::wrapToPi(nextGT.phi()));

		this->internal_simulControlStep(m_firmware_control_period);

		//Now rotate our current Odo velocity into GT coordinates
		m_GT_vel = getCurrentOdometricVelLocal();
		m_GT_vel.rotate(m_GT_pose.phi);

		//Add some errors
		if (m_use_odo_error)
		{
			nextGT.x_incr(m_Ax_err_bias + m_Ax_err_std * mrpt::random::randomGenerator.drawGaussian1D_normalized());
			nextGT.y_incr(m_Ay_err_bias + m_Ay_err_std * mrpt::random::randomGenerator.drawGaussian1D_normalized());
			nextGT.phi_incr(m_Aphi_err_bias + m_Aphi_err_std * mrpt::random::randomGenerator.drawGaussian1D_normalized());
			nextGT.phi(mrpt::math::wrapToPi(nextGT.phi()));
		}

		m_odometry = nextOdometry;
		m_GT_pose = nextGT;

		m_time += m_firmware_control_period; // Move forward

	}
}

void CVehicleSimulVirtualBase::resetStatus()
{
	m_GT_pose= mrpt::math::TPose2D(.0,.0,.0);
	m_GT_vel = mrpt::math::TTwist2D(.0,.0,.0);
	m_odometry = mrpt::math::TPose2D(.0,.0,.0);
	m_odometric_vel = mrpt::math::TTwist2D(.0,.0,.0);
	internal_clear();
}

void CVehicleSimulVirtualBase::resetTime()
{
	m_time = .0;
}

mrpt::math::TTwist2D CVehicleSimulVirtualBase::getCurrentGTVelLocal() const
{
	mrpt::math::TTwist2D tl = this->m_GT_vel;
	tl.rotate(-m_GT_pose.phi);
	return tl;
}

mrpt::math::TTwist2D CVehicleSimulVirtualBase::getCurrentOdometricVelLocal() const
{
	mrpt::math::TTwist2D tl = this->m_odometric_vel;
	tl.rotate(-m_odometry.phi);
	return tl;
}
<|endoftext|>


<commit_before>#include "application.h"
#include "element.h"
#include "sharedworkspace.h"
#include "event.h"
#include "axlib.h"

#define internal static
#define local_persist static

enum ax_application_notifications
{
    AXApplication_Notification_WindowCreated,
    AXApplication_Notification_WindowFocused,
    AXApplication_Notification_WindowMoved,
    AXApplication_Notification_WindowResized,
    AXApplication_Notification_WindowTitle,

    AXApplication_Notification_Count
};

internal CFStringRef
AXNotificationFromEnum(int Type)
{
    switch(Type)
    {
        case AXApplication_Notification_WindowCreated:
        {
            return kAXWindowCreatedNotification;
        } break;
        case AXApplication_Notification_WindowFocused:
        {
            return kAXFocusedWindowChangedNotification;
        } break;
        case AXApplication_Notification_WindowMoved:
        {
            return kAXWindowMovedNotification;
        } break;
        case AXApplication_Notification_WindowResized:
        {
            return kAXWindowResizedNotification;
        } break;
        case AXApplication_Notification_WindowTitle:
        {
            return kAXTitleChangedNotification;
        } break;
        default: { return NULL; /* NOTE(koekeishiya): Should never happen */ } break;
    }
}

internal inline ax_window *
AXLibGetWindowByRef(ax_application *Application, AXUIElementRef WindowRef)
{
    uint32_t WID = AXLibGetWindowID(WindowRef);
    return AXLibFindApplicationWindow(Application, WID);
}

internal inline void
AXLibUpdateApplicationWindowTitle(ax_application *Application, AXUIElementRef WindowRef)
{
    ax_window *Window = AXLibGetWindowByRef(Application, WindowRef);
    if(Window)
        Window->Name = AXLibGetWindowTitle(WindowRef);
}

internal inline void
AXLibDestroyInvalidWindow(ax_window *Window)
{
    AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXUIElementDestroyedNotification);
    AXLibDestroyWindow(Window);
}

OBSERVER_CALLBACK(AXApplicationCallback)
{
    ax_application *Application = (ax_application *) Reference;

    if(CFEqual(Notification, kAXWindowCreatedNotification))
    {
        /* NOTE(koekeishiya): Construct ax_window struct for the newly created window */
        ax_window *Window = AXLibConstructWindow(Application, Element);
        if(AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXUIElementDestroyedNotification, Window) == kAXErrorSuccess)
        {
            AXLibAddApplicationWindow(Application, Window);

            /* NOTE(koekeishiya): Triggers an AXEvent_WindowCreated and passes a pointer to the new ax_window */
            AXLibConstructEvent(AXEvent_WindowCreated, Window);

            /* NOTE(koekeishiya): When a new window is created, we incorrectly receive the kAXFocusedWindowChangedNotification
                                  first, for some reason. We discard that notification and restore it when we have the window to work with. */
            AXApplicationCallback(Observer, Window->Ref, kAXFocusedWindowChangedNotification, Application);
        }
        else
        {
            /* NOTE(koekeishiya): This element is not destructible and cannot be an application window (?) */
            AXLibDestroyInvalidWindow(Window);
        }
    }
    else if(CFEqual(Notification, kAXUIElementDestroyedNotification))
    {
        /* NOTE(koekeishiya): If the destroyed UIElement is a window, remove it from the list. */
        ax_window *Window = (ax_window *) Reference;
        if(Window)
        {
            AXLibRemoveApplicationWindow(Window->Application, Window->ID);
            Window->Application->Focus = AXLibGetFocusedWindow(Window->Application);

            /* NOTE(koekeishiya): The callback is responsible for calling AXLibDestroyWindow(Window); */
            AXLibConstructEvent(AXEvent_WindowDestroyed, Window);
        }
    }
    else if(CFEqual(Notification, kAXFocusedWindowChangedNotification))
    {
        /* NOTE(koekeishiya): This notification could be received before the window itself is created.
                              Make sure that the window actually exists before we notify our callback. */
        ax_window *Window = AXLibGetWindowByRef(Application, Element);
        if(Window)
        {
            AXLibConstructEvent(AXEvent_WindowFocused, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowMiniaturizedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowMinimized and passes a pointer to the ax_window */
        ax_window *Window = (ax_window *) Reference;
        if(Window)
        {
            AXLibConstructEvent(AXEvent_WindowMinimized, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowDeminiaturizedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowDeminimized and passes a pointer to the ax_window */
        ax_window *Window = (ax_window *) Reference;
        if(Window)
        {
            AXLibConstructEvent(AXEvent_WindowDeminimized, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowMovedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowMoved and passes a pointer to the ax_window */
        ax_window *Window = AXLibGetWindowByRef(Application, Element);
        if(Window)
        {
            Window->Position = AXLibGetWindowPosition(Window->Ref);
            AXLibConstructEvent(AXEvent_WindowMoved, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowResizedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowResized and passes a pointer to the ax_window */
        ax_window *Window = AXLibGetWindowByRef(Application, Element);
        if(Window)
        {
            Window->Position = AXLibGetWindowPosition(Window->Ref);
            Window->Size = AXLibGetWindowSize(Window->Ref);
            AXLibConstructEvent(AXEvent_WindowResized, Window);
        }
    }
    else if(CFEqual(Notification, kAXTitleChangedNotification))
    {
        AXLibUpdateApplicationWindowTitle(Application, Element);
    }
}

ax_application AXLibConstructApplication(pid_t PID, std::string Name)
{
    ax_application Application = {};

    Application.Ref = AXUIElementCreateApplication(PID);
    GetProcessForPID(PID, &Application.PSN);
    Application.Name = Name;
    Application.PID = PID;

    return Application;
}

void AXLibInitializeApplication(ax_application *Application)
{
    AXLibAddApplicationObserver(Application);
    AXLibAddApplicationWindows(Application);
    Application->Focus = AXLibGetFocusedWindow(Application);
}

void AXLibAddApplicationObserver(ax_application *Application)
{
    AXLibConstructObserver(Application, AXApplicationCallback);
    if(Application->Observer.Valid)
    {
        printf("AXLIB Create observer: %s\n", Application->Name.c_str());
        for(int Notification = AXApplication_Notification_WindowCreated;
                Notification < AXApplication_Notification_Count;
                ++Notification)
        {
            int Attempts = 10;
            while((--Attempts > 0) &&
                  (AXLibAddObserverNotification(&Application->Observer, Application->Ref, AXNotificationFromEnum(Notification), Application) != kAXErrorSuccess))
            {
                /* NOTE(koekeishiya): Could not add notification because the application has not finishied initializing yet.
                                      Sleep for a short while and try again. We limit the number of tries to prevent a deadlock. */
                usleep(10000);
            }

            /* NOTE(koekeishiya): Do we want to schedule a future event for the given application here if we failed (?)
                bool Success = Attempts != 0;
                printf("AXLIB Add notification %d, success %d\n", Notification, Success);
            */
        }

        AXLibStartObserver(&Application->Observer);
    }
}

void AXLibRemoveApplicationObserver(ax_application *Application)
{
    if(Application->Observer.Valid)
    {
        AXLibStopObserver(&Application->Observer);

        for(int Notification = AXApplication_Notification_WindowCreated;
                Notification < AXApplication_Notification_Count;
                ++Notification)
        {
            AXLibRemoveObserverNotification(&Application->Observer, Application->Ref, AXNotificationFromEnum(Notification));
        }

        AXLibDestroyObserver(&Application->Observer);
    }
}

void AXLibAddApplicationWindows(ax_application *Application)
{
    CFArrayRef Windows = (CFArrayRef) AXLibGetWindowProperty(Application->Ref, kAXWindowsAttribute);
    if(Windows)
    {
        CFIndex Count = CFArrayGetCount(Windows);
        for(CFIndex Index = 0; Index < Count; ++Index)
        {
            AXUIElementRef Ref = (AXUIElementRef) CFArrayGetValueAtIndex(Windows, Index);
            ax_window *Window = AXLibConstructWindow(Application, Ref);
            CFRelease(Ref);

            if(AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXUIElementDestroyedNotification, Window) == kAXErrorSuccess)
            {
                AXLibAddApplicationWindow(Application, Window);
            }
            else
            {
                AXLibDestroyInvalidWindow(Window);
            }
        }
    }
}

void AXLibRemoveApplicationWindows(ax_application *Application)
{
    std::map<uint32_t, ax_window*>::iterator It;
    for(It = Application->Windows.begin(); It != Application->Windows.end(); ++It)
    {
        ax_window *Window = It->second;
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXUIElementDestroyedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowMiniaturizedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowDeminiaturizedNotification);
        AXLibDestroyWindow(Window);
    }

    Application->Windows.clear();
}

ax_window *AXLibFindApplicationWindow(ax_application *Application, uint32_t WID)
{
    std::map<uint32_t, ax_window*>::iterator It;
    It = Application->Windows.find(WID);
    if(It != Application->Windows.end())
        return It->second;
    else
        return NULL;
}

void AXLibAddApplicationWindow(ax_application *Application, ax_window *Window)
{
    if(!AXLibFindApplicationWindow(Application, Window->ID))
    {
        AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXWindowMiniaturizedNotification, Window);
        AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXWindowDeminiaturizedNotification, Window);
        Application->Windows[Window->ID] = Window;
    }
}

void AXLibRemoveApplicationWindow(ax_application *Application, uint32_t WID)
{
    ax_window *Window = AXLibFindApplicationWindow(Application, WID);
    if(Window)
    {
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXUIElementDestroyedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowMiniaturizedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowDeminiaturizedNotification);
        Application->Windows.erase(WID);
    }
}

void AXLibActivateApplication(ax_application *Application)
{
    SharedWorkspaceActivateApplication(Application->PID);
}

bool AXLibIsApplicationActive(ax_application *Application)
{
    return SharedWorkspaceIsApplicationActive(Application->PID);
}

bool AXLibIsApplicationHidden(ax_application *Application)
{
    return SharedWorkspaceIsApplicationHidden(Application->PID);
}

void AXLibDestroyApplication(ax_application *Application)
{
    AXLibRemoveApplicationWindows(Application);
    AXLibRemoveApplicationObserver(Application);
    CFRelease(Application->Ref);
    Application->Ref = NULL;
}
<commit_msg>AddApplicationWindows(..) should only add windows we did not know about<commit_after>#include "application.h"
#include "element.h"
#include "sharedworkspace.h"
#include "event.h"
#include "axlib.h"

#define internal static
#define local_persist static

enum ax_application_notifications
{
    AXApplication_Notification_WindowCreated,
    AXApplication_Notification_WindowFocused,
    AXApplication_Notification_WindowMoved,
    AXApplication_Notification_WindowResized,
    AXApplication_Notification_WindowTitle,

    AXApplication_Notification_Count
};

internal CFStringRef
AXNotificationFromEnum(int Type)
{
    switch(Type)
    {
        case AXApplication_Notification_WindowCreated:
        {
            return kAXWindowCreatedNotification;
        } break;
        case AXApplication_Notification_WindowFocused:
        {
            return kAXFocusedWindowChangedNotification;
        } break;
        case AXApplication_Notification_WindowMoved:
        {
            return kAXWindowMovedNotification;
        } break;
        case AXApplication_Notification_WindowResized:
        {
            return kAXWindowResizedNotification;
        } break;
        case AXApplication_Notification_WindowTitle:
        {
            return kAXTitleChangedNotification;
        } break;
        default: { return NULL; /* NOTE(koekeishiya): Should never happen */ } break;
    }
}

internal inline ax_window *
AXLibGetWindowByRef(ax_application *Application, AXUIElementRef WindowRef)
{
    uint32_t WID = AXLibGetWindowID(WindowRef);
    return AXLibFindApplicationWindow(Application, WID);
}

internal inline void
AXLibUpdateApplicationWindowTitle(ax_application *Application, AXUIElementRef WindowRef)
{
    ax_window *Window = AXLibGetWindowByRef(Application, WindowRef);
    if(Window)
        Window->Name = AXLibGetWindowTitle(WindowRef);
}

internal inline void
AXLibDestroyInvalidWindow(ax_window *Window)
{
    AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXUIElementDestroyedNotification);
    AXLibDestroyWindow(Window);
}

OBSERVER_CALLBACK(AXApplicationCallback)
{
    ax_application *Application = (ax_application *) Reference;

    if(CFEqual(Notification, kAXWindowCreatedNotification))
    {
        /* NOTE(koekeishiya): Construct ax_window struct for the newly created window */
        ax_window *Window = AXLibConstructWindow(Application, Element);
        if(AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXUIElementDestroyedNotification, Window) == kAXErrorSuccess)
        {
            AXLibAddApplicationWindow(Application, Window);

            /* NOTE(koekeishiya): Triggers an AXEvent_WindowCreated and passes a pointer to the new ax_window */
            AXLibConstructEvent(AXEvent_WindowCreated, Window);

            /* NOTE(koekeishiya): When a new window is created, we incorrectly receive the kAXFocusedWindowChangedNotification
                                  first, for some reason. We discard that notification and restore it when we have the window to work with. */
            AXApplicationCallback(Observer, Window->Ref, kAXFocusedWindowChangedNotification, Application);
        }
        else
        {
            /* NOTE(koekeishiya): This element is not destructible and cannot be an application window (?) */
            AXLibDestroyInvalidWindow(Window);
        }
    }
    else if(CFEqual(Notification, kAXUIElementDestroyedNotification))
    {
        /* NOTE(koekeishiya): If the destroyed UIElement is a window, remove it from the list. */
        ax_window *Window = (ax_window *) Reference;
        if(Window)
        {
            AXLibRemoveApplicationWindow(Window->Application, Window->ID);
            Window->Application->Focus = AXLibGetFocusedWindow(Window->Application);

            /* NOTE(koekeishiya): The callback is responsible for calling AXLibDestroyWindow(Window); */
            AXLibConstructEvent(AXEvent_WindowDestroyed, Window);
        }
    }
    else if(CFEqual(Notification, kAXFocusedWindowChangedNotification))
    {
        /* NOTE(koekeishiya): This notification could be received before the window itself is created.
                              Make sure that the window actually exists before we notify our callback. */
        ax_window *Window = AXLibGetWindowByRef(Application, Element);
        if(Window)
        {
            AXLibConstructEvent(AXEvent_WindowFocused, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowMiniaturizedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowMinimized and passes a pointer to the ax_window */
        ax_window *Window = (ax_window *) Reference;
        if(Window)
        {
            AXLibConstructEvent(AXEvent_WindowMinimized, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowDeminiaturizedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowDeminimized and passes a pointer to the ax_window */
        ax_window *Window = (ax_window *) Reference;
        if(Window)
        {
            AXLibConstructEvent(AXEvent_WindowDeminimized, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowMovedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowMoved and passes a pointer to the ax_window */
        ax_window *Window = AXLibGetWindowByRef(Application, Element);
        if(Window)
        {
            Window->Position = AXLibGetWindowPosition(Window->Ref);
            AXLibConstructEvent(AXEvent_WindowMoved, Window);
        }
    }
    else if(CFEqual(Notification, kAXWindowResizedNotification))
    {
        /* NOTE(koekeishiya): Triggers an AXEvent_WindowResized and passes a pointer to the ax_window */
        ax_window *Window = AXLibGetWindowByRef(Application, Element);
        if(Window)
        {
            Window->Position = AXLibGetWindowPosition(Window->Ref);
            Window->Size = AXLibGetWindowSize(Window->Ref);
            AXLibConstructEvent(AXEvent_WindowResized, Window);
        }
    }
    else if(CFEqual(Notification, kAXTitleChangedNotification))
    {
        AXLibUpdateApplicationWindowTitle(Application, Element);
    }
}

ax_application AXLibConstructApplication(pid_t PID, std::string Name)
{
    ax_application Application = {};

    Application.Ref = AXUIElementCreateApplication(PID);
    GetProcessForPID(PID, &Application.PSN);
    Application.Name = Name;
    Application.PID = PID;

    return Application;
}

void AXLibInitializeApplication(ax_application *Application)
{
    AXLibAddApplicationObserver(Application);
    AXLibAddApplicationWindows(Application);
    Application->Focus = AXLibGetFocusedWindow(Application);
}

void AXLibAddApplicationObserver(ax_application *Application)
{
    AXLibConstructObserver(Application, AXApplicationCallback);
    if(Application->Observer.Valid)
    {
        printf("AXLIB Create observer: %s\n", Application->Name.c_str());
        for(int Notification = AXApplication_Notification_WindowCreated;
                Notification < AXApplication_Notification_Count;
                ++Notification)
        {
            int Attempts = 10;
            while((--Attempts > 0) &&
                  (AXLibAddObserverNotification(&Application->Observer, Application->Ref, AXNotificationFromEnum(Notification), Application) != kAXErrorSuccess))
            {
                /* NOTE(koekeishiya): Could not add notification because the application has not finishied initializing yet.
                                      Sleep for a short while and try again. We limit the number of tries to prevent a deadlock. */
                usleep(20000);
            }

            /* NOTE(koekeishiya): Do we want to schedule a future event for the given application here if we failed (?)
            */
                bool Success = Attempts != 0;
                if(!Success)
                    printf("AXLIB Add notification %d, success %d\n", Notification, Success);
        }

        AXLibStartObserver(&Application->Observer);
    }
}

void AXLibRemoveApplicationObserver(ax_application *Application)
{
    if(Application->Observer.Valid)
    {
        AXLibStopObserver(&Application->Observer);

        for(int Notification = AXApplication_Notification_WindowCreated;
                Notification < AXApplication_Notification_Count;
                ++Notification)
        {
            AXLibRemoveObserverNotification(&Application->Observer, Application->Ref, AXNotificationFromEnum(Notification));
        }

        AXLibDestroyObserver(&Application->Observer);
    }
}

void AXLibAddApplicationWindows(ax_application *Application)
{
    CFArrayRef Windows = (CFArrayRef) AXLibGetWindowProperty(Application->Ref, kAXWindowsAttribute);
    if(Windows)
    {
        CFIndex Count = CFArrayGetCount(Windows);
        for(CFIndex Index = 0; Index < Count; ++Index)
        {
            AXUIElementRef Ref = (AXUIElementRef) CFArrayGetValueAtIndex(Windows, Index);
            if(!AXLibGetWindowByRef(Application, Ref))
            {
                ax_window *Window = AXLibConstructWindow(Application, Ref);
                if(AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXUIElementDestroyedNotification, Window) == kAXErrorSuccess)
                {
                    AXLibAddApplicationWindow(Application, Window);
                }
                else
                {
                    AXLibDestroyInvalidWindow(Window);
                }
            }
            CFRelease(Ref);
        }
    }
}

void AXLibRemoveApplicationWindows(ax_application *Application)
{
    std::map<uint32_t, ax_window*>::iterator It;
    for(It = Application->Windows.begin(); It != Application->Windows.end(); ++It)
    {
        ax_window *Window = It->second;
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXUIElementDestroyedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowMiniaturizedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowDeminiaturizedNotification);
        AXLibDestroyWindow(Window);
    }

    Application->Windows.clear();
}

ax_window *AXLibFindApplicationWindow(ax_application *Application, uint32_t WID)
{
    std::map<uint32_t, ax_window*>::iterator It;
    It = Application->Windows.find(WID);
    if(It != Application->Windows.end())
        return It->second;
    else
        return NULL;
}

void AXLibAddApplicationWindow(ax_application *Application, ax_window *Window)
{
    if(!AXLibFindApplicationWindow(Application, Window->ID))
    {
        AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXWindowMiniaturizedNotification, Window);
        AXLibAddObserverNotification(&Application->Observer, Window->Ref, kAXWindowDeminiaturizedNotification, Window);
        Application->Windows[Window->ID] = Window;
    }
}

void AXLibRemoveApplicationWindow(ax_application *Application, uint32_t WID)
{
    ax_window *Window = AXLibFindApplicationWindow(Application, WID);
    if(Window)
    {
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXUIElementDestroyedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowMiniaturizedNotification);
        AXLibRemoveObserverNotification(&Window->Application->Observer, Window->Ref, kAXWindowDeminiaturizedNotification);
        Application->Windows.erase(WID);
    }
}

void AXLibActivateApplication(ax_application *Application)
{
    SharedWorkspaceActivateApplication(Application->PID);
}

bool AXLibIsApplicationActive(ax_application *Application)
{
    return SharedWorkspaceIsApplicationActive(Application->PID);
}

bool AXLibIsApplicationHidden(ax_application *Application)
{
    return SharedWorkspaceIsApplicationHidden(Application->PID);
}

void AXLibDestroyApplication(ax_application *Application)
{
    AXLibRemoveApplicationWindows(Application);
    AXLibRemoveApplicationObserver(Application);
    CFRelease(Application->Ref);
    Application->Ref = NULL;
}
<|endoftext|>