<commit_before>/**
 * ZNC Mailer Module
 *
 * A ZNC Module that uses the Unix mail command to send mentions and private
 * messages to an email address when you are not connected to ZNC.
 *
 * Copyright (c) 2011 Dougal Matthews
 * Licensed under the MIT license
 */

#include <main.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <list>

#include <Modules.h>
#include <IRCSock.h>
#include <User.h>
#include <Nick.h>
#include <Chan.h>

class CMailerTimer: public CTimer {
public:

    CMailerTimer(CModule* pModule, unsigned int uInterval, unsigned int uCycles, const CString& sLabel, const CString& sDescription) : CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
    virtual ~CMailerTimer() {}

protected:
    virtual void RunJob();

};

class CMailer : public CModule {

protected:
    CUser *ConnectedUser;
    list<CString> MessagesList;
    CString NotificationSubject;
    CString NotificationEmail;
    unsigned int MaxNotifications;
    bool DebugMode;

public:

    MODCONSTRUCTOR(CMailer) {
        ConnectedUser = GetUser();
        DebugMode = false;
        NotificationSubject = "IRC Notification";
    }

    virtual ~CMailer() {}

    void DebugPrint(string sMessage){
        if (DebugMode){
            PutModule(sMessage);
        }
    }

    virtual bool OnLoad(const CString& sArgs, CString& sErrorMsg) {

        AddTimer(new CMailerTimer(this, 1200, 0, "Mail", "Send emails every 20 mins."));
        MaxNotifications = 50;

        PutModule("Please tell me what email address you want notifications to be sent to with 'email <address>'");

        VCString tokens;
        int token_count = sArgs.Split(" ", tokens, false);

        if (token_count < 1)
        {
            return true;
        }

        CString action = tokens[0].AsLower();

        if (action == "debug"){
            PutModule("DEBUG ON");
            DebugMode = true;
        }

        return true;

    }

    virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) {

        Handle(Nick, Channel.GetName(), sMessage);

        return CONTINUE;
    }

    virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {

        Handle(Nick, "PRIVATE", sMessage);

        return CONTINUE;
    }

    void OnModCommand(const CString& command)
    {
        VCString tokens;
        int token_count = command.Split(" ", tokens, false);

        if (token_count < 1)
        {
            return;
        }

        CString action = tokens[0].AsLower();

        if (action == "email"){

            if (token_count < 2)
            {
                PutModule("Email: " + NotificationEmail);
                PutModule("Usage: email <email address>");
                return;
            }

            NotificationEmail = tokens[1].AsLower();

            PutModule("email address set");

        } else if (action == "subject"){

            if (token_count < 2)
            {
                PutModule("Subject: " + NotificationSubject);
                PutModule("Usage: subject <email subject>");
                return;
            }

            NotificationSubject = tokens[1].AsLower();

            PutModule("email subject set.");

        } else if (action == "help") {

                PutModule("View the documentation at...");

        } else {

            if (!DebugMode){
                PutModule("Error: invalid command, try `help`");
            }

        }

        DebugCommands(command);

    }

    void DebugCommands(const CString& command){

        if (!DebugMode){
            return;
        }

        VCString tokens;
        int token_count = command.Split(" ", tokens, false);

        if (token_count < 1)
        {
            return;
        }

        CString action = tokens[0].AsLower();

        if (action == "testemail"){

            CString message;
            message = "This is a testing email.";
            Send(message);

        } else if (action == "testfull"){

            CString message = "Testing";
            MessagesList.push_front(message);
            BatchSend();
        } else if (action == "testshowqueue"){

            list<CString>::iterator it;

            CString message;

            for ( it=MessagesList.begin() ; it != MessagesList.end(); it++ ){
                DebugPrint(*it);
            }

        } else if (action == "testbatchsend"){

            BatchSend();

        }

    }

    void Handle(CNick& Nick, const CString& location, CString& sMessage){

        if (SendNotification(Nick, sMessage) || location == "PRIVATE"){

            CString message = "<" + location + ":" + Nick.GetNick() + "> " + sMessage + "\n\n";
            MessagesList.push_front(message);

            DebugPrint("Added message...");
            DebugPrint(message);

            if (MessagesList.size() > MaxNotifications){
                MessagesList.pop_back();
            }

        }
    }

    bool SendNotification(CNick& Nick, CString& sMessage){

        // Don't send notifications if DebugMode is off and the ConnectedUser is not attached.
        if (!DebugMode && ConnectedUser->IsUserAttached()){
            return false;
        }

        CString UserNick = ConnectedUser->GetNick().AsLower();

        size_t found = sMessage.AsLower().find(UserNick);

        if (found!=string::npos){
            return true;
        } else {
            return false;
        }

    }

    void BatchSend(){

        if (!DebugMode && ConnectedUser->IsUserAttached()){
            return;
        }

        list<CString>::iterator it;

        CString message;

        if (MessagesList.size() <= 0){
            return;
        }

        for ( it=MessagesList.begin() ; it != MessagesList.end(); it++ ){
            message = message + *it;
        }

        Send(message);

        MessagesList.erase(MessagesList.begin(),MessagesList.end());

    }

    void Send(CString& sMessage){

        CString command;
        command = "mail -s '" + NotificationSubject + "' " + NotificationEmail;

        if (DebugMode){
            DebugPrint(command);
        }

        DebugPrint("Sending");

        FILE *email= popen(command.c_str(), "w");

        if (!email){
            PutModule("Problems with mail command.");
            return;
        }

        fprintf(email, "%s", (char*) sMessage.c_str());
        pclose(email);

        DebugPrint(sMessage);
        DebugPrint("Sent");

    }

};

void CMailerTimer::RunJob(){

    CMailer *p = (CMailer *)m_pModule;

    p->BatchSend();

}

MODULEDEFS(CMailer, "To be used to send mentions as an email")
<commit_msg>Reverse the batch processing, to make sure the messages are in chronological order with oldest at the bottom.<commit_after>/**
 * ZNC Mailer Module
 *
 * A ZNC Module that uses the Unix mail command to send mentions and private
 * messages to an email address when you are not connected to ZNC.
 *
 * Copyright (c) 2011 Dougal Matthews
 * Licensed under the MIT license
 */

#include <main.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <list>

#include <Modules.h>
#include <IRCSock.h>
#include <User.h>
#include <Nick.h>
#include <Chan.h>

class CMailerTimer: public CTimer {
public:

    CMailerTimer(CModule* pModule, unsigned int uInterval, unsigned int uCycles, const CString& sLabel, const CString& sDescription) : CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
    virtual ~CMailerTimer() {}

protected:
    virtual void RunJob();

};

class CMailer : public CModule {

protected:
    CUser *ConnectedUser;
    list<CString> MessagesList;
    CString NotificationSubject;
    CString NotificationEmail;
    unsigned int MaxNotifications;
    bool DebugMode;

public:

    MODCONSTRUCTOR(CMailer) {
        ConnectedUser = GetUser();
        DebugMode = false;
        NotificationSubject = "IRC Notification";
    }

    virtual ~CMailer() {}

    void DebugPrint(string sMessage){
        if (DebugMode){
            PutModule(sMessage);
        }
    }

    virtual bool OnLoad(const CString& sArgs, CString& sErrorMsg) {

        AddTimer(new CMailerTimer(this, 1200, 0, "Mail", "Send emails every 20 mins."));
        MaxNotifications = 50;

        PutModule("Please tell me what email address you want notifications to be sent to with 'email <address>'");

        VCString tokens;
        int token_count = sArgs.Split(" ", tokens, false);

        if (token_count < 1)
        {
            return true;
        }

        CString action = tokens[0].AsLower();

        if (action == "debug"){
            PutModule("DEBUG ON");
            DebugMode = true;
        }

        return true;

    }

    virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) {

        Handle(Nick, Channel.GetName(), sMessage);

        return CONTINUE;
    }

    virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {

        Handle(Nick, "PRIVATE", sMessage);

        return CONTINUE;
    }

    void OnModCommand(const CString& command)
    {
        VCString tokens;
        int token_count = command.Split(" ", tokens, false);

        if (token_count < 1)
        {
            return;
        }

        CString action = tokens[0].AsLower();

        if (action == "email"){

            if (token_count < 2)
            {
                PutModule("Email: " + NotificationEmail);
                PutModule("Usage: email <email address>");
                return;
            }

            NotificationEmail = tokens[1].AsLower();

            PutModule("email address set");

        } else if (action == "subject"){

            if (token_count < 2)
            {
                PutModule("Subject: " + NotificationSubject);
                PutModule("Usage: subject <email subject>");
                return;
            }

            NotificationSubject = tokens[1].AsLower();

            PutModule("email subject set.");

        } else if (action == "help") {

                PutModule("View the documentation at...");

        } else {

            if (!DebugMode){
                PutModule("Error: invalid command, try `help`");
            }

        }

        DebugCommands(command);

    }

    void DebugCommands(const CString& command){

        if (!DebugMode){
            return;
        }

        VCString tokens;
        int token_count = command.Split(" ", tokens, false);

        if (token_count < 1)
        {
            return;
        }

        CString action = tokens[0].AsLower();

        if (action == "testemail"){

            CString message;
            message = "This is a testing email.";
            Send(message);

        } else if (action == "testfull"){

            CString message = "Testing";
            MessagesList.push_front(message);
            BatchSend();
        } else if (action == "testshowqueue"){

            list<CString>::iterator it;

            CString message;

            for ( it=MessagesList.begin() ; it != MessagesList.end(); it++ ){
                DebugPrint(*it);
            }

        } else if (action == "testbatchsend"){

            BatchSend();

        }

    }

    void Handle(CNick& Nick, const CString& location, CString& sMessage){

        if (SendNotification(Nick, sMessage) || location == "PRIVATE"){

            CString message = "<" + location + ":" + Nick.GetNick() + "> " + sMessage + "\n\n";
            MessagesList.push_front(message);

            DebugPrint("Added message...");
            DebugPrint(message);

            if (MessagesList.size() > MaxNotifications){
                MessagesList.pop_back();
            }

        }
    }

    bool SendNotification(CNick& Nick, CString& sMessage){

        // Don't send notifications if DebugMode is off and the ConnectedUser is not attached.
        if (!DebugMode && ConnectedUser->IsUserAttached()){
            return false;
        }

        CString UserNick = ConnectedUser->GetNick().AsLower();

        size_t found = sMessage.AsLower().find(UserNick);

        if (found!=string::npos){
            return true;
        } else {
            return false;
        }

    }

    void BatchSend(){

        if (!DebugMode && ConnectedUser->IsUserAttached()){
            return;
        }

        list<CString>::iterator it;

        CString message;

        if (MessagesList.size() <= 0){
            return;
        }

        for ( it=MessagesList.end() ; it != MessagesList.begin(); it-- ){
            message = message + *it;
        }

        Send(message);

        MessagesList.erase(MessagesList.begin(),MessagesList.end());

    }

    void Send(CString& sMessage){

        CString command;
        command = "mail -s '" + NotificationSubject + "' " + NotificationEmail;

        if (DebugMode){
            DebugPrint(command);
        }

        DebugPrint("Sending");

        FILE *email= popen(command.c_str(), "w");

        if (!email){
            PutModule("Problems with mail command.");
            return;
        }

        fprintf(email, "%s", (char*) sMessage.c_str());
        pclose(email);

        DebugPrint(sMessage);
        DebugPrint("Sent");

    }

};

