<commit_before>/* GNE - Game Networking Engine, a portable multithreaded networking library.
 * Copyright (C) 2001 Jason Winnebeck (gillius@mail.rit.edu)
 * Project website: http://www.rit.edu/~jpw9607/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "gneintern.h"
#include "PacketStream.h"
#include "Packet.h"
#include "Connection.h"
#include "RawPacket.h"
#include "PacketParser.h"

const int BUF_LEN = 1024;

namespace GNE {

//##ModelId=3B07538101BD
PacketStream::PacketStream(int outRate2, int inRate2, Connection& ourOwner)
: owner(ourOwner), inRate(inRate2), outRate(outRate2) {
}

//##ModelId=3B07538101C0
PacketStream::~PacketStream() {
}

//##ModelId=3B07538101C2
int PacketStream::getInLength() const {
  int ret;
  inQCtrl.acquire();
  ret = in.size();
  inQCtrl.release();
  return ret;
}

//##ModelId=3B07538101C4
int PacketStream::getOutLength() const {
  int ret;
  outQCtrl.acquire();
  ret = out.size();
  outQCtrl.release();
  return ret;
}

//##ModelId=3B07538101C6
bool PacketStream::isNextPacket() const {
  return (getInLength() != 0);
}

//##ModelId=3B07538101C8
Packet* PacketStream::getNextPacket() {
  Packet* ret = NULL;
  inQCtrl.acquire();
  if (!in.empty()) {
    ret = in.front();
    in.pop();
  }
  inQCtrl.release();
  return ret;
}

//##ModelId=3B07538101C9
void PacketStream::writePacket(const Packet& packet, bool reliable) {
  //Create the new data to be in the queue
  PacketStreamData* newNode = new PacketStreamData;
  newNode->reliable = reliable;
  newNode->packet = packet.makeClone();

  //Perform operations on the outgoing queue
  outQCtrl.acquire();
  bool notify = out.empty();
  out.push(newNode);
  outQCtrl.release();

  //If we need to, wake up the writer thread.
  if (notify)
    outQCtrl.signal();
}

//##ModelId=3B07538101FD
PacketStream::PacketStreamData* PacketStream::getNextPacketToSend() {
  PacketStream::PacketStreamData* ret = NULL;
  outQCtrl.acquire();
  if (!out.empty()) {
    ret = out.front();
    out.pop();
  }
  outQCtrl.release();
  return ret;
}

//##ModelId=3B07538101F5
int PacketStream::getInRate() const {
  return inRate;
}

//##ModelId=3B07538101F7
int PacketStream::getOutRate() const {
  return outRate;
}

/**
 * \todo write this function for real.
 */
//##ModelId=3B07538101F9
void PacketStream::waitToSendAll() {
	//Only temporary for now
	//When we write this function for real, make sure that if the PacketSteam
	//is shutting down that we properly exit from this function.
	Thread::sleep(2000);
}

//##ModelId=3B8DC5D10096
void PacketStream::shutDown() {
	Thread::shutDown();
	//We acquire the mutex to avoid the possiblity of a deadlock between the
	// test for the shutdown variable and the wait.
	outQCtrl.acquire();
	outQCtrl.signal();
	outQCtrl.release();
}

/**
 * \todo combine packets, do throttling, call onDoneWriting
 */
//##ModelId=3B07538101FA
void PacketStream::run() {
  while (!shutdown) {
    outQCtrl.acquire();
    while (out.empty() && !shutdown) {
      outQCtrl.wait();
    }
    outQCtrl.release();
    if (!shutdown) {
      //Do throttled writes
			PacketStreamData* next = getNextPacketToSend();
			RawPacket raw;
			next->packet->writePacket(raw);
			raw << PacketParser::END_OF_PACKET;
      if (owner.sockets.rawWrite(next->reliable, raw.getData(), raw.getPosition()) == NL_INVALID) {
				owner.processError(Error::Write);
			}
			delete next;
    }
  }
}

//##ModelId=3B07538101FB
void PacketStream::addIncomingPacket(Packet* packet) {
  inQCtrl.acquire();
  in.push(packet);
  inQCtrl.release();
}

}

<commit_msg>Now generates onDoneWriting event.<commit_after>/* GNE - Game Networking Engine, a portable multithreaded networking library.
 * Copyright (C) 2001 Jason Winnebeck (gillius@mail.rit.edu)
 * Project website: http://www.rit.edu/~jpw9607/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "gneintern.h"
#include "PacketStream.h"
#include "Packet.h"
#include "Connection.h"
#include "RawPacket.h"
#include "PacketParser.h"

const int BUF_LEN = 1024;

namespace GNE {

//##ModelId=3B07538101BD
PacketStream::PacketStream(int outRate2, int inRate2, Connection& ourOwner)
: owner(ourOwner), inRate(inRate2), outRate(outRate2) {
}

//##ModelId=3B07538101C0
PacketStream::~PacketStream() {
}

//##ModelId=3B07538101C2
int PacketStream::getInLength() const {
  int ret;
  inQCtrl.acquire();
  ret = in.size();
  inQCtrl.release();
  return ret;
}

//##ModelId=3B07538101C4
int PacketStream::getOutLength() const {
  int ret;
  outQCtrl.acquire();
  ret = out.size();
  outQCtrl.release();
  return ret;
}

//##ModelId=3B07538101C6
bool PacketStream::isNextPacket() const {
  return (getInLength() != 0);
}

//##ModelId=3B07538101C8
Packet* PacketStream::getNextPacket() {
  Packet* ret = NULL;
  inQCtrl.acquire();
  if (!in.empty()) {
    ret = in.front();
    in.pop();
  }
  inQCtrl.release();
  return ret;
}

//##ModelId=3B07538101C9
void PacketStream::writePacket(const Packet& packet, bool reliable) {
  //Create the new data to be in the queue
  PacketStreamData* newNode = new PacketStreamData;
  newNode->reliable = reliable;
  newNode->packet = packet.makeClone();

  //Perform operations on the outgoing queue
  outQCtrl.acquire();
  bool notify = out.empty();
  out.push(newNode);
  outQCtrl.release();

  //If we need to, wake up the writer thread.
  if (notify)
    outQCtrl.signal();
}

//##ModelId=3B07538101FD
PacketStream::PacketStreamData* PacketStream::getNextPacketToSend() {
  PacketStream::PacketStreamData* ret = NULL;
  outQCtrl.acquire();
  if (!out.empty()) {
    ret = out.front();
    out.pop();
  }
  outQCtrl.release();
  return ret;
}

//##ModelId=3B07538101F5
int PacketStream::getInRate() const {
  return inRate;
}

//##ModelId=3B07538101F7
int PacketStream::getOutRate() const {
  return outRate;
}

/**
 * \todo write this function for real.
 */
//##ModelId=3B07538101F9
void PacketStream::waitToSendAll() {
	//Only temporary for now
	//When we write this function for real, make sure that if the PacketSteam
	//is shutting down that we properly exit from this function.
	Thread::sleep(2000);
}

//##ModelId=3B8DC5D10096
void PacketStream::shutDown() {
	Thread::shutDown();
	//We acquire the mutex to avoid the possiblity of a deadlock between the
	// test for the shutdown variable and the wait.
	outQCtrl.acquire();
	outQCtrl.signal();
	outQCtrl.release();
}

/**
 * \todo combine packets, do throttling, optimize
 */
//##ModelId=3B07538101FA
void PacketStream::run() {
  while (!shutdown) {
    outQCtrl.acquire();
    while (out.empty() && !shutdown) {
      outQCtrl.wait();
    }
    outQCtrl.release();
    if (!shutdown) {
      //Do throttled writes
			PacketStreamData* next = getNextPacketToSend();
			RawPacket raw;
			next->packet->writePacket(raw);
			raw << PacketParser::END_OF_PACKET;
      if (owner.sockets.rawWrite(next->reliable, raw.getData(), raw.getPosition()) == NL_INVALID) {
				owner.processError(Error::Write);
			}
			delete next;

			//Optimize this code later
			bool done = false;
			outQCtrl.acquire();
			if (out.empty())
				done = true;
			outQCtrl.release();
			if (done)
				owner.onDoneWriting();
    }
  }
}

//##ModelId=3B07538101FB
void PacketStream::addIncomingPacket(Packet* packet) {
  inQCtrl.acquire();
  in.push(packet);
  inQCtrl.release();
}

}

<|endoftext|>


