<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BulkMessageTest.h"

#include <activemq/util/CMSListener.h>
#include <activemq/exceptions/ActiveMQException.h>

#include <decaf/lang/Thread.h>
#include <decaf/util/UUID.h>
#include <decaf/lang/Pointer.h>

using namespace std;
using namespace cms;
using namespace activemq;
using namespace activemq::test;
using namespace activemq::util;
using namespace activemq::exceptions;
using namespace decaf;
using namespace decaf::lang;
using namespace decaf::util;

////////////////////////////////////////////////////////////////////////////////
namespace {

    class ProducerThread : public Thread {
    private:

        std::auto_ptr<activemq::util::CMSProvider> cmsProducerProvider;
        int num;
        int size;

    private:

        ProducerThread(const ProducerThread&);
        ProducerThread& operator= (const ProducerThread&);

    public:

        ProducerThread(const std::string& brokerURL, const std::string& destinationName, const std::string& subscription, int num, int size) :
            cmsProducerProvider(new activemq::util::CMSProvider(brokerURL, destinationName, subscription)), num(num), size(size) {
        }

        virtual ~ProducerThread() {}

        virtual void run() {

            cms::Session* session( cmsProducerProvider->getSession() );
            Destination* destination = cmsProducerProvider->getDestination();
            Pointer<MessageProducer> producer( session->createProducer( destination ) );
            producer->setDeliveryMode( cms::DeliveryMode::NON_PERSISTENT );

            std::string DATA = "abcdefghijklmnopqrstuvwxyz";
            std::string body = "";
            for( int i=0; i < size; i ++) {
                body += DATA.at(i % DATA.length());
            }

            Pointer<BytesMessage> message;

            for( int i = 0; i < num; ++i ) {
                message.reset( session->createBytesMessage( (const unsigned char*) body.c_str(), body.length() ) );
                producer->send( message.get() );
            }
        }
    };
}

////////////////////////////////////////////////////////////////////////////////
BulkMessageTest::BulkMessageTest() {
}

////////////////////////////////////////////////////////////////////////////////
BulkMessageTest::~BulkMessageTest() {
}

////////////////////////////////////////////////////////////////////////////////
void BulkMessageTest::testBulkMessageSendReceive() {

    static const int MSG_COUNT = 5000;
    static const int MSG_SIZE = 8192;

    // Create CMS Object for consumer Comms
    cms::Session* session( cmsProvider->getSession() );
    cms::MessageConsumer* consumer = cmsProvider->getConsumer();
    Destination* destination = cmsProvider->getDestination();

    ProducerThread thread( this->getBrokerURL(), cmsProvider->getDestinationName(), cmsProvider->getSubscription(), MSG_COUNT, MSG_SIZE );
    thread.start();

    Pointer<cms::Message> message;

    for( int i = 0; i < MSG_COUNT ; ++i ) {
        CPPUNIT_ASSERT_NO_THROW( message.reset( consumer->receive( 2000 ) ) );
        CPPUNIT_ASSERT( message.get() != NULL );
    }
}
<commit_msg>Fix some warnings <commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BulkMessageTest.h"

#include <activemq/util/CMSListener.h>
#include <activemq/exceptions/ActiveMQException.h>

#include <decaf/lang/Thread.h>
#include <decaf/util/UUID.h>
#include <decaf/lang/Pointer.h>

using namespace std;
using namespace cms;
using namespace activemq;
using namespace activemq::test;
using namespace activemq::util;
using namespace activemq::exceptions;
using namespace decaf;
using namespace decaf::lang;
using namespace decaf::util;

////////////////////////////////////////////////////////////////////////////////
namespace {

    class ProducerThread : public Thread {
    private:

        std::auto_ptr<activemq::util::CMSProvider> cmsProducerProvider;
        int num;
        int size;

    private:

        ProducerThread(const ProducerThread&);
        ProducerThread& operator= (const ProducerThread&);

    public:

        ProducerThread(const std::string& brokerURL, const std::string& destinationName, const std::string& subscription, int num, int size) :
            cmsProducerProvider(new activemq::util::CMSProvider(brokerURL, destinationName, subscription)), num(num), size(size) {
        }

        virtual ~ProducerThread() {}

        virtual void run() {

            cms::Session* session( cmsProducerProvider->getSession() );
            Destination* destination = cmsProducerProvider->getDestination();
            Pointer<MessageProducer> producer( session->createProducer( destination ) );
            producer->setDeliveryMode( cms::DeliveryMode::NON_PERSISTENT );

            std::string DATA = "abcdefghijklmnopqrstuvwxyz";
            std::string body = "";
            for( int i=0; i < size; i ++) {
                body += DATA.at(i % DATA.length());
            }

            Pointer<BytesMessage> message;

            for( int i = 0; i < num; ++i ) {
                message.reset( session->createBytesMessage( (const unsigned char*) body.c_str(), (int) body.length() ) );
                producer->send( message.get() );
            }
        }
    };
}

////////////////////////////////////////////////////////////////////////////////
BulkMessageTest::BulkMessageTest() {
}

////////////////////////////////////////////////////////////////////////////////
BulkMessageTest::~BulkMessageTest() {
}

////////////////////////////////////////////////////////////////////////////////
void BulkMessageTest::testBulkMessageSendReceive() {

    static const int MSG_COUNT = 5000;
    static const int MSG_SIZE = 8192;

    // Create CMS Object for consumer Comms
    cms::MessageConsumer* consumer = cmsProvider->getConsumer();

    ProducerThread thread(this->getBrokerURL(), cmsProvider->getDestinationName(), cmsProvider->getSubscription(), MSG_COUNT, MSG_SIZE);
    thread.start();

    Pointer<cms::Message> message;

    for (int i = 0; i < MSG_COUNT; ++i) {
        CPPUNIT_ASSERT_NO_THROW(message.reset(consumer->receive(2000)));
        CPPUNIT_ASSERT(message.get() != NULL);
    }
}
<|endoftext|>


<commit_before>#include "classui.h"
#include "listworker.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

classUI::classUI()
{

}

void classUI::run()
{
    bool runOn = true;
    string choice;
    do
    {
        cout << "List of things: " << endl;
        cout << "-----------------------------------------------------------" << endl;
        cout << "add - Add to the list" << endl;
        cout << "remove - Remove from the list" << endl;
        cout << "view - View the entire list" << endl;
        cout << "save - save the file" << endl;
        cout << "search - Search the list" << endl;
        cout << "sort - Sort the list by name/yearofbirth" << endl;
        cout << "exit - Exit" << endl;
        cin >> choice;
        if (choice != "exit"){
           select(choice);
        }
        else{
            runOn = false;
        }

    }while(runOn == true);
}

void classUI::select(string ch)
{
    if(ch == "add" || ch == "ADD" || ch == "Add" ){
        addPerson();
    }

    else if(ch == "view" || ch == "View" || ch == "VIEW")
    {
    viewAll();
    }
    else if(ch == "sort")
    {
        string sortcho;
        cout << "Enter 'name' or 'year' and then re-enter the 'view' command." << endl;
        cin >> sortcho;

        if(sortcho == "name")
        {
            list.sortNames();
        }
        else if(sortcho == "year")
        {
            list.sortBirth();
        }

    }
    else if(ch == "search" || ch == "Search" || ch == "SEARCH"){
        searching();
    }
    else if(ch == "remove" || ch == "Remove" || ch == "REMOVE"){
        remove();
    }
    else if(ch == "save" || ch == "Save" || ch == "SAVE"){
        save();
    }
    else
    {
        cout << "Invalid input" << endl;
    }
}
void classUI::view(int i)
{
    int nameSize  = list.getNameSize(i);
    cout << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << "Name" << "\t" << "\t" << "\t" << "\t" << "|Gender " << "|Born " << "\t" << "|Death" << endl;
    cout << "--------------------------------|-------|-------|-------------" << endl;

    cout << list.getName(i);
    if(nameSize > 0 && nameSize <= 7)
    {
        cout << "\t" << "\t" << "\t" << "\t";
    }
    else if(nameSize > 7 && nameSize <= 15)
    {
        cout << "\t" << "\t" << "\t";
    }
    else if(nameSize > 15 && nameSize <= 23)
    {
        cout << "\t" << "\t";
    }
    else if(nameSize > 23 && nameSize <= 31)
    {
        cout << "\t";
    }

    if(list.getGender(i) == 'M' || list.getGender(i) == 'm')
    {
        cout << "|Male" << "\t";
    }
    else
    {
        cout << "|Female" << "\t";
    }
    cout  << "|" << list.getBirth(i);
    if(list.getDeath(i) == 0)
    {
        cout << "\t" << "|Still kickin'"  << endl;
    }
    else
    {
        cout << "\t" << "|" << list.getDeath(i)  << endl;
    }
    cout << list.getComment(i) << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << endl;
}

void classUI::searching()
{

    cout << "----------Select any of the following options----------" << endl;
    cout << "What do you want to search for? " << endl;
    cout << "Name -- Searches for a name" << endl;
    cout << "Gender -- Searches for a Gender" << endl;
    cout << "Year -- Searches for a year born" << endl;
    search();
}
void classUI::addPerson()
{
    string name;
    char gender;
    int yearOfBirth = 0;
    int yearOfDeath = 0;
    string comment;

    cout << "Input Name: ";
    cin.ignore();
    std::getline(std::cin,name);
    cout << "Input gender (M/F): ";
    cin >> gender;
    if (gender == 'm' || gender == 'M' || gender == 'f' || gender == 'F')
    {
       cout << "Input year of birth: ";
       cin >> yearOfBirth;
       cout << "Input year of death: ";
       cin >> yearOfDeath;
       cout << "Input a comment: ";
       cin >> comment;
    }
    else
    {
        cout << "Invalid gender! Try again." << endl;
        addPerson();
    }
    list.addNewPerson(name, gender, yearOfBirth, yearOfDeath, comment);

}