void CMailerTimer::RunJob(){

    CMailer *p = (CMailer *)m_pModule;

    p->BatchSend();

}

MODULEDEFS(CMailer, "To be used to send mentions as an email")
<|endoftext|>


<commit_before>#include <iostream>

#include <boost/program_options.hpp>

#include <plasp/sas/Description.h>
#include <plasp/sas/TranslatorASP.h>

int main(int argc, char **argv)
{
	namespace po = boost::program_options;

	po::options_description description("Allowed options");
	description.add_options()
		("help,h", "Display this help message.")
		("version,v", "Display version information.")
		("input,i", po::value<std::string>(), "Specify the SAS input file.");

	po::positional_options_description positionalOptionsDescription;
	positionalOptionsDescription.add("input", -1);

	po::variables_map variablesMap;

	const auto printHelp =
		[&]()
		{
			std::cout << "Usage: plasp file [options]" << std::endl;
			std::cout << "Translate PDDL instances to ASP facts." << std::endl << std::endl;

			std::cout << description;
		};

	try
	{
		po::store(po::command_line_parser(argc, argv)
			.options(description)
			.positional(positionalOptionsDescription)
			.run(),
			variablesMap);
		po::notify(variablesMap);
	}
	catch (const po::error &e)
	{
		std::cerr << "Error: " << e.what() << std::endl << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	if (variablesMap.count("help"))
	{
		printHelp();
		return EXIT_SUCCESS;
	}

	if (variablesMap.count("version"))
	{
		std::cout << "plasp version 3.0.0" << std::endl;
		return EXIT_SUCCESS;
	}

	if (!variablesMap.count("input"))
	{
		std::cerr << "Error: No input file specified" << std::endl << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	try
	{
		const auto sasDescription = plasp::sas::Description::fromFile(variablesMap["input"].as<std::string>());
		const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription);
		sasTranslator.translate(std::cout);
	}
	catch (const std::exception &e)
	{
		std::cerr << "Error: " << e.what() << std::endl << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
<commit_msg>Added support for input from std::cin.<commit_after>#include <iostream>

#include <boost/program_options.hpp>

#include <plasp/sas/Description.h>
#include <plasp/sas/TranslatorASP.h>

int main(int argc, char **argv)
{
	namespace po = boost::program_options;

	po::options_description description("Allowed options");
	description.add_options()
		("help,h", "Display this help message.")
		("version,v", "Display version information.")
		("input,i", po::value<std::string>(), "Specify the SAS input file.");

	po::positional_options_description positionalOptionsDescription;
	positionalOptionsDescription.add("input", -1);

	po::variables_map variablesMap;

	const auto printHelp =
		[&]()
		{
			std::cout << "Usage: plasp file [options]" << std::endl;
			std::cout << "Translate PDDL instances to ASP facts." << std::endl << std::endl;

			std::cout << description;
		};

	try
	{
		po::store(po::command_line_parser(argc, argv)
			.options(description)
			.positional(positionalOptionsDescription)
			.run(),
			variablesMap);
		po::notify(variablesMap);
	}
	catch (const po::error &e)
	{
		std::cerr << "Error: " << e.what() << std::endl << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	if (variablesMap.count("help"))
	{
		printHelp();
		return EXIT_SUCCESS;
	}

	if (variablesMap.count("version"))
	{
		std::cout << "plasp version 3.0.0" << std::endl;
		return EXIT_SUCCESS;
	}

	try
	{
		const auto sasDescription = variablesMap.count("input")
			? plasp::sas::Description::fromFile(variablesMap["input"].as<std::string>())
			: plasp::sas::Description::fromStream(std::cin);

		const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription);
		sasTranslator.translate(std::cout);
	}
	catch (const std::exception &e)
	{
		std::cerr << "Error: " << e.what() << std::endl << std::endl;
		printHelp();
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Multi-aligner

#include "malign.h"

using namespace std;
/*
 * MAligner
 */

MAligner::MAligner(int nseq, char** seqs, char** names){

   global_matrix = (dp_matrix*) malloc(sizeof(dp_matrix));
   global_matrix->matrix = NULL;
   global_matrix->size   = 0;

    for( int ii = 0; ii < nseq; ++ii ){
        MAlignerEntry *en = new MAlignerEntry(names[ii], seqs[ii], global_matrix);
        entries.insert(pair<string,MAlignerEntry*>(string(seqs[ii]),en));
    }

}

MAligner::~MAligner(){
    if( global_matrix->matrix != NULL ){
        free(global_matrix->matrix);
    }

    free(global_matrix);
}

priority_queue<MAlignerEntry*> MAligner::align(char* input){
    queue<MAlignerEntry*> robin;
    map<string, MAlignerEntry*>::iterator entry_itr;

    int len = strlen(input);

    for( entry_itr = entries.begin(); entry_itr != entries.end(); entry_itr++ ){
        MAlignerEntry *e = (*entry_itr).second;
        e->initialize(input, len);
        robin.push(e);
    }

    return this->roundRobin(robin);

}

priority_queue<MAlignerEntry*> MAligner::alignWith(char* input, int nnames, char** names){

    queue<MAlignerEntry*> robin;
    int len = strlen(input);

    map<string,MAlignerEntry*>::iterator search_itr;
    for( int ii = 0; ii < nnames ; ++ii ){
        search_itr = entries.find(string(names[ii]));
        if( search_itr != entries.end() ){
            (*search_itr).second->initialize(input, len);
            robin.push( (*search_itr).second );
        }
    }

    return this->roundRobin(robin);

}

priority_queue<MAlignerEntry*> MAligner::roundRobin(queue<MAlignerEntry*> robin){

    priority_queue<MAlignerEntry*> results;
    int bestLowerBound = MINVAL;

    while( !robin.empty() ){
        MAlignerEntry *mae = robin.front();
        robin.pop();

        if( mae->upperBound() > bestLowerBound ){
            mae->step();

            if( mae->lowerBound() > bestLowerBound ){
                bestLowerBound = mae->lowerBound();
            }

            if( mae->upperBound() >= bestLowerBound
                && !mae->isAligned() ){
                robin.push(mae);
            }
        }

        if( mae->isAligned() ){
            results.push(mae);
        }
    }

    return results;
}

bool  MAligner::initialize(char* input){
    map<string, MAlignerEntry*>::iterator entry_itr;

    int len = strlen(input);

    for( entry_itr = entries.begin() ; entry_itr != entries.end() ; entry_itr++ ){
        (*entry_itr).second->initialize(input, len);
    }

    return true;
}

/*
 * MAlignerEntry
 */
MAlignerEntry::MAlignerEntry(const char *nm, const char *seq, dp_matrix *dp){

    this->name = (char*) malloc(strlen(nm) + 1);
    this->refSequence = (char*) malloc(strlen(seq) + 1);
    this->testSequence = NULL;
    strcpy(this->name, nm);
    strcpy(this->refSequence, seq);

    this->ref_length = strlen(this->refSequence);

    this->dpm = dp;
    this->num_rows = NULL;
    this->num_cols = NULL; // initialize this when we load it with a sequence

    this->uBound = MINVAL;
    this->lBound = MINVAL;
    this->matrix_size = MINVAL;

    this->gap      = -1;
    this->match    =  1;
    this->mismatch = -1;

    this->initialized = false;
    this->setLowerBound(0,0,0);
    this->setUpperBound(0,0,0);
}

MAlignerEntry::~MAlignerEntry(){
    free(this->name);
    free(this->refSequence);
}

bool MAlignerEntry::isAligned() {
    return aligned;
}

const bool MAlignerEntry::operator< (MAlignerEntry& entry){
    return this->getScore() > entry.getScore();
}
const bool MAlignerEntry::operator> (MAlignerEntry& entry){
    return this->getScore() < entry.getScore();
}

int MAlignerEntry::getScore(){
    return score;
}

int MAlignerEntry::upperBound(){
    return this->uBound;
}

int MAlignerEntry::lowerBound(){
    return this->lBound;
}

int MAlignerEntry::setUpperBound(int x, int y, int score){

    if( !this->initialized ){ return MINVAL; }

    int d = min(this->num_cols - x, this->num_rows - y); // get the maximum score along the diagonal
    int h = max(this->num_cols - x - d, this->num_rows - y - d);

    assert(h >= 0);
    this->uBound = score + d * this->match - h * this->gap;
    return uBound;
}

int MAlignerEntry::setLowerBound(int x, int y, int score){

    if( !this->initialized ){ return MINVAL; }

    int perimeter     = (this->num_cols - x) + (this->num_rows - y);
    int mismatchPath  = min(this->num_cols - x, this->num_rows - y);
    int mismatchPerimeter =
          max(this->num_cols - x - mismatchPath, this->num_rows - y - mismatchPath);
/*
    assert(perimeter >= 0);
    assert(mismatchPath >= 0);
    assert(mismatchPerimeter >= 0);
*/
    int perimeterScore = perimeter * this->gap;
    int mismatchScore = mismatchPath * this->mismatch + mismatchPerimeter * this->gap;

    this->lBound = score + max(perimeterScore, mismatchScore);
    return lBound;
}

int MAlignerEntry::grow(bool growLeft, bool growRight){

    if( growLeft ){
        this->left = min(this->left * 2, this->num_cols / 2);
    }

    if( growRight ){
        this->right = min(this->right * 2, this->num_cols / 2);
    }

    int l = this->left;
    int r = this->right;
    int d = this->num_rows - this->num_cols;
    this->matrix_size =
        this->num_rows
        * (l + r + 1)
        - (l * (l + 1) / 2)
        - (r * (r + 1) / 2)
        - (r * d)
        - (d * (d+1) / 2); // account for left hand overflow and the diagonal

    printf("diff: %d Left: %d Right: %d Rows: %d Cols: %d Size: %d\n", d, l, r, this->num_rows, this->num_cols, this->matrix_size);
    // Ask for a bigger scratch space if we need it
    if(this->dpm->size < this->matrix_size ){
        free(this->dpm->matrix);
        this->dpm->matrix = (int*) malloc(sizeof(int) * this->matrix_size);
        this->dpm->size = this->matrix_size;
    }

    return this->matrix_size;
}

bool MAlignerEntry::initialize(const char* testSeq, int len=0){

    this->test_length = strlen(testSeq);

    //printf("Initialized entry with '%s' and length %d...\n", testSeq, len);
    this->testSequence = (char*) malloc(this->test_length + 1);
    strcpy(this->testSequence, testSeq);

    // test will be the row
    if( this->test_length > this->ref_length ) {
        this->row_seq  = this->testSequence;
        this->num_rows = this->test_length;
        this->col_seq  = this->refSequence;
        this->num_cols = this->ref_length;
    // reference will be the row
    } else {
        this->row_seq  = this->refSequence;
        this->num_rows = this->ref_length;
        this->col_seq  = this->testSequence;
        this->num_cols = this->test_length;
    }
    this->initialized = true;
    this->left  = (this->num_cols < this->num_rows ? this->num_rows - this->num_cols : 1);
    this->right = 1;
    this->aligned = false;
    grow(false, false);
    return true;
}

int MAlignerEntry::align(){

    if( !this->initialized ) { return MINVAL; }

    while( !this->isAligned() ){
        this->step();
    }

    return getScore();

}

bool MAlignerEntry::step(){

    int num_rows = this->num_rows;
    int num_cols = this->num_cols;

    int *prevRow = NULL;
    int *thisRow = this->dpm->matrix;

    bool boundary = false;

    const int left  = this->left;
    const int right = this->right;

    int ii = 0;

    for(int y = 0; y < num_rows; ++y ){

        int start = (y >= left ? y - left : 0 );
        int stop  = (num_cols < y + right + 1 ? num_cols : y + right + 1);
        int lmax = MINVAL;
        int rmax = MINVAL;
        int line_max = MINVAL;

        int max_x, max_y;
        int rowOffset = 0;

        // This offset is necessary for the cases where the lefthand side of
        // the search window falls outside of the DP matrix.
        // By doing this we can avoid any sort of zany offset garbage.
        if( start == 0 ){
            prevRow = prevRow - 1;
        }

        for( int x = start ; x < stop; ++x){
            assert( (ii > 0 && !(x == 0 && y == 0)) || ii == 0 );

            // add a matrix entry
            int t = this->scoreDP(x, y, rowOffset, prevRow, thisRow);

            // we need to know if we've run into a boundary
            if( x == start && x > 0){ lmax = t; }
            if( x == stop - 1 && x < num_cols - 1){ rmax = t; }
            if( t > line_max ){
                line_max = t;
                max_x = x;
                max_y = y;
            }

            ++rowOffset;
            ++ii;
        }

        prevRow = thisRow;
        thisRow = thisRow + rowOffset; //TODO off by one?

        // if we've hit a boundary, short circuit our way out of the loop
        // and increase the boundary sizes
        if( num_cols > y + right + 1 ){
            bool grow_left = false;
            bool grow_right = false;

            if( line_max == lmax
                && this->left != this->num_cols / 2 ){
                boundary = true;
                grow_left = true;
            }

            if( line_max == rmax
                && this->right != this->num_cols / 2){
                boundary = true;
                grow_right = true;
            }

            if( boundary ){
                this->grow(grow_left, grow_right);
                this->setUpperBound(max_x, max_y, line_max);
                this->setLowerBound(max_x, max_y, line_max);

                return MINVAL;
            }
        }
    }

    int s = this->dpm->matrix[ii - 1];
    if( !boundary ){
        this->aligned = true;
        this->score = s;
        return s;
    }

    return MINVAL;
}

int MAlignerEntry::scoreDP(
        int x,
        int y,
        int rowOffset,
        int *prevRow,
        int *thisRow) {

    int leftVal = MINVAL;
    int upVal = MINVAL;
    int upleftVal = this->gap * x + this->gap * y;

    const char* row_seq = this->row_seq;
    const char* col_seq = this->col_seq;

    if(rowOffset > 0 ){
        leftVal = thisRow[rowOffset - 1] + this->gap;
    } else {
        leftVal = MINVAL;
    }

    if(y > 0 && x > 0){
        upleftVal = prevRow[rowOffset] + (row_seq[y] == col_seq[x] ? this->match : this->mismatch );
    } else {
        upleftVal = upleftVal + (row_seq[y] == col_seq[x] ? this->match : this->mismatch);
    }

    if((y > 0)
       && ( prevRow + rowOffset + 1 < thisRow )){
        upVal = prevRow[rowOffset + 1] + this->gap;
    } else {
        upVal = MINVAL;
    }

    thisRow[rowOffset] = max(upleftVal, max(leftVal, upVal));

    //printf("<%p, %p, %p> [x:%d y:%d] %d (%p)\n", upVal, leftVal, upleftVal, x, y, *(thisRow + rowOffset), (thisRow + rowOffset));
    return thisRow[rowOffset];
}

int main(int argc, char** argv){

    dp_matrix *dpm = (dp_matrix*) malloc(sizeof(dp_matrix));
    dpm->matrix = NULL;
    dpm->size = 0;

    MAlignerEntry *aligner = new MAlignerEntry(string("Sample").c_str(), string("ABCDEFGHIJKL").c_str(), dpm);

    aligner->initialize(string("ABCDEFGHIJKLMNOP").c_str());
    aligner->align();
    printf("%d\n", aligner->getScore());
    //aligner->initialize(string("XXXXXXXXXXXX").c_str());
    //aligner->align();
    //aligner->initialize(string("XXXXXXX").c_str());
    //aligner->align();
    //aligner->initialize(string("ABCDEFG").c_str());
    //aligner->align();

    delete aligner;

    return 0;
}
<commit_msg>Upper and lower bounds are set on completed alignment. Better Multi-aligner destructor.<commit_after>// Multi-aligner

#include "malign.h"

using namespace std;
/*
 * MAligner
 */

MAligner::MAligner(int nseq, char** seqs, char** names){

   global_matrix = (dp_matrix*) malloc(sizeof(dp_matrix));
   global_matrix->matrix = NULL;
   global_matrix->size   = 0;

    for( int ii = 0; ii < nseq; ++ii ){
        MAlignerEntry *en = new MAlignerEntry(names[ii], seqs[ii], global_matrix);
        entries.insert(pair<string,MAlignerEntry*>(string(seqs[ii]),en));
    }

}

MAligner::~MAligner(){
    list<MAlignerEntry*>::iterator entry_itr;

    for( entry_itr = this->entries->begin() ; entry_itr != this->entries->end(); entry_itr++ ){
        delete (*entry_itr);
    }

    if( global_matrix->matrix != NULL ){
        free(global_matrix->matrix);
    }

    free(global_matrix);
}

priority_queue<MAlignerEntry*> MAligner::align(char* input){
    queue<MAlignerEntry*> robin;
    map<string, MAlignerEntry*>::iterator entry_itr;

    int len = strlen(input);

    for( entry_itr = entries.begin(); entry_itr != entries.end(); entry_itr++ ){
        MAlignerEntry *e = (*entry_itr).second;
        e->initialize(input, len);
        robin.push(e);
    }

    return this->roundRobin(robin);

}

priority_queue<MAlignerEntry*> MAligner::alignWith(char* input, int nnames, char** names){

    queue<MAlignerEntry*> robin;
    int len = strlen(input);

    map<string,MAlignerEntry*>::iterator search_itr;
    for( int ii = 0; ii < nnames ; ++ii ){
        search_itr = entries.find(string(names[ii]));
        if( search_itr != entries.end() ){
            (*search_itr).second->initialize(input, len);
            robin.push( (*search_itr).second );
        }
    }

    return this->roundRobin(robin);

}

priority_queue<MAlignerEntry*> MAligner::roundRobin(queue<MAlignerEntry*> robin){

    priority_queue<MAlignerEntry*> results;
    int bestLowerBound = MINVAL;

    while( !robin.empty() ){
        MAlignerEntry *mae = robin.front();
        robin.pop();

        if( mae->upperBound() > bestLowerBound ){
            mae->step();

            if( mae->lowerBound() > bestLowerBound ){
                bestLowerBound = mae->lowerBound();
            }

            if( mae->upperBound() >= bestLowerBound
                && !mae->isAligned() ){
                robin.push(mae);
            }
        }

        if( mae->isAligned() ){
            results.push(mae);
        }
    }

    return results;
}

bool  MAligner::initialize(char* input){
    map<string, MAlignerEntry*>::iterator entry_itr;

    int len = strlen(input);

    for( entry_itr = entries.begin() ; entry_itr != entries.end() ; entry_itr++ ){
        (*entry_itr).second->initialize(input, len);
    }

    return true;
}

/*
 * MAlignerEntry
 */
MAlignerEntry::MAlignerEntry(const char *nm, const char *seq, dp_matrix *dp){

    // copy the reference into place
    this->name = (char*) malloc(strlen(nm) + 1);
    this->refSequence = (char*) malloc(strlen(seq) + 1);
    this->testSequence = NULL;
    strcpy(this->name, nm);
    strcpy(this->refSequence, seq);

    this->ref_length = strlen(this->refSequence);

    this->dpm = dp;
    this->num_rows = NULL;
    this->num_cols = NULL; // initialize this when we load it with a sequence

    this->uBound = MINVAL;
    this->lBound = MINVAL;
    this->matrix_size = MINVAL;

    this->gap      = -1;
    this->match    =  1;
    this->mismatch = -1;

    this->initialized = false;
    this->setLowerBound(0,0,0);
    this->setUpperBound(0,0,0);
}

MAlignerEntry::~MAlignerEntry(){
    free(this->name);
    free(this->refSequence);
    if( this->testSequence ){ free(this->testSequence); }
}

bool MAlignerEntry::isAligned() {
    return aligned;
}

const bool MAlignerEntry::operator< (MAlignerEntry& entry){
    return this->getScore() > entry.getScore();
}
const bool MAlignerEntry::operator> (MAlignerEntry& entry){
    return this->getScore() < entry.getScore();
}

int MAlignerEntry::getScore(){
    return score;
}

int MAlignerEntry::upperBound(){
    return this->uBound;
}

int MAlignerEntry::lowerBound(){
    return this->lBound;
}

int MAlignerEntry::setUpperBound(int x, int y, int score){

    if( !this->initialized ){ return MINVAL; }

    int d = min(this->num_cols - x, this->num_rows - y); // get the maximum score along the diagonal
    int h = max(this->num_cols - x - d, this->num_rows - y - d);

    assert(h >= 0);
    this->uBound = score + d * this->match - h * this->gap;
    return uBound;
}

int MAlignerEntry::setLowerBound(int x, int y, int score){

    if( !this->initialized ){ return MINVAL; }

    int perimeter     = (this->num_cols - x) + (this->num_rows - y);
    int mismatchPath  = min(this->num_cols - x, this->num_rows - y);
    int mismatchPerimeter =
          max(this->num_cols - x - mismatchPath, this->num_rows - y - mismatchPath);
/*
    assert(perimeter >= 0);
    assert(mismatchPath >= 0);
    assert(mismatchPerimeter >= 0);
*/
    int perimeterScore = perimeter * this->gap;
    int mismatchScore = mismatchPath * this->mismatch + mismatchPerimeter * this->gap;

    this->lBound = score + max(perimeterScore, mismatchScore);
    return lBound;
}

int MAlignerEntry::grow(bool growLeft, bool growRight){

    if( growLeft ){
        this->left = min(this->left * 2, this->num_cols / 2);
    }

    if( growRight ){
        this->right = min(this->right * 2, this->num_cols / 2);
    }

    int l = this->left;
    int r = this->right;
    int d = this->num_rows - this->num_cols;
    this->matrix_size =
        this->num_rows
        * (l + r + 1)
        - (l * (l + 1) / 2)
        - (r * (r + 1) / 2)
        - (r * d)
        - (d * (d+1) / 2); // account for left hand overflow and the diagonal

    printf("diff: %d Left: %d Right: %d Rows: %d Cols: %d Size: %d\n", d, l, r, this->num_rows, this->num_cols, this->matrix_size);
    // Ask for a bigger scratch space if we need it
    if(this->dpm->size < this->matrix_size ){
        free(this->dpm->matrix);
        this->dpm->matrix = (int*) malloc(sizeof(int) * this->matrix_size);
        this->dpm->size = this->matrix_size;
    }

    return this->matrix_size;
}

bool MAlignerEntry::initialize(const char* testSeq, int len=0){

    this->test_length = strlen(testSeq);

    //printf("Initialized entry with '%s' and length %d...\n", testSeq, len);
    this->testSequence = (char*) malloc(this->test_length + 1);
    strcpy(this->testSequence, testSeq);

    // test will be the row
    if( this->test_length > this->ref_length ) {
        this->row_seq  = this->testSequence;
        this->num_rows = this->test_length;
        this->col_seq  = this->refSequence;
        this->num_cols = this->ref_length;
    // reference will be the row
    } else {
        this->row_seq  = this->refSequence;
        this->num_rows = this->ref_length;
        this->col_seq  = this->testSequence;
        this->num_cols = this->test_length;
    }
    this->initialized = true;
    this->left  = (this->num_cols < this->num_rows ? this->num_rows - this->num_cols : 1);
    this->right = 1;
    this->aligned = false;
    grow(false, false);
    return true;
}

int MAlignerEntry::align(){

    if( !this->initialized ) { return MINVAL; }

    while( !this->isAligned() ){
        this->step();
    }

    return getScore();

}

bool MAlignerEntry::step(){

    int num_rows = this->num_rows;
    int num_cols = this->num_cols;

    int *prevRow = NULL;
    int *thisRow = this->dpm->matrix;

    bool boundary = false;

    const int left  = this->left;
    const int right = this->right;

    int ii = 0;

    for(int y = 0; y < num_rows; ++y ){

        int start = (y >= left ? y - left : 0 );
        int stop  = (num_cols < y + right + 1 ? num_cols : y + right + 1);
        int lmax = MINVAL;
        int rmax = MINVAL;
        int line_max = MINVAL;

        int max_x, max_y;
        int rowOffset = 0;

        // This offset is necessary for the cases where the lefthand side of
        // the search window falls outside of the DP matrix.
        // By doing this we can avoid any sort of zany offset garbage.
        if( start == 0 ){
            prevRow = prevRow - 1;
        }

        for( int x = start ; x < stop; ++x){
            assert( (ii > 0 && !(x == 0 && y == 0)) || ii == 0 );

            // add a matrix entry
            int t = this->scoreDP(x, y, rowOffset, prevRow, thisRow);

            // we need to know if we've run into a boundary
            if( x == start && x > 0){ lmax = t; }
            if( x == stop - 1 && x < num_cols - 1){ rmax = t; }
            if( t > line_max ){
                line_max = t;
                max_x = x;
                max_y = y;
            }

            ++rowOffset;
            ++ii;
        }

        prevRow = thisRow;
        thisRow = thisRow + rowOffset; //TODO off by one?

        // if we've hit a boundary, short circuit our way out of the loop
        // and increase the boundary sizes
        if( num_cols > y + right + 1 ){
            bool grow_left = false;
            bool grow_right = false;

            if( line_max == lmax
                && this->left != this->num_cols / 2 ){
                boundary = true;
                grow_left = true;
            }

            if( line_max == rmax
                && this->right != this->num_cols / 2){
                boundary = true;
                grow_right = true;
            }

            if( boundary ){
                this->grow(grow_left, grow_right);
                this->setUpperBound(max_x, max_y, line_max);
                this->setLowerBound(max_x, max_y, line_max);

                return MINVAL;
            }
        }
    }

    int s = this->dpm->matrix[ii - 1];
    if( !boundary ){
        this->aligned = true;
        this->score = s;
        this->uBound = s;
        this->lBound = s;
        return s;
    }

    return MINVAL;
}

int MAlignerEntry::scoreDP(
        int x,
        int y,
        int rowOffset,
        int *prevRow,
        int *thisRow) {

    int leftVal = MINVAL;
    int upVal = MINVAL;
    int upleftVal = this->gap * x + this->gap * y;

    const char* row_seq = this->row_seq;
    const char* col_seq = this->col_seq;

    if(rowOffset > 0 ){
        leftVal = thisRow[rowOffset - 1] + this->gap;
    } else {
        leftVal = MINVAL;
    }

    if(y > 0 && x > 0){
        upleftVal = prevRow[rowOffset] + (row_seq[y] == col_seq[x] ? this->match : this->mismatch );
    } else {
        upleftVal = upleftVal + (row_seq[y] == col_seq[x] ? this->match : this->mismatch);
    }

    if((y > 0)
       && ( prevRow + rowOffset + 1 < thisRow )){
        upVal = prevRow[rowOffset + 1] + this->gap;
    } else {
        upVal = MINVAL;
    }

    thisRow[rowOffset] = max(upleftVal, max(leftVal, upVal));

    //printf("<%p, %p, %p> [x:%d y:%d] %d (%p)\n", upVal, leftVal, upleftVal, x, y, *(thisRow + rowOffset), (thisRow + rowOffset));
    return thisRow[rowOffset];
}

int main(int argc, char** argv){

    dp_matrix *dpm = (dp_matrix*) malloc(sizeof(dp_matrix));
    dpm->matrix = NULL;
    dpm->size = 0;

    MAlignerEntry *aligner = new MAlignerEntry(string("Sample").c_str(), string("ABCDEFGHIJKL").c_str(), dpm);

    aligner->initialize(string("XXXXXXXXXXXXXXXXXXX").c_str());
    aligner->align();
    printf("%d (%d,%d)\n", aligner->getScore(), aligner->lowerBound(), aligner->upperBound());
    //aligner->initialize(string("XXXXXXXXXXXX").c_str());
    //aligner->align();
    //aligner->initialize(string("XXXXXXX").c_str());
    //aligner->align();
    //aligner->initialize(string("ABCDEFG").c_str());
    //aligner->align();

    delete aligner;

    return 0;
}
<|endoftext|>


<commit_before>// $Id: fourth_error_estimators.C,v 1.5 2005-06-11 03:59:18 jwpeterson Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2004  Benjamin S. Kirk, John W. Peterson

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

// C++ includes
#include <algorithm> // for std::fill
#include <math.h>    // for sqrt

// Local Includes
#include "libmesh_common.h"
#include "fourth_error_estimators.h"
#include "dof_map.h"
#include "fe.h"
#include "fe_interface.h"
#include "quadrature_clough.h"
#include "libmesh_logging.h"
#include "elem.h"
#include "mesh.h"
#include "system.h"

//-----------------------------------------------------------------
// ErrorEstimator implementations
#ifndef ENABLE_SECOND_DERIVATIVES

void LaplacianErrorEstimator::estimate_error (const System&,
					      std::vector<float>&)
{
  std::cerr << "ERROR:  This functionalitry requires second-derivative support!"
	    << std::endl;
  error();
}

#else // defined (ENABLE_SECOND_DERIVATIVES)

void LaplacianErrorEstimator::estimate_error (const System& system,
					      std::vector<float>& error_per_cell)
{
  START_LOG("laplacian_jump()", "LaplacianErrorEstimator");

  /*

  - e & f are global element ids

  Case (1.) Elements are at the same level, e<f
            Compute the laplacian jump on the face and
	    add it as a contribution to error_per_cell[e]
	    and error_per_cell[f]

                   ----------------------
		  |           |          |
		  |           |    f     |
		  |           |          |
		  |    e      |---> n    |
		  |           |          |
		  |           |          |
                   ----------------------

   Case (2.) The neighbor is at a higher level.
             Compute the laplacian jump on e's face and
	     add it as a contribution to error_per_cell[e]
	     and error_per_cell[f]

                   ----------------------
		  |     |     |          |
		  |     |  e  |---> n    |
		  |     |     |          |
		  |-----------|    f     |
		  |     |     |          |
		  |     |     |          |
		  |     |     |          |
                   ----------------------
*/

  // The current mesh
  const Mesh& mesh = system.get_mesh();

  // The dimensionality of the mesh
  const unsigned int dim = mesh.mesh_dimension();

  // The number of variables in the system
  const unsigned int n_vars = system.n_vars();

  // The DofMap for this system
  const DofMap& dof_map = system.get_dof_map();

  // Resize the error_per_cell vector to be
  // the number of elements, initialize it to 0.
  error_per_cell.resize (mesh.n_elem());
  std::fill (error_per_cell.begin(), error_per_cell.end(), 0.);

  // Check for a valid component_mask
  if (!component_mask.empty())
    if (component_mask.size() != n_vars)
      {
	std::cerr << "ERROR: component_mask is the wrong size:"
		  << std::endl
		  << " component_mask.size()=" << component_mask.size()
		  << std::endl
		  << " n_vars=" << n_vars
		  << std::endl;
	error();
      }

  // Loop over all the variables in the system
  for (unsigned int var=0; var<n_vars; var++)
    {
      // Possibly skip this variable
      if (!component_mask.empty())
	if (component_mask[var] == false) continue;

      // The type of finite element to use for this variable
      const FEType& fe_type = dof_map.variable_type (var);

      // Finite element objects for the same face from
      // different sides
      AutoPtr<FEBase> fe_e (FEBase::build (dim, fe_type));
      AutoPtr<FEBase> fe_f (FEBase::build (dim, fe_type));

      // Build an appropriate Clough-Tocher quadrature rule
      QClough qrule (dim-1, fe_type.default_quadrature_order());

      // Tell the finite element for element e about the quadrature
      // rule.  The finite element for element f need not know about it
      fe_e->attach_quadrature_rule (&qrule);

      // By convention we will always do the integration
      // on the face of element e.  Get its Jacobian values, etc..
      const std::vector<Real>&  JxW_face     = fe_e->get_JxW();
      const std::vector<Point>& qface_point  = fe_e->get_xyz();
//      const std::vector<Point>& face_normals = fe_e->get_normals();

      // The quadrature points on element f.  These will be computed
      // from the quadrature points on element e.
      std::vector<Point> qp_f;

      // The shape function second derivatives on elements e & f
      const std::vector<std::vector<RealTensor> > & d2phi_e =
		      fe_e->get_d2phi();
      const std::vector<std::vector<RealTensor> > & d2phi_f =
		      fe_f->get_d2phi();

      // The global DOF indices for elements e & f
      std::vector<unsigned int> dof_indices_e;
      std::vector<unsigned int> dof_indices_f;

      // Iterate over all the active elements in the mesh
      // that live on this processor.

      MeshBase::const_element_iterator       elem_it  =
		      mesh.active_local_elements_begin();
      const MeshBase::const_element_iterator elem_end =
		      mesh.active_local_elements_end();

      for (; elem_it != elem_end; ++elem_it)
	{
	  // e is necessarily an active element on the local processor
	  const Elem* e = *elem_it;
	  const unsigned int e_id = e->id();

	  // Loop over the neighbors of element e
	  for (unsigned int n_e=0; n_e<e->n_neighbors(); n_e++)
	    if (e->neighbor(n_e) != NULL) // e is not on the boundary
	      {
		const Elem* f           = e->neighbor(n_e);
		const unsigned int f_id = f->id();

		if (   //-------------------------------------
		    ((f->active()) &&
		     (f->level() == e->level()) &&
		     (e_id < f_id))                 // Case 1.

		    || //-------------------------------------

		    (f->level() < e->level())       // Case 2.

		    )  //-------------------------------------
		  {
		    // Update the shape functions on side s_e of
		    // element e
		    fe_e->reinit (e, n_e);

		    // Build the side
		    AutoPtr<Elem> side (e->build_side(n_e));

		    // Get the maximum h for this side
		    const Real h = side->hmax();

		    // Get the DOF indices for the two elements
		    dof_map.dof_indices (e, dof_indices_e, var);
		    dof_map.dof_indices (f, dof_indices_f, var);

		    // The number of DOFS on each element
		    const unsigned int n_dofs_e = dof_indices_e.size();
		    const unsigned int n_dofs_f = dof_indices_f.size();

		    // The number of quadrature points
		    const unsigned int n_qp = qrule.n_points();

		    // Find the location of the quadrature points
		    // on element f
		    FEInterface::inverse_map (dim, fe_type, f,
					      qface_point, qp_f);

		    // Compute the shape functions on element f
		    // at the quadrature points of element e
		    fe_f->reinit (f, &qp_f);

		    // The error contribution from this face
		    Real error = 1.e-10;

		    // loop over the integration points on the face
		    for (unsigned int qp=0; qp<n_qp; qp++)
		      {
			// The solution laplacian from each element
			Number lap_e = 0., lap_f = 0.;

			// Compute the solution laplacian on element e
			for (unsigned int i=0; i<n_dofs_e; i++)
			  {
			  lap_e += d2phi_e[i][qp](0,0) *
				system.current_solution(dof_indices_e[i]);
			  lap_e += d2phi_e[i][qp](1,1) *
				system.current_solution(dof_indices_e[i]);
			  }

			// Compute the solution gradient on element f
			for (unsigned int i=0; i<n_dofs_f; i++)
			  {
			  lap_f += d2phi_f[i][qp](0,0) *
				system.current_solution(dof_indices_f[i]);
			  lap_f += d2phi_f[i][qp](1,1) *
				system.current_solution(dof_indices_f[i]);
			  }

			// The flux jump at the face
			const Number jump = lap_e - lap_f;

			// The flux jump squared
#ifndef USE_COMPLEX_NUMBERS
			const Real jump2 = jump*jump;
#else
			const Real jump2 = std::norm(jump);
#endif

			// Integrate the error on the face
			error += JxW_face[qp]*h*jump2;

		      } // End quadrature point loop

		    // Add the error contribution to elements e & f
		    error_per_cell[e_id] += error;
		    error_per_cell[f_id] += error;

		  }
	      } // if (e->neigbor(n_e) != NULL)

	} // End loop over active local elements

    } // End loop over variables

  // Each processor has now computed the error contribuions
  // for its local elements.  We need to sum the vector
  // and then take the square-root of each component.  Note
  // that we only need to sum if we are running on multiple
  // processors, and we only need to take the square-root
  // if the value is nonzero.  There will in general be many
  // zeros for the inactive elements.

  // First sum the vector
  this->reduce_error(error_per_cell);

  // Compute the square-root of each component.
  for (unsigned int i=0; i<error_per_cell.size(); i++)
    if (error_per_cell[i] != 0.)
      error_per_cell[i] = sqrt(error_per_cell[i]);

  STOP_LOG("laplacian_jump()", "LaplacianErrorEstimator");
}

#endif // defined (ENABLE_SECOND_DERIVATIVES)
<commit_msg>Changed component_mask to component_scale.<commit_after>// $Id: fourth_error_estimators.C,v 1.6 2005-06-14 00:14:56 jwpeterson Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2004  Benjamin S. Kirk, John W. Peterson

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

// C++ includes
#include <algorithm> // for std::fill
#include <math.h>    // for sqrt

// Local Includes
#include "libmesh_common.h"
#include "fourth_error_estimators.h"
#include "dof_map.h"
#include "fe.h"
#include "fe_interface.h"
#include "quadrature_clough.h"
#include "libmesh_logging.h"
#include "elem.h"
#include "mesh.h"
#include "system.h"

//-----------------------------------------------------------------
// ErrorEstimator implementations
#ifndef ENABLE_SECOND_DERIVATIVES

void LaplacianErrorEstimator::estimate_error (const System&,
					      std::vector<float>&)
{
  std::cerr << "ERROR:  This functionalitry requires second-derivative support!"
	    << std::endl;
  error();
}

#else // defined (ENABLE_SECOND_DERIVATIVES)

void LaplacianErrorEstimator::estimate_error (const System& system,
					      std::vector<float>& error_per_cell)
{
  START_LOG("laplacian_jump()", "LaplacianErrorEstimator");

  /*

  - e & f are global element ids

  Case (1.) Elements are at the same level, e<f
            Compute the laplacian jump on the face and
	    add it as a contribution to error_per_cell[e]
	    and error_per_cell[f]

                   ----------------------
		  |           |          |
		  |           |    f     |
		  |           |          |
		  |    e      |---> n    |
		  |           |          |
		  |           |          |
                   ----------------------

   Case (2.) The neighbor is at a higher level.
             Compute the laplacian jump on e's face and
	     add it as a contribution to error_per_cell[e]
	     and error_per_cell[f]

                   ----------------------
		  |     |     |          |
		  |     |  e  |---> n    |
		  |     |     |          |
		  |-----------|    f     |
		  |     |     |          |
		  |     |     |          |
		  |     |     |          |
                   ----------------------
*/

  // The current mesh
  const Mesh& mesh = system.get_mesh();

  // The dimensionality of the mesh
  const unsigned int dim = mesh.mesh_dimension();

  // The number of variables in the system
  const unsigned int n_vars = system.n_vars();

  // The DofMap for this system
  const DofMap& dof_map = system.get_dof_map();

  // Resize the error_per_cell vector to be
  // the number of elements, initialize it to 0.
  error_per_cell.resize (mesh.n_elem());
  std::fill (error_per_cell.begin(), error_per_cell.end(), 0.);

  // Check for a valid component_mask
  if (!component_scale.empty())
    {
      if (component_scale.size() != n_vars)
	{
	  std::cerr << "ERROR: component_scale is the wrong size:"
		    << std::endl
		    << " component_scale.size()=" << component_scale.size()
		    << std::endl
		    << " n_vars=" << n_vars
		    << std::endl;
	  error();
	}
    }
  else
    {
      // No specified scaling.  Scale all variables by one.
      component_scale.resize (n_vars);
      std::fill (component_scale.begin(), component_scale.end(), 1.0);
    }

  // Loop over all the variables in the system
  for (unsigned int var=0; var<n_vars; var++)
    {
      // Possibly skip this variable
      if (!component_scale.empty())
	if (component_scale[var] == false) continue;

      // The type of finite element to use for this variable
      const FEType& fe_type = dof_map.variable_type (var);

      // Finite element objects for the same face from
      // different sides
      AutoPtr<FEBase> fe_e (FEBase::build (dim, fe_type));
      AutoPtr<FEBase> fe_f (FEBase::build (dim, fe_type));

      // Build an appropriate Clough-Tocher quadrature rule
      QClough qrule (dim-1, fe_type.default_quadrature_order());

      // Tell the finite element for element e about the quadrature
      // rule.  The finite element for element f need not know about it
      fe_e->attach_quadrature_rule (&qrule);

      // By convention we will always do the integration
      // on the face of element e.  Get its Jacobian values, etc..
      const std::vector<Real>&  JxW_face     = fe_e->get_JxW();
      const std::vector<Point>& qface_point  = fe_e->get_xyz();
//      const std::vector<Point>& face_normals = fe_e->get_normals();

      // The quadrature points on element f.  These will be computed
      // from the quadrature points on element e.
      std::vector<Point> qp_f;

      // The shape function second derivatives on elements e & f
      const std::vector<std::vector<RealTensor> > & d2phi_e =
		      fe_e->get_d2phi();
      const std::vector<std::vector<RealTensor> > & d2phi_f =
		      fe_f->get_d2phi();

      // The global DOF indices for elements e & f
      std::vector<unsigned int> dof_indices_e;
      std::vector<unsigned int> dof_indices_f;

      // Iterate over all the active elements in the mesh
      // that live on this processor.

      MeshBase::const_element_iterator       elem_it  =
		      mesh.active_local_elements_begin();
      const MeshBase::const_element_iterator elem_end =
		      mesh.active_local_elements_end();

      for (; elem_it != elem_end; ++elem_it)
	{
	  // e is necessarily an active element on the local processor
	  const Elem* e = *elem_it;
	  const unsigned int e_id = e->id();

	  // Loop over the neighbors of element e
	  for (unsigned int n_e=0; n_e<e->n_neighbors(); n_e++)
	    if (e->neighbor(n_e) != NULL) // e is not on the boundary
	      {
		const Elem* f           = e->neighbor(n_e);
		const unsigned int f_id = f->id();

		if (   //-------------------------------------
		    ((f->active()) &&
		     (f->level() == e->level()) &&
		     (e_id < f_id))                 // Case 1.

		    || //-------------------------------------

		    (f->level() < e->level())       // Case 2.

		    )  //-------------------------------------
		  {
		    // Update the shape functions on side s_e of
		    // element e
		    fe_e->reinit (e, n_e);

		    // Build the side
		    AutoPtr<Elem> side (e->build_side(n_e));

		    // Get the maximum h for this side
		    const Real h = side->hmax();

		    // Get the DOF indices for the two elements
		    dof_map.dof_indices (e, dof_indices_e, var);
		    dof_map.dof_indices (f, dof_indices_f, var);

		    // The number of DOFS on each element
		    const unsigned int n_dofs_e = dof_indices_e.size();
		    const unsigned int n_dofs_f = dof_indices_f.size();

		    // The number of quadrature points
		    const unsigned int n_qp = qrule.n_points();

		    // Find the location of the quadrature points
		    // on element f
		    FEInterface::inverse_map (dim, fe_type, f,
					      qface_point, qp_f);

		    // Compute the shape functions on element f
		    // at the quadrature points of element e
		    fe_f->reinit (f, &qp_f);

		    // The error contribution from this face
		    Real error = 1.e-10;

		    // loop over the integration points on the face
		    for (unsigned int qp=0; qp<n_qp; qp++)
		      {
			// The solution laplacian from each element
			Number lap_e = 0., lap_f = 0.;

			// Compute the solution laplacian on element e
			for (unsigned int i=0; i<n_dofs_e; i++)
			  {
			  lap_e += d2phi_e[i][qp](0,0) *
				system.current_solution(dof_indices_e[i]);
			  lap_e += d2phi_e[i][qp](1,1) *
				system.current_solution(dof_indices_e[i]);
			  }

			// Compute the solution gradient on element f
			for (unsigned int i=0; i<n_dofs_f; i++)
			  {
			  lap_f += d2phi_f[i][qp](0,0) *
				system.current_solution(dof_indices_f[i]);
			  lap_f += d2phi_f[i][qp](1,1) *
				system.current_solution(dof_indices_f[i]);
			  }

			// The flux jump at the face
			const Number jump = lap_e - lap_f;

			// The flux jump squared
#ifndef USE_COMPLEX_NUMBERS
			const Real jump2 = jump*jump;
#else
			const Real jump2 = std::norm(jump);
#endif

			// Integrate the error on the face
			error += JxW_face[qp]*h*jump2;

		      } // End quadrature point loop

		    // Add the error contribution to elements e & f
		    error_per_cell[e_id] += error;
		    error_per_cell[f_id] += error;

		  }
	      } // if (e->neigbor(n_e) != NULL)

	} // End loop over active local elements

    } // End loop over variables

  // Each processor has now computed the error contribuions
  // for its local elements.  We need to sum the vector
  // and then take the square-root of each component.  Note
  // that we only need to sum if we are running on multiple
  // processors, and we only need to take the square-root
  // if the value is nonzero.  There will in general be many
  // zeros for the inactive elements.

  // First sum the vector
  this->reduce_error(error_per_cell);

  // Compute the square-root of each component.
  for (unsigned int i=0; i<error_per_cell.size(); i++)
    if (error_per_cell[i] != 0.)
      error_per_cell[i] = sqrt(error_per_cell[i]);

  STOP_LOG("laplacian_jump()", "LaplacianErrorEstimator");
}

#endif // defined (ENABLE_SECOND_DERIVATIVES)
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/url_request/url_request_job_manager.h"

#include "build/build_config.h"
#include "base/string_util.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_about_job.h"
#include "net/url_request/url_request_error_job.h"
#if defined(OS_WIN)
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_ftp_job.h"
#else
// TODO(playmobil): Implement on non-windows platforms.
#endif
#include "net/url_request/url_request_http_job.h"
#include "net/url_request/url_request_view_cache_job.h"

// The built-in set of protocol factories
namespace {

struct SchemeToFactory {
  const char* scheme;
  URLRequest::ProtocolFactory* factory;
};

}  // namespace

static const SchemeToFactory kBuiltinFactories[] = {
  { "http", URLRequestHttpJob::Factory },
  { "https", URLRequestHttpJob::Factory },
#if defined(OS_WIN)
  { "file", URLRequestFileJob::Factory },
  { "ftp", URLRequestFtpJob::Factory },
#else
// TODO(playmobil): Implement on non-windows platforms.
#endif
  { "about", URLRequestAboutJob::Factory },
  { "view-cache", URLRequestViewCacheJob::Factory },
};

URLRequestJobManager::URLRequestJobManager() {
#ifndef NDEBUG
  allowed_thread_ = 0;
  allowed_thread_initialized_ = false;
#endif
}

URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  // If we are given an invalid URL, then don't even try to inspect the scheme.
  if (!request->url().is_valid())
    return new URLRequestErrorJob(request, net::ERR_INVALID_URL);

  const std::string& scheme = request->url().scheme();  // already lowercase

  // We do this here to avoid asking interceptors about unsupported schemes.
  if (!SupportsScheme(scheme))
    return new URLRequestErrorJob(request, net::ERR_UNKNOWN_URL_SCHEME);

  // THREAD-SAFETY NOTICE:
  //   We do not need to acquire the lock here since we are only reading our
  //   data structures.  They should only be modified on the current thread.

  // See if the request should be intercepted.
  if (!(request->load_flags() & net::LOAD_DISABLE_INTERCEPT)) {
    InterceptorList::const_iterator i;
    for (i = interceptors_.begin(); i != interceptors_.end(); ++i) {
      URLRequestJob* job = (*i)->MaybeIntercept(request);
      if (job)
        return job;
    }
  }

  // See if the request should be handled by a registered protocol factory.
  // If the registered factory returns null, then we want to fall-back to the
  // built-in protocol factory.
  FactoryMap::const_iterator i = factories_.find(scheme);
  if (i != factories_.end()) {
    URLRequestJob* job = i->second(request, scheme);
    if (job)
      return job;
  }

  // See if the request should be handled by a built-in protocol factory.
  for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) {
    if (scheme == kBuiltinFactories[i].scheme) {
      URLRequestJob* job = (kBuiltinFactories[i].factory)(request, scheme);
      DCHECK(job);  // The built-in factories are not expected to fail!
      return job;
    }
  }

  // If we reached here, then it means that a registered protocol factory
  // wasn't interested in handling the URL.  That is fairly unexpected, and we
  // don't know have a specific error to report here :-(
  return new URLRequestErrorJob(request, net::ERR_FAILED);
}

bool URLRequestJobManager::SupportsScheme(const std::string& scheme) const {
  // The set of registered factories may change on another thread.
  {
    AutoLock locked(lock_);
    if (factories_.find(scheme) != factories_.end())
      return true;
  }

  for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i)
    if (LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme))
      return true;

  return false;
}

URLRequest::ProtocolFactory* URLRequestJobManager::RegisterProtocolFactory(
    const std::string& scheme,
    URLRequest::ProtocolFactory* factory) {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  AutoLock locked(lock_);

  URLRequest::ProtocolFactory* old_factory;
  FactoryMap::iterator i = factories_.find(scheme);
  if (i != factories_.end()) {
    old_factory = i->second;
  } else {
    old_factory = NULL;
  }
  if (factory) {
    factories_[scheme] = factory;
  } else if (i != factories_.end()) {  // uninstall any old one
    factories_.erase(i);
  }
  return old_factory;
}

void URLRequestJobManager::RegisterRequestInterceptor(
    URLRequest::Interceptor* interceptor) {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  AutoLock locked(lock_);

  DCHECK(std::find(interceptors_.begin(), interceptors_.end(), interceptor) ==
         interceptors_.end());
  interceptors_.push_back(interceptor);
}

void URLRequestJobManager::UnregisterRequestInterceptor(
    URLRequest::Interceptor* interceptor) {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  AutoLock locked(lock_);

  InterceptorList::iterator i =
      std::find(interceptors_.begin(), interceptors_.end(), interceptor);
  DCHECK(i != interceptors_.end());
  interceptors_.erase(i);
}

<commit_msg>fix build bustage due to missing header<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/url_request/url_request_job_manager.h"

#include <algorithm>

#include "build/build_config.h"
#include "base/string_util.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_about_job.h"
#include "net/url_request/url_request_error_job.h"
#if defined(OS_WIN)
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_ftp_job.h"
#else
// TODO(playmobil): Implement on non-windows platforms.
#endif
#include "net/url_request/url_request_http_job.h"
#include "net/url_request/url_request_view_cache_job.h"

// The built-in set of protocol factories
namespace {

struct SchemeToFactory {
  const char* scheme;
  URLRequest::ProtocolFactory* factory;
};

}  // namespace

static const SchemeToFactory kBuiltinFactories[] = {
  { "http", URLRequestHttpJob::Factory },
  { "https", URLRequestHttpJob::Factory },
#if defined(OS_WIN)
  { "file", URLRequestFileJob::Factory },
  { "ftp", URLRequestFtpJob::Factory },
#else
// TODO(playmobil): Implement on non-windows platforms.
#endif
  { "about", URLRequestAboutJob::Factory },
  { "view-cache", URLRequestViewCacheJob::Factory },
};

URLRequestJobManager::URLRequestJobManager() {
#ifndef NDEBUG
  allowed_thread_ = 0;
  allowed_thread_initialized_ = false;
#endif
}

URLRequestJob* URLRequestJobManager::CreateJob(URLRequest* request) const {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  // If we are given an invalid URL, then don't even try to inspect the scheme.
  if (!request->url().is_valid())
    return new URLRequestErrorJob(request, net::ERR_INVALID_URL);

  const std::string& scheme = request->url().scheme();  // already lowercase

  // We do this here to avoid asking interceptors about unsupported schemes.
  if (!SupportsScheme(scheme))
    return new URLRequestErrorJob(request, net::ERR_UNKNOWN_URL_SCHEME);

  // THREAD-SAFETY NOTICE:
  //   We do not need to acquire the lock here since we are only reading our
  //   data structures.  They should only be modified on the current thread.

  // See if the request should be intercepted.
  if (!(request->load_flags() & net::LOAD_DISABLE_INTERCEPT)) {
    InterceptorList::const_iterator i;
    for (i = interceptors_.begin(); i != interceptors_.end(); ++i) {
      URLRequestJob* job = (*i)->MaybeIntercept(request);
      if (job)
        return job;
    }
  }

  // See if the request should be handled by a registered protocol factory.
  // If the registered factory returns null, then we want to fall-back to the
  // built-in protocol factory.
  FactoryMap::const_iterator i = factories_.find(scheme);
  if (i != factories_.end()) {
    URLRequestJob* job = i->second(request, scheme);
    if (job)
      return job;
  }

  // See if the request should be handled by a built-in protocol factory.
  for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) {
    if (scheme == kBuiltinFactories[i].scheme) {
      URLRequestJob* job = (kBuiltinFactories[i].factory)(request, scheme);
      DCHECK(job);  // The built-in factories are not expected to fail!
      return job;
    }
  }

  // If we reached here, then it means that a registered protocol factory
  // wasn't interested in handling the URL.  That is fairly unexpected, and we
  // don't know have a specific error to report here :-(
  return new URLRequestErrorJob(request, net::ERR_FAILED);
}