<commit_before>// Filename: StaggeredStokesOpenBoundaryStabilizer.C
// Created on 29 Aug 2012 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "StaggeredStokesOpenBoundaryStabilizer.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBAMR_config
#include <IBAMR_config.h>
#define included_IBAMR_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBAMR INCLUDES
#include <ibamr/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBAMR
{
/////////////////////////////// STATIC ///////////////////////////////////////

////////////////////////////// PUBLIC ///////////////////////////////////////

StaggeredStokesOpenBoundaryStabilizer::StaggeredStokesOpenBoundaryStabilizer(
    unsigned int comp_idx,
    RobinBcCoefStrategy<NDIM>* comp_bc_coef,
    Pointer<Database> input_db,
    const INSStaggeredHierarchyIntegrator* fluid_solver)
    : d_alpha(std::numeric_limits<double>::quiet_NaN()),
      d_beta(std::numeric_limits<double>::quiet_NaN()),
      d_comp_idx(comp_idx),
      d_comp_bc_coef(comp_bc_coef),
      d_open_bdry(false),
      d_inflow_bdry(false),
      d_outflow_bdry(false),
      d_fluid_solver(fluid_solver)
{
    if (input_db)
    {
        if (input_db->keyExists("alpha")) d_alpha = input_db->getDouble("alpha");
        if (input_db->keyExists("beta")) d_beta = input_db->getDouble("beta");
        for (int location_index = 0; location_index < 2*NDIM; ++location_index)
        {
            std::ostringstream stabilization_type_stream;
            stabilization_type_stream << "stabilization_type_" << location_index;
            const std::string stabilization_type_key = stabilization_type_stream.str();
            if (input_db->keyExists(stabilization_type_key))
            {
                const std::string stabilization_type = input_db->getString(stabilization_type_key);
                if (stabilization_type == "INFLOW")
                {
                    d_open_bdry   [location_index] = true;
                    d_inflow_bdry [location_index] = true;
                    d_outflow_bdry[location_index] = false;
                }
                else if (stabilization_type == "OUTFLOW")
                {
                    d_open_bdry   [location_index] = true;
                    d_inflow_bdry [location_index] = false;
                    d_outflow_bdry[location_index] = true;
                }
                else if (stabilization_type != "NONE")
                {
                    TBOX_ERROR("StaggeredStokesOpenBoundaryStabilizer::StaggeredStokesOpenBoundaryStabilizer():\n"
                               << "  unsupported stabilization type: ``" << stabilization_type << "''\n"
                               << "  supported values are: ``INFLOW'', ``OUTFLOW'', or ``NONE''\n");
                }
            }
        }
    }
    return;
}// StaggeredStokesOpenBoundaryStabilizer

StaggeredStokesOpenBoundaryStabilizer::~StaggeredStokesOpenBoundaryStabilizer()
{
    // intentionally blank
    return;
}// ~StaggeredStokesOpenBoundaryStabilizer

void
StaggeredStokesOpenBoundaryStabilizer::setTargetPatchDataIndex(
    int target_idx)
{
    ExtendedRobinBcCoefStrategy::setTargetPatchDataIndex(target_idx);
    ExtendedRobinBcCoefStrategy* p_comp_bc_coef = dynamic_cast<ExtendedRobinBcCoefStrategy*>(d_comp_bc_coef);
    if (p_comp_bc_coef) p_comp_bc_coef->setTargetPatchDataIndex(target_idx);
    return;
}// setTargetPatchDataIndex

void
StaggeredStokesOpenBoundaryStabilizer::setHomogeneousBc(
    bool homogeneous_bc)
{
    ExtendedRobinBcCoefStrategy::setHomogeneousBc(homogeneous_bc);
    ExtendedRobinBcCoefStrategy* p_comp_bc_coef = dynamic_cast<ExtendedRobinBcCoefStrategy*>(d_comp_bc_coef);
    if (p_comp_bc_coef) p_comp_bc_coef->setHomogeneousBc(homogeneous_bc);
    return;
}// setHomogeneousBc

void
StaggeredStokesOpenBoundaryStabilizer::setBcCoefs(
    Pointer<ArrayData<NDIM,double> >& acoef_data,
    Pointer<ArrayData<NDIM,double> >& bcoef_data,
    Pointer<ArrayData<NDIM,double> >& gcoef_data,
    const Pointer<Variable<NDIM> >& variable,
    const Patch<NDIM>& patch,
    const BoundaryBox<NDIM>& bdry_box,
    double fill_time) const
{
    // Set the unmodified velocity bc coefs.
    d_comp_bc_coef->setBcCoefs(acoef_data, bcoef_data, gcoef_data, variable, patch, bdry_box, fill_time);

    // If we are not setting inhomogeneous coefficients; at an open boundary;
    // not operating on the correct velocity component; or not currently
    // performing a solve then there is nothing else to do.
    if (!gcoef_data || d_homogeneous_bc) return;
    const unsigned int location_index = bdry_box.getLocationIndex();
    if (!d_open_bdry[location_index]) return;
    const unsigned int bdry_normal_axis = location_index/2;
    if (bdry_normal_axis != d_comp_idx) return;
    if (d_fluid_solver->getCurrentCycleNumber() < 0) return;

    // Attempt to obtain the velocity data.  If the current velocity data is
    // NULL, there is nothing else to do.
    VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase();
    const int u_current_idx = var_db->mapVariableAndContextToIndex(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getCurrentContext());
    const int u_new_idx     = var_db->mapVariableAndContextToIndex(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getNewContext());
    Pointer<SideData<NDIM,double> > u_current_data = patch.getPatchData(u_current_idx);
    Pointer<SideData<NDIM,double> > u_new_data     = patch.getPatchData(u_new_idx);
    if (!u_current_data) return;
    Box<NDIM> ghost_box = u_current_data->getGhostBox();
    if (u_new_data) ghost_box * u_new_data->getGhostBox();

    // Where appropriate, update normal traction boundary conditions to penalize
    // flow reversal.
    const bool is_lower = location_index%2 == 0;
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(acoef_data);
    TBOX_ASSERT(bcoef_data);
    TBOX_ASSERT(gcoef_data);
#endif
    Box<NDIM> bc_coef_box = acoef_data->getBox();
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(bc_coef_box == acoef_data->getBox());
    TBOX_ASSERT(bc_coef_box == bcoef_data->getBox());
    TBOX_ASSERT(bc_coef_box == gcoef_data->getBox());
#endif
    for (unsigned int d = 0; d < NDIM; ++d)
    {
        if (d != bdry_normal_axis)
        {
            bc_coef_box.lower(d) = std::max(bc_coef_box.lower(d), ghost_box.lower(d));
            bc_coef_box.upper(d) = std::min(bc_coef_box.upper(d), ghost_box.upper(d));
        }
    }
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    for (Box<NDIM>::Iterator it(bc_coef_box); it; it++)
    {
        const Index<NDIM>& i = it();
        const double& alpha = (*acoef_data)(i,0);
        const double& beta  = (*bcoef_data)(i,0);
        double& gamma = (*gcoef_data)(i,0);
        const bool traction_bc = MathUtilities<double>::equalEps(beta ,1.0);
#ifdef DEBUG_CHECK_ASSERTIONS
        const bool velocity_bc = MathUtilities<double>::equalEps(alpha,1.0);
        TBOX_ASSERT((velocity_bc || traction_bc) && !(velocity_bc && traction_bc));
#endif
        if (traction_bc)
        {
#ifdef DEBUG_CHECK_ASSERTIONS
            TBOX_ASSERT(d_comp_idx == bdry_normal_axis);
#endif
            const SideIndex<NDIM> i_s(i, bdry_normal_axis, SideIndex<NDIM>::Lower);
            const double u_n = (is_lower ? -1.0 : 1.0) * (cycle_num > 0 ? 0.5*((*u_current_data)(i_s) + (*u_new_data)(i_s)) : (*u_current_data)(i_s));
            if (d_inflow_bdry[location_index] && u_n > 0.0)
            {
                gamma -= d_alpha*pow(std::abs(u_n),d_beta);
            }
            else if (d_outflow_bdry[location_index] && u_n < 0.0)
            {
                gamma += d_alpha*pow(std::abs(u_n),d_beta);
            }
        }
    }
    return;
}// setBcCoefs

SAMRAI::hier::IntVector<NDIM>
StaggeredStokesOpenBoundaryStabilizer::numberOfExtensionsFillable() const
{
    return d_comp_bc_coef->numberOfExtensionsFillable();
}// numberOfExtensionsFillable

/////////////////////////////// PROTECTED ////////////////////////////////////

/////////////////////////////// PRIVATE //////////////////////////////////////

/////////////////////////////// NAMESPACE ////////////////////////////////////

} // namespace IBAMR

//////////////////////////////////////////////////////////////////////////////
<commit_msg>branch boyceg: fixing stabilizer to only act within a solver cycle<commit_after>// Filename: StaggeredStokesOpenBoundaryStabilizer.C
// Created on 29 Aug 2012 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "StaggeredStokesOpenBoundaryStabilizer.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBAMR_config
#include <IBAMR_config.h>
#define included_IBAMR_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBAMR INCLUDES
#include <ibamr/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBAMR
{
/////////////////////////////// STATIC ///////////////////////////////////////

////////////////////////////// PUBLIC ///////////////////////////////////////

StaggeredStokesOpenBoundaryStabilizer::StaggeredStokesOpenBoundaryStabilizer(
    unsigned int comp_idx,
    RobinBcCoefStrategy<NDIM>* comp_bc_coef,
    Pointer<Database> input_db,
    const INSStaggeredHierarchyIntegrator* fluid_solver)
    : d_alpha(std::numeric_limits<double>::quiet_NaN()),
      d_beta(std::numeric_limits<double>::quiet_NaN()),
      d_comp_idx(comp_idx),
      d_comp_bc_coef(comp_bc_coef),
      d_open_bdry(false),
      d_inflow_bdry(false),
      d_outflow_bdry(false),
      d_fluid_solver(fluid_solver)
{
    if (input_db)
    {
        if (input_db->keyExists("alpha")) d_alpha = input_db->getDouble("alpha");
        if (input_db->keyExists("beta")) d_beta = input_db->getDouble("beta");
        for (int location_index = 0; location_index < 2*NDIM; ++location_index)
        {
            std::ostringstream stabilization_type_stream;
            stabilization_type_stream << "stabilization_type_" << location_index;
            const std::string stabilization_type_key = stabilization_type_stream.str();
            if (input_db->keyExists(stabilization_type_key))
            {
                const std::string stabilization_type = input_db->getString(stabilization_type_key);
                if (stabilization_type == "INFLOW")
                {
                    d_open_bdry   [location_index] = true;
                    d_inflow_bdry [location_index] = true;
                    d_outflow_bdry[location_index] = false;
                }
                else if (stabilization_type == "OUTFLOW")
                {
                    d_open_bdry   [location_index] = true;
                    d_inflow_bdry [location_index] = false;
                    d_outflow_bdry[location_index] = true;
                }
                else if (stabilization_type != "NONE")
                {
                    TBOX_ERROR("StaggeredStokesOpenBoundaryStabilizer::StaggeredStokesOpenBoundaryStabilizer():\n"
                               << "  unsupported stabilization type: ``" << stabilization_type << "''\n"
                               << "  supported values are: ``INFLOW'', ``OUTFLOW'', or ``NONE''\n");
                }
            }
        }
    }
    return;
}// StaggeredStokesOpenBoundaryStabilizer

StaggeredStokesOpenBoundaryStabilizer::~StaggeredStokesOpenBoundaryStabilizer()
{
    // intentionally blank
    return;
}// ~StaggeredStokesOpenBoundaryStabilizer

void
StaggeredStokesOpenBoundaryStabilizer::setTargetPatchDataIndex(
    int target_idx)
{
    ExtendedRobinBcCoefStrategy::setTargetPatchDataIndex(target_idx);
    ExtendedRobinBcCoefStrategy* p_comp_bc_coef = dynamic_cast<ExtendedRobinBcCoefStrategy*>(d_comp_bc_coef);
    if (p_comp_bc_coef) p_comp_bc_coef->setTargetPatchDataIndex(target_idx);
    return;
}// setTargetPatchDataIndex

void
StaggeredStokesOpenBoundaryStabilizer::setHomogeneousBc(
    bool homogeneous_bc)
{
    ExtendedRobinBcCoefStrategy::setHomogeneousBc(homogeneous_bc);
    ExtendedRobinBcCoefStrategy* p_comp_bc_coef = dynamic_cast<ExtendedRobinBcCoefStrategy*>(d_comp_bc_coef);
    if (p_comp_bc_coef) p_comp_bc_coef->setHomogeneousBc(homogeneous_bc);
    return;
}// setHomogeneousBc

void
StaggeredStokesOpenBoundaryStabilizer::setBcCoefs(
    Pointer<ArrayData<NDIM,double> >& acoef_data,
    Pointer<ArrayData<NDIM,double> >& bcoef_data,
    Pointer<ArrayData<NDIM,double> >& gcoef_data,
    const Pointer<Variable<NDIM> >& variable,
    const Patch<NDIM>& patch,
    const BoundaryBox<NDIM>& bdry_box,
    double fill_time) const
{
    // Set the unmodified velocity bc coefs.
    d_comp_bc_coef->setBcCoefs(acoef_data, bcoef_data, gcoef_data, variable, patch, bdry_box, fill_time);

    // If we are not setting inhomogeneous coefficients; at an open boundary; or
    // not operating on the correct velocity component, then there is nothing
    // else to do.
    if (!gcoef_data || d_homogeneous_bc) return;
    const unsigned int location_index = bdry_box.getLocationIndex();
    if (!d_open_bdry[location_index]) return;
    const unsigned int bdry_normal_axis = location_index/2;
    if (bdry_normal_axis != d_comp_idx) return;

    // Attempt to obtain the velocity data.  If the current velocity data is
    // NULL, there is nothing else to do.
    VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase();
    const int u_current_idx = var_db->mapVariableAndContextToIndex(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getCurrentContext());
    const int u_new_idx     = var_db->mapVariableAndContextToIndex(d_fluid_solver->getVelocityVariable(), d_fluid_solver->getNewContext());
    Pointer<SideData<NDIM,double> > u_current_data = patch.getPatchData(u_current_idx);
    Pointer<SideData<NDIM,double> > u_new_data     = patch.getPatchData(u_new_idx);
    if (!u_current_data) return;
    Box<NDIM> ghost_box = u_current_data->getGhostBox();
    if (u_new_data) ghost_box * u_new_data->getGhostBox();

    // Where appropriate, update normal traction boundary conditions to penalize
    // flow reversal.
    const bool is_lower = location_index%2 == 0;
    Box<NDIM> bc_coef_box = acoef_data->getBox();
    for (unsigned int d = 0; d < NDIM; ++d)
    {
        if (d != bdry_normal_axis)
        {
            bc_coef_box.lower(d) = std::max(bc_coef_box.lower(d), ghost_box.lower(d));
            bc_coef_box.upper(d) = std::min(bc_coef_box.upper(d), ghost_box.upper(d));
        }
    }
    const int cycle_num = d_fluid_solver->getCurrentCycleNumber();
    for (Box<NDIM>::Iterator it(bc_coef_box); it; it++)
    {
        const Index<NDIM>& i = it();
        const double& alpha = (*acoef_data)(i,0);
        const double& beta  = (*bcoef_data)(i,0);
        double& gamma = (*gcoef_data)(i,0);
        const bool traction_bc = MathUtilities<double>::equalEps(beta ,1.0);
#ifdef DEBUG_CHECK_ASSERTIONS
        const bool velocity_bc = MathUtilities<double>::equalEps(alpha,1.0);
        TBOX_ASSERT((velocity_bc || traction_bc) && !(velocity_bc && traction_bc));
#endif
        if (traction_bc)
        {
#ifdef DEBUG_CHECK_ASSERTIONS
            TBOX_ASSERT(d_comp_idx == bdry_normal_axis);
#endif
            const SideIndex<NDIM> i_s(i, bdry_normal_axis, SideIndex<NDIM>::Lower);
            const double u_n = (is_lower ? -1.0 : 1.0) * (cycle_num > 0 ? 0.5*((*u_current_data)(i_s) + (*u_new_data)(i_s)) : (*u_current_data)(i_s));
            if (d_inflow_bdry[location_index] && u_n > 0.0)
            {
                gamma -= d_alpha*pow(std::abs(u_n),d_beta);
            }
            else if (d_outflow_bdry[location_index] && u_n < 0.0)
            {
                gamma += d_alpha*pow(std::abs(u_n),d_beta);
            }
        }
    }
    return;
}// setBcCoefs

SAMRAI::hier::IntVector<NDIM>
StaggeredStokesOpenBoundaryStabilizer::numberOfExtensionsFillable() const
{
    return d_comp_bc_coef->numberOfExtensionsFillable();
}// numberOfExtensionsFillable

/////////////////////////////// PROTECTED ////////////////////////////////////

/////////////////////////////// PRIVATE //////////////////////////////////////

/////////////////////////////// NAMESPACE ////////////////////////////////////

} // namespace IBAMR