void classUI::search()
{
        string searchChoice;
        cin >> searchChoice;
        if (searchChoice == "Name" || searchChoice == "name" || searchChoice == "NAME")
        {
                string namesearch;
                cout << "Enter a name you want to search for: ";
                cin >> namesearch;

                for(int i = 0; i < list.getPersonsSize();++i)
                {
                    if(namesearch == list.getName(i))
                    {
                        namesearch =  list.getName(i);
                        view(i);
                    }
                }
                /*if ( eitthvad dot)
                {
                    cout << "Sorry that name is not in our database, but you can add a new instance in the 'Add' section in the main menu" << endl;
                }*/

        }
        else if (searchChoice == "Gender" || searchChoice == "GENDER" || searchChoice == "gender")
        {
                char gendersearch;

                cout << "Enter a Gender you want to search for: ";
                cin >> gendersearch;

                for(int i = 0; i < list.getPersonsSize();++i)
                {
                    if(gendersearch == list.getGender(i))
                    {
                        gendersearch = gendersearch  + list.getGender(i);
                        view(i);
                    }
                }
                /*
                if (eitthvad dot)
                {
                    cout << "Sorry that gender is not in our database, but you can add a new instance in the 'Add' section in the main menu" << endl;
                }*/

        }
        else if (searchChoice == "year" || searchChoice == "YEAR" || searchChoice == "Year")
        {
                int yearsearch;
                cout << "Enter a Year you want to search for: ";
                cin >> yearsearch;

                for(int i = 0; i < list.getPersonsSize();++i)
                {
                    if(yearsearch == list.getBirth(i))
                    {
                        yearsearch = yearsearch + list.getBirth(i);

                         view(i);
                    }
                }/*
                if (eitthvad dot)
                {
                    cout << "Sorry that year is not in our database, but you can add a new instance in the 'Add' section in the main menu" << endl;
                }*/
           }
        else
        {
            cout << "Error reading input" << endl;
        }

}

void classUI::remove()
{
    string name;
    cout << "Enter a name of person that you want to remove: ";
    cin >> name;
    if (list.removePerson(name) == true)
    {
        cout << "Person removed!" << endl;
    }
    else
    {
        cout << "Person not found!" << endl;
    }
}
void classUI::save()
{
    list.saveFile();
}
void classUI::viewAll()
{
    for(int i = 0; i < list.getPersonsSize(); i++)
    {
        view(i);
    }
}
<commit_msg>sma lagfaeringar<commit_after>#include "classui.h"
#include "listworker.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

classUI::classUI()
{

}

void classUI::run()
{
    bool runOn = true;
    string choice;
    do
    {
        cout << "List of things: " << endl;
        cout << "-----------------------------------------------------------" << endl;
        cout << "add - Add to the list" << endl;
        cout << "remove - Remove from the list" << endl;
        cout << "view - View the entire list" << endl;
        cout << "save - save the file" << endl;
        cout << "search - Search the list" << endl;
        cout << "sort - Sort the list by name/yearofbirth" << endl;
        cout << "exit - Exit" << endl;
        cin >> choice;
        if (choice != "exit"){
           select(choice);
        }
        else{
            runOn = false;
        }

    }while(runOn == true);
}

void classUI::select(string ch)
{
    if(ch == "add" || ch == "ADD" || ch == "Add" ){
        addPerson();
    }

    else if(ch == "view" || ch == "View" || ch == "VIEW")
    {
    viewAll();
    }
    else if(ch == "sort")
    {
        string sortcho;
        cout << "Enter 'name' or 'year' and then re-enter the 'view' command." << endl;
        cin >> sortcho;

        if(sortcho == "name")
        {
            list.sortNames();
        }
        else if(sortcho == "year")
        {
            list.sortBirth();
        }

    }
    else if(ch == "search" || ch == "Search" || ch == "SEARCH"){
        searching();
    }
    else if(ch == "remove" || ch == "Remove" || ch == "REMOVE"){
        remove();
    }
    else if(ch == "save" || ch == "Save" || ch == "SAVE"){
        save();
    }
    else
    {
        cout << "Invalid input" << endl;
    }
}
void classUI::view(int i)
{
    int nameSize  = list.getNameSize(i);
    cout << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << "Name" << "\t" << "\t" << "\t" << "\t" << "|Gender " << "|Born " << "\t" << "|Death" << endl;
    cout << "--------------------------------|-------|-------|-------------" << endl;

    cout << list.getName(i);
    if(nameSize > 0 && nameSize <= 7)
    {
        cout << "\t" << "\t" << "\t" << "\t";
    }
    else if(nameSize > 7 && nameSize <= 15)
    {
        cout << "\t" << "\t" << "\t";
    }
    else if(nameSize > 15 && nameSize <= 23)
    {
        cout << "\t" << "\t";
    }
    else if(nameSize > 23 && nameSize <= 31)
    {
        cout << "\t";
    }

    if(list.getGender(i) == 'M' || list.getGender(i) == 'm')
    {
        cout << "|Male" << "\t";
    }
    else
    {
        cout << "|Female" << "\t";
    }
    cout  << "|" << list.getBirth(i);
    if(list.getDeath(i) == 0)
    {
        cout << "\t" << "|Still kickin'"  << endl;
    }
    else
    {
        cout << "\t" << "|" << list.getDeath(i)  << endl;
    }
    cout << list.getComment(i) << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << endl;
}

void classUI::searching()
{

    cout << "----------Select any of the following options----------" << endl;
    cout << "What do you want to search for? " << endl;
    cout << "Name -- Searches for a name" << endl;
    cout << "Gender -- Searches for a Gender" << endl;
    cout << "Year -- Searches for a year born" << endl;
    search();
}
void classUI::addPerson()
{
    string name;
    char gender;
    int yearOfBirth = 0;
    int yearOfDeath = 0;
    string comment;

    cout << "Input Name: ";
    cin.ignore();
    std::getline(std::cin,name);
    cout << "Input gender (M/F): ";
    cin >> gender;
    if (gender == 'm' || gender == 'M' || gender == 'f' || gender == 'F')
    {
       cout << "Input year of birth: ";
       cin >> yearOfBirth;
       cout << "Input year of death: ";
       cin >> yearOfDeath;
       cout << "Input a comment: ";
       cin >> comment;
    }
    else
    {
        cout << "Invalid gender! Try again." << endl;
        addPerson();
    }
    list.addNewPerson(name, gender, yearOfBirth, yearOfDeath, comment);

}

void classUI::search()
{
        string searchChoice;
        cin >> searchChoice;
        if (searchChoice == "Name" || searchChoice == "name" || searchChoice == "NAME")
        {
                string namesearch;
                cout << "Enter a name you want to search for: ";
                cin >> namesearch;

                for(int i = 0; i < list.getPersonsSize();++i)
                {
                    if(namesearch == list.getName(i))
                    {
                        namesearch =  list.getName(i);
                        view(i);
                    }
                }
                /*if ( eitthvad dot)
                {
                    cout << "Sorry that name is not in our database, but you can add a new instance in the 'Add' section in the main menu" << endl;
                }*/

        }
        else if (searchChoice == "Gender" || searchChoice == "GENDER" || searchChoice == "gender")
        {
                char gendersearch;

                cout << "Enter a Gender you want to search for: (m/f)";
                cin >> gendersearch;

                for(int i = 0; i < list.getPersonsSize();++i)
                {
                    if(gendersearch == list.getGender(i))
                    {
                        gendersearch = list.getGender(i);
                        view(i);
                        cout << "blabla" << endl;
                    }
                }
                /*
                if (eitthvad dot)
                {
                    cout << "Sorry that gender is not in our database, but you can add a new instance in the 'Add' section in the main menu" << endl;
                }*/

        }
        else if (searchChoice == "year" || searchChoice == "YEAR" || searchChoice == "Year")
        {
                int yearsearch;
                cout << "Enter a Year you want to search for: ";
                cin >> yearsearch;

                for(int i = 0; i < list.getPersonsSize();++i)
                {
                    if(yearsearch == list.getBirth(i))
                    {
                        yearsearch = list.getBirth(i);

                         view(i);
                    }
                }/*
                if (eitthvad dot)
                {
                    cout << "Sorry that year is not in our database, but you can add a new instance in the 'Add' section in the main menu" << endl;
                }*/
           }
        else
        {
            cout << "Error reading input" << endl;
        }

}

void classUI::remove()
{
    string name;
    cout << "Enter a name of person that you want to remove: ";
    cin >> name;
    if (list.removePerson(name) == true)
    {
        cout << "Person removed!" << endl;
    }
    else
    {
        cout << "Person not found!" << endl;
    }
}
void classUI::save()
{
    list.saveFile();
}
void classUI::viewAll()
{
    for(int i = 0; i < list.getPersonsSize(); i++)
    {
        view(i);
    }
}
<|endoftext|>


<commit_before>// BubbleSort.cpp
// by Xiaoguang Zhu (id est smdsbz) of the Backstage Group

#include <iostream>
#include <vector>
using namespace std;

int main() {
	// get the numbers from user input
	vector<int> array;
	cout << "Enter at least two numbers to start the bubble sort." << endl;
	for (int p = 0, input = 0; cin >> input; ++p) {
		array.push_back(input);
		cout << "I get that! Give me some more OR Enter \'eof\' to start sorting!" << endl;
	}
	// print out the input numbers
	cout << "\nThe array you\'ve entered was: ";
	for (int p = 0; p < array.size(); ++p)
		cout << array [p] << " ";

	cout << "\n\nNow sorting..." << endl;
	// start bubble sorting
	int i = 1, exch = 0;
	while (i < array.size()) {
		if (array [i - 1] <= array [i])
			++i;
		else {
			// block of code to move the bigger number to the end of the line like a bubble!
			for (int p = i; p < array.size(); ++p) {
				exch = array [p - 1];
				array [p - 1] = array [p];
				array [p] = exch;
// debug output
//				for (int p = 0; p < array.size(); ++p)
//					cout << array [p] << " ";
//				cout << endl;
				}
			// roll back to the first number if there is number moved
			i = 1;
			}
		}
	// giving the final output - the sorted array
	cout << "\nThe moment of truth!" << endl;
	for (int p = 0; p < array.size(); ++p)
		cout << array [p] << " ";
	cout << endl;
	return 0;
}
<commit_msg>deleted cpp<commit_after><|endoftext|>


<commit_before>/* Definition of member functions of class ErrorReporter */

#include "../headers/ErrorReporter.hpp"

#include <iomanip>
#include <sstream>
#include <string>

using namespace std;

ErrorReporter::ErrorReporter() :
  m_errorOut(),
  m_outFileName("errores.out"),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_instance(nullptr)
{
}

ErrorReporter::ErrorReporter(const string& outFileName) :
  m_errorOut(),
  m_outFileName(outFileName),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_instance(nullptr)

{
}

// Singleton, so this should not be used. Written for removing EffC++ warnings.
ErrorReporter::ErrorReporter(const ErrorReporter& source) :
  m_errorOut(),
  m_outFileName(),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_instance(nullptr)

{
  m_instance = source.m_instance;
}

ErrorReporter::~ErrorReporter()
{
  delete m_instance;
}

ErrorReporter* ErrorReporter::getInstance()
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter();
    return m_instance;
  }
  return m_instance;
}

ErrorReporter* ErrorReporter::getInstance(const string& outFileName)
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter(outFileName);
    return m_instance;
  }
  return m_instance;
}

void ErrorReporter::writeError(const string& message)
{
  writeErrorsFileHeader();

  m_errorOut << setw(WIDTH_NUMBER) << ' ' <<
      setw(WIDTH_NUMBER) << ' ' <<
      setw(WIDTH_LEXEME) << ' ' <<
      setw(WIDTH_MESSAGE) << message <<
      setw(WIDTH_LINE) << ' ' << endl;
}