bool URLRequestJobManager::SupportsScheme(const std::string& scheme) const {
  // The set of registered factories may change on another thread.
  {
    AutoLock locked(lock_);
    if (factories_.find(scheme) != factories_.end())
      return true;
  }

  for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i)
    if (LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme))
      return true;

  return false;
}

URLRequest::ProtocolFactory* URLRequestJobManager::RegisterProtocolFactory(
    const std::string& scheme,
    URLRequest::ProtocolFactory* factory) {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  AutoLock locked(lock_);

  URLRequest::ProtocolFactory* old_factory;
  FactoryMap::iterator i = factories_.find(scheme);
  if (i != factories_.end()) {
    old_factory = i->second;
  } else {
    old_factory = NULL;
  }
  if (factory) {
    factories_[scheme] = factory;
  } else if (i != factories_.end()) {  // uninstall any old one
    factories_.erase(i);
  }
  return old_factory;
}

void URLRequestJobManager::RegisterRequestInterceptor(
    URLRequest::Interceptor* interceptor) {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  AutoLock locked(lock_);

  DCHECK(std::find(interceptors_.begin(), interceptors_.end(), interceptor) ==
         interceptors_.end());
  interceptors_.push_back(interceptor);
}

void URLRequestJobManager::UnregisterRequestInterceptor(
    URLRequest::Interceptor* interceptor) {
#ifndef NDEBUG
  DCHECK(IsAllowedThread());
#endif

  AutoLock locked(lock_);

  InterceptorList::iterator i =
      std::find(interceptors_.begin(), interceptors_.end(), interceptor);
  DCHECK(i != interceptors_.end());
  interceptors_.erase(i);
}