//////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#pragma once
#include <Doremi/Core/Include/GameCore.hpp>
#include <vector>

namespace Doremi
{
    namespace Core
    {
        class Manager;
        class EntityInterface;
    }
}

namespace Doremi
{

    class ServerMain : public Core::GameCore
    {
    public:
        /**
            Constructor
        */
        ServerMain();

        /**
            Destructor
        */
        virtual ~ServerMain();

        /**
            doc
        */
        void Start();

        /**
        doc
        */
        void Stop();

    private:
        /**
            TODOCM doc
        */
        void Initialize();

        /**
            TODOCM doc
        */
        void SpawnDebugWorld(const DoremiEngine::Core::SharedContext& sharedContext);

        /**
            TODOCM doc
        */
        void Run();

        /**
            TODOCM doc
        */
        void UpdateGame(double p_deltaTime);

        /**
            TOODCM doc
        */
        std::vector<Core::Manager*> m_managers;
    };
}<commit_msg>Removed unused forward declaration<commit_after>#pragma once
#include <Doremi/Core/Include/GameCore.hpp>
#include <vector>

namespace Doremi
{
    namespace Core
    {
        class Manager;
    }
}

namespace Doremi
{

    class ServerMain : public Core::GameCore
    {
    public:
        /**
            Constructor
        */
        ServerMain();

        /**
            Destructor
        */
        virtual ~ServerMain();

        /**
            doc
        */
        void Start();

        /**
        doc
        */
        void Stop();

    private:
        /**
            TODOCM doc
        */
        void Initialize();

        /**
            TODOCM doc
        */
        void SpawnDebugWorld(const DoremiEngine::Core::SharedContext& sharedContext);

        /**
            TODOCM doc
        */
        void Run();

        /**
            TODOCM doc
        */
        void UpdateGame(double p_deltaTime);

        /**
            TOODCM doc
        */
        std::vector<Core::Manager*> m_managers;
    };
}<|endoftext|>


<commit_before>#include <cassert>
#include <cstdlib>
#include <memory>
#include <ostream>
#include <string>

#ifndef MATRIX_HPP
#define MATRIX_HPP

class Matrix;
typedef std::shared_ptr<Matrix> SMatrix;

int _matrix_index_for(int rows, int row, int col) { return col * rows + row; }

class Matrix {
public:
  int rows, cols;
  double *data;

  Matrix(int rows, int cols) {
    this->rows = rows;
    this->cols = cols;

    data = new double[rows * cols];
    for (auto i = 0; i < rows * cols; ++i) {
      data[i] = 0;
    }
  }

  template <typename T, std::size_t rowC, std::size_t colC>
  Matrix(T (&arr)[rowC][colC]) : Matrix(rowC, colC) {
    for (auto r = 0; r < rows; ++r) {
      for (auto c = 0; c < cols; ++c) {
        data[_matrix_index_for(rows, r, c)] = arr[r][c];
      }
    }
  }

  ~Matrix() { delete[] data; }

  SMatrix mean() {
    auto m = std::make_shared<Matrix>(1, cols);
    for (auto r = 0; r < rows; ++r) {
      for (auto c = 0; c < cols; ++c) {
        m->data[c] += data[_matrix_index_for(rows, r, c)];
      }
    }
    for (auto c = 0; c < cols; ++c) {
      m->data[c] /= rows;
    }
    return m;
  }

  SMatrix repeat(int makeRows, int copies) {
    assert(rows == 1);
    auto rm = std::make_shared<Matrix>(makeRows, cols * copies);
    for (auto r = 0; r < makeRows; ++r) {
      for (auto o = 0; o < copies; ++o) {
        for (auto c = 0; c < cols; ++c) {
          rm->data[_matrix_index_for(makeRows, r, o * cols + c)] =
              data[_matrix_index_for(rows, 0, c)];
        }
      }
    }
    return rm;
  }
};

std::ostream &operator<<(std::ostream &stream, const Matrix &matrix) {
  for (auto r = 0; r < matrix.rows; ++r) {
    for (auto c = 0; c < matrix.cols; ++c) {
      stream << matrix.data[_matrix_index_for(matrix.rows, r, c)];
      stream << " ";
    }
    stream << "\n";
  }
}

SMatrix operator-(const Matrix &m1, const Matrix &m2) {
  assert(m1.rows == m2.rows && m1.cols == m2.cols);
  auto rm = std::make_shared<Matrix>(m1.rows, m1.cols);
  for (auto i = 0; i < m1.rows * m2.cols; ++i) {
    rm->data[i] = m1.data[i] - m2.data[i];
  }
  return rm;
}

SMatrix operator-(const SMatrix &m1, const SMatrix &m2) {
  return *m1.get() - *m2.get();
}

bool operator==(const Matrix &m1, const Matrix &m2) {
  if (m1.rows != m2.rows || m1.cols != m2.cols) {
    return false;
  }
  for (auto i = 0; i < m1.rows * m1.cols; ++i) {
    if (m1.data[i] != m2.data[i])
      return false;
  }
  return true;
}

bool operator==(const SMatrix &m1, const Matrix &m2) { return *m1.get() == m2; }

#endif
<commit_msg>Remove stream code<commit_after>#include <cassert>
#include <cstdlib>
#include <memory>
#include <ostream>
#include <string>

#ifndef MATRIX_HPP
#define MATRIX_HPP

class Matrix;
typedef std::shared_ptr<Matrix> SMatrix;

int _matrix_index_for(int rows, int row, int col) { return col * rows + row; }

class Matrix {
public:
  int rows, cols;
  double *data;

  Matrix(int rows, int cols) {
    this->rows = rows;
    this->cols = cols;

    data = new double[rows * cols];
    for (auto i = 0; i < rows * cols; ++i) {
      data[i] = 0;
    }
  }

  template <typename T, std::size_t rowC, std::size_t colC>
  Matrix(T (&arr)[rowC][colC]) : Matrix(rowC, colC) {
    for (auto r = 0; r < rows; ++r) {
      for (auto c = 0; c < cols; ++c) {
        data[_matrix_index_for(rows, r, c)] = arr[r][c];
      }
    }
  }

  ~Matrix() { delete[] data; }

  SMatrix mean() {
    auto m = std::make_shared<Matrix>(1, cols);
    for (auto r = 0; r < rows; ++r) {
      for (auto c = 0; c < cols; ++c) {
        m->data[c] += data[_matrix_index_for(rows, r, c)];
      }
    }
    for (auto c = 0; c < cols; ++c) {
      m->data[c] /= rows;
    }
    return m;
  }

  SMatrix repeat(int makeRows, int copies) {
    assert(rows == 1);
    auto rm = std::make_shared<Matrix>(makeRows, cols * copies);
    for (auto r = 0; r < makeRows; ++r) {
      for (auto o = 0; o < copies; ++o) {
        for (auto c = 0; c < cols; ++c) {
          rm->data[_matrix_index_for(makeRows, r, o * cols + c)] =
              data[_matrix_index_for(rows, 0, c)];
        }
      }
    }
    return rm;
  }
};

SMatrix operator-(const Matrix &m1, const Matrix &m2) {
  assert(m1.rows == m2.rows && m1.cols == m2.cols);
  auto rm = std::make_shared<Matrix>(m1.rows, m1.cols);
  for (auto i = 0; i < m1.rows * m2.cols; ++i) {
    rm->data[i] = m1.data[i] - m2.data[i];
  }
  return rm;
}

SMatrix operator-(const SMatrix &m1, const SMatrix &m2) {
  return *m1.get() - *m2.get();
}

bool operator==(const Matrix &m1, const Matrix &m2) {
  if (m1.rows != m2.rows || m1.cols != m2.cols) {
    return false;
  }
  for (auto i = 0; i < m1.rows * m1.cols; ++i) {
    if (m1.data[i] != m2.data[i])
      return false;
  }
  return true;
}

bool operator==(const SMatrix &m1, const Matrix &m2) { return *m1.get() == m2; }

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {srs.las}
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// This example describes how to read a HDF (Hierarchical Data Format) file. This
// format is widely use to store remote sensing images especially use by the well-known MODIS (Moderate-resolution Imaging Spectroradiometer)
// scientific instrument launched into Earth orbit by NASA.
// HDF format is designed to store and organize large amounts of numerical data
// including multidimensional arrays, raster images, and tables.
// A specific feature of this format is that it works with container structures which can hold datasets and other groups
//
// The first step toward the use of these filters is to include the proper header files.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbVectorImage.h"
#include "otbImageFileReader.h"

int main(int argc, char * argv[])
{
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// We need now to declare the data types that we will be using and instanciate the
// reader (which is a \doxygen{otb}{PointSetFileReader}).
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  typedef unsigned char InputPixelType;
  const unsigned int Dimension = 2;
  typedef otb::VectorImage<InputPixelType,  Dimension> InputImageType;
  typedef otb::ImageFileReader<InputImageType> HDFReaderType;

  HDFReaderType::Pointer reader = HDFReaderType::New();
// Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // If you specify the path name of the hdf file, by default the reader will open the first dataset in the container.
  // Otherwise, there are 2 ways to access HDF subdatasets in OTB. The basic idea is to concatenate the subdataset
  // name or number to the input filename. For example myfile.hdf:SubdatasetName or myfile.hdf:SubdatasetNumber
  // In this example we will access the first dataset of the MODIS MOD09Q1G_EVI.A2006233.h07v03.005.2008338190308.hdf:1
  //
  // Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  const char * inputFilename  = argv[1];
  reader->SetFileName(inputFilename);
  reader->UpdateOutputInformation();
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// You can access to subdatasets list in the HDF file
//
// Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  otb::GDALImageIO::Pointer readerGDAL = otb::GDALImageIO::New();

  readerGDAL->SetFileName(inputFilename);

  std::vector<std::string> vectSubdatasetNames;
  std::vector<std::string> vectorSubdatasetDescriptions;

  if (readerGDAL->CanReadFile(inputFilename))
    {
    if (readerGDAL->GetSubDatasetInfo(vectSubdatasetNames, vectorSubdatasetDescriptions))
      {
      // Fill vDataset with subdataset descriptor info
      for( unsigned int itSubDataset = 0; itSubDataset < (unsigned int) vectorSubdatasetDescriptions.size(); itSubDataset++ )
        {
        std::cout << "Dataset Number " <<  itSubDataset+1 << " name is " << vectorSubdatasetDescriptions[itSubDataset].c_str() << std::endl;
        }
      }
    }
  // Software Guide : EndCodeSnippet
  return EXIT_SUCCESS;
}

<commit_msg>DOC:review of HDFREaderExample<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {GSSTF_NCEP.2b.2008.12.31.he5}
//    OUTPUTS: {HDFReaderExample.png}
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// This example describes how to read a MODIS image(Moderate-resolution Imaging Spectroradiometer)
// .This scientific instrument was launched into Earth orbit by NASA. The MODIS image format is HDF (Hierarchical Data Format). This
// format is widely use to store remote sensing images.
// HDF format is designed to store and organize large amounts of numerical data
// including multidimensional arrays, raster images, and tables.
// A specific feature of this format is that it works with container structures which can hold datasets and other groups. It implies that
// access to these structures in OTB presents some adaptations compare to other image formats.
// OTB is using GDAL to support HDF. HDF4 and HDF5 supports in Gdal is not activated by default. You need to download the HDF run-time
// libraries and compile Gdal by adding the support of these formats. You can find more informations here : \url{http://trac.osgeo.org/gdal/wiki/HDF}
//
//
// The first step toward the use of these filters is to include the proper header files.
//
// Software Guide : EndLatex