void ErrorReporter::writeLexicalError(int state, char currentChar,
                                      const string& line, const string& lexeme,
                                      int lineNo, int columnNo) {
  writeErrorsFileHeader();

  ostringstream messageBuilder;
  switch (state) {
    case 0 :
      messageBuilder << "simbolo ilegal: '" << currentChar << "'";
      break;
    case 3 :
      messageBuilder << "constante hexadecimal incompleta, se encontro : '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba digito";
      break;
    case 6 :
    case 10 :
      messageBuilder << "constante flotante incompleta, se encontro : '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba digito";
      break;
    case 9 :
      messageBuilder <<
          "constante flotante incompleta, se encontro : '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba digito o signo";
      break;
    case 17 :
      messageBuilder << "comentario multilinea sin cerrar";
      break;
    case 20 :
      messageBuilder << "operador logico incompleto, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '|'";
      break;
    case 21 :
      messageBuilder << "operador logico incompleto, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '&'";
      break;
    case 30 :
      messageBuilder << "constante caracter incompleta, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '\\' o letra";
      break;
    case 31 :
      messageBuilder << "constante caracter incompleta, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba letra";
      break;
    case 32 :
      messageBuilder << "constante caracter incompleta, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '''";
      break;
    case 34 :
      messageBuilder << "comentario multilinea sin cerrar";
      break;
    default :
      messageBuilder << "error desconocido";
      break;
  }

  string errorMessage = messageBuilder.str();
  m_errorOut << setw(WIDTH_NUMBER) << lineNo <<
      setw(WIDTH_NUMBER) << columnNo <<
      setw(WIDTH_LEXEME) << lexeme <<
      setw(WIDTH_MESSAGE) << errorMessage <<
      setw(WIDTH_LINE) << line;
}

void ErrorReporter::writeErrorsFileHeader() {
  if (!m_errorOut.is_open()) {
    m_errorOut.open(m_outFileName, ios::app);

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;

    m_errorOut << setw(WIDTH_NUMBER) << "Linea" <<
        setw(WIDTH_NUMBER) << "Columna" <<
        setw(WIDTH_LEXEME) << "Lexema" <<
        setw(WIDTH_MESSAGE) << "Mensaje de error" <<
        setw(WIDTH_LINE) << "Linea" << endl;

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;
  }
}

ErrorReporter& ErrorReporter::operator=(const ErrorReporter& rhs)
{
  m_instance = rhs.m_instance;

  return *this;
}

void ErrorReporter::setMaxErrors(int maxErrors)
{
  m_maxErrors = maxErrors;
}

int  ErrorReporter::getMaxErrors() const
{
  return m_maxErrors;
}

int  ErrorReporter::getErrors() const
{
  return m_errors;
}

int  ErrorReporter::getWarnings() const
{
  return m_warnings;
}

<commit_msg>added increments to error counter in error functions<commit_after>/* Definition of member functions of class ErrorReporter */

#include "../headers/ErrorReporter.hpp"

#include <iomanip>
#include <sstream>
#include <string>

using namespace std;

ErrorReporter::ErrorReporter() :
  m_errorOut(),
  m_outFileName("errores.out"),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_instance(nullptr)
{
}

ErrorReporter::ErrorReporter(const string& outFileName) :
  m_errorOut(),
  m_outFileName(outFileName),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_instance(nullptr)

{
}

// Singleton, so this should not be used. Written for removing EffC++ warnings.
ErrorReporter::ErrorReporter(const ErrorReporter& source) :
  m_errorOut(),
  m_outFileName(),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_instance(nullptr)

{
  m_instance = source.m_instance;
}

ErrorReporter::~ErrorReporter()
{
  delete m_instance;
}

ErrorReporter* ErrorReporter::getInstance()
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter();
    return m_instance;
  }
  return m_instance;
}

ErrorReporter* ErrorReporter::getInstance(const string& outFileName)
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter(outFileName);
    return m_instance;
  }
  return m_instance;
}

void ErrorReporter::writeError(const string& message)
{
  writeErrorsFileHeader();

  m_errorOut << setw(WIDTH_NUMBER) << ' ' <<
      setw(WIDTH_NUMBER) << ' ' <<
      setw(WIDTH_LEXEME) << ' ' <<
      setw(WIDTH_MESSAGE) << message <<
      setw(WIDTH_LINE) << ' ' << endl;
  ++m_errors;
}

void ErrorReporter::writeLexicalError(int state, char currentChar,
                                      const string& line, const string& lexeme,
                                      int lineNo, int columnNo) {
  writeErrorsFileHeader();

  ostringstream messageBuilder;
  switch (state) {
    case 0 :
      messageBuilder << "simbolo ilegal: '" << currentChar << "'";
      break;
    case 3 :
      messageBuilder << "constante hexadecimal incompleta, se encontro : '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba digito";
      break;
    case 6 :
    case 10 :
      messageBuilder << "constante flotante incompleta, se encontro : '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba digito";
      break;
    case 9 :
      messageBuilder <<
          "constante flotante incompleta, se encontro : '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba digito o signo";
      break;
    case 17 :
      messageBuilder << "comentario multilinea sin cerrar";
      break;
    case 20 :
      messageBuilder << "operador logico incompleto, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '|'";
      break;
    case 21 :
      messageBuilder << "operador logico incompleto, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '&'";
      break;
    case 30 :
      messageBuilder << "constante caracter incompleta, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '\\' o letra";
      break;
    case 31 :
      messageBuilder << "constante caracter incompleta, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba letra";
      break;
    case 32 :
      messageBuilder << "constante caracter incompleta, se encontro: '";
      if (!isspace(currentChar))
        messageBuilder << currentChar;
      else
        messageBuilder << ' ';
      messageBuilder << "', se esperaba '''";
      break;
    case 34 :
      messageBuilder << "comentario multilinea sin cerrar";
      break;
    default :
      messageBuilder << "error desconocido";
      break;
  }

  string errorMessage = messageBuilder.str();
  m_errorOut << setw(WIDTH_NUMBER) << lineNo <<
      setw(WIDTH_NUMBER) << columnNo <<
      setw(WIDTH_LEXEME) << lexeme <<
      setw(WIDTH_MESSAGE) << errorMessage <<
      setw(WIDTH_LINE) << line;

  ++m_errors;
}

void ErrorReporter::writeErrorsFileHeader() {
  if (!m_errorOut.is_open()) {
    m_errorOut.open(m_outFileName, ios::app);

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;

    m_errorOut << setw(WIDTH_NUMBER) << "Linea" <<
        setw(WIDTH_NUMBER) << "Columna" <<
        setw(WIDTH_LEXEME) << "Lexema" <<
        setw(WIDTH_MESSAGE) << "Mensaje de error" <<
        setw(WIDTH_LINE) << "Linea" << endl;

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;
  }
}

ErrorReporter& ErrorReporter::operator=(const ErrorReporter& rhs)
{
  m_instance = rhs.m_instance;

  return *this;
}

void ErrorReporter::setMaxErrors(int maxErrors)
{
  m_maxErrors = maxErrors;
}

int  ErrorReporter::getMaxErrors() const
{
  return m_maxErrors;
}

int  ErrorReporter::getErrors() const
{
  return m_errors;
}

int  ErrorReporter::getWarnings() const
{
  return m_warnings;
}

<|endoftext|>


<commit_before>/* Definition of member functions of class ErrorReporter */

#include "../headers/ErrorReporter.hpp"

#include <iomanip>
#include <sstream>
#include <string>

#ifdef DEBUG
# include <iostream>
#endif

using namespace std;

ErrorReporter::ErrorReporter() :
  m_errorOut(),
  m_outFileName("errores.out"),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_fileReader(nullptr)
{
}

ErrorReporter::ErrorReporter(const string& outFileName) :
  m_errorOut(),
  m_outFileName(outFileName),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_fileReader(nullptr)
{
}

ErrorReporter* ErrorReporter::m_instance = nullptr;

ErrorReporter::~ErrorReporter()
{
  delete m_instance;
}

ErrorReporter* ErrorReporter::getInstance()
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter();
    return m_instance;
  }
  return m_instance;
}

ErrorReporter* ErrorReporter::getInstance(const string& outFileName)
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter(outFileName);
    return m_instance;
  }
  return m_instance;
}

void ErrorReporter::writeError(const string& message)
{
  writeErrorsFileHeader();

  m_errorOut << setw(WIDTH_NUMBER) << ' ' <<
      setw(WIDTH_NUMBER) << ' ' <<
      setw(WIDTH_LEXEME) << ' ' <<
      setw(WIDTH_MESSAGE) << message <<
      setw(WIDTH_LINE) << ' ' << endl;
  ++m_errors;
}

void ErrorReporter::writeLexicalError(int state, char currentChar,
                                      const string& lexeme, int line,
                                      int column)
{
  writeErrorsFileHeader();

  ostringstream messageBuilder;
  switch (state)
  {
  case 0 :
    messageBuilder << "simbolo ilegal: '" << currentChar << "'";
    break;
  case 3 :
    messageBuilder << "constante hexadecimal incompleta, se encontro : '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba digito";
    break;
  case 6 :
  case 10 :
    messageBuilder << "constante flotante incompleta, se encontro : '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba digito";
    break;
  case 9 :
    messageBuilder <<
        "constante flotante incompleta, se encontro : '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba digito o signo";
    break;
  case 17 :
    messageBuilder << "comentario multilinea sin cerrar";
    break;
  case 20 :
    messageBuilder << "operador logico incompleto, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '|'";
    break;
  case 21 :
    messageBuilder << "operador logico incompleto, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '&'";
    break;
  case 30 :
    messageBuilder << "constante caracter incompleta, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '\\' o letra";
    break;
  case 31 :
    messageBuilder << "constante caracter incompleta, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba letra";
    break;
  case 32 :
    messageBuilder << "constante caracter incompleta, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '''";
    break;
  case 34 :
    messageBuilder << "comentario multilinea sin cerrar";
    break;
  default :
    messageBuilder << "error desconocido";
    break;
  }

  m_errorOut << setw(WIDTH_NUMBER) << line <<
      setw(WIDTH_NUMBER) << column <<
      setw(WIDTH_LEXEME) << lexeme <<
      setw(WIDTH_MESSAGE) << messageBuilder.str() <<
      setw(WIDTH_LINE) << m_fileReader->getTextAtLine(line - 1);
  m_errorOut.flush();

  ++m_errors;
}