<|endoftext|>


<commit_before>/*
 * module_param_cache.cpp
 *
 *  Created on: 19 Jul 2012
 *      Author: andreas
 */

#include "planner_modules_pr2/module_param_cache.h"

std::string ModuleParamCache::baseNamespace = "/tfd_modules/cache";

ModuleParamCache::ModuleParamCache()
{
    node = NULL;
}

void ModuleParamCache::initialize(const std::string& moduleNamespace, ros::NodeHandle* node)
{
    this->node = node;
    this->baseNamespace = baseNamespace;
    keyPrefix = baseNamespace + "/" + moduleNamespace + "/";
}

ModuleParamCache::~ModuleParamCache()
{
}

void ModuleParamCache::clearAll()
{
    ros::NodeHandle s_node = ros::NodeHandle();
    if (s_node.hasParam(baseNamespace))
    {
        s_node.deleteParam(baseNamespace);
    }
}

void ModuleParamCache::set(const std::string& key, double value)
{
    ROS_INFO("[cache]: writing to cache: %s -> %f", key.c_str(), value);
    node->setParam(keyPrefix + key, value);
}

bool ModuleParamCache::get(const std::string& key, double& value) const
{
    ROS_INFO("[cache]: lookup in cache: %s -> %f", key.c_str(), value);
    return node->getParamCached(keyPrefix + key, value);
}