#include <sstream>
// Software Guide : BeginCodeSnippet
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

int main(int argc, char * argv[])
{
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// We need now to declare the data types that we will be using and instanciate the
// reader (which is a \doxygen{otb}{PointSetFileReader}).
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  typedef unsigned char InputPixelType;
  const unsigned int Dimension = 2;
  typedef otb::VectorImage<InputPixelType,  Dimension> InputImageType;
  typedef otb::ImageFileReader<InputImageType> HDFReaderType;
  typedef otb::ImageFileWriter<InputImageType> HDFWriterType;

  HDFReaderType::Pointer reader = HDFReaderType::New();
// Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // If you specify the path name of the hdf file, by default the reader will open the first dataset in the container.
  // Otherwise, there are 2 ways to access HDF subdatasets in OTB. The basic idea is to concatenate the subdataset
  // name or number to the input filename. The ':' character is the standard separator in the input filename.
  // For example myfile.hdf:SubdatasetName or myfile.hdf:SubdatasetNumber
  // In this example we will access the first dataset of the MODIS MOD09Q1G_EVI.A2006233.h07v03.005.2008338190308.hdf:0
  //
  // Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  const std::string inputFilename (argv[1]);
  const std::string outputFilename (argv[2]);
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// You can access to subdatasets' informations available in the HDF file using
// the \code{GetSubDatasetInfo} method of \doxygen{otb}{GDALImageIO}.
// It allows to store HDF subdatasets names and descriptions in vector of string.
// You can find below how to print the name and the decription
// of all the subdatasets.
//
// Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  otb::GDALImageIO::Pointer readerGDAL = otb::GDALImageIO::New();

  readerGDAL->SetFileName(inputFilename.c_str());

  std::vector<std::string> vectSubdatasetNames;
  std::vector<std::string> vectorSubdatasetDescriptions;

  if (readerGDAL->CanReadFile(inputFilename.c_str()))
    {
    if (readerGDAL->GetSubDatasetInfo(vectSubdatasetNames, vectorSubdatasetDescriptions))
      {
      // Fill vDataset with subdataset descriptor info
      for( unsigned int itSubDataset = 0; itSubDataset < (unsigned int) vectorSubdatasetDescriptions.size(); itSubDataset++ )
        {
        std::cout << "Dataset Number " <<  itSubDataset << " name is: " << vectSubdatasetNames[itSubDataset].c_str()
            << " and description is: " << vectSubdatasetNames[itSubDataset].c_str() << std::endl;
        }
      }
    }
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Then we write the first dataset of the MODIS product. As explained above,
  // we instantiate the reader with the correct input filename.
  //
  // Software Guide : EndLatex
  HDFWriterType::Pointer writer = HDFWriterType::New();

  // Software Guide : BeginCodeSnippet
  std::ostringstream out;
  out << inputFilename;
  out << ":";
  out << 0;

  reader->SetFileName(out.str());
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // We can then built the pipeline And execute it by calling the \code{Update} method of
  //  the writer.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  writer->SetFileName(outputFilename.c_str());
  writer->SetInput(reader->GetOutput());

  writer->Update();
  // Software Guide : EndCodeSnippet

  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // \begin{figure}
  // \center
  // \includegraphics[width=0.44\textwidth]{HDFReaderExample0.eps}
  // \itkcaption[HDF Dataset]{Quicklook of the first dataset extraction of MODIS product.}
  // \label{fig:IMAGERY_HDF_0}
  // \end{figure}
  //
  //
  //  Figures \ref{fig:IMAGERY_HDF_0} illustrates the extraction of MODIS
  //  subdataset through \doxygen{otb}{ImageFileReader}.
  //
  //  Software Guide : EndLatex
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int neutralTable[KEY_CNT];
void initNeutralTable(){
    int i;
    for (i = 0; i < KEY_CNT; ++i){
        neutralTable[i] = i;
    }

    neutralTable[KEY_Q         ] = KEY_APOSTROPHE;
    neutralTable[KEY_W         ] = KEY_COMMA;
    neutralTable[KEY_E         ] = KEY_DOT;
    neutralTable[KEY_R         ] = KEY_P;
    neutralTable[KEY_T         ] = KEY_Y;
    neutralTable[KEY_Y         ] = KEY_F;
    neutralTable[KEY_U         ] = KEY_G;
    neutralTable[KEY_I         ] = KEY_C;
    neutralTable[KEY_O         ] = KEY_R;
    neutralTable[KEY_P         ] = KEY_L;
    neutralTable[KEY_LEFTBRACE ] = KEY_SLASH;
    neutralTable[KEY_S         ] = KEY_O;
    neutralTable[KEY_D         ] = KEY_E;
    neutralTable[KEY_F         ] = KEY_U;
    neutralTable[KEY_G         ] = KEY_I;
    neutralTable[KEY_H         ] = KEY_D;
    neutralTable[KEY_J         ] = KEY_H;
    neutralTable[KEY_K         ] = KEY_T;
    neutralTable[KEY_L         ] = KEY_N;
    neutralTable[KEY_SEMICOLON ] = KEY_S;
    neutralTable[KEY_APOSTROPHE] = KEY_MINUS;
    neutralTable[KEY_Z         ] = KEY_SEMICOLON;
    neutralTable[KEY_X         ] = KEY_Q;
    neutralTable[KEY_C         ] = KEY_J;
    neutralTable[KEY_V         ] = KEY_K;
    neutralTable[KEY_B         ] = KEY_X;
    neutralTable[KEY_N         ] = KEY_B;
    neutralTable[KEY_M         ] = KEY_M;
    neutralTable[KEY_COMMA     ] = KEY_W;
    neutralTable[KEY_DOT       ] = KEY_V;
    neutralTable[KEY_SLASH     ] = KEY_Z;

    neutralTable[KEY_CAPSLOCK] = KEY_LEFTCTRL;
    neutralTable[KEY_MUHENKAN] = KEY_LEFTMETA;
    neutralTable[KEY_HANJA   ] = KEY_LEFTMETA;
}

int henkanTable[KEY_CNT];
void initHenkanTable(){
    int i;
    for (i = 0; i < KEY_CNT; ++i){
        henkanTable[i] = i;
    }

    henkanTable[KEY_Q         ] = KEY_1;
    henkanTable[KEY_W         ] = KEY_2;
    henkanTable[KEY_E         ] = KEY_3;
    henkanTable[KEY_R         ] = KEY_4;
    henkanTable[KEY_T         ] = KEY_5;
    henkanTable[KEY_Y         ] = KEY_6;
    henkanTable[KEY_U         ] = KEY_7;
    henkanTable[KEY_I         ] = KEY_8;
    henkanTable[KEY_O         ] = KEY_9;
    henkanTable[KEY_P         ] = KEY_0;
    henkanTable[KEY_LEFTBRACE ] = KEY_SLASH;
    henkanTable[KEY_A         ] = KEY_TAB;
    henkanTable[KEY_S         ] = KEY_ESC;
    henkanTable[KEY_D         ] = KEY_ENTER;
    henkanTable[KEY_F         ] = KEY_BACKSPACE;
    henkanTable[KEY_G         ] = KEY_DELETE;
    henkanTable[KEY_H         ] = KEY_LEFTBRACE;
    henkanTable[KEY_J         ] = KEY_RO;
    henkanTable[KEY_K         ] = KEY_RIGHTBRACE;
    henkanTable[KEY_L         ] = KEY_BACKSLASH;
    henkanTable[KEY_SEMICOLON ] = KEY_YEN;
    henkanTable[KEY_APOSTROPHE] = KEY_MINUS;
    henkanTable[KEY_Z         ] = KEY_LEFT;
    henkanTable[KEY_X         ] = KEY_DOWN;
    henkanTable[KEY_C         ] = KEY_UP;
    henkanTable[KEY_V         ] = KEY_RIGHT;
    henkanTable[KEY_B         ] = KEY_X;
    henkanTable[KEY_N         ] = KEY_B;
    henkanTable[KEY_M         ] = KEY_GRAVE;
    henkanTable[KEY_COMMA     ] = KEY_HOME;
    henkanTable[KEY_DOT       ] = KEY_END;
    henkanTable[KEY_SLASH     ] = KEY_EQUAL;

    henkanTable[KEY_CAPSLOCK] = KEY_LEFTCTRL;
    henkanTable[KEY_MUHENKAN] = KEY_LEFTMETA;
    henkanTable[KEY_HANJA   ] = KEY_LEFTMETA;
}

static int do_terminate = 0;

void exit_with_error(const char* str) {
    perror(str);
    exit(EXIT_FAILURE);
}

void send_event(int fd, int type, int code, int value) {
    struct input_event event;
    memset(&event, 0, sizeof(event));

    gettimeofday(&event.time, NULL);

    event.type = type;
    event.code = code;
    event.value = value;

    if (write(fd, &event, sizeof(event)) < 0) {
        exit_with_error("error: write");
    }
}

void ioctl_set(int fd, int set, int value) {
    if (ioctl(fd, set, value) < 0) {
        exit_with_error("error: ioctl failed");
    }
}

void create_uinput_device (int fd) {
    struct uinput_user_dev uidev;
    memset(&uidev, 0, sizeof(uidev));

    snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Dudrack");
    uidev.id.bustype = BUS_USB;
    uidev.id.vendor  = 0xDEAD;
    uidev.id.product = 0xBEEF;
    uidev.id.version = 1;

    if (write(fd, &uidev, sizeof(uidev)) < 0) {
        exit_with_error("create_uinput_device: write");
    }

    if (ioctl(fd, UI_DEV_CREATE) < 0) {
        exit_with_error("create_uinput_device: ioctl");
    }
}

void destroy_uinput_device(int fd) {
    if (ioctl(fd, UI_DEV_DESTROY) < 0) {
        exit_with_error("destroy_uinput_device: ioctl");
    }
}

void on_signal(int signal) {
    printf("TERM\n");
    do_terminate = 1;
}

void set_signal_handler() {
    sigset_t mask;
    sigemptyset(&mask);
    signal(SIGTERM, on_signal);
    signal(SIGINT, on_signal);
    sigaddset(&mask, SIGTERM);
    sigaddset(&mask, SIGINT);
    sigprocmask(SIG_UNBLOCK, &mask, NULL);
}

int main(int argc, char** argv) {
    if (argc != 2) {
        exit_with_error("Usage: dudrack <INPUT_DEVICE_EVENT>");
    }

    int input_device;
    while ((input_device = open(argv[1], O_RDONLY)) < 0) {
        usleep(1);
    }

    int output_device;
    while ((output_device = open("/dev/uinput", O_WRONLY | O_NONBLOCK)) < 0) {
        usleep(1);
    }

    ioctl_set(output_device, UI_SET_EVBIT, EV_KEY);
    for (int i = 0; i < KEY_CNT; ++i){
        ioctl_set(output_device, UI_SET_KEYBIT, i);
    }

    create_uinput_device(output_device);

    struct input_event event;
    int size_read;

    set_signal_handler();

    initNeutralTable();
    initHenkanTable();

    for (int i = 0; i < KEY_CNT; ++i) {
        send_event(output_device, EV_KEY, i, 0);
    }

    ioctl(input_device, EVIOCGRAB, 1);

    bool is_henkan = false, use_dudrack = true;
    int space_key_state = 0;
    while (!do_terminate && (size_read = read(input_device, &event, sizeof(struct input_event)))) {
        if (size_read < 0) {
            continue;
        }

        if (event.type == EV_KEY) {
            if (event.code == KEY_PAGEUP) {
                use_dudrack = true;
                continue;
            } else if (event.code == KEY_PAGEDOWN) {
                use_dudrack = false;
                continue;
            }

            if (use_dudrack) {
                if (event.code == KEY_HENKAN || event.code == KEY_HANGEUL) {
                    is_henkan = event.value;
                    continue;
                }

                // SandS
                if (event.code == KEY_SPACE) {
                    switch (space_key_state) {
                        case 0:
                            if (event.value > 0) {
                                space_key_state = 1;
                            }
                            continue;

                        case 1:
                            if (event.value == 0) {
                                send_event(output_device, EV_KEY, KEY_SPACE, 1);
                                send_event(output_device, EV_SYN, SYN_REPORT, 0);
                                send_event(output_device, EV_KEY, KEY_SPACE, 0);
                                send_event(output_device, EV_SYN, SYN_REPORT, 0);
                                space_key_state = 0;
                            }
                            continue;

                        case 2:
                            if (event.value == 0) {
                                send_event(output_device, EV_KEY, KEY_LEFTSHIFT, 0);
                                space_key_state = 0;
                            }
                            continue;
                    }
                }

                if (event.code != KEY_SPACE && event.value > 0 && space_key_state == 1) {
                    send_event(output_device, EV_KEY, KEY_LEFTSHIFT, 1);
                    space_key_state = 2;
                }

                if (event.value > 0) {
                    int key_code = is_henkan ? henkanTable[event.code] : neutralTable[event.code];
                    send_event(output_device, EV_KEY, key_code, 1);
                }

                if (event.value == 0) {
                    send_event(output_device, EV_KEY, neutralTable[event.code], 0);
                    send_event(output_device, EV_KEY, henkanTable[event.code], 0);
                }
            } else {
                if (event.code == KEY_HENKAN || event.code == KEY_HANGEUL) {
                    is_henkan = event.value;
                }
                send_event(output_device, EV_KEY, event.code, event.value);
            }

            send_event(output_device, EV_SYN, SYN_REPORT, 0);
        }
    }

    ioctl(input_device, EVIOCGRAB, 0);

    destroy_uinput_device(output_device);

    close(output_device);
    close(input_device);

    exit(EXIT_SUCCESS);
}
<commit_msg>Use muhenkan as shift + henkan<commit_after>#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int neutralTable[KEY_CNT];
void initNeutralTable(){
    int i;
    for (i = 0; i < KEY_CNT; ++i){
        neutralTable[i] = i;
    }

    neutralTable[KEY_Q         ] = KEY_APOSTROPHE;
    neutralTable[KEY_W         ] = KEY_COMMA;
    neutralTable[KEY_E         ] = KEY_DOT;
    neutralTable[KEY_R         ] = KEY_P;
    neutralTable[KEY_T         ] = KEY_Y;
    neutralTable[KEY_Y         ] = KEY_F;
    neutralTable[KEY_U         ] = KEY_G;
    neutralTable[KEY_I         ] = KEY_C;
    neutralTable[KEY_O         ] = KEY_R;
    neutralTable[KEY_P         ] = KEY_L;
    neutralTable[KEY_LEFTBRACE ] = KEY_SLASH;
    neutralTable[KEY_S         ] = KEY_O;
    neutralTable[KEY_D         ] = KEY_E;
    neutralTable[KEY_F         ] = KEY_U;
    neutralTable[KEY_G         ] = KEY_I;
    neutralTable[KEY_H         ] = KEY_D;
    neutralTable[KEY_J         ] = KEY_H;
    neutralTable[KEY_K         ] = KEY_T;
    neutralTable[KEY_L         ] = KEY_N;
    neutralTable[KEY_SEMICOLON ] = KEY_S;
    neutralTable[KEY_APOSTROPHE] = KEY_MINUS;
    neutralTable[KEY_Z         ] = KEY_SEMICOLON;
    neutralTable[KEY_X         ] = KEY_Q;
    neutralTable[KEY_C         ] = KEY_J;
    neutralTable[KEY_V         ] = KEY_K;
    neutralTable[KEY_B         ] = KEY_X;
    neutralTable[KEY_N         ] = KEY_B;
    neutralTable[KEY_M         ] = KEY_M;
    neutralTable[KEY_COMMA     ] = KEY_W;
    neutralTable[KEY_DOT       ] = KEY_V;
    neutralTable[KEY_SLASH     ] = KEY_Z;

    neutralTable[KEY_CAPSLOCK        ] = KEY_LEFTCTRL;
    neutralTable[KEY_MUHENKAN        ] = KEY_LEFTSHIFT;
    neutralTable[KEY_HANJA           ] = KEY_LEFTSHIFT;
    neutralTable[KEY_LEFTALT         ] = KEY_LEFTMETA;
    neutralTable[KEY_KATAKANAHIRAGANA] = KEY_RIGHTMETA;
}

int henkanTable[KEY_CNT];
void initHenkanTable(){
    int i;
    for (i = 0; i < KEY_CNT; ++i){
        henkanTable[i] = i;
    }

    henkanTable[KEY_Q         ] = KEY_1;
    henkanTable[KEY_W         ] = KEY_2;
    henkanTable[KEY_E         ] = KEY_3;
    henkanTable[KEY_R         ] = KEY_4;
    henkanTable[KEY_T         ] = KEY_5;
    henkanTable[KEY_Y         ] = KEY_6;
    henkanTable[KEY_U         ] = KEY_7;
    henkanTable[KEY_I         ] = KEY_8;
    henkanTable[KEY_O         ] = KEY_9;
    henkanTable[KEY_P         ] = KEY_0;
    henkanTable[KEY_LEFTBRACE ] = KEY_SLASH;
    henkanTable[KEY_A         ] = KEY_TAB;
    henkanTable[KEY_S         ] = KEY_ESC;
    henkanTable[KEY_D         ] = KEY_ENTER;
    henkanTable[KEY_F         ] = KEY_BACKSPACE;
    henkanTable[KEY_G         ] = KEY_DELETE;
    henkanTable[KEY_H         ] = KEY_LEFTBRACE;
    henkanTable[KEY_J         ] = KEY_RO;
    henkanTable[KEY_K         ] = KEY_RIGHTBRACE;
    henkanTable[KEY_L         ] = KEY_BACKSLASH;
    henkanTable[KEY_SEMICOLON ] = KEY_YEN;
    henkanTable[KEY_APOSTROPHE] = KEY_MINUS;
    henkanTable[KEY_Z         ] = KEY_LEFT;
    henkanTable[KEY_X         ] = KEY_DOWN;
    henkanTable[KEY_C         ] = KEY_UP;
    henkanTable[KEY_V         ] = KEY_RIGHT;
    henkanTable[KEY_B         ] = KEY_X;
    henkanTable[KEY_N         ] = KEY_B;
    henkanTable[KEY_M         ] = KEY_GRAVE;
    henkanTable[KEY_COMMA     ] = KEY_HOME;
    henkanTable[KEY_DOT       ] = KEY_END;
    henkanTable[KEY_SLASH     ] = KEY_EQUAL;

    henkanTable[KEY_CAPSLOCK        ] = KEY_LEFTCTRL;
    henkanTable[KEY_MUHENKAN        ] = KEY_LEFTSHIFT;
    henkanTable[KEY_HANJA           ] = KEY_LEFTSHIFT;
    henkanTable[KEY_LEFTALT         ] = KEY_LEFTMETA;
    henkanTable[KEY_KATAKANAHIRAGANA] = KEY_RIGHTMETA;
}

static int do_terminate = 0;

void exit_with_error(const char* str) {
    perror(str);
    exit(EXIT_FAILURE);
}

void send_event(int fd, int type, int code, int value) {
    struct input_event event;
    memset(&event, 0, sizeof(event));

    gettimeofday(&event.time, NULL);

    event.type = type;
    event.code = code;
    event.value = value;

    if (write(fd, &event, sizeof(event)) < 0) {
        exit_with_error("error: write");
    }
}

void ioctl_set(int fd, int set, int value) {
    if (ioctl(fd, set, value) < 0) {
        exit_with_error("error: ioctl failed");
    }
}

void create_uinput_device (int fd) {
    struct uinput_user_dev uidev;
    memset(&uidev, 0, sizeof(uidev));

    snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Dudrack");
    uidev.id.bustype = BUS_USB;
    uidev.id.vendor  = 0xDEAD;
    uidev.id.product = 0xBEEF;
    uidev.id.version = 1;

    if (write(fd, &uidev, sizeof(uidev)) < 0) {
        exit_with_error("create_uinput_device: write");
    }

    if (ioctl(fd, UI_DEV_CREATE) < 0) {
        exit_with_error("create_uinput_device: ioctl");
    }
}

void destroy_uinput_device(int fd) {
    if (ioctl(fd, UI_DEV_DESTROY) < 0) {
        exit_with_error("destroy_uinput_device: ioctl");
    }
}

void on_signal(int signal) {
    printf("TERM\n");
    do_terminate = 1;
}

void set_signal_handler() {
    sigset_t mask;
    sigemptyset(&mask);
    signal(SIGTERM, on_signal);
    signal(SIGINT, on_signal);
    sigaddset(&mask, SIGTERM);
    sigaddset(&mask, SIGINT);
    sigprocmask(SIG_UNBLOCK, &mask, NULL);
}

int main(int argc, char** argv) {
    if (argc != 2) {
        exit_with_error("Usage: dudrack <INPUT_DEVICE_EVENT>");
    }

    int input_device;
    while ((input_device = open(argv[1], O_RDONLY)) < 0) {
        usleep(1);
    }

    int output_device;
    while ((output_device = open("/dev/uinput", O_WRONLY | O_NONBLOCK)) < 0) {
        usleep(1);
    }

    ioctl_set(output_device, UI_SET_EVBIT, EV_KEY);
    for (int i = 0; i < KEY_CNT; ++i){
        ioctl_set(output_device, UI_SET_KEYBIT, i);
    }

    create_uinput_device(output_device);

    struct input_event event;
    int size_read;

    set_signal_handler();

    initNeutralTable();
    initHenkanTable();

    for (int i = 0; i < KEY_CNT; ++i) {
        send_event(output_device, EV_KEY, i, 0);
    }

    ioctl(input_device, EVIOCGRAB, 1);

    bool is_henkan = false, is_muhenkan = false, use_dudrack = true;
    int space_key_state = 0;
    while (!do_terminate && (size_read = read(input_device, &event, sizeof(struct input_event)))) {
        if (size_read < 0) {
            continue;
        }

        if (event.type == EV_KEY) {
            if (event.code == KEY_PAGEUP) {
                use_dudrack = true;
                continue;
            } else if (event.code == KEY_PAGEDOWN) {
                use_dudrack = false;
                continue;
            }

            if (use_dudrack) {
                if (event.code == KEY_HENKAN || event.code == KEY_HANGEUL) {
                    is_henkan = event.value;
                    continue;
                }

                if (event.code == KEY_MUHENKAN || event.code == KEY_HANJA) {
                    is_muhenkan = event.value;
                }

                // SandS
                if (event.code == KEY_SPACE) {
                    switch (space_key_state) {
                        case 0:
                            if (event.value > 0) {
                                space_key_state = 1;
                            }
                            continue;

                        case 1:
                            if (event.value == 0) {
                                send_event(output_device, EV_KEY, KEY_SPACE, 1);
                                send_event(output_device, EV_KEY, KEY_SPACE, 0);
                                send_event(output_device, EV_SYN, SYN_REPORT, 0);
                                space_key_state = 0;
                            }
                            continue;

                        case 2:
                            if (event.value == 0) {
                                send_event(output_device, EV_KEY, KEY_LEFTSHIFT, 0);
                                space_key_state = 0;
                            }
                            continue;
                    }
                }

                if (event.code != KEY_SPACE && event.value > 0 && space_key_state == 1) {
                    send_event(output_device, EV_KEY, KEY_LEFTSHIFT, 1);
                    space_key_state = 2;
                }

                if (event.value > 0) {
                    int key_code = (is_henkan || is_muhenkan) ? henkanTable[event.code] : neutralTable[event.code];
                    send_event(output_device, EV_KEY, key_code, 1);

                    if (event.code == KEY_MUHENKAN || event.code == KEY_HANJA) {
                        send_event(output_device, EV_KEY, KEY_LEFTSHIFT, 1);
                    }
                }

                if (event.value == 0) {
                    send_event(output_device, EV_KEY, neutralTable[event.code], 0);
                    send_event(output_device, EV_KEY, henkanTable[event.code], 0);

                    if (event.code == KEY_MUHENKAN || event.code == KEY_HANJA) {
                        send_event(output_device, EV_KEY, KEY_LEFTSHIFT, 0);
                    }
                }
            } else {
                if (event.code == KEY_HENKAN || event.code == KEY_HANGEUL) {
                    is_henkan = event.value;
                }

                if (event.code == KEY_MUHENKAN || event.code == KEY_HANJA) {
                    is_muhenkan = event.value;
                }

                send_event(output_device, EV_KEY, event.code, event.value);
            }

            send_event(output_device, EV_SYN, SYN_REPORT, 0);
        }
    }

    ioctl(input_device, EVIOCGRAB, 0);

    destroy_uinput_device(output_device);

    close(output_device);
    close(input_device);

    exit(EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "lighting.h"

#include <QtGui>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0)
{
    setScene(&m_scene);

    setupScene();

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(animate()));
    timer->setInterval(30);
    timer->start();

    setRenderHint(QPainter::Antialiasing, true);
    setFrameStyle(QFrame::NoFrame);
}

void Lighting::setupScene()
{
    m_scene.setSceneRect(-300, -200, 600, 460);

    QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100));
    linearGrad.setColorAt(0, QColor(255, 255, 255));
    linearGrad.setColorAt(1, QColor(192, 192, 255));
    setBackgroundBrush(linearGrad);

    QRadialGradient radialGrad(30, 30, 30);
    radialGrad.setColorAt(0, Qt::yellow);
    radialGrad.setColorAt(0.2, Qt::yellow);
    radialGrad.setColorAt(1, Qt::transparent);
    QPixmap pixmap(60, 60);
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setPen(Qt::NoPen);
    painter.setBrush(radialGrad);
    painter.drawEllipse(0, 0, 60, 60);
    painter.end();

    m_lightSource = m_scene.addPixmap(pixmap);
    m_lightSource->setZValue(2);

    for (int i = -2; i < 3; ++i)
        for (int j = -2; j < 3; ++j) {
            QAbstractGraphicsShapeItem *item;
            if ((i + j) & 1)
                item = new QGraphicsEllipseItem(0, 0, 50, 50);
            else
                item = new QGraphicsRectItem(0, 0, 50, 50);

            item->setPen(QPen(Qt::black));
            item->setBrush(QBrush(Qt::white));
            item->setGraphicsEffect(new QGraphicsDropShadowEffect);
            item->setZValue(1);
            item->setPos(i * 80, j * 80);
            m_scene.addItem(item);
            m_items << item;
        }

}