void ErrorReporter::writeSyntaxError(const std::string& expectedLexeme,
    const std::string& actualLexeme, int line, int column)
{
  writeErrorsFileHeader();

  ostringstream messageBuilder;

  messageBuilder << "se esperaba lexema: \"" << expectedLexeme <<
                    "\", se recibio: \"" << actualLexeme << "\"";

  m_errorOut << setw(WIDTH_NUMBER) << line <<
      setw(WIDTH_NUMBER) << column <<
      setw(WIDTH_LEXEME) << actualLexeme <<
      setw(WIDTH_MESSAGE) << messageBuilder.str() <<
      setw(WIDTH_LINE) << m_fileReader->getTextAtLine(line - 1);
  m_errorOut.flush();
  ++m_errors;
}

void ErrorReporter::writeSyntaxError(TokenType_t expectedToken,
    TokenType_t actualToken, const string& actualLexeme, int line, int column)
{
  writeErrorsFileHeader();

  ostringstream messageBuilder;

  messageBuilder << "se esperaba token: \"" <<
                    TokenLexeme::getTokenString(expectedToken) <<
                    "\", se recibio: \"" <<
                    TokenLexeme::getTokenString(actualToken) << "\"";

  m_errorOut << setw(WIDTH_NUMBER) << line <<
      setw(WIDTH_NUMBER) << column <<
      setw(WIDTH_LEXEME) << actualLexeme <<
      setw(WIDTH_MESSAGE) << messageBuilder.str() <<
      setw(WIDTH_LINE) << m_fileReader->getTextAtLine(line - 1);
  m_errorOut.flush();
  ++m_errors;
}

void ErrorReporter::writeErrorsFileHeader()
{
  if (!m_errorOut.is_open())
  {
    m_errorOut.open(m_outFileName, ios::trunc);

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;

    m_errorOut << setw(WIDTH_NUMBER) << "Linea" <<
        setw(WIDTH_NUMBER) << "Columna" <<
        setw(WIDTH_LEXEME) << "Lexema" <<
        setw(WIDTH_MESSAGE) << "Mensaje de error" <<
        setw(WIDTH_LINE) << "Linea" << endl;

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;
  }
}

void ErrorReporter::setFileReader(FileReader* fileReader)
{
  m_fileReader = fileReader;
}

void ErrorReporter::setMaxErrors(int maxErrors)
{
  m_maxErrors = maxErrors;
}

int  ErrorReporter::getMaxErrors() const
{
  return m_maxErrors;
}

int  ErrorReporter::getErrors() const
{
  return m_errors;
}

int  ErrorReporter::getWarnings() const
{
  return m_warnings;
}

<commit_msg>added conditions for writing no more than maxErrors to errors.out file<commit_after>/* Definition of member functions of class ErrorReporter */

#include "../headers/ErrorReporter.hpp"

#include <iomanip>
#include <sstream>
#include <string>

#ifdef DEBUG
# include <iostream>
#endif

using namespace std;

ErrorReporter::ErrorReporter() :
  m_errorOut(),
  m_outFileName("errores.out"),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_fileReader(nullptr)
{
}

ErrorReporter::ErrorReporter(const string& outFileName) :
  m_errorOut(),
  m_outFileName(outFileName),
  m_warnings(0),
  m_errors(0),
  m_maxErrors(5),
  m_fileReader(nullptr)
{
}

ErrorReporter* ErrorReporter::m_instance = nullptr;

ErrorReporter::~ErrorReporter()
{
  delete m_instance;
}

ErrorReporter* ErrorReporter::getInstance()
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter();
    return m_instance;
  }
  return m_instance;
}

ErrorReporter* ErrorReporter::getInstance(const string& outFileName)
{
  if (m_instance == nullptr)
  {
    m_instance = new ErrorReporter(outFileName);
    return m_instance;
  }
  return m_instance;
}

void ErrorReporter::writeError(const string& message)
{
  writeErrorsFileHeader();

  if (m_errors < m_maxErrors)
  {
    m_errorOut << setw(WIDTH_NUMBER) << ' ' <<
        setw(WIDTH_NUMBER) << ' ' <<
        setw(WIDTH_LEXEME) << ' ' <<
        setw(WIDTH_MESSAGE) << message <<
        setw(WIDTH_LINE) << ' ' << endl;
  }

  ++m_errors;
}

void ErrorReporter::writeLexicalError(int state, char currentChar,
                                      const string& lexeme, int line,
                                      int column)
{
  writeErrorsFileHeader();

  ostringstream messageBuilder;
  switch (state)
  {
  case 0 :
    messageBuilder << "simbolo ilegal: '" << currentChar << "'";
    break;
  case 3 :
    messageBuilder << "constante hexadecimal incompleta, se encontro : '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba digito";
    break;
  case 6 :
  case 10 :
    messageBuilder << "constante flotante incompleta, se encontro : '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba digito";
    break;
  case 9 :
    messageBuilder <<
        "constante flotante incompleta, se encontro : '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba digito o signo";
    break;
  case 17 :
    messageBuilder << "comentario multilinea sin cerrar";
    break;
  case 20 :
    messageBuilder << "operador logico incompleto, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '|'";
    break;
  case 21 :
    messageBuilder << "operador logico incompleto, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '&'";
    break;
  case 30 :
    messageBuilder << "constante caracter incompleta, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '\\' o letra";
    break;
  case 31 :
    messageBuilder << "constante caracter incompleta, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba letra";
    break;
  case 32 :
    messageBuilder << "constante caracter incompleta, se encontro: '";
    if (!isspace(currentChar))
      messageBuilder << currentChar;
    else
      messageBuilder << ' ';
    messageBuilder << "', se esperaba '''";
    break;
  case 34 :
    messageBuilder << "comentario multilinea sin cerrar";
    break;
  default :
    messageBuilder << "error desconocido";
    break;
  }

  if (m_errors < m_maxErrors)
  {
    m_errorOut << setw(WIDTH_NUMBER) << line <<
        setw(WIDTH_NUMBER) << column <<
        setw(WIDTH_LEXEME) << lexeme <<
        setw(WIDTH_MESSAGE) << messageBuilder.str() <<
        setw(WIDTH_LINE) << m_fileReader->getTextAtLine(line - 1);
    m_errorOut.flush();
  }

  ++m_errors;
}

void ErrorReporter::writeSyntaxError(const std::string& expectedLexeme,
    const std::string& actualLexeme, int line, int column)
{
  writeErrorsFileHeader();

  ostringstream messageBuilder;

  messageBuilder << "se esperaba lexema: \"" << expectedLexeme <<
                    "\", se recibio: \"" << actualLexeme << "\"";

  if (m_errors < m_maxErrors)
  {
    m_errorOut << setw(WIDTH_NUMBER) << line <<
        setw(WIDTH_NUMBER) << column <<
        setw(WIDTH_LEXEME) << actualLexeme <<
        setw(WIDTH_MESSAGE) << messageBuilder.str() <<
        setw(WIDTH_LINE) << m_fileReader->getTextAtLine(line - 1);
    m_errorOut.flush();
  }

  ++m_errors;
}

void ErrorReporter::writeSyntaxError(TokenType_t expectedToken,
    TokenType_t actualToken, const string& actualLexeme, int line, int column)
{
  writeErrorsFileHeader();

  ostringstream messageBuilder;

  messageBuilder << "se esperaba token: \"" <<
                    TokenLexeme::getTokenString(expectedToken) <<
                    "\", se recibio: \"" <<
                    TokenLexeme::getTokenString(actualToken) << "\"";

  if (m_errors < m_maxErrors)
  {
    m_errorOut << setw(WIDTH_NUMBER) << line <<
        setw(WIDTH_NUMBER) << column <<
        setw(WIDTH_LEXEME) << actualLexeme <<
        setw(WIDTH_MESSAGE) << messageBuilder.str() <<
        setw(WIDTH_LINE) << m_fileReader->getTextAtLine(line - 1);
    m_errorOut.flush();
  }

  ++m_errors;
}

void ErrorReporter::writeErrorsFileHeader()
{
  if (!m_errorOut.is_open())
  {
    m_errorOut.open(m_outFileName, ios::trunc);

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;

    m_errorOut << setw(WIDTH_NUMBER) << "Linea" <<
        setw(WIDTH_NUMBER) << "Columna" <<
        setw(WIDTH_LEXEME) << "Lexema" <<
        setw(WIDTH_MESSAGE) << "Mensaje de error" <<
        setw(WIDTH_LINE) << "Linea" << endl;

    for (int i = 0;
         i < (WIDTH_NUMBER * 2 + WIDTH_LEXEME + WIDTH_MESSAGE + WIDTH_LINE);
         ++i)
      m_errorOut << '-';
    m_errorOut << endl;
  }
}

void ErrorReporter::setFileReader(FileReader* fileReader)
{
  m_fileReader = fileReader;
}

void ErrorReporter::setMaxErrors(int maxErrors)
{
  m_maxErrors = maxErrors;
}

int  ErrorReporter::getMaxErrors() const
{
  return m_maxErrors;
}

int  ErrorReporter::getErrors() const
{
  return m_errors;
}

int  ErrorReporter::getWarnings() const
{
  return m_warnings;
}

<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(k)
// KMP Algorithm
class Solution {
public:
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    int strStr(const char *source, const char *target) {
        if (source != nullptr && target != nullptr) {
            string src(source), tgt(target);
            if (tgt.empty()) {
                return 0;
            }

            return KMP(src, tgt);
        }
        return -1;
    }

    int KMP(const string& text, const string& pattern) {
        vector<int> prefix = getPrefix(pattern);
        int j = -1;
        for (int i = 0; i < text.length(); ++i) {
            while (j > -1 && pattern[j + 1] != text[i]) {
                j = prefix[j];
            }
            if (pattern[j + 1] == text[i]) {
                ++j;
            }
            if (j == pattern.length() - 1) {
                return i - j;
            }
        }
        return -1;
    }

    vector<int> getPrefix(const string& pattern) {
        vector<int> prefix(pattern.length(), -1);
        int j = -1;
        for (int i = 1; i < pattern.length(); ++i) {
            while (j > -1 && pattern[j + 1] != pattern[i]) {
                j = prefix[j];
            }
            if (pattern[j + 1] == pattern[i]) {
                ++j;
            }
            prefix[i] = j;
        }
        return prefix;
    }
};

// Time:  O(k * n)
// Space: O(k)
class Solution2 {
public:
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    int strStr(const char *source, const char *target) {
        if (source != nullptr && target != nullptr) {
            string src(source), tgt(target);
            for (int i = 0; i < src.length() - tgt.length() + 1; ++i) {
                if(src.substr(i, tgt.length()) == tgt) {
                    return i;
                }
            }
        }
        return -1;
    }
};

<commit_msg>update<commit_after>// Time:  O(n)
// Space: O(k)
// KMP Algorithm
class Solution {
public:
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    int strStr(const char *source, const char *target) {
        if (source != nullptr && target != nullptr) {
            string src(source), tgt(target);
            if (tgt.empty()) {
                return 0;
            }

            return KMP(src, tgt);
        }
        return -1;
    }