<commit_msg>planner_modules_pr2: removed debug messages from module param cache<commit_after>/*
 * module_param_cache.cpp
 *
 *  Created on: 19 Jul 2012
 *      Author: andreas
 */

#include "planner_modules_pr2/module_param_cache.h"

std::string ModuleParamCache::baseNamespace = "/tfd_modules/cache";

ModuleParamCache::ModuleParamCache()
{
    node = NULL;
}

void ModuleParamCache::initialize(const std::string& moduleNamespace, ros::NodeHandle* node)
{
    this->node = node;
    this->baseNamespace = baseNamespace;
    keyPrefix = baseNamespace + "/" + moduleNamespace + "/";
}

ModuleParamCache::~ModuleParamCache()
{
}

void ModuleParamCache::clearAll()
{
    ros::NodeHandle s_node = ros::NodeHandle();
    if (s_node.hasParam(baseNamespace))
    {
        s_node.deleteParam(baseNamespace);
    }
}

void ModuleParamCache::set(const std::string& key, double value)
{
//    ROS_INFO("[cache]: writing to cache: %s -> %f", key.c_str(), value);
    node->setParam(keyPrefix + key, value);
}

bool ModuleParamCache::get(const std::string& key, double& value) const
{
//    ROS_INFO("[cache]: lookup in cache: %s -> %f", key.c_str(), value);
    return node->getParamCached(keyPrefix + key, value);
}