void Lighting::animate()
{
    angle += (M_PI / 30);
    qreal xs = 200 * sin(angle) - 40 + 25;
    qreal ys = 200 * cos(angle) - 40 + 25;
    m_lightSource->setPos(xs, ys);

    for (int i = 0; i < m_items.size(); ++i) {
        QGraphicsItem *item = m_items.at(i);
        Q_ASSERT(item);
        QGraphicsDropShadowEffect *effect = static_cast<QGraphicsDropShadowEffect *>(item->graphicsEffect());
        Q_ASSERT(effect);

        QPointF delta(item->x() - xs, item->y() - ys);
        effect->setOffset(delta.toPoint() / 30);

        qreal dx = delta.x();
        qreal dy = delta.y();
        qreal dd = sqrt(dx * dx + dy * dy);
        QColor color = effect->color();
        color.setAlphaF(qBound(0.4, 1 - dd / 200.0, 0.7));
        effect->setColor(color);
    }

    m_scene.update();
}

<commit_msg>Bring back the blurry drop shadow in the lighting example.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "lighting.h"

#include <QtGui>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0)
{
    setScene(&m_scene);

    setupScene();

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(animate()));
    timer->setInterval(30);
    timer->start();

    setRenderHint(QPainter::Antialiasing, true);
    setFrameStyle(QFrame::NoFrame);
}