    int KMP(const string& text, const string& pattern) {
        vector<int> prefix = getPrefix(pattern);
        int j = -1;
        for (int i = 0; i < text.length(); ++i) {
            while (j > -1 && pattern[j + 1] != text[i]) {
                j = prefix[j];
            }
            if (pattern[j + 1] == text[i]) {
                ++j;
            }
            if (j == pattern.length() - 1) {
                return i - j;
            }
        }
        return -1;
    }

    vector<int> getPrefix(const string& pattern) {
        vector<int> prefix(pattern.length(), -1);
        int j = -1;
        for (int i = 1; i < pattern.length(); ++i) {
            while (j > -1 && pattern[j + 1] != pattern[i]) {
                j = prefix[j];
            }
            if (pattern[j + 1] == pattern[i]) {
                ++j;
            }
            prefix[i] = j;
        }
        return prefix;
    }
};

// Time:  O(k * n)
// Space: O(k)
class Solution2 {
public:
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    int strStr(const char *source, const char *target) {
        if (source != nullptr && target != nullptr) {
            string src(source), tgt(target);
            for (int i = 0; i < src.length() - tgt.length() + 1; ++i) {
                if (src.substr(i, tgt.length()) == tgt) {
                    return i;
                }
            }
        }
        return -1;
    }
};

<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "db.h"
#include "database.h"

#define UNIQUE_TROPHY_FAERIE 33313
#define PERMA_DEATH_FAERIE 33314
#define FAERIE_CASTER_LEVEL 50
#define MAX_TIME 5 // max idle time

// only important that higher is better
// rate players by number of unique creatures killed
int getUniqueTrophyRank(TBeing *targ)
{
  TDatabase db(DB_SNEEZY);

  if (!targ) {
    vlogf(LOG_BUG, "getUniqueTrophyRank entered with null targ");
    return 0;
  }
  db.query("select t.count from trophyplayer t where t.player_id=%i",
      targ->getPlayerID());
  if (!db.isResults())
    return 0;
  if (db.fetchRow()) {
    return convertTo<int>(db["count"]);
  } else
    return 0;
}

void uniqueTrophyIntro(TBeing *faerie, TBeing *targ)
{
  if (!targ) {
    vlogf(LOG_BUG, "uniqueTrophyIntro entered with null targ");
    return;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "uniqueTrophyIntro entered with null faerie");
    return;
  }
  faerie->doTell(targ->getName(),
    "You are greatly respected amongst my people for the breadth of your travels.");
  faerie->doTell(targ->getName(),
    "I have been sent to help you in your endeavors!");
}

// feral wrath, but only the stat part (no AC penalty), stat part is halved
void addUniqueTrophyEffects(TBeing *faerie, TBeing *targ)
{
  affectedData aff2;

  if (!targ) {
    vlogf(LOG_BUG, "addUniqueTrophyEffects entered with null targ");
    return;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "addUniqueTrophyEffects entered with null faerie");
    return;
  }
  int modifier = FAERIE_CASTER_LEVEL/2 * ::number(80,125)/100;
  int which = ::number(1,3);

  switch (which) {
    case 1:
      aff2.location = APPLY_STR;
      aff2.modifier = modifier;
      break;
    case 2:
      aff2.location = APPLY_DEX;
      aff2.modifier = modifier;
      break;
    case 3:
      aff2.location = APPLY_SPE;
      aff2.modifier = modifier;
      break;
  }
  aff2.type = SPELL_FERAL_WRATH;
  aff2.duration = 2*UPDATES_PER_MUDHOUR;
  aff2.bitvector = 0;

  if (!targ->affectJoin(targ, &aff2, AVG_DUR_NO, AVG_EFF_YES)) {
    vlogf(LOG_BUG, "Failed to join aff2 in addUniqueTrophyEffects");
    targ->sendTo("The faerie's magic fails.");
  } else {
    if (aff2.location == APPLY_STR) {
      act("The misty shape of a large bear settles on you.\n\rYou feel stronger.", FALSE, targ, NULL, NULL, TO_CHAR);
      act("A light mist in the shape of a large bear settles on $n.",
          FALSE, targ, NULL, NULL, TO_ROOM);
    } else if (aff2.location == APPLY_DEX) {
      act("The misty shape of a great cat settles on you.\n\rYou feel your reflexes quicken.", FALSE, targ, NULL, NULL, TO_CHAR);
      act("A light mist in the shape of a great cat settles on $n.",
          FALSE, targ, NULL, NULL, TO_ROOM);
    } else if (aff2.location == APPLY_SPE) {
      act("The misty shape of a snake settles on you.\n\rYou feel you can strike with great speed.", FALSE, targ, NULL, NULL, TO_CHAR);
      act("A light mist in the shape of a snake settles on $n.",
          FALSE, targ, NULL, NULL, TO_ROOM);
    }

  }
}

int clearUniqueTrophyEffects(TBeing *faerie, TBeing *targ)
{
  int rc;

  if (!targ) {
    vlogf(LOG_BUG, "Missing target in clearUniqueTrophyEffects.");
    return FALSE;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "Missing faerie in clearUniqueTrophyEffects.");
    return FALSE;
  }
  rc = targ->spellWearOff(SPELL_FERAL_WRATH, SAFE_YES);
  if (IS_SET_DELETE(rc, DELETE_THIS))
    return DELETE_VICT;
  targ->affectFrom(SPELL_FERAL_WRATH);

  return TRUE;

}

// only important that higher is better
int getPermaDeathRank(TBeing *targ)
{
  if (!targ) {
    vlogf(LOG_BUG, "getPermaDeathRank entered with null target");
    return 0;
  }
  if (!targ->hasQuestBit(TOG_PERMA_DEATH_CHAR))
    return 0;
  else return (int) max(1.,(targ->getExp()/100)); // don't want to overflow int
}

void permaDeathIntro(TBeing *faerie, TBeing *targ)
{
  if (!faerie) {
    vlogf(LOG_BUG, "permaDeathIntro entered with null faerie");
    return;
  }
  if (!targ) {
    vlogf(LOG_BUG, "permaDeathIntro entered with null targ");
    return;
  }
  faerie->doTell(targ->getName(),
    "You are greatly respected amongst my people for your great bravery.");
  faerie->doTell(targ->getName(),
    "I have been sent to help you in your endeavors!");
}

// barkskin
void addPermaDeathEffects(TBeing *faerie, TBeing *targ)
{
  affectedData aff;
  if (!targ) {
    vlogf(LOG_BUG, "addPermaDeathEffects entered with null targ");
    return;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "addPermaDeathEffects entered with null faerie");
    return;
  }

  aff.type = SKILL_BARKSKIN;
  aff.location = APPLY_ARMOR;
  aff.duration = 2*UPDATES_PER_MUDHOUR;
  aff.bitvector = 0;
  aff.modifier = -90;

  if (!targ->affectJoin(targ, &aff, AVG_DUR_NO, AVG_EFF_YES)) {
    vlogf(LOG_BUG, "Failed to join aff in addPermaDeathEffects");
    targ->sendTo("The faerie's magic fails.");
  } else {
    act("Your skin turns into an extremely hard, oak-like bark.",
        FALSE, targ, NULL, NULL, TO_CHAR);
    act("$n's skin turns into an extremely hard, oak-like bark.",
        TRUE, targ, NULL, NULL, TO_ROOM);
  }

}

int clearPermaDeathEffects(TBeing *faerie, TBeing *targ)
{
  int rc;

  if (!targ) {
    vlogf(LOG_BUG, "Missing target in clearPermaDeathEffects.");
    return FALSE;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "Missing faerie in clearPermaDeathEffects.");
    return FALSE;
  }
  rc = targ->spellWearOff(SKILL_BARKSKIN, SAFE_YES);
  if (IS_SET_DELETE(rc, DELETE_THIS))
    return DELETE_VICT;
  targ->affectFrom(SKILL_BARKSKIN);

  return TRUE;

}

// wrapper function
int heroFaerie(TBeing *ch, cmdTypeT cmd, const char *arg,
  TMonster *myself, TObj *) {
  return heroFaerie(ch, cmd, arg, myself, NULL, FALSE);
}