<|endoftext|>


<commit_before>#pragma once
#include "node.hpp"
#include "type.hpp"
#include "ctype.hpp"

namespace backend {

class copier
    : public no_op_visitor<std::shared_ptr<node> >
{
protected:
    //If you know you're not going to do any rewriting at deeper
    //levels of the AST, just grab the pointer from the node
    template<typename Node>
    result_type get_node_ptr(const Node &n) {
        return std::const_pointer_cast<node>(n.shared_from_this());
    }
    template<typename Type>
    std::shared_ptr<type_t> get_type_ptr(const Type &n) {
        return std::const_pointer_cast<type_t>(n.shared_from_this());
    }
    template<typename Ctype>
    std::shared_ptr<ctype::type_t> get_ctype_ptr(const Ctype &n) {
        return std::const_pointer_cast<ctype::type_t>(n.shared_from_this());
    }
public:
    using backend::no_op_visitor<std::shared_ptr<node> >::operator();

    virtual result_type operator()(const literal& n) {
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());
        return result_type(new literal(n.id(), t, ct));
    }
    virtual result_type operator()(const name &n) {
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());
        return result_type(new name(n.id(), t, ct));
    }
    virtual result_type operator()(const tuple &n) {
        std::vector<std::shared_ptr<expression> > n_values;
        for(auto i = n.begin(); i != n.end(); i++) {
            auto n_i = std::static_pointer_cast<expression>(boost::apply_visitor(*this, *i));
            n_values.push_back(n_i);
        }
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());

        return result_type(new tuple(std::move(n_values), t, ct));
    }
    virtual result_type operator()(const apply &n) {
        auto n_fn = std::static_pointer_cast<name>(boost::apply_visitor(*this, n.fn()));
        auto n_args = std::static_pointer_cast<tuple>((*this)(n.args()));
        return result_type(new apply(n_fn, n_args));
    }
    virtual result_type operator()(const lambda &n) {
        auto n_args = std::static_pointer_cast<tuple>((*this)(n.args()));
        auto n_body = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.body()));
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());
        return result_type(new lambda(n_args, n_body, t, ct));
    }
    virtual result_type operator()(const closure &n) {
        return result_type(new closure());
    }
    virtual result_type operator()(const conditional &n) {
        return result_type(new conditional());
    }
    virtual result_type operator()(const ret &n) {
        auto n_val = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.val()));
        return result_type(new ret(n_val));
    }
    virtual result_type operator()(const bind &n) {
        auto n_lhs = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.lhs()));
        auto n_rhs = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.rhs()));
        return result_type(new bind(n_lhs, n_rhs));
    }
    virtual result_type operator()(const call &n) {
        auto n_sub = std::static_pointer_cast<apply>(boost::apply_visitor(*this, n.sub()));
        return result_type(new call(n_sub));
    }
    virtual result_type operator()(const procedure &n) {
        auto n_id = std::static_pointer_cast<name>((*this)(n.id()));
        auto n_args = std::static_pointer_cast<tuple>((*this)(n.args()));
        auto n_stmts = std::static_pointer_cast<suite>((*this)(n.stmts()));
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());

        return result_type(new procedure(n_id, n_args, n_stmts, t, ct));
    }
    virtual result_type operator()(const suite &n) {
        std::vector<std::shared_ptr<statement> > n_stmts;
        for(auto i = n.begin(); i != n.end(); i++) {
            auto n_stmt = std::static_pointer_cast<statement>(boost::apply_visitor(*this, *i));
            n_stmts.push_back(n_stmt);
        }
        return result_type(new suite(std::move(n_stmts)));
    }
    virtual result_type operator()(const structure &n) {
        auto n_id = std::static_pointer_cast<name>((*this)(n.id()));
        auto n_stmts = std::static_pointer_cast<suite>((*this)(n.stmts()));
        return result_type(new structure(n_id, n_stmts));
    }
    virtual result_type operator()(const templated_name &n) {
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());
        auto n_args = std::static_pointer_cast<ctype::tuple_t>(
            get_ctype_ptr(n.template_types()));
        return result_type(new templated_name(n.id(), n_args, t, ct));
    }
    virtual result_type operator()(const include &n) {
        std::shared_ptr<name> id = std::static_pointer_cast<name>(
            boost::apply_visitor(*this, n.id()));
        return result_type(new include(id));
    }
};

}
<commit_msg>Reuse AST nodes when possible.<commit_after>#pragma once
#include "node.hpp"
#include "type.hpp"
#include "ctype.hpp"