void Lighting::setupScene()
{
    m_scene.setSceneRect(-300, -200, 600, 460);

    QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100));
    linearGrad.setColorAt(0, QColor(255, 255, 255));
    linearGrad.setColorAt(1, QColor(192, 192, 255));
    setBackgroundBrush(linearGrad);

    QRadialGradient radialGrad(30, 30, 30);
    radialGrad.setColorAt(0, Qt::yellow);
    radialGrad.setColorAt(0.2, Qt::yellow);
    radialGrad.setColorAt(1, Qt::transparent);
    QPixmap pixmap(60, 60);
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setPen(Qt::NoPen);
    painter.setBrush(radialGrad);
    painter.drawEllipse(0, 0, 60, 60);
    painter.end();

    m_lightSource = m_scene.addPixmap(pixmap);
    m_lightSource->setZValue(2);

    for (int i = -2; i < 3; ++i)
        for (int j = -2; j < 3; ++j) {
            QAbstractGraphicsShapeItem *item;
            if ((i + j) & 1)
                item = new QGraphicsEllipseItem(0, 0, 50, 50);
            else
                item = new QGraphicsRectItem(0, 0, 50, 50);

            item->setPen(QPen(Qt::black));
            item->setBrush(QBrush(Qt::white));
            QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
            effect->setBlurRadius(8);
            item->setGraphicsEffect(effect);
            item->setZValue(1);
            item->setPos(i * 80, j * 80);
            m_scene.addItem(item);
            m_items << item;
        }

}

void Lighting::animate()
{
    angle += (M_PI / 30);
    qreal xs = 200 * sin(angle) - 40 + 25;
    qreal ys = 200 * cos(angle) - 40 + 25;
    m_lightSource->setPos(xs, ys);

    for (int i = 0; i < m_items.size(); ++i) {
        QGraphicsItem *item = m_items.at(i);
        Q_ASSERT(item);
        QGraphicsDropShadowEffect *effect = static_cast<QGraphicsDropShadowEffect *>(item->graphicsEffect());
        Q_ASSERT(effect);

        QPointF delta(item->x() - xs, item->y() - ys);
        effect->setOffset(delta.toPoint() / 30);

        qreal dx = delta.x();
        qreal dy = delta.y();
        qreal dd = sqrt(dx * dx + dy * dy);
        QColor color = effect->color();
        color.setAlphaF(qBound(0.4, 1 - dd / 200.0, 0.7));
        effect->setColor(color);
    }

    m_scene.update();
}

<|endoftext|>


<commit_before>#include "bandit_base.h"
#include "msg.h"

go_bandit([]()
{
    describe("Msg add and str", []()
    {
        PtrT<Msg> pMsgWithString;
        PtrT<Msg> pMsgWithInt;
        PtrT<Msg> pMsgWithFloat;
        before_each([&]() {
            pMsgWithString.reset(new Msg(cstr("Hello %s.")));
            pMsgWithInt.reset(new Msg(cstr("Lucky %d.")));
            pMsgWithFloat.reset(new Msg(cstr("%f %% juice.")));
        });

        describe("Msg with string", [&]() {
            it("adds world", [&](){
                pMsgWithString->add("world");
                AssertThat(pMsgWithString->str(), Equals("Hello world."));
            });
            it("adds John", [&](){
                pMsgWithString->add("John");
                AssertThat(pMsgWithString->str(), Equals("Hello John."));
            });
        });

        describe("Add integer to MsgWithInt", [&]() {
            it("adds 7", [&]() {
                pMsgWithInt->add(7);
                AssertThat(pMsgWithInt->str(), Equals("Lucky 7."));
            });

            it("adds 5566", [&]() {
                pMsgWithInt->add(5566);
                AssertThat(pMsgWithInt->str(), Equals("Lucky 5566."));
            });
        });

        describe("Add float number to MsgWithFloat", [&]() {
            it("adds 75.5", [&]() {
                pMsgWithFloat->add(75.5);
                AssertThat(pMsgWithInt->str(), Equals("75.5 % juice."));
            });

            it("adds 100.0", [&]() {
                pMsgWithFloat->add(100.0);
                AssertThat(pMsgWithInt->str(), Equals("100 % juice."));
            });
        });

    });

    describe("args counts", [&]() {
        it("runs no args", [&]() {
            AssertThat(Msg(cstr("%% %%")).count_args(), Equals(0));
            AssertThat(Msg(cstr("abc abc %% %%")).count_args(), Equals(0));
            AssertThat(Msg(cstr("dce de%%")).count_args(), Equals(0));
            AssertThat(Msg(cstr("asflkjsafklw")).count_args(), Equals(0));
        });

        it("runs 1 arg", [&]() {
            AssertThat(Msg(cstr("%% %d")).count_args(), Equals(1));
            AssertThat(Msg(cstr("abc %f abc %% %%")).count_args(), Equals(1));
            AssertThat(Msg(cstr("dce%d de%%")).count_args(), Equals(1));
            AssertThat(Msg(cstr("asfl%skjsafklw")).count_args(), Equals(1));
        });

        it("runs 5 args", [&]() {
            AssertThat(Msg(cstr("%s %d %d %f %s")).count_args(), Equals(5));
            AssertThat(Msg(cstr("%sf%s%d%fa%sf")).count_args(), Equals(5));
            AssertThat(Msg(cstr("%f%s%d%%s%f%%s%d")).count_args(), Equals(5));
            AssertThat(Msg(cstr("Hello %s %f is %d and %d and %f")).count_args(), Equals(5));
        });
    });

    describe("str args counts", [&]() {
        it("runs no args", [&]() {
            AssertThat(Msg(cstr("%% %%")).count_args(Msg::ArgType::Str), Equals(0));
        });
        it("runs 0 arg - 2", [&](){
            AssertThat(Msg(cstr("abc abc %f %%")).count_args(Msg::ArgType::Str), Equals(0));
        });
        it("runs 0 arg - 3", [&](){
            AssertThat(Msg(cstr("dce de%d")).count_args(Msg::ArgType::Str), Equals(0));
        });
        it("runs 0 arg - 4", [&](){
            AssertThat(Msg(cstr("as%flkjs%daklw")).count_args(Msg::ArgType::Str), Equals(0));
        });

        it("runs 1 arg - 1", [&]() {
            AssertThat(Msg(cstr("%s %d")).count_args(Msg::ArgType::Str), Equals(1));
        });
        it("runs 1 arg - 2", [&](){
            AssertThat(Msg(cstr("abc %s abc %% %%")).count_args(Msg::ArgType::Str), Equals(1));
        });
        it("runs 1 arg - 3", [&](){
            AssertThat(Msg(cstr("dce%d de%s")).count_args(Msg::ArgType::Str), Equals(1));
        });
        it("runs 1 arg - 4", [&](){
            AssertThat(Msg(cstr("asfl%skjsafklw")).count_args(Msg::ArgType::Str), Equals(1));
        });

        it("runs 5 args", [&]() {
            AssertThat(Msg(cstr("%s %s %s %s %s")).count_args(Msg::ArgType::Str), Equals(5));
        });
        it("runs 5 args - 2", [&]() {
            AssertThat(Msg(cstr("%sf%s%d%sa%sf%s")).count_args(Msg::ArgType::Str), Equals(5));
        });
        it("runs 5 args - 3", [&]() {
            AssertThat(Msg(cstr("%%s%s%s%%d%%s%f%s%d%s%%%s")).count_args(Msg::ArgType::Str), Equals(5));
        });
        it("runs 5 args - 4", [&]() {
            AssertThat(Msg(cstr("Hello %s %s is %s and %s and %s")).count_args(Msg::ArgType::Str), Equals(5));
        });
    });
});
<commit_msg>refine args counting test and still pass<commit_after>#include "bandit_base.h"
#include "msg.h"

go_bandit([]()
{
    describe("Msg add and str", []()
    {
        PtrT<Msg> pMsgWithString;
        PtrT<Msg> pMsgWithInt;
        PtrT<Msg> pMsgWithFloat;
        before_each([&]() {
            pMsgWithString.reset(new Msg(cstr("Hello %s.")));
            pMsgWithInt.reset(new Msg(cstr("Lucky %d.")));
            pMsgWithFloat.reset(new Msg(cstr("%f %% juice.")));
        });

        describe("Msg with string", [&]() {
            it("adds world", [&](){
                pMsgWithString->add("world");
                AssertThat(pMsgWithString->str(), Equals("Hello world."));
            });
            it("adds John", [&](){
                pMsgWithString->add("John");
                AssertThat(pMsgWithString->str(), Equals("Hello John."));
            });
        });

        describe("Add integer to MsgWithInt", [&]() {
            it("adds 7", [&]() {
                pMsgWithInt->add(7);
                AssertThat(pMsgWithInt->str(), Equals("Lucky 7."));
            });

            it("adds 5566", [&]() {
                pMsgWithInt->add(5566);
                AssertThat(pMsgWithInt->str(), Equals("Lucky 5566."));
            });
        });

        describe("Add float number to MsgWithFloat", [&]() {
            it("adds 75.5", [&]() {
                pMsgWithFloat->add(75.5);
                AssertThat(pMsgWithInt->str(), Equals("75.5 % juice."));
            });

            it("adds 100.0", [&]() {
                pMsgWithFloat->add(100.0);
                AssertThat(pMsgWithInt->str(), Equals("100 % juice."));
            });
        });

    });

    describe("counts_args", [&]() {
        Msg msg(cstr("%%s%s%s%%d%%s%f%s%d%s%%%s%f%%f%f%d%%d%d%%d%%%d"));
        //             %  s s %  %  f s d s % s f %  f d %  d %  % d

        it("counts str", [&]() {
            AssertThat(msg.count_args(Msg::ArgType::Str), Equals(5));
        });

        it("counts int", [&]() {
            AssertThat(msg.count_args(Msg::ArgType::Int), Equals(4));
        });

        it("counts float", [&]() {
            AssertThat(msg.count_args(Msg::ArgType::Float), Equals(3));
        });
    });
});
<|endoftext|>