int heroFaerie(TBeing *ch, cmdTypeT cmd, const char *arg,
  TMonster *myself, TObj *, bool login)
{
  TBeing *newMaster = NULL;
  int rc = FALSE;

  if (!ch || !cmd || !myself)
    return FALSE;

  if (cmd == CMD_RENT) {
    myself->stopFollower(FALSE);
    act("$n disappears.  *pop*" , TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    // reinsert at birth room
    *real_roomp(myself->brtRoom) += *myself;
    return FALSE;
  }

  if (!login && cmd != CMD_GENERIC_PULSE)
    return FALSE;

  if (myself->master && ::number(0,119)) // on most of the time but !spammy
    return FALSE;

  if (login)
    vlogf(LOG_MAROR, "Calling heroFaerie on login.");

  if (!myself->awake())
    myself->doWake("");

  myself->doFly();

  // put faerie and master in the same room
  if (myself->master && myself->roomp != myself->master->roomp) {
    act("$N left without you!  Can't have that!.  *pop*",
        FALSE, myself, 0, myself->master, TO_CHAR);
    act("$n disappears.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    *myself->master->roomp += *myself;
    myself->doLook("",CMD_LOOK);
    act("$n appears in the room.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    act("$n tells you, <1>\"<c>Hey!  Why'd you leave me behind?<1>\"",
        TRUE, myself, 0, myself->master, TO_VICT);
    myself->master->addFollower(myself);
  }

  // erase effects on current target
  if (myself->master && myself->roomp == myself->master->roomp) {
    act("Time for something new!  You point at $N, then touch your nose and wiggle your bottom.",
        FALSE, myself, 0, myself->master, TO_CHAR);
    act("$n points at you, then touches $s nose and wiggles $s bottom.",
        FALSE, myself, 0, myself->master, TO_VICT);
    act("$n points at $N, then touches $s nose and wiggles $s bottom.",
        FALSE, myself, 0, myself->master, TO_NOTVICT);
    switch(myself->mobVnum()) {
      case UNIQUE_TROPHY_FAERIE:
        rc = clearUniqueTrophyEffects(myself, myself->master);
        break;
      case PERMA_DEATH_FAERIE:
        rc = clearPermaDeathEffects(myself, myself->master);
        break;
      default:
        break;
    }
  }

  if (IS_SET_DELETE(rc, DELETE_THIS)) {
    myself->master->reformGroup();
    delete myself->master;
    myself->master = NULL;
  }

  if (myself->master && myself->master->getTimer() > MAX_TIME) {
    myself->doSay("I'm bored.");
    myself->stopFollower(FALSE);
  }

  // identify new master
  Descriptor *d;
  for (d = descriptor_list; d; d = d->next) {
    if (d->connected != CON_PLYNG)
      continue;

    TBeing *targ = d->character;

    if (!targ || targ->GetMaxLevel() > MAX_MORT)
      continue;

    if (targ->getTimer() > MAX_TIME)
      continue;

    if (targ->roomp == real_roomp(ROOM_VOID))
      continue;

    switch(myself->mobVnum()) {
      case UNIQUE_TROPHY_FAERIE:
        if ( !newMaster ||
            getUniqueTrophyRank(targ) > getUniqueTrophyRank(newMaster)) {
          newMaster = targ;
        }
        break;
      case PERMA_DEATH_FAERIE:
        if ( (getPermaDeathRank(targ) > 0 && !newMaster) ||
            ( newMaster &&
              getPermaDeathRank(targ) > getPermaDeathRank(newMaster))) {
          newMaster = targ;
        }
        break;
      default:
    vlogf(LOG_BUG, fmt("defaulting with myself->mobVnum()=%d") % myself->mobVnum());
        break;
    }
  }

  // check for new target, if no target return DELETE_THIS
  // if target is new, move there and give intro message
  if (!newMaster) {
    act("You can't find a master, so you go on your way. *pop*",
        FALSE, myself, 0, NULL, TO_CHAR);
    act("$n disappears.  *pop*" , TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    // reinsert at birth room
    *real_roomp(myself->brtRoom) += *myself;
    return TRUE;
  } else if (myself->master != newMaster) {
    if (myself->master)
      act("$n tells you, <1>\"<c>Sorry, gotta go.  Someone more interesting has arrived.<1>\"",
          TRUE, myself, 0, myself->master, TO_VICT);
    act("You go to $N, your new master.  *pop*",
        FALSE, myself, 0, newMaster, TO_CHAR);
    act("$n disappears.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    *newMaster->roomp += *myself;
    myself->doLook("",CMD_LOOK);
    act("$n appears in the room.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);

    switch(myself->mobVnum()) {
      case UNIQUE_TROPHY_FAERIE:
        uniqueTrophyIntro(myself, newMaster);
        break;
      case PERMA_DEATH_FAERIE:
        permaDeathIntro(myself, newMaster);
        break;
      default:
        break;
    }
    myself->stopFollower(FALSE);
    newMaster->addFollower(myself);
  } else if (myself->roomp != myself->master->roomp) {
    vlogf(LOG_BUG, "Master and heroFaerie in different rooms - this should not happen at this point.");
    act("$N left without you!  Can't have that!.  *pop*",
        FALSE, myself, 0, myself->master, TO_CHAR);
    act("$n disappears.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    *myself->master->roomp += *myself;
    myself->doLook("",CMD_LOOK);
    act("$n appears in the room.  *pop", TRUE, myself, 0, NULL, TO_ROOM);
    act("$n tells you, <1>\"<c>Hey!  Why'd you leave me behind?<1>\"",
        TRUE, myself, 0, myself->master, TO_VICT);
    myself->master->addFollower(myself);
  }

  act("$n claps $s hands twice and sprinkles you with glittery dust.",
    TRUE, myself, 0, myself->master, TO_VICT);
  act("$n claps $s hands twice and sprinkles $N with glittery dust.",
    TRUE, myself, 0, myself->master, TO_NOTVICT);

  // spell up target
  switch(myself->mobVnum()) {
    case UNIQUE_TROPHY_FAERIE:
      addUniqueTrophyEffects(myself, newMaster);
      break;
    case PERMA_DEATH_FAERIE:
      addPermaDeathEffects(myself, newMaster);
      break;
    default:
      break;
  }

  return TRUE;

}

<commit_msg>changed room moved to thing_to_room to handle bad rooms<commit_after>#include "stdsneezy.h"
#include "db.h"
#include "database.h"

#define UNIQUE_TROPHY_FAERIE 33313
#define PERMA_DEATH_FAERIE 33314
#define FAERIE_CASTER_LEVEL 50
#define MAX_TIME 5 // max idle time

// only important that higher is better
// rate players by number of unique creatures killed
int getUniqueTrophyRank(TBeing *targ)
{
  TDatabase db(DB_SNEEZY);

  if (!targ) {
    vlogf(LOG_BUG, "getUniqueTrophyRank entered with null targ");
    return 0;
  }
  db.query("select t.count from trophyplayer t where t.player_id=%i",
      targ->getPlayerID());
  if (!db.isResults())
    return 0;
  if (db.fetchRow()) {
    return convertTo<int>(db["count"]);
  } else
    return 0;
}

void uniqueTrophyIntro(TBeing *faerie, TBeing *targ)
{
  if (!targ) {
    vlogf(LOG_BUG, "uniqueTrophyIntro entered with null targ");
    return;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "uniqueTrophyIntro entered with null faerie");
    return;
  }
  faerie->doTell(targ->getName(),
    "You are greatly respected amongst my people for the breadth of your travels.");
  faerie->doTell(targ->getName(),
    "I have been sent to help you in your endeavors!");
}

// feral wrath, but only the stat part (no AC penalty), stat part is halved
void addUniqueTrophyEffects(TBeing *faerie, TBeing *targ)
{
  affectedData aff2;

  if (!targ) {
    vlogf(LOG_BUG, "addUniqueTrophyEffects entered with null targ");
    return;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "addUniqueTrophyEffects entered with null faerie");
    return;
  }
  int modifier = FAERIE_CASTER_LEVEL/2 * ::number(80,125)/100;
  int which = ::number(1,3);

  switch (which) {
    case 1:
      aff2.location = APPLY_STR;
      aff2.modifier = modifier;
      break;
    case 2:
      aff2.location = APPLY_DEX;
      aff2.modifier = modifier;
      break;
    case 3:
      aff2.location = APPLY_SPE;
      aff2.modifier = modifier;
      break;
  }
  aff2.type = SPELL_FERAL_WRATH;
  aff2.duration = 2*UPDATES_PER_MUDHOUR;
  aff2.bitvector = 0;

  if (!targ->affectJoin(targ, &aff2, AVG_DUR_NO, AVG_EFF_YES)) {
    vlogf(LOG_BUG, "Failed to join aff2 in addUniqueTrophyEffects");
    targ->sendTo("The faerie's magic fails.");
  } else {
    if (aff2.location == APPLY_STR) {
      act("The misty shape of a large bear settles on you.\n\rYou feel stronger.", FALSE, targ, NULL, NULL, TO_CHAR);
      act("A light mist in the shape of a large bear settles on $n.",
          FALSE, targ, NULL, NULL, TO_ROOM);
    } else if (aff2.location == APPLY_DEX) {
      act("The misty shape of a great cat settles on you.\n\rYou feel your reflexes quicken.", FALSE, targ, NULL, NULL, TO_CHAR);
      act("A light mist in the shape of a great cat settles on $n.",
          FALSE, targ, NULL, NULL, TO_ROOM);
    } else if (aff2.location == APPLY_SPE) {
      act("The misty shape of a snake settles on you.\n\rYou feel you can strike with great speed.", FALSE, targ, NULL, NULL, TO_CHAR);
      act("A light mist in the shape of a snake settles on $n.",
          FALSE, targ, NULL, NULL, TO_ROOM);
    }

  }
}

int clearUniqueTrophyEffects(TBeing *faerie, TBeing *targ)
{
  int rc;

  if (!targ) {
    vlogf(LOG_BUG, "Missing target in clearUniqueTrophyEffects.");
    return FALSE;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "Missing faerie in clearUniqueTrophyEffects.");
    return FALSE;
  }
  rc = targ->spellWearOff(SPELL_FERAL_WRATH, SAFE_YES);
  if (IS_SET_DELETE(rc, DELETE_THIS))
    return DELETE_VICT;
  targ->affectFrom(SPELL_FERAL_WRATH);

  return TRUE;

}

// only important that higher is better
int getPermaDeathRank(TBeing *targ)
{
  if (!targ) {
    vlogf(LOG_BUG, "getPermaDeathRank entered with null target");
    return 0;
  }
  if (!targ->hasQuestBit(TOG_PERMA_DEATH_CHAR))
    return 0;
  else return (int) max(1.,(targ->getExp()/100)); // don't want to overflow int
}

void permaDeathIntro(TBeing *faerie, TBeing *targ)
{
  if (!faerie) {
    vlogf(LOG_BUG, "permaDeathIntro entered with null faerie");
    return;
  }
  if (!targ) {
    vlogf(LOG_BUG, "permaDeathIntro entered with null targ");
    return;
  }
  faerie->doTell(targ->getName(),
    "You are greatly respected amongst my people for your great bravery.");
  faerie->doTell(targ->getName(),
    "I have been sent to help you in your endeavors!");
}

// barkskin
void addPermaDeathEffects(TBeing *faerie, TBeing *targ)
{
  affectedData aff;
  if (!targ) {
    vlogf(LOG_BUG, "addPermaDeathEffects entered with null targ");
    return;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "addPermaDeathEffects entered with null faerie");
    return;
  }

  aff.type = SKILL_BARKSKIN;
  aff.location = APPLY_ARMOR;
  aff.duration = 2*UPDATES_PER_MUDHOUR;
  aff.bitvector = 0;
  aff.modifier = -90;

  if (!targ->affectJoin(targ, &aff, AVG_DUR_NO, AVG_EFF_YES)) {
    vlogf(LOG_BUG, "Failed to join aff in addPermaDeathEffects");
    targ->sendTo("The faerie's magic fails.");
  } else {
    act("Your skin turns into an extremely hard, oak-like bark.",
        FALSE, targ, NULL, NULL, TO_CHAR);
    act("$n's skin turns into an extremely hard, oak-like bark.",
        TRUE, targ, NULL, NULL, TO_ROOM);
  }

}

int clearPermaDeathEffects(TBeing *faerie, TBeing *targ)
{
  int rc;

  if (!targ) {
    vlogf(LOG_BUG, "Missing target in clearPermaDeathEffects.");
    return FALSE;
  }
  if (!faerie) {
    vlogf(LOG_BUG, "Missing faerie in clearPermaDeathEffects.");
    return FALSE;
  }
  rc = targ->spellWearOff(SKILL_BARKSKIN, SAFE_YES);
  if (IS_SET_DELETE(rc, DELETE_THIS))
    return DELETE_VICT;
  targ->affectFrom(SKILL_BARKSKIN);

  return TRUE;

}

// wrapper function
int heroFaerie(TBeing *ch, cmdTypeT cmd, const char *arg,
  TMonster *myself, TObj *) {
  return heroFaerie(ch, cmd, arg, myself, NULL, FALSE);
}

int heroFaerie(TBeing *ch, cmdTypeT cmd, const char *arg,
  TMonster *myself, TObj *, bool login)
{
  TBeing *newMaster = NULL;
  int rc = FALSE;

  if (!ch || !cmd || !myself)
    return FALSE;

  if (cmd == CMD_RENT) {
    myself->stopFollower(FALSE);
    act("$n disappears.  *pop*" , TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    // reinsert at birth room
    thing_to_room(myself, myself->brtRoom);
    return FALSE;
  }

  if (!login && cmd != CMD_GENERIC_PULSE)
    return FALSE;

  if (myself->master && ::number(0,119)) // on most of the time but !spammy
    return FALSE;

  if (login)
    vlogf(LOG_MAROR, "Calling heroFaerie on login.");

  if (!myself->awake())
    myself->doWake("");

  myself->doFly();

  // put faerie and master in the same room
  if (myself->master && myself->roomp != myself->master->roomp) {
    act("$N left without you!  Can't have that!.  *pop*",
        FALSE, myself, 0, myself->master, TO_CHAR);
    act("$n disappears.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    *myself->master->roomp += *myself;
    myself->doLook("",CMD_LOOK);
    act("$n appears in the room.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    act("$n tells you, <1>\"<c>Hey!  Why'd you leave me behind?<1>\"",
        TRUE, myself, 0, myself->master, TO_VICT);
    myself->master->addFollower(myself);
  }

  // erase effects on current target
  if (myself->master && myself->roomp == myself->master->roomp) {
    act("Time for something new!  You point at $N, then touch your nose and wiggle your bottom.",
        FALSE, myself, 0, myself->master, TO_CHAR);
    act("$n points at you, then touches $s nose and wiggles $s bottom.",
        FALSE, myself, 0, myself->master, TO_VICT);
    act("$n points at $N, then touches $s nose and wiggles $s bottom.",
        FALSE, myself, 0, myself->master, TO_NOTVICT);
    switch(myself->mobVnum()) {
      case UNIQUE_TROPHY_FAERIE:
        rc = clearUniqueTrophyEffects(myself, myself->master);
        break;
      case PERMA_DEATH_FAERIE:
        rc = clearPermaDeathEffects(myself, myself->master);
        break;
      default:
        break;
    }
  }

  if (IS_SET_DELETE(rc, DELETE_THIS)) {
    myself->master->reformGroup();
    delete myself->master;
    myself->master = NULL;
  }

  if (myself->master && myself->master->getTimer() > MAX_TIME) {
    myself->doSay("I'm bored.");
    myself->stopFollower(FALSE);
  }

  // identify new master
  Descriptor *d;
  for (d = descriptor_list; d; d = d->next) {
    if (d->connected != CON_PLYNG)
      continue;

    TBeing *targ = d->character;

    if (!targ || targ->GetMaxLevel() > MAX_MORT)
      continue;

    if (targ->getTimer() > MAX_TIME)
      continue;

    if (targ->roomp == real_roomp(ROOM_VOID))
      continue;

    switch(myself->mobVnum()) {
      case UNIQUE_TROPHY_FAERIE:
        if ( !newMaster ||
            getUniqueTrophyRank(targ) > getUniqueTrophyRank(newMaster)) {
          newMaster = targ;
        }
        break;
      case PERMA_DEATH_FAERIE:
        if ( (getPermaDeathRank(targ) > 0 && !newMaster) ||
            ( newMaster &&
              getPermaDeathRank(targ) > getPermaDeathRank(newMaster))) {
          newMaster = targ;
        }
        break;
      default:
    vlogf(LOG_BUG, fmt("defaulting with myself->mobVnum()=%d") % myself->mobVnum());
        break;
    }
  }

  // check for new target, if no target return DELETE_THIS
  // if target is new, move there and give intro message
  if (!newMaster) {
    act("You can't find a master, so you go on your way. *pop*",
        FALSE, myself, 0, NULL, TO_CHAR);
    act("$n disappears.  *pop*" , TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    // reinsert at birth room
    thing_to_room(myself, myself->brtRoom);
    return TRUE;
  } else if (myself->master != newMaster) {
    if (myself->master)
      act("$n tells you, <1>\"<c>Sorry, gotta go.  Someone more interesting has arrived.<1>\"",
          TRUE, myself, 0, myself->master, TO_VICT);
    act("You go to $N, your new master.  *pop*",
        FALSE, myself, 0, newMaster, TO_CHAR);
    act("$n disappears.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    *newMaster->roomp += *myself;
    myself->doLook("",CMD_LOOK);
    act("$n appears in the room.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);

    switch(myself->mobVnum()) {
      case UNIQUE_TROPHY_FAERIE:
        uniqueTrophyIntro(myself, newMaster);
        break;
      case PERMA_DEATH_FAERIE:
        permaDeathIntro(myself, newMaster);
        break;
      default:
        break;
    }
    myself->stopFollower(FALSE);
    newMaster->addFollower(myself);
  } else if (myself->roomp != myself->master->roomp) {
    vlogf(LOG_BUG, "Master and heroFaerie in different rooms - this should not happen at this point.");
    act("$N left without you!  Can't have that!.  *pop*",
        FALSE, myself, 0, myself->master, TO_CHAR);
    act("$n disappears.  *pop*", TRUE, myself, 0, NULL, TO_ROOM);
    --(*myself);
    *myself->master->roomp += *myself;
    myself->doLook("",CMD_LOOK);
    act("$n appears in the room.  *pop", TRUE, myself, 0, NULL, TO_ROOM);
    act("$n tells you, <1>\"<c>Hey!  Why'd you leave me behind?<1>\"",
        TRUE, myself, 0, myself->master, TO_VICT);
    myself->master->addFollower(myself);
  }

  act("$n claps $s hands twice and sprinkles you with glittery dust.",
    TRUE, myself, 0, myself->master, TO_VICT);
  act("$n claps $s hands twice and sprinkles $N with glittery dust.",
    TRUE, myself, 0, myself->master, TO_NOTVICT);

  // spell up target
  switch(myself->mobVnum()) {
    case UNIQUE_TROPHY_FAERIE:
      addUniqueTrophyEffects(myself, newMaster);
      break;
    case PERMA_DEATH_FAERIE:
      addPermaDeathEffects(myself, newMaster);
      break;
    default:
      break;
  }

  return TRUE;

}

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "matrix_algs.h"
#include "combined_matrix_store.h"

namespace fm
{

namespace alg
{

static size_t get_nnz(sparse_matrix::ptr mat)
{
	int num_nodes = matrix_conf.get_num_nodes();
	detail::matrix_store::ptr out_store = detail::matrix_store::create(
			mat->get_num_rows(), 1, matrix_layout_t::L_ROW,
			get_scalar_type<size_t>(), num_nodes, true);
	dense_matrix::ptr one = dense_matrix::create_const<size_t>(1,
			mat->get_num_cols(), 1, matrix_layout_t::L_ROW, num_nodes, true);
	mat->multiply<size_t, size_t>(one->get_raw_store(), out_store);
	dense_matrix::ptr out_deg = dense_matrix::create(out_store);
	scalar_variable::ptr v = out_deg->sum();
	return scalar_variable::get_val<size_t>(*v);
}

// trace of W %*% H
static double trace_MM(dense_matrix::ptr W, dense_matrix::ptr H)
{
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tmp = W->multiply_ele(*tH);
	scalar_variable::ptr res = tmp->sum();
	return scalar_variable::get_val<double>(*res);
}

static dense_matrix::ptr multiply(sparse_matrix::ptr S, dense_matrix::ptr D,
		size_t num_in_mem)
{
	size_t k = D->get_num_cols();
	if (num_in_mem >= k * 2) {
		detail::mem_matrix_store::ptr res = detail::mem_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), D->get_raw_store()->get_num_nodes());
		S->multiply<double, double>(D->get_raw_store(), res);
		return dense_matrix::create(res);
	}
	else if (num_in_mem > k) {
		return dense_matrix::ptr();
#if 0
		detail::matrix_store::ptr res = detail::cached_col_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), D->get_type(),
				D->get_raw_store()->get_num_nodes(), num_in_mem - k);
		S->multiply<double, double>(D->get_raw_store(), res);
		return dense_matrix::create(res);
#endif
	}
	else if (num_in_mem == k) {
		detail::matrix_store::ptr res = detail::matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), -1, false);
		S->multiply<double, double>(D->get_raw_store(), res);
		return dense_matrix::create(res);
	}
	else {
		std::vector<detail::matrix_store::const_ptr> res_mats;
		for (size_t i = 0; i < k; i += num_in_mem) {
			size_t sub_ncol = std::min(num_in_mem, k - i);
			std::vector<off_t> col_idxs(sub_ncol);
			for (size_t j = 0; j < sub_ncol; j++)
				col_idxs[j] = i + j;
			dense_matrix::ptr sub_in = D->get_cols(col_idxs);
			detail::matrix_store::ptr out = detail::matrix_store::create(
					S->get_num_rows(), sub_in->get_num_cols(),
					matrix_layout_t::L_COL, D->get_type(), -1, false);
			S->multiply<double, double>(sub_in->get_raw_store(), out);
			res_mats.push_back(out);
		}
		return dense_matrix::create(
				detail::combined_matrix_store::create(res_mats,
					matrix_layout_t::L_COL));
	}
}

// ||A - W %*% H||^2
static double Fnorm(sparse_matrix::ptr A, size_t Annz, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	// tAW <- t(A) %*% W
	sparse_matrix::ptr tA = A->transpose();
	dense_matrix::ptr tAW = multiply(tA, W, num_in_mem);

	// tHtWW <- t(H) %*% (t(W) %*% W)
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tHtWW = tH->multiply(*tWW);

	// sumA2 - 2 * trace.MM(tAW, H) + trace.MM(tHtWW, H)
	// TODO H is read twice in this implementation.
	// TODO tAW doesn't need to be materialized.
	return Annz - 2 * trace_MM(tAW, H) + trace_MM(tHtWW, H);
}

struct nmf_state
{
	dense_matrix::ptr W;
	dense_matrix::ptr H;
	dense_matrix::ptr tWW;

	nmf_state(dense_matrix::ptr W, dense_matrix::ptr H,
			dense_matrix::ptr tWW) {
		this->W = W;
		this->H = H;
		this->tWW = tWW;
	}
};

static nmf_state update_lee(sparse_matrix::ptr mat, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	double eps = 10e-9;
	// den <- (t(W) %*% W) %*% H
	dense_matrix::ptr D;
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// t(H) %*% (t(W) %*% W)
		dense_matrix::ptr tD = tH->multiply(*tWW);
		D = tD->transpose();
	}

	// H <- fm.pmax2(H * t(tA %*% W), eps) / (den + eps)
	{
		sparse_matrix::ptr tmat = mat->transpose();
		// tA %*% W
		dense_matrix::ptr tmp1 = multiply(tmat, W, num_in_mem);
		// t(tA %*% W)
		tmp1 = tmp1->transpose();
		// H * t(tA %*% W)
		assert(tmp1->store_layout() == H->store_layout());
		tmp1 = tmp1->multiply_ele(*H);
		// fm.pmax2(H * t(tA %*% W), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp3 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp3->store_layout());
		H = tmp1->div(*tmp3);
		H->set_materialize_level(materialize_level::MATER_FULL);
	}

	// den <- W %*% (H %*% t(H))
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// H %*% t(H)
		dense_matrix::ptr tmp1 = H->multiply(*tH);
		D = W->multiply(*tmp1);
	}

	// W <- fm.pmax2(W * (A %*% t(H)), eps) / (den + eps)
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// A %*% t(H)
		dense_matrix::ptr tmp1 = multiply(mat, tH, num_in_mem);
		// W * (A %*% t(H))
		assert(W->store_layout() == tmp1->store_layout());
		tmp1 = W->multiply_ele(*tmp1);
		// fm.pmax2(W * (A %*% t(H)), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp2 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp2->store_layout());
		W = tmp1->div(*tmp2);
		W->set_materialize_level(materialize_level::MATER_FULL);
	}

	dense_matrix::ptr tW = W->transpose();
	tWW = tW->multiply(*W);
	// TODO We have to materialize these matrices here.
	// Otherwise, we'll get segmentation fault. Why?
	W->materialize_self();
	H->materialize_self();
	return nmf_state(W, H, tWW);
}