namespace backend {

class copier
    : public no_op_visitor<std::shared_ptr<node> >
{
protected:
    //If you know you're not going to do any rewriting at deeper
    //levels of the AST, just grab the pointer from the node
    template<typename Node>
    result_type get_node_ptr(const Node &n) {
        return std::const_pointer_cast<node>(n.shared_from_this());
    }
    template<typename Type>
    std::shared_ptr<type_t> get_type_ptr(const Type &n) {
        return std::const_pointer_cast<type_t>(n.shared_from_this());
    }
    template<typename Ctype>
    std::shared_ptr<ctype::type_t> get_ctype_ptr(const Ctype &n) {
        return std::const_pointer_cast<ctype::type_t>(n.shared_from_this());
    }
    bool m_match;
    void start_match() {
        m_match = true;
    }
    template<typename T, typename U>
    inline void update_match(const T& t, const U& u) {
        m_match = m_match && (t == get_node_ptr(u));
    }
    bool is_match() {
        return m_match;
    }

public:
    using backend::no_op_visitor<std::shared_ptr<node> >::operator();

    virtual result_type operator()(const literal& n) {
        return get_node_ptr(n);
    }
    virtual result_type operator()(const name &n) {
        return get_node_ptr(n);
    }
    virtual result_type operator()(const tuple &n) {
        start_match();
        std::vector<std::shared_ptr<expression> > n_values;
        for(auto i = n.begin(); i != n.end(); i++) {
            auto n_i = std::static_pointer_cast<expression>(boost::apply_visitor(*this, *i));
            update_match(n_i, *i);
            n_values.push_back(n_i);
        }
        if (is_match())
            return get_node_ptr(n);

        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());

        return result_type(new tuple(std::move(n_values), t, ct));
    }
    virtual result_type operator()(const apply &n) {
        auto n_fn = std::static_pointer_cast<name>(boost::apply_visitor(*this, n.fn()));
        auto n_args = std::static_pointer_cast<tuple>((*this)(n.args()));
        start_match();
        update_match(n_fn, n.fn());
        update_match(n_args, n.args());
        if (is_match())
            return get_node_ptr(n);
        return result_type(new apply(n_fn, n_args));
    }
    virtual result_type operator()(const lambda &n) {
        auto n_args = std::static_pointer_cast<tuple>((*this)(n.args()));
        auto n_body = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.body()));
        start_match();
        update_match(n_args, n.args());
        update_match(n_body, n.body());
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());
        return result_type(new lambda(n_args, n_body, t, ct));
    }
    virtual result_type operator()(const closure &n) {
        return result_type(new closure());
    }
    virtual result_type operator()(const conditional &n) {
        return result_type(new conditional());
    }
    virtual result_type operator()(const ret &n) {
        auto n_val = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.val()));
        start_match();
        update_match(n_val, n.val());
        if (is_match())
            return get_node_ptr(n);
        return result_type(new ret(n_val));
    }
    virtual result_type operator()(const bind &n) {
        auto n_lhs = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.lhs()));
        auto n_rhs = std::static_pointer_cast<expression>(boost::apply_visitor(*this, n.rhs()));
        start_match();
        update_match(n_lhs, n.lhs());
        update_match(n_rhs, n.rhs());
        if (is_match())
            return get_node_ptr(n);
        return result_type(new bind(n_lhs, n_rhs));
    }
    virtual result_type operator()(const call &n) {
        auto n_sub = std::static_pointer_cast<apply>(boost::apply_visitor(*this, n.sub()));
        start_match();
        update_match(n_sub, n.sub());
        if (is_match())
            return get_node_ptr(n);
        return result_type(new call(n_sub));
    }
    virtual result_type operator()(const procedure &n) {
        auto n_id = std::static_pointer_cast<name>((*this)(n.id()));
        auto n_args = std::static_pointer_cast<tuple>((*this)(n.args()));
        auto n_stmts = std::static_pointer_cast<suite>((*this)(n.stmts()));
        start_match();
        update_match(n_id, n.id());
        update_match(n_args, n.args());
        update_match(n_stmts, n.stmts());
        if (is_match())
            return get_node_ptr(n);
        std::shared_ptr<type_t> t = get_type_ptr(n.type());
        std::shared_ptr<ctype::type_t> ct = get_ctype_ptr(n.ctype());

        return result_type(new procedure(n_id, n_args, n_stmts, t, ct));
    }
    virtual result_type operator()(const suite &n) {
        start_match();
        std::vector<std::shared_ptr<statement> > n_stmts;
        for(auto i = n.begin(); i != n.end(); i++) {
            auto n_stmt = std::static_pointer_cast<statement>(boost::apply_visitor(*this, *i));
            update_match(n_stmt, *i);
            n_stmts.push_back(n_stmt);
        }
        if (is_match())
            return get_node_ptr(n);
        return result_type(new suite(std::move(n_stmts)));
    }
    virtual result_type operator()(const structure &n) {
        auto n_id = std::static_pointer_cast<name>((*this)(n.id()));
        auto n_stmts = std::static_pointer_cast<suite>((*this)(n.stmts()));
        start_match();
        update_match(n_id, n.id());
        update_match(n_stmts, n.stmts());
        if (is_match())
            return get_node_ptr(n);
        return result_type(new structure(n_id, n_stmts));
    }
    virtual result_type operator()(const templated_name &n) {
        return get_node_ptr(n);
    }
    virtual result_type operator()(const include &n) {
        return get_node_ptr(n);
    }
};

}
<|endoftext|>


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