<commit_before>/*
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/preprocessor/HessianLocallyLinearEmbedding.h>
#ifdef HAVE_LAPACK
#include <shogun/mathematics/arpack.h>
#include <shogun/mathematics/lapack.h>
#include <shogun/lib/common.h>
#include <shogun/mathematics/Math.h>
#include <shogun/io/SGIO.h>
#include <shogun/distance/Distance.h>
#include <shogun/lib/Signal.h>

#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif

using namespace shogun;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
struct HESSIANESTIMATION_THREAD_PARAM
{
	/// starting index of loop
	int32_t idx_start;
	/// step of loop
	int32_t idx_step;
	/// end index of loop
	int32_t idx_stop;
	/// number of neighbors
	int32_t m_k;
	/// current dimensionality
	int32_t dim;
	///
	int32_t N;
	/// dp
	int32_t dp;
	/// target dimensionality
	int32_t m_target_dim;
	/// matrix containing indexes of neighbors of ith vector in ith column
	const int32_t* neighborhood_matrix;
	/// feature matrix
	const float64_t* feature_matrix;
	/// local feature matrix contating features of neighbors
	float64_t* local_feature_matrix;
	/// Yi matrix
	float64_t* Yi_matrix;
	/// mean vector
	float64_t* mean_vector;
	/// singular values vector
	float64_t* s_values_vector;
	/// QR factorization reflectors
	float64_t* tau;
	/// length of reflectors vector
	int32_t tau_len;
	/// w sum vector
	float64_t* w_sum_vector;
	/// q matrix
	float64_t* q_matrix;
	/// weight matrix
	float64_t* W_matrix;
#ifdef HAVE_PTHREAD
	/// lock used on modifying of weight matrix
	PTHREAD_LOCK_T* W_matrix_lock;
#endif
};
#endif

CHessianLocallyLinearEmbedding::CHessianLocallyLinearEmbedding() :
		CLocallyLinearEmbedding()
{
}

CHessianLocallyLinearEmbedding::~CHessianLocallyLinearEmbedding()
{
}

bool CHessianLocallyLinearEmbedding::init(CFeatures* features)
{
	return true;
}

void CHessianLocallyLinearEmbedding::cleanup()
{
}

SGMatrix<float64_t> CHessianLocallyLinearEmbedding::construct_weight_matrix(CSimpleFeatures<float64_t>* simple_features,float64_t* W_matrix,
                                                                            SGMatrix<int32_t> neighborhood_matrix)
{
	int32_t N = simple_features->get_num_vectors();
	int32_t dim = simple_features->get_num_features();
	int32_t dp = m_target_dim*(m_target_dim+1)/2;
	ASSERT(m_k>=(1+m_target_dim+dp));
	int32_t t;
#ifdef HAVE_PTHREAD
	int32_t num_threads = parallel->get_num_threads();
	ASSERT(num_threads>0);
	// allocate threads and params
	pthread_t* threads = SG_MALLOC(pthread_t, num_threads);
	HESSIANESTIMATION_THREAD_PARAM* parameters = SG_MALLOC(HESSIANESTIMATION_THREAD_PARAM, num_threads);

#else
	int32_t num_threads = 1;
#endif

	// init matrices to be used
	float64_t* local_feature_matrix = SG_MALLOC(float64_t, m_k*dim*num_threads);
	float64_t* s_values_vector = SG_MALLOC(float64_t, dim*num_threads);
	int32_t tau_len = CMath::min((1+m_target_dim+dp), m_k);
	float64_t* tau = SG_MALLOC(float64_t, tau_len*num_threads);
	float64_t* mean_vector = SG_MALLOC(float64_t, dim*num_threads);
	float64_t* q_matrix = SG_MALLOC(float64_t, m_k*m_k*num_threads);
	float64_t* w_sum_vector = SG_MALLOC(float64_t, dp*num_threads);
	float64_t* Yi_matrix = SG_MALLOC(float64_t, m_k*(1+m_target_dim+dp)*num_threads);
	// get feature matrix
	SGMatrix<float64_t> feature_matrix = simple_features->get_feature_matrix();

#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T W_matrix_lock;
	pthread_attr_t attr;
	PTHREAD_LOCK_INIT(&W_matrix_lock);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	for (t=0; t<num_threads; t++)
	{
		parameters[t].idx_start = t;
		parameters[t].idx_step = num_threads;
		parameters[t].idx_stop = N;
		parameters[t].m_k = m_k;
		parameters[t].dim = dim;
		parameters[t].m_target_dim = m_target_dim;
		parameters[t].N = N;
		parameters[t].dp = dp;
		parameters[t].neighborhood_matrix = neighborhood_matrix.matrix;
		parameters[t].feature_matrix = feature_matrix.matrix;
		parameters[t].local_feature_matrix = local_feature_matrix + (m_k*dim)*t;
		parameters[t].Yi_matrix = Yi_matrix + (m_k*(1+m_target_dim+dp))*t;
		parameters[t].mean_vector = mean_vector + dim*t;
		parameters[t].s_values_vector = s_values_vector + dim*t;
		parameters[t].tau = tau+tau_len*t;
		parameters[t].tau_len = tau_len;
		parameters[t].w_sum_vector = w_sum_vector + dp*t;
		parameters[t].q_matrix = q_matrix + (m_k*m_k)*t;
		parameters[t].W_matrix = W_matrix;
		parameters[t].W_matrix_lock = &W_matrix_lock;
		pthread_create(&threads[t], &attr, run_hessianestimation_thread, (void*)&parameters[t]);
	}
	for (t=0; t<num_threads; t++)
		pthread_join(threads[t], NULL);
	PTHREAD_LOCK_DESTROY(&W_matrix_lock);
	SG_FREE(parameters);
	SG_FREE(threads);
#else
	HESSIANESTIMATION_THREAD_PARAM single_thread_param;
	single_thread_param.idx_start = t;
	single_thread_param.idx_step = num_threads;
	single_thread_param.idx_stop = N;
	single_thread_param.m_k = m_k;
	single_thread_param.dim = dim;
	single_thread_param.m_target_dim = m_target_dim;
	single_thread_param.N = N;
	single_thread_param.dp = dp;
	single_thread_param.neighborhood_matrix = neighborhood_matrix.matrix;
	single_thread_param.feature_matrix = feature_matrix.matrix;
	single_thread_param.local_feature_matrix = local_feature_matrix;
	single_thread_param.Yi_matrix = Yi_matrix;
	single_thread_param.mean_vector = mean_vector;
	single_thread_param.s_values_vector = s_values_vector;
	single_thread_param.tau = tau;
	single_thread_param.tau_len = tau_len;
	single_thread_param.w_sum_vector = w_sum_vector;
	single_thread_param.q_matrix = q_matrix;
	single_thread_param.W_matrix = W_matrix;
	run_hessianestimation_thread((void*)&single_thread_param);
#endif

	// clean
	SG_FREE(Yi_matrix);
	SG_FREE(s_values_vector);
	SG_FREE(mean_vector);
	SG_FREE(tau);
	SG_FREE(w_sum_vector);
	SG_FREE(local_feature_matrix);
	SG_FREE(q_matrix);

	return SGMatrix<float64_t>(W_matrix,N,N);
}

void* CHessianLocallyLinearEmbedding::run_hessianestimation_thread(void* p)
{
	HESSIANESTIMATION_THREAD_PARAM* parameters = (HESSIANESTIMATION_THREAD_PARAM*)p;
	int32_t idx_start = parameters->idx_start;
	int32_t idx_step = parameters->idx_step;
	int32_t idx_stop = parameters->idx_stop;
	int32_t m_k = parameters->m_k;
	int32_t dim = parameters->dim;
	int32_t N = parameters->N;
	int32_t dp = parameters->dp;
	int32_t m_target_dim = parameters->m_target_dim;
	const int32_t* neighborhood_matrix = parameters->neighborhood_matrix;
	const float64_t* feature_matrix = parameters->feature_matrix;
	float64_t* local_feature_matrix = parameters->local_feature_matrix;
	float64_t* Yi_matrix = parameters->Yi_matrix;
	float64_t* mean_vector = parameters->mean_vector;
	float64_t* s_values_vector = parameters->s_values_vector;
	float64_t* tau = parameters->tau;
	int32_t tau_len = parameters->tau_len;
	float64_t* w_sum_vector = parameters->w_sum_vector;
	float64_t* q_matrix = parameters->q_matrix;
	float64_t* W_matrix = parameters->W_matrix;
#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T* W_matrix_lock = parameters->W_matrix_lock;
#endif

	int i,j,k,l;

	for (i=idx_start; i<idx_stop; i+=idx_step)
	{
		// Yi(:,0) = 1
		for (j=0; j<m_k; j++)
			Yi_matrix[j] = 1.0;

		// fill mean vector with zeros
		for (j=0; j<dim; j++)
			mean_vector[j] = 0.0;

		// compute local feature matrix containing neighbors of i-th vector
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<dim; k++)
			{
				local_feature_matrix[j*dim+k] = feature_matrix[neighborhood_matrix[j*N+i]*dim+k];
				mean_vector[k] += local_feature_matrix[j*dim+k];
			}
		}

		// compute mean
		for (j=0; j<dim; j++)
			mean_vector[j] /= m_k;

		// center feature vectors by mean
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<dim; k++)
				local_feature_matrix[j*dim+k] -= mean_vector[k];
		}

		int32_t info = 0;
		// find right eigenvectors of local_feature_matrix
		wrap_dgesvd('N','O', dim,m_k,local_feature_matrix,dim,
		                     s_values_vector,
		                     NULL,1, NULL,1, &info);
		ASSERT(info==0);

		// Yi(0:m_k,1:1+m_target_dim) = Vh(0:m_k, 0:target_dim)
		for (j=0; j<m_target_dim; j++)
		{
			for (k=0; k<m_k; k++)
				Yi_matrix[(j+1)*m_k+k] = local_feature_matrix[k*dim+j];
		}

		int32_t ct = 0;

		// construct 2nd order hessian approx
		for (j=0; j<m_target_dim; j++)
		{
			for (k=0; k<m_target_dim-j; k++)
			{
				for (l=0; l<m_k; l++)
				{
					Yi_matrix[(ct+k+1+m_target_dim)*m_k+l] = Yi_matrix[(j+1)*m_k+l]*Yi_matrix[(j+k+1)*m_k+l];
				}
			}
			ct += ct + m_target_dim - j;
		}

		// perform QR factorization
		wrap_dgeqrf(m_k,(1+m_target_dim+dp),Yi_matrix,m_k,tau,&info);
		ASSERT(info==0);
		wrap_dorgqr(m_k,(1+m_target_dim+dp),tau_len,Yi_matrix,m_k,tau,&info);
		ASSERT(info==0);

		float64_t* Pii = (Yi_matrix+m_k*(1+m_target_dim));

		for (j=0; j<dp; j++)
		{
			w_sum_vector[j] = 0.0;
			for (k=0; k<m_k; k++)
			{
				w_sum_vector[j] += Pii[j*m_k+k];
			}
			if (w_sum_vector[j]<0.001)
				w_sum_vector[j] = 1.0;
			for (k=0; k<m_k; k++)
				Pii[j*m_k+k] /= w_sum_vector[j];
		}

		cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans,
		            m_k,m_k,dp,
		            1.0,Pii,m_k,
		                Pii,m_k,
		            0.0,q_matrix,m_k);
#ifdef HAVE_PTHREAD
		PTHREAD_LOCK(W_matrix_lock);
#endif
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<m_k; k++)
				W_matrix[N*neighborhood_matrix[k*N+i]+neighborhood_matrix[j*N+i]] += q_matrix[j*m_k+k];
		}
#ifdef HAVE_PTHREAD
		PTHREAD_UNLOCK(W_matrix_lock);
#endif
	}
	return NULL;
}
#endif /* HAVE_LAPACK */
<commit_msg>BLASed HLLE<commit_after>/*
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/preprocessor/HessianLocallyLinearEmbedding.h>
#ifdef HAVE_LAPACK
#include <shogun/mathematics/arpack.h>
#include <shogun/mathematics/lapack.h>
#include <shogun/lib/common.h>
#include <shogun/mathematics/Math.h>
#include <shogun/io/SGIO.h>
#include <shogun/distance/Distance.h>
#include <shogun/lib/Signal.h>

#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif

using namespace shogun;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
struct HESSIANESTIMATION_THREAD_PARAM
{
	/// starting index of loop
	int32_t idx_start;
	/// step of loop
	int32_t idx_step;
	/// end index of loop
	int32_t idx_stop;
	/// number of neighbors
	int32_t m_k;
	/// current dimensionality
	int32_t dim;
	///
	int32_t N;
	/// dp
	int32_t dp;
	/// target dimensionality
	int32_t m_target_dim;
	/// matrix containing indexes of neighbors of ith vector in ith column
	const int32_t* neighborhood_matrix;
	/// feature matrix
	const float64_t* feature_matrix;
	/// local feature matrix contating features of neighbors
	float64_t* local_feature_matrix;
	/// Yi matrix
	float64_t* Yi_matrix;
	/// mean vector
	float64_t* mean_vector;
	/// singular values vector
	float64_t* s_values_vector;
	/// QR factorization reflectors
	float64_t* tau;
	/// length of reflectors vector
	int32_t tau_len;
	/// w sum vector
	float64_t* w_sum_vector;
	/// q matrix
	float64_t* q_matrix;
	/// weight matrix
	float64_t* W_matrix;
#ifdef HAVE_PTHREAD
	/// lock used on modifying of weight matrix
	PTHREAD_LOCK_T* W_matrix_lock;
#endif
};
#endif

CHessianLocallyLinearEmbedding::CHessianLocallyLinearEmbedding() :
		CLocallyLinearEmbedding()
{
}

CHessianLocallyLinearEmbedding::~CHessianLocallyLinearEmbedding()
{
}

bool CHessianLocallyLinearEmbedding::init(CFeatures* features)
{
	return true;
}

void CHessianLocallyLinearEmbedding::cleanup()
{
}

SGMatrix<float64_t> CHessianLocallyLinearEmbedding::construct_weight_matrix(CSimpleFeatures<float64_t>* simple_features,float64_t* W_matrix,
                                                                            SGMatrix<int32_t> neighborhood_matrix)
{
	int32_t N = simple_features->get_num_vectors();
	int32_t dim = simple_features->get_num_features();
	int32_t dp = m_target_dim*(m_target_dim+1)/2;
	ASSERT(m_k>=(1+m_target_dim+dp));
	int32_t t;
#ifdef HAVE_PTHREAD
	int32_t num_threads = parallel->get_num_threads();
	ASSERT(num_threads>0);
	// allocate threads and params
	pthread_t* threads = SG_MALLOC(pthread_t, num_threads);
	HESSIANESTIMATION_THREAD_PARAM* parameters = SG_MALLOC(HESSIANESTIMATION_THREAD_PARAM, num_threads);

#else
	int32_t num_threads = 1;
#endif

	// init matrices to be used
	float64_t* local_feature_matrix = SG_MALLOC(float64_t, m_k*dim*num_threads);
	float64_t* s_values_vector = SG_MALLOC(float64_t, dim*num_threads);
	int32_t tau_len = CMath::min((1+m_target_dim+dp), m_k);
	float64_t* tau = SG_MALLOC(float64_t, tau_len*num_threads);
	float64_t* mean_vector = SG_MALLOC(float64_t, dim*num_threads);
	float64_t* q_matrix = SG_MALLOC(float64_t, m_k*m_k*num_threads);
	float64_t* w_sum_vector = SG_MALLOC(float64_t, dp*num_threads);
	float64_t* Yi_matrix = SG_MALLOC(float64_t, m_k*(1+m_target_dim+dp)*num_threads);
	// get feature matrix
	SGMatrix<float64_t> feature_matrix = simple_features->get_feature_matrix();

#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T W_matrix_lock;
	pthread_attr_t attr;
	PTHREAD_LOCK_INIT(&W_matrix_lock);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	for (t=0; t<num_threads; t++)
	{
		parameters[t].idx_start = t;
		parameters[t].idx_step = num_threads;
		parameters[t].idx_stop = N;
		parameters[t].m_k = m_k;
		parameters[t].dim = dim;
		parameters[t].m_target_dim = m_target_dim;
		parameters[t].N = N;
		parameters[t].dp = dp;
		parameters[t].neighborhood_matrix = neighborhood_matrix.matrix;
		parameters[t].feature_matrix = feature_matrix.matrix;
		parameters[t].local_feature_matrix = local_feature_matrix + (m_k*dim)*t;
		parameters[t].Yi_matrix = Yi_matrix + (m_k*(1+m_target_dim+dp))*t;
		parameters[t].mean_vector = mean_vector + dim*t;
		parameters[t].s_values_vector = s_values_vector + dim*t;
		parameters[t].tau = tau+tau_len*t;
		parameters[t].tau_len = tau_len;
		parameters[t].w_sum_vector = w_sum_vector + dp*t;
		parameters[t].q_matrix = q_matrix + (m_k*m_k)*t;
		parameters[t].W_matrix = W_matrix;
		parameters[t].W_matrix_lock = &W_matrix_lock;
		pthread_create(&threads[t], &attr, run_hessianestimation_thread, (void*)&parameters[t]);
	}
	for (t=0; t<num_threads; t++)
		pthread_join(threads[t], NULL);
	PTHREAD_LOCK_DESTROY(&W_matrix_lock);
	SG_FREE(parameters);
	SG_FREE(threads);
#else
	HESSIANESTIMATION_THREAD_PARAM single_thread_param;
	single_thread_param.idx_start = t;
	single_thread_param.idx_step = num_threads;
	single_thread_param.idx_stop = N;
	single_thread_param.m_k = m_k;
	single_thread_param.dim = dim;
	single_thread_param.m_target_dim = m_target_dim;
	single_thread_param.N = N;
	single_thread_param.dp = dp;
	single_thread_param.neighborhood_matrix = neighborhood_matrix.matrix;
	single_thread_param.feature_matrix = feature_matrix.matrix;
	single_thread_param.local_feature_matrix = local_feature_matrix;
	single_thread_param.Yi_matrix = Yi_matrix;
	single_thread_param.mean_vector = mean_vector;
	single_thread_param.s_values_vector = s_values_vector;
	single_thread_param.tau = tau;
	single_thread_param.tau_len = tau_len;
	single_thread_param.w_sum_vector = w_sum_vector;
	single_thread_param.q_matrix = q_matrix;
	single_thread_param.W_matrix = W_matrix;
	run_hessianestimation_thread((void*)&single_thread_param);
#endif

	// clean
	SG_FREE(Yi_matrix);
	SG_FREE(s_values_vector);
	SG_FREE(mean_vector);
	SG_FREE(tau);
	SG_FREE(w_sum_vector);
	SG_FREE(local_feature_matrix);
	SG_FREE(q_matrix);

	return SGMatrix<float64_t>(W_matrix,N,N);
}

void* CHessianLocallyLinearEmbedding::run_hessianestimation_thread(void* p)
{
	HESSIANESTIMATION_THREAD_PARAM* parameters = (HESSIANESTIMATION_THREAD_PARAM*)p;
	int32_t idx_start = parameters->idx_start;
	int32_t idx_step = parameters->idx_step;
	int32_t idx_stop = parameters->idx_stop;
	int32_t m_k = parameters->m_k;
	int32_t dim = parameters->dim;
	int32_t N = parameters->N;
	int32_t dp = parameters->dp;
	int32_t m_target_dim = parameters->m_target_dim;
	const int32_t* neighborhood_matrix = parameters->neighborhood_matrix;
	const float64_t* feature_matrix = parameters->feature_matrix;
	float64_t* local_feature_matrix = parameters->local_feature_matrix;
	float64_t* Yi_matrix = parameters->Yi_matrix;
	float64_t* mean_vector = parameters->mean_vector;
	float64_t* s_values_vector = parameters->s_values_vector;
	float64_t* tau = parameters->tau;
	int32_t tau_len = parameters->tau_len;
	float64_t* w_sum_vector = parameters->w_sum_vector;
	float64_t* q_matrix = parameters->q_matrix;
	float64_t* W_matrix = parameters->W_matrix;
#ifdef HAVE_PTHREAD
	PTHREAD_LOCK_T* W_matrix_lock = parameters->W_matrix_lock;
#endif

	int i,j,k,l;

	for (i=idx_start; i<idx_stop; i+=idx_step)
	{
		// Yi(:,0) = 1
		for (j=0; j<m_k; j++)
			Yi_matrix[j] = 1.0;

		// fill mean vector with zeros
		memset(mean_vector,0,sizeof(float64_t)*dim);

		// compute local feature matrix containing neighbors of i-th vector
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<dim; k++)
				local_feature_matrix[j*dim+k] = feature_matrix[neighborhood_matrix[j*N+i]*dim+k];

			cblas_daxpy(dim,1.0,local_feature_matrix+j*dim,1,mean_vector,1);
		}

		// compute mean
		cblas_dscal(dim,1.0/m_k,mean_vector,1);

		// center feature vectors by mean
		for (j=0; j<m_k; j++)
			cblas_daxpy(dim,-1.0,mean_vector,1,local_feature_matrix+j*dim,1);

		int32_t info = 0;
		// find right eigenvectors of local_feature_matrix
		wrap_dgesvd('N','O', dim,m_k,local_feature_matrix,dim,
		                     s_values_vector,
		                     NULL,1, NULL,1, &info);
		ASSERT(info==0);

		// Yi(0:m_k,1:1+m_target_dim) = Vh(0:m_k, 0:target_dim)
		for (j=0; j<m_target_dim; j++)
		{
			for (k=0; k<m_k; k++)
				Yi_matrix[(j+1)*m_k+k] = local_feature_matrix[k*dim+j];
		}

		int32_t ct = 0;

		// construct 2nd order hessian approx
		for (j=0; j<m_target_dim; j++)
		{
			for (k=0; k<m_target_dim-j; k++)
			{
				for (l=0; l<m_k; l++)
				{
					Yi_matrix[(ct+k+1+m_target_dim)*m_k+l] = Yi_matrix[(j+1)*m_k+l]*Yi_matrix[(j+k+1)*m_k+l];
				}
			}
			ct += ct + m_target_dim - j;
		}

		// perform QR factorization
		wrap_dgeqrf(m_k,(1+m_target_dim+dp),Yi_matrix,m_k,tau,&info);
		ASSERT(info==0);
		wrap_dorgqr(m_k,(1+m_target_dim+dp),tau_len,Yi_matrix,m_k,tau,&info);
		ASSERT(info==0);

		float64_t* Pii = (Yi_matrix+m_k*(1+m_target_dim));

		for (j=0; j<dp; j++)
		{
			w_sum_vector[j] = 0.0;
			for (k=0; k<m_k; k++)
			{
				w_sum_vector[j] += Pii[j*m_k+k];
			}
			if (w_sum_vector[j]<0.001)
				w_sum_vector[j] = 1.0;
			for (k=0; k<m_k; k++)
				Pii[j*m_k+k] /= w_sum_vector[j];
		}

		cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans,
		            m_k,m_k,dp,
		            1.0,Pii,m_k,
		                Pii,m_k,
		            0.0,q_matrix,m_k);
#ifdef HAVE_PTHREAD
		PTHREAD_LOCK(W_matrix_lock);
#endif
		for (j=0; j<m_k; j++)
		{
			for (k=0; k<m_k; k++)
				W_matrix[N*neighborhood_matrix[k*N+i]+neighborhood_matrix[j*N+i]] += q_matrix[j*m_k+k];
		}
#ifdef HAVE_PTHREAD
		PTHREAD_UNLOCK(W_matrix_lock);
#endif
	}
	return NULL;
}
#endif /* HAVE_LAPACK */
<|endoftext|>