std::pair<dense_matrix::ptr, dense_matrix::ptr> NMF(sparse_matrix::ptr mat,
		size_t k, size_t max_niters, size_t num_in_mem)
{
	if (mat->get_entry_size() > 0) {
		BOOST_LOG_TRIVIAL(error) << "can only handle binary sparse matrix";
		return std::pair<dense_matrix::ptr, dense_matrix::ptr>();
	}
	size_t n = mat->get_num_rows();
	size_t m = mat->get_num_cols();
	size_t nnz = get_nnz(mat);
	int num_nodes = matrix_conf.get_num_nodes();
	dense_matrix::ptr W, H;
	if (num_in_mem >= 2 * k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, true);
	}
	else if (num_in_mem > k && num_in_mem < 2 * k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_ROW, num_nodes, false);
	}
	else {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_COL, num_nodes, false);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_ROW, num_nodes, false);
	}

	dense_matrix::ptr tWW;
	{
		dense_matrix::ptr tW = W->transpose();
		tWW = tW->multiply(*W);
	}
	nmf_state state(W, H, tWW);
	for (size_t i = 0; i < max_niters; i++) {
		struct timeval start, end;
		gettimeofday(&start, NULL);
		state = update_lee(mat, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		double update_time = time_diff(start, end);
		start = end;
		double dist = Fnorm(mat, nnz, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		printf("iteration %ld: distance: %f, update time: %.3fs, Fnorm: %.3f\n",
				i, dist, update_time, time_diff(start, end));
	}
	return std::pair<dense_matrix::ptr, dense_matrix::ptr>(state.W, state.H);
}

}

}
<commit_msg>[Matrix]: fix a bug in NMF.<commit_after>/*
 * Copyright 2015 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "matrix_algs.h"
#include "combined_matrix_store.h"

namespace fm
{

namespace alg
{

static size_t get_nnz(sparse_matrix::ptr mat)
{
	int num_nodes = matrix_conf.get_num_nodes();
	detail::matrix_store::ptr out_store = detail::matrix_store::create(
			mat->get_num_rows(), 1, matrix_layout_t::L_ROW,
			get_scalar_type<size_t>(), num_nodes, true);
	dense_matrix::ptr one = dense_matrix::create_const<size_t>(1,
			mat->get_num_cols(), 1, matrix_layout_t::L_ROW, num_nodes, true);
	mat->multiply<size_t, size_t>(one->get_raw_store(), out_store);
	dense_matrix::ptr out_deg = dense_matrix::create(out_store);
	scalar_variable::ptr v = out_deg->sum();
	return scalar_variable::get_val<size_t>(*v);
}

// trace of W %*% H
static double trace_MM(dense_matrix::ptr W, dense_matrix::ptr H)
{
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tmp = W->multiply_ele(*tH);
	scalar_variable::ptr res = tmp->sum();
	return scalar_variable::get_val<double>(*res);
}

static dense_matrix::ptr multiply(sparse_matrix::ptr S, dense_matrix::ptr D,
		size_t num_in_mem)
{
	size_t k = D->get_num_cols();
	if (num_in_mem >= k * 2) {
		detail::mem_matrix_store::ptr res = detail::mem_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), D->get_raw_store()->get_num_nodes());
		S->multiply<double, double>(D->get_raw_store(), res);
		return dense_matrix::create(res);
	}
	else if (num_in_mem > k) {
		return dense_matrix::ptr();
#if 0
		detail::matrix_store::ptr res = detail::cached_col_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), D->get_type(),
				D->get_raw_store()->get_num_nodes(), num_in_mem - k);
		S->multiply<double, double>(D->get_raw_store(), res);
		return dense_matrix::create(res);
#endif
	}
	else if (num_in_mem == k) {
		detail::matrix_store::ptr res = detail::matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), -1, false);
		S->multiply<double, double>(D->get_raw_store(), res);
		return dense_matrix::create(res);
	}
	else {
		std::vector<detail::matrix_store::const_ptr> res_mats;
		for (size_t i = 0; i < k; i += num_in_mem) {
			size_t sub_ncol = std::min(num_in_mem, k - i);
			std::vector<off_t> col_idxs(sub_ncol);
			for (size_t j = 0; j < sub_ncol; j++)
				col_idxs[j] = i + j;
			dense_matrix::ptr sub_in = D->get_cols(col_idxs);
			detail::matrix_store::ptr out = detail::matrix_store::create(
					S->get_num_rows(), sub_in->get_num_cols(),
					matrix_layout_t::L_COL, D->get_type(), -1, false);
			S->multiply<double, double>(sub_in->get_raw_store(), out);
			res_mats.push_back(out);
		}
		return dense_matrix::create(
				detail::combined_matrix_store::create(res_mats,
					matrix_layout_t::L_COL));
	}
}

// ||A - W %*% H||^2
static double Fnorm(sparse_matrix::ptr A, size_t Annz, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	// tAW <- t(A) %*% W
	sparse_matrix::ptr tA = A->transpose();
	dense_matrix::ptr tAW = multiply(tA, W, num_in_mem);

	// tHtWW <- t(H) %*% (t(W) %*% W)
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tHtWW = tH->multiply(*tWW);

	// sumA2 - 2 * trace.MM(tAW, H) + trace.MM(tHtWW, H)
	// TODO H is read twice in this implementation.
	// TODO tAW doesn't need to be materialized.
	return Annz - 2 * trace_MM(tAW, H) + trace_MM(tHtWW, H);
}

struct nmf_state
{
	dense_matrix::ptr W;
	dense_matrix::ptr H;
	dense_matrix::ptr tWW;

	nmf_state(dense_matrix::ptr W, dense_matrix::ptr H,
			dense_matrix::ptr tWW) {
		this->W = W;
		this->H = H;
		this->tWW = tWW;
	}
};

static nmf_state update_lee(sparse_matrix::ptr mat, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	double eps = 10e-9;
	// den <- (t(W) %*% W) %*% H
	dense_matrix::ptr D;
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// t(H) %*% (t(W) %*% W)
		dense_matrix::ptr tD = tH->multiply(*tWW);
		D = tD->transpose();
	}

	// H <- fm.pmax2(H * t(tA %*% W), eps) / (den + eps)
	{
		sparse_matrix::ptr tmat = mat->transpose();
		// tA %*% W
		dense_matrix::ptr tmp1 = multiply(tmat, W, num_in_mem);
		// t(tA %*% W)
		tmp1 = tmp1->transpose();
		// H * t(tA %*% W)
		assert(tmp1->store_layout() == H->store_layout());
		tmp1 = tmp1->multiply_ele(*H);
		// fm.pmax2(H * t(tA %*% W), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp3 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp3->store_layout());
		H = tmp1->div(*tmp3);
		H->set_materialize_level(materialize_level::MATER_FULL);
	}

	// den <- W %*% (H %*% t(H))
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// H %*% t(H)
		dense_matrix::ptr tmp1 = H->multiply(*tH);
		D = W->multiply(*tmp1);
	}

	// W <- fm.pmax2(W * (A %*% t(H)), eps) / (den + eps)
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// A %*% t(H)
		dense_matrix::ptr tmp1 = multiply(mat, tH, num_in_mem);
		// W * (A %*% t(H))
		assert(W->store_layout() == tmp1->store_layout());
		tmp1 = W->multiply_ele(*tmp1);
		// fm.pmax2(W * (A %*% t(H)), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp2 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp2->store_layout());
		W = tmp1->div(*tmp2);
		W->set_materialize_level(materialize_level::MATER_FULL);
	}

	dense_matrix::ptr tW = W->transpose();
	tWW = tW->multiply(*W);
	// TODO We have to materialize these matrices here.
	// Otherwise, we'll get segmentation fault. Why?
	W->materialize_self();
	H->materialize_self();
	return nmf_state(W, H, tWW);
}

std::pair<dense_matrix::ptr, dense_matrix::ptr> NMF(sparse_matrix::ptr mat,
		size_t k, size_t max_niters, size_t num_in_mem)
{
	if (mat->get_entry_size() > 0) {
		BOOST_LOG_TRIVIAL(error) << "can only handle binary sparse matrix";
		return std::pair<dense_matrix::ptr, dense_matrix::ptr>();
	}
	size_t n = mat->get_num_rows();
	size_t m = mat->get_num_cols();
	size_t nnz = get_nnz(mat);
	int num_nodes = matrix_conf.get_num_nodes();
	dense_matrix::ptr W, H;
	if (num_in_mem >= 2 * k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, true);
	}
	else if (num_in_mem > k && num_in_mem < 2 * k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_ROW, num_nodes, false);
	}
	else if (num_in_mem == k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, false);
	}
	else {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_COL, num_nodes, false);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_ROW, num_nodes, false);
	}

	dense_matrix::ptr tWW;
	{
		dense_matrix::ptr tW = W->transpose();
		tWW = tW->multiply(*W);
	}
	nmf_state state(W, H, tWW);
	for (size_t i = 0; i < max_niters; i++) {
		struct timeval start, end;
		gettimeofday(&start, NULL);
		state = update_lee(mat, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		double update_time = time_diff(start, end);
		start = end;
		double dist = Fnorm(mat, nnz, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		printf("iteration %ld: distance: %f, update time: %.3fs, Fnorm: %.3f\n",
				i, dist, update_time, time_diff(start, end));
	}
	return std::pair<dense_matrix::ptr, dense_matrix::ptr>(state.W, state.H);
}

}

}
<|endoftext|>