#include <cstdlib>
#include <iostream>
#include "opcodes.h"
#include "vm.h"

namespace clever {

/*
 * Destroy the opcodes data
 */
VM::~VM(void) {
	OpcodeList::iterator it = m_opcodes->begin();

	while (it < m_opcodes->end()) {
		if ((*it)->get_op1()) {
			(*it)->get_op1()->delRef();
		}
		if ((*it)->get_op2()) {
			(*it)->get_op2()->delRef();
		}
		if ((*it)->get_result()) {
			(*it)->get_result()->delRef();
		}
		delete *it;
		++it;
	}
}

/*
 * Displays an error message
 */
void VM::error(const char* message) const {
	std::cout << "Runtime error: " << message << std::endl;
	exit(1);
}

/*
 * Execute the collected opcodes
 */
void VM::run(void) {
	OpcodeList::iterator it = m_opcodes->begin();

	m_symbols.pushVarMap(SymbolTable::var_map());

	while (it < m_opcodes->end()) {
		Opcode* opcode = *it;

		(this->*((*it)->get_handler()))(*it);
		++it;
	}

	m_symbols.popVarMap();
}

/*
 * echo statemenet
 */
void VM::echo_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());

	std::cout << op1->toString() << std::endl;
}

/*
 * x + y
 */
void VM::plus_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2) && op1->hasSameType(op2)) {
		switch (op1->get_type()) {
			case Value::STRING:
				opcode->get_result()->set_value(new ConstantValue(CSTRING(op1->getString() + op2->getString())));
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() + op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

/*
 * x / y
 */
void VM::div_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2) && op1->hasSameType(op2)) {
		switch (op1->get_type()) {
			case Value::STRING:
				error("Operation not allow in strings!");
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() / op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

/*
 * x - y
 */
void VM::minus_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2) && op1->hasSameType(op2)) {
		switch (op1->get_type()) {
			case Value::STRING:
				error("Operation not allow in strings!");
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() - op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

/*
 * x * y
 */
void VM::mult_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2) && op1->hasSameType(op2)) {
		switch (op1->get_type()) {
			case Value::STRING:
				error("Operation not allow in strings!");
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() * op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

void VM::new_scope_handler(CLEVER_VM_HANDLER_ARGS) {
	m_symbols.pushVarMap(SymbolTable::var_map());
}

void VM::end_scope_handler(CLEVER_VM_HANDLER_ARGS) {
	m_symbols.popVarMap();
}

void VM::var_decl_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* value = opcode->get_op2();

	value->addRef();

	m_symbols.register_var(opcode->get_op1()->toString(), value);
}

} // clever
<commit_msg>- Added runtime typemismatch checking<commit_after>/*
 * Clever language
 * Copyright (c) 2010 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * $Id: parser.y 67 2010-12-22 18:55:54Z felipensp $
 */

#include <cstdlib>
#include <iostream>
#include "opcodes.h"
#include "vm.h"

namespace clever {

/*
 * Destroy the opcodes data
 */
VM::~VM(void) {
	OpcodeList::iterator it = m_opcodes->begin();

	while (it < m_opcodes->end()) {
		if ((*it)->get_op1()) {
			(*it)->get_op1()->delRef();
		}
		if ((*it)->get_op2()) {
			(*it)->get_op2()->delRef();
		}
		if ((*it)->get_result()) {
			(*it)->get_result()->delRef();
		}
		delete *it;
		++it;
	}
}

/*
 * Displays an error message
 */
void VM::error(const char* message) const {
	std::cout << "Runtime error: " << message << std::endl;
	exit(1);
}

/*
 * Execute the collected opcodes
 */
void VM::run(void) {
	OpcodeList::iterator it = m_opcodes->begin();

	m_symbols.pushVarMap(SymbolTable::var_map());

	while (it < m_opcodes->end()) {
		Opcode* opcode = *it;

		(this->*((*it)->get_handler()))(*it);
		++it;
	}

	m_symbols.popVarMap();
}

/*
 * echo statemenet
 */
void VM::echo_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());

	std::cout << op1->toString() << std::endl;
}

/*
 * x + y
 */
void VM::plus_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2)) {
		if (!op1->hasSameType(op2)) {
			error("Type mismatch!");
		}
		switch (op1->get_type()) {
			case Value::STRING:
				opcode->get_result()->set_value(new ConstantValue(CSTRING(op1->getString() + op2->getString())));
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() + op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

/*
 * x / y
 */
void VM::div_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2)) {
		if (!op1->hasSameType(op2)) {
			error("Type mismatch!");
		}
		switch (op1->get_type()) {
			case Value::STRING:
				error("Operation not allow in strings!");
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() / op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

/*
 * x - y
 */
void VM::minus_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2)) {
		if (!op1->hasSameType(op2)) {
			error("Type mismatch!");
		}
		switch (op1->get_type()) {
			case Value::STRING:
				error("Operation not allow in strings!");
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() - op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

/*
 * x * y
 */
void VM::mult_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* op1 = getValue(opcode->get_op1());
	Value* op2 = getValue(opcode->get_op2());

	if (op1->isConst() && op1->hasSameKind(op2)) {
		if (!op1->hasSameType(op2)) {
			error("Type mismatch!");
		}
		switch (op1->get_type()) {
			case Value::STRING:
				error("Operation not allow in strings!");
				break;
			case Value::INTEGER:
				opcode->get_result()->set_value(new ConstantValue(op1->getInteger() * op2->getInteger()));
				break;
			case Value::DOUBLE:
				opcode->get_result()->set_value(new ConstantValue(op1->getDouble() + op2->getDouble()));
				break;
		}
	}
}

void VM::new_scope_handler(CLEVER_VM_HANDLER_ARGS) {
	m_symbols.pushVarMap(SymbolTable::var_map());
}

void VM::end_scope_handler(CLEVER_VM_HANDLER_ARGS) {
	m_symbols.popVarMap();
}

void VM::var_decl_handler(CLEVER_VM_HANDLER_ARGS) {
	Value* value = opcode->get_op2();

	value->addRef();

	m_symbols.register_var(opcode->get_op1()->toString(), value);
}

} // clever
<|endoftext|>