<commit_before>/**
 * memory.cpp - Implementation of memory model
 * Define classes and method to operate with memory of simulated architecture
 * Copyright 2009 MDSP team
 */

#include <iostream>
#include <cassert>
#include <math.h>
#ifndef MEMORY_HEADER
#define MEMORY_HEADER
#include "memory.h"
#endif /* MEMORY_HEADER*/

/**
 * Implementation of class ByteLine
 */
ByteLine::ByteLine()
{
    byte_line = new vector<Byte>;
    output = DEFAULT_OUT;
}

ByteLine::ByteLine( unsigned int count)
{
    byte_line = new vector<Byte>;
    output = DEFAULT_OUT;
    try
    {
        (*byte_line).resize( count);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

ByteLine::ByteLine( const ByteLine& line)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>( line.getSizeOfLine());
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
    for ( unsigned int i = 0 ; i < line.getSizeOfLine(); i++)
    {
        ( *byte_line).at( i).setByteVal( line.getByteVal( i));
    }
}
ByteLine::ByteLine( const Byte& byte)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        ( *byte_line).push_back( byte);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

    /* Conversion functions ByteLine into hostUInt8, hostUInt16, hostUInt32 */
hostUInt8 ByteLine::getHostUInt8()
{
    return this->getByteVal( 0);
}

hostUInt16 ByteLine::getHostUInt16()
{
    hostUInt8 temp[] = { this->getByteVal( 1), this->getByteVal( 0)};
    hostUInt16 var = 0;
    var += temp[ 0];
    var = ( var << 8);
    var += temp[ 1];
    return var;
}

hostUInt32 ByteLine::getHostUInt32()
{
    hostUInt8 temp[] = { this->getByteVal( 3), this->getByteVal( 2),
        this->getByteVal( 1), this->getByteVal( 0)};
    hostUInt32 var = 0;
    for ( int i = 0; i < 3; i++)
    {
        var += temp[ i];
        var = ( var << 8);
    }
    var += temp[3];
    return var;
}

    /* Private functions converting hostUInt8,16,32 into vector<Byte> *byte_line */
void ByteLine::convert8( vector<Byte> *byte_line, hostUInt8 var)
{
    Byte byte( var);
    ( *byte_line).push_back( byte);
}

void ByteLine::convert16( vector<Byte> *byte_line, hostUInt16 var, OrderType type)
{
/*    hostUInt8 temp1 = 0;
    hostUInt8 temp2 = 0;
    for ( int i = 0; i < 8; i++)
    {
        if ( var & 1)
            temp1 += ( 1 << i);
        var  = (var >> 1);
    }
    for ( int i = 0; i < 8; i++)
    {
        if ( var & 1)
            temp2 += ( 1 << i);
        var = ( var >> 1);
    }
    Byte a( temp1);
    Byte b( temp2);
    if ( type == HIGH_FIRST)
    {
        ( *byte_line).push_back( a);
        ( *byte_line).push_back( b);
    } else
    {
        ( *byte_line).push_back( b);
        ( *byte_line).push_back( a);
    }
*/
    hostUInt8 temp[2] = { 0, 0};
    for ( int i = 0; i < 2; i++)
    {
        for( int k = 0; k < 8; k++)
        {
            if ( var & 1)
                temp[ i] += ( 1 << k);
            var = ( var >> 1);
        }
    }
    Byte byte[] = { temp[ 0], temp[ 1]};
    if ( type == HIGH_FIRST)
    {
        for ( int i = 0; i < 2; i++)
            ( *byte_line).push_back( byte[ i]);
    } else
    {
        for ( int i = 2; i > 0; i--)
            ( *byte_line).push_back( byte[ i-1]);
    }
}

void ByteLine::convert32( vector<Byte> *byte_line, hostUInt32 var, OrderType type)
{
/*
    hostUInt8 temp1 = 0;
    hostUInt8 temp2 = 0;
    hostUInt8 temp3 = 0;
    hostUInt8 temp4 = 0;
    for ( int i = 0; i < 8; i++)
    {
        if ( var & 1)
            temp1 += ( 1 << i);
        var  = (var >> 1);
    }
    for ( int i = 0; i < 8; i++)
    {
        if ( var & 1)
            temp2 += ( 1 << i);
        var  = (var >> 1);
    }
    for ( int i = 0; i < 8; i++)
    {
        if ( var & 1)
            temp3 += ( 1 << i);
        var  = (var >> 1);
    }
    for ( int i = 0; i < 8; i++)
    {
        if ( var & 1)
            temp4 += ( 1 << i);
        var  = (var >> 1);
    }
    Byte a( temp1);
    Byte b( temp2);
    Byte c( temp3);
    Byte d( temp4);

    if ( type == HIGH_FIRST)
    {
        ( *byte_line).push_back( a);
        ( *byte_line).push_back( b);
        ( *byte_line).push_back( c);
        ( *byte_line).push_back( d);
    } else
    {
        ( *byte_line).push_back( d);
        ( *byte_line).push_back( c);
        ( *byte_line).push_back( b);
        ( *byte_line).push_back( a);
    }
*/
    hostUInt8 temp[4] = { 0, 0, 0, 0};
    for ( int i = 0; i < 4; i++)
    {
        for( int k = 0; k < 8; k++)
        {
            if ( var & 1)
                temp[ i] += ( 1 << k);
            var = ( var >> 1);
        }
    }
    Byte byte[] = { temp[ 0], temp[ 1], temp[ 2], temp[ 3]};
    if ( type == HIGH_FIRST)
    {
        for ( int i = 0; i < 4; i++)
            ( *byte_line).push_back( byte[ i]);
    } else
    {
        for ( int i = 4; i > 0; i--)
            ( *byte_line).push_back( byte[ i-1]);
    }
}

    /* Conversion constructors hostUInt8, hostUInt16 and hostUInt32 in Byteline */
ByteLine::ByteLine( hostUInt8 var, OrderType type)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        convert8( byte_line, var);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

ByteLine::ByteLine( hostUInt16 var, OrderType type)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        convert16( byte_line, var, type);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}
ByteLine::ByteLine( hostUInt32 var, OrderType type)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        convert32( byte_line, var, type);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

ByteLine::ByteLine(unsigned int var, ConversionType ctype, OrderType type)
{
    output = DEFAULT_OUT;
    switch( ctype)
    {
    case HUINT8:
        try
        {
           byte_line = new vector<Byte>;
           convert8( byte_line, var);
        }catch ( std::bad_alloc)
        {
            cout << "ERROR: Can not allocate memory!\n";
            assert( 0);
        }
        break;
    case HUINT16:
        try
        {
            byte_line = new vector<Byte>;
            convert16( byte_line, var, type);
        }catch ( std::bad_alloc)
        {
            cout << "ERROR: Can not allocate memory!\n";
            assert( 0);
        }
        break;
    case HUINT32:
        try
        {
            byte_line = new vector<Byte>;
            convert32( byte_line, var, type);
        }catch ( std::bad_alloc)
        {
            cout << "ERROR: Can not allocate memory!\n";
            assert( 0);
        }
        break;
    }
}

hostUInt8 ByteLine::getByteVal( unsigned int byte_num) const
{
    if ( byte_num > this->getSizeOfLine())
    {
        cout << "ERROR: Size of byte line is less than target byte number!\n";
        assert( 0);
    }
    if ( ( *byte_line).empty())
    {
        cout << "ERROR: Byte line is empty!\n";
        assert( 0);
    }
    return ( *byte_line).at( byte_num).getByteVal();
}

Byte ByteLine::getByte( unsigned int byte_num) const
{
    if ( byte_num > this->getSizeOfLine())
    {
        cout << "ERROR: Size of byte line is less than target byte number!\n";
        assert( 0);
    }
    if ( ( *byte_line).empty())
    {
        cout << "ERROR: Byte line is empty!\n";
        assert( 0);
    }
    return ( *byte_line).at( byte_num);
}

void ByteLine::setByte( unsigned int byte_num, const Byte& byte)
{
    if ( byte_num > this->getSizeOfLine())
    {
        cout << "ERROR: Size of byte line is less than target byte number!\n";
        assert( 0);
    }
    if ( ( *byte_line).empty())
    {
        cout << "ERROR: Byte line is empty!\n";
        assert( 0);
    }
    ( *byte_line).at( byte_num) = byte;
}

void ByteLine::addByte( const Byte& byte)
{
    try
    {
        ( *byte_line).push_back( byte);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}
void ByteLine::resizeByteLine( unsigned int count)
{
    try
    {
        ( *byte_line).resize( count);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

/**
 * Implementation of class MemVal
 */

void MemVal::recountLenght()
{
    unsigned int temp = getSizeOfMemVal() % size_of_segmentation;
    if ( temp != 0 && size_of_segmentation != 1)
    {
        temp = size_of_segmentation - temp;
        temp += getSizeOfMemVal();
        resizeByteLine( temp);
    }
}

ByteLine MemVal::getByteLine( unsigned int index, unsigned int count) const
{
    if ( getSizeOfMemVal() < index + count)
    {
        cout << "ERROR: Size of MemVal is less than target byte number!\n";
        assert( 0);
    }
    ByteLine temp( count);
    for ( unsigned int i = 0; i < count ; i++)
    {
        temp.setByte( i, getByte( i + index));
    }
    return temp;
}
ByteLine MemVal::getByteLine() const
{
    ByteLine temp( getSizeOfMemVal());
    for ( unsigned int i = 0; i < getSizeOfMemVal(); i++)
    {
        temp.setByte( i, getByte( i));
    }
    return temp;
}

void MemVal::writeByteLine( const ByteLine& line, unsigned int index)
{
    if ( getSizeOfMemVal() < index + line.getSizeOfLine())
    {
        cout << "ERROR: Size of MemVal is less than target byte number!\n";
        assert( 0);
    }
    for ( unsigned int i = 0; i < line.getSizeOfLine(); i++)
    {
        setByte( i + index, line.getByte( i));
    }
}
void MemVal::writeByteLine( const ByteLine & line)
{
    if ( getSizeOfMemVal() < line.getSizeOfLine())
    {
        cout << "ERROR: Size of MemVal is less than target byte number!\n";
        assert( 0);
    }
    for ( unsigned int i = 0; i < line.getSizeOfLine(); i++)
    {
        setByte( i, line.getByte( i));
    }
}

/**
 * Implementation of Memory Model
 */

MemoryModel::MemoryModel( unsigned int size)
{
	mem_model = new memMap;
	size_of_segmentation = size;

}

ByteLine MemoryModel::read(  mathAddr read_ptr, unsigned int num_of_bytes)
{
	if ( ( *mem_model).empty())
	{
		cout << "ERROR!\n";
        assert( 0);
	}

	memMap::iterator pos, start, end;
	start = find( read_ptr);
	mathAddr temp_addr = start->first;
	end = find( read_ptr + num_of_bytes - 1);
	if ( start == ( *mem_model).end() || end == ( *mem_model).end())
	{
		cout << "ERROR!\n";
        assert( 0);
	}
	MemVal memval = start->second;
	for ( pos = start; pos != end; ++pos)
	{
		if ( countDistance( pos) > 0)
		{
			cout << "ERROR!\n";
			assert( 0);
		}
		mergeMemVal( pos, &memval);

	}
	( *mem_model).erase( start, end);
	( *mem_model).erase( end);
	( *mem_model)[ temp_addr] = memval;
	return memval.getByteLine( read_ptr - temp_addr, num_of_bytes);

}

void MemoryModel::mergeMemVal( memMap::iterator pos, MemVal *mem_val)
{
	if ( countDistance( pos) > 0)
	{
			mem_val->resizeMemVal( ( pos + 1)->first - pos->first);
	}
		( *mem_val) = ( *mem_val) + ( pos + 1)->second;
}

void MemoryModel::write( mathAddr write_ptr, const ByteLine& line)
{
	memMap::iterator pos, start, end ;
	start = findOrInit( write_ptr);
	mathAddr temp_addr = start->first;
	end = findOrInit( write_ptr + line.getSizeOfLine() - 1);

	MemVal memval = start->second;
	for ( pos = start; pos != end; ++pos)
	{
		mergeMemVal( pos, &memval);

	}
	( *mem_model).erase( start, end);
	( *mem_model).erase( end);

	memval.writeByteLine( line, write_ptr - temp_addr);
	( *mem_model)[ temp_addr] = memval;
}

memMap::iterator MemoryModel::findOrInit( mathAddr ptr)
{
	memMap::iterator pos;
	MemVal temp( size_of_segmentation);
	mathAddr addr = ptr - ( ptr % size_of_segmentation);

	for ( pos = ( *mem_model).begin(); pos != ( *mem_model).end(); ++pos)
	{
		if ( pos == ptr)
		{
			return pos;
		}
		if ( ( pos->first) > ptr)
		{
			( *mem_model)[ addr] = temp;
			pos = ( *mem_model).find( addr);
			return pos;

		}
	}
	( *mem_model)[ addr] = temp;
	pos = ( *mem_model).find( addr);
	return pos;

}

memMap::iterator MemoryModel::find( mathAddr ptr)
{
	memMap::iterator pos;
	mathAddr adrr;
	adrr = ptr - ( ptr % size_of_segmentation);
	for ( pos = ( *mem_model).begin(); pos != ( *mem_model).end(); ++pos)
	{
		if ( pos == ptr)
		{
			return pos;
		}
	}
	return pos = ( *mem_model).end();
}

unsigned int MemoryModel::countDistance( const memMap::iterator pos)
{
	return ( pos + 1)->first - ( pos->first + ( pos->second).getSizeOfMemVal());
}
<commit_msg>Deleting unnecessary comments in my folder<commit_after>/**
 * memory.cpp - Implementation of memory model
 * Define classes and method to operate with memory of simulated architecture
 * Copyright 2009 MDSP team
 */

#include <iostream>
#include <cassert>
#include <math.h>
#ifndef MEMORY_HEADER
#define MEMORY_HEADER
#include "memory.h"
#endif /* MEMORY_HEADER*/

/**
 * Implementation of class ByteLine
 */
ByteLine::ByteLine()
{
    byte_line = new vector<Byte>;
    output = DEFAULT_OUT;
}

ByteLine::ByteLine( unsigned int count)
{
    byte_line = new vector<Byte>;
    output = DEFAULT_OUT;
    try
    {
        (*byte_line).resize( count);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

ByteLine::ByteLine( const ByteLine& line)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>( line.getSizeOfLine());
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
    for ( unsigned int i = 0 ; i < line.getSizeOfLine(); i++)
    {
        ( *byte_line).at( i).setByteVal( line.getByteVal( i));
    }
}
ByteLine::ByteLine( const Byte& byte)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        ( *byte_line).push_back( byte);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

    /* Conversion functions ByteLine into hostUInt8, hostUInt16, hostUInt32 */
hostUInt8 ByteLine::getHostUInt8()
{
    return this->getByteVal( 0);
}

hostUInt16 ByteLine::getHostUInt16()
{
    hostUInt8 temp[] = { this->getByteVal( 1), this->getByteVal( 0)};
    hostUInt16 var = 0;
    var += temp[ 0];
    var = ( var << 8);
    var += temp[ 1];
    return var;
}

hostUInt32 ByteLine::getHostUInt32()
{
    hostUInt8 temp[] = { this->getByteVal( 3), this->getByteVal( 2),
        this->getByteVal( 1), this->getByteVal( 0)};
    hostUInt32 var = 0;
    for ( int i = 0; i < 3; i++)
    {
        var += temp[ i];
        var = ( var << 8);
    }
    var += temp[3];
    return var;
}

    /* Private functions converting hostUInt8,16,32 into vector<Byte> *byte_line */
void ByteLine::convert8( vector<Byte> *byte_line, hostUInt8 var)
{
    Byte byte( var);
    ( *byte_line).push_back( byte);
}

void ByteLine::convert16( vector<Byte> *byte_line, hostUInt16 var, OrderType type)
{
    hostUInt8 temp[2] = { 0, 0};
    for ( int i = 0; i < 2; i++)
    {
        for( int k = 0; k < 8; k++)
        {
            if ( var & 1)
                temp[ i] += ( 1 << k);
            var = ( var >> 1);
        }
    }
    Byte byte[] = { temp[ 0], temp[ 1]};
    if ( type == HIGH_FIRST)
    {
        for ( int i = 0; i < 2; i++)
            ( *byte_line).push_back( byte[ i]);
    } else
    {
        for ( int i = 2; i > 0; i--)
            ( *byte_line).push_back( byte[ i-1]);
    }
}

void ByteLine::convert32( vector<Byte> *byte_line, hostUInt32 var, OrderType type)
{
    hostUInt8 temp[4] = { 0, 0, 0, 0};
    for ( int i = 0; i < 4; i++)
    {
        for( int k = 0; k < 8; k++)
        {
            if ( var & 1)
                temp[ i] += ( 1 << k);
            var = ( var >> 1);
        }
    }
    Byte byte[] = { temp[ 0], temp[ 1], temp[ 2], temp[ 3]};
    if ( type == HIGH_FIRST)
    {
        for ( int i = 0; i < 4; i++)
            ( *byte_line).push_back( byte[ i]);
    } else
    {
        for ( int i = 4; i > 0; i--)
            ( *byte_line).push_back( byte[ i-1]);
    }
}

    /* Conversion constructors hostUInt8, hostUInt16 and hostUInt32 in Byteline */
ByteLine::ByteLine( hostUInt8 var, OrderType type)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        convert8( byte_line, var);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

ByteLine::ByteLine( hostUInt16 var, OrderType type)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        convert16( byte_line, var, type);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}
ByteLine::ByteLine( hostUInt32 var, OrderType type)
{
    output = DEFAULT_OUT;
    try
    {
        byte_line = new vector<Byte>;
        convert32( byte_line, var, type);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

ByteLine::ByteLine(unsigned int var, ConversionType ctype, OrderType type)
{
    output = DEFAULT_OUT;
    switch( ctype)
    {
    case HUINT8:
        try
        {
           byte_line = new vector<Byte>;
           convert8( byte_line, var);
        }catch ( std::bad_alloc)
        {
            cout << "ERROR: Can not allocate memory!\n";
            assert( 0);
        }
        break;
    case HUINT16:
        try
        {
            byte_line = new vector<Byte>;
            convert16( byte_line, var, type);
        }catch ( std::bad_alloc)
        {
            cout << "ERROR: Can not allocate memory!\n";
            assert( 0);
        }
        break;
    case HUINT32:
        try
        {
            byte_line = new vector<Byte>;
            convert32( byte_line, var, type);
        }catch ( std::bad_alloc)
        {
            cout << "ERROR: Can not allocate memory!\n";
            assert( 0);
        }
        break;
    }
}

hostUInt8 ByteLine::getByteVal( unsigned int byte_num) const
{
    if ( byte_num > this->getSizeOfLine())
    {
        cout << "ERROR: Size of byte line is less than target byte number!\n";
        assert( 0);
    }
    if ( ( *byte_line).empty())
    {
        cout << "ERROR: Byte line is empty!\n";
        assert( 0);
    }
    return ( *byte_line).at( byte_num).getByteVal();
}

Byte ByteLine::getByte( unsigned int byte_num) const
{
    if ( byte_num > this->getSizeOfLine())
    {
        cout << "ERROR: Size of byte line is less than target byte number!\n";
        assert( 0);
    }
    if ( ( *byte_line).empty())
    {
        cout << "ERROR: Byte line is empty!\n";
        assert( 0);
    }
    return ( *byte_line).at( byte_num);
}

void ByteLine::setByte( unsigned int byte_num, const Byte& byte)
{
    if ( byte_num > this->getSizeOfLine())
    {
        cout << "ERROR: Size of byte line is less than target byte number!\n";
        assert( 0);
    }
    if ( ( *byte_line).empty())
    {
        cout << "ERROR: Byte line is empty!\n";
        assert( 0);
    }
    ( *byte_line).at( byte_num) = byte;
}

void ByteLine::addByte( const Byte& byte)
{
    try
    {
        ( *byte_line).push_back( byte);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}
void ByteLine::resizeByteLine( unsigned int count)
{
    try
    {
        ( *byte_line).resize( count);
    }catch ( std::bad_alloc)
    {
        cout << "ERROR: Can not allocate memory!\n";
        assert( 0);
    }
}

/**
 * Implementation of class MemVal
 */

void MemVal::recountLenght()
{
    unsigned int temp = getSizeOfMemVal() % size_of_segmentation;
    if ( temp != 0 && size_of_segmentation != 1)
    {
        temp = size_of_segmentation - temp;
        temp += getSizeOfMemVal();
        resizeByteLine( temp);
    }
}

ByteLine MemVal::getByteLine( unsigned int index, unsigned int count) const
{
    if ( getSizeOfMemVal() < index + count)
    {
        cout << "ERROR: Size of MemVal is less than target byte number!\n";
        assert( 0);
    }
    ByteLine temp( count);
    for ( unsigned int i = 0; i < count ; i++)
    {
        temp.setByte( i, getByte( i + index));
    }
    return temp;
}
ByteLine MemVal::getByteLine() const
{
    ByteLine temp( getSizeOfMemVal());
    for ( unsigned int i = 0; i < getSizeOfMemVal(); i++)
    {
        temp.setByte( i, getByte( i));
    }
    return temp;
}

void MemVal::writeByteLine( const ByteLine& line, unsigned int index)
{
    if ( getSizeOfMemVal() < index + line.getSizeOfLine())
    {
        cout << "ERROR: Size of MemVal is less than target byte number!\n";
        assert( 0);
    }
    for ( unsigned int i = 0; i < line.getSizeOfLine(); i++)
    {
        setByte( i + index, line.getByte( i));
    }
}
void MemVal::writeByteLine( const ByteLine & line)
{
    if ( getSizeOfMemVal() < line.getSizeOfLine())
    {
        cout << "ERROR: Size of MemVal is less than target byte number!\n";
        assert( 0);
    }
    for ( unsigned int i = 0; i < line.getSizeOfLine(); i++)
    {
        setByte( i, line.getByte( i));
    }
}

/**
 * Implementation of Memory Model
 */

MemoryModel::MemoryModel( unsigned int size)
{
	mem_model = new memMap;
	size_of_segmentation = size;

}

ByteLine MemoryModel::read(  mathAddr read_ptr, unsigned int num_of_bytes)
{
	if ( ( *mem_model).empty())
	{
		cout << "ERROR!\n";
        assert( 0);
	}

	memMap::iterator pos, start, end;
	start = find( read_ptr);
	mathAddr temp_addr = start->first;
	end = find( read_ptr + num_of_bytes - 1);
	if ( start == ( *mem_model).end() || end == ( *mem_model).end())
	{
		cout << "ERROR!\n";
        assert( 0);
	}
	MemVal memval = start->second;
	for ( pos = start; pos != end; ++pos)
	{
		if ( countDistance( pos) > 0)
		{
			cout << "ERROR!\n";
			assert( 0);
		}
		mergeMemVal( pos, &memval);

	}
	( *mem_model).erase( start, end);
	( *mem_model).erase( end);
	( *mem_model)[ temp_addr] = memval;
	return memval.getByteLine( read_ptr - temp_addr, num_of_bytes);

}

void MemoryModel::mergeMemVal( memMap::iterator pos, MemVal *mem_val)
{
	if ( countDistance( pos) > 0)
	{
			mem_val->resizeMemVal( ( pos + 1)->first - pos->first);
	}
		( *mem_val) = ( *mem_val) + ( pos + 1)->second;
}

void MemoryModel::write( mathAddr write_ptr, const ByteLine& line)
{
	memMap::iterator pos, start, end ;
	start = findOrInit( write_ptr);
	mathAddr temp_addr = start->first;
	end = findOrInit( write_ptr + line.getSizeOfLine() - 1);

	MemVal memval = start->second;
	for ( pos = start; pos != end; ++pos)
	{
		mergeMemVal( pos, &memval);

	}
	( *mem_model).erase( start, end);
	( *mem_model).erase( end);

	memval.writeByteLine( line, write_ptr - temp_addr);
	( *mem_model)[ temp_addr] = memval;
}

memMap::iterator MemoryModel::findOrInit( mathAddr ptr)
{
	memMap::iterator pos;
	MemVal temp( size_of_segmentation);
	mathAddr addr = ptr - ( ptr % size_of_segmentation);

	for ( pos = ( *mem_model).begin(); pos != ( *mem_model).end(); ++pos)
	{
		if ( pos == ptr)
		{
			return pos;
		}
		if ( ( pos->first) > ptr)
		{
			( *mem_model)[ addr] = temp;
			pos = ( *mem_model).find( addr);
			return pos;

		}
	}
	( *mem_model)[ addr] = temp;
	pos = ( *mem_model).find( addr);
	return pos;

}

memMap::iterator MemoryModel::find( mathAddr ptr)
{
	memMap::iterator pos;
	mathAddr adrr;
	adrr = ptr - ( ptr % size_of_segmentation);
	for ( pos = ( *mem_model).begin(); pos != ( *mem_model).end(); ++pos)
	{
		if ( pos == ptr)
		{
			return pos;
		}
	}
	return pos = ( *mem_model).end();
}

unsigned int MemoryModel::countDistance( const memMap::iterator pos)
{
	return ( pos + 1)->first - ( pos->first + ( pos->second).getSizeOfMemVal());
}
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the New-BSD license. Please see LICENSE file in the project root for terms.
#include <jni.h>
#include <arpa/inet.h>
#include "addr_support.h"
#include "com_yahoo_wildwest_PowersawValidator.h"

#define EXPECTED_IPV4 "192.168.1.111"
#define EXPECTED_IPV6 "2001:4998:0:1::1007"

int checkAddress(const char *expected, int ai_family,
        const ipv6_sockaddr *addr) {
    if (NULL == expected && NULL == addr) {
        return 0;
    }

    if (NULL == expected) {
        return -1;
    }

    if (NULL == addr) {
        return -2;
    }

    const void *addr_s = NULL;
    /* get the IP address as string passed to this function */
    char ipstr[INET6_ADDRSTRLEN] = { 0, };
    if (ai_family == AF_INET) {
        /* IPv4 */
        const struct sockaddr_in *ipv4 = &(addr->sin);
        addr_s = (const void*) &(ipv4->sin_addr);
    } else {
        /* IPv6 */
        const struct sockaddr_in6 *ipv6 = &(addr->sin6);
        addr_s = (const void*) &(ipv6->sin6_addr);
    }

    if (NULL == inet_ntop(ai_family, addr_s, ipstr, sizeof(ipstr))) {
        return -3;
    }

    fprintf(stderr, "comparing %s to %s\n", expected, ipstr);
    return strcmp(expected, ipstr);
}

int checkAddress(const char *expected, const struct addrinfo *addr) {
    if (NULL == expected && NULL == addr) {
        return 0;
    }

    if (NULL == expected) {
        return -1;
    }

    if (NULL == addr) {
        return -2;
    }

    return checkAddress(expected, addr->ai_family,
            (const ipv6_sockaddr*) addr->ai_addr);
}

/*
 * Class:     com_yahoo_wildwest_PowersawValidator
 * Method:    validateIpv4
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL Java_com_yahoo_wildwest_PowersawValidator_validateIpv4(
        JNIEnv *, jclass, jlong address, jlong length) {
    fprintf(stderr, "calling validateIpv6\n");

    ipv6_sockaddr v6sa;
    memset(&v6sa, 0, sizeof(ipv6_sockaddr));
    unsafeToSockAddr(v6sa, address, length);
    return checkAddress(EXPECTED_IPV4, AF_INET, &v6sa);
}

/*
 * Class:     com_yahoo_wildwest_PowersawValidator
 * Method:    validateIpv6
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL Java_com_yahoo_wildwest_PowersawValidator_validateIpv6(
        JNIEnv *, jclass, jlong address, jlong length) {
    fprintf(stderr, "calling validateIpv6\n");

    ipv6_sockaddr v6sa;
    memset(&v6sa, 0, sizeof(ipv6_sockaddr));
    unsafeToSockAddr(v6sa, address, length);
    return checkAddress(EXPECTED_IPV6, AF_INET6, &v6sa);
}

/*
 * Class:     com_yahoo_wildwest_PowersawValidator
 * Method:    validateAddresses
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL Java_com_yahoo_wildwest_PowersawValidator_validateAddresses(
        JNIEnv *, jclass, jlong addresses, jlong length) {

    fprintf(stderr, "calling validateAddresses\n");

    ScopedAddrInfo aiScope;
    if (!allocAddrInfo(aiScope, addresses, length)) {
        return -2;
    }

    int ret;

    // check the first address
    ret = checkAddress(EXPECTED_IPV4, aiScope.get()->ai_family,
            (const ipv6_sockaddr*) aiScope.get()->ai_addr);

    if (0 != ret) {
        return ret;
    }

    // should not be lazy and loop all of them.
    // that would be way better testing.
    if (NULL != aiScope.get()->ai_next) {
        addrinfo *next = aiScope.get()->ai_next;
        ret = checkAddress(EXPECTED_IPV6, next->ai_family,
                (const ipv6_sockaddr*) next->ai_addr);

        if (0 != ret) {
            return ret;
        }
    }

    return 0;
}
<commit_msg>Add more prints for when things go south<commit_after>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the New-BSD license. Please see LICENSE file in the project root for terms.
#include <jni.h>
#include <arpa/inet.h>
#include "addr_support.h"
#include "com_yahoo_wildwest_PowersawValidator.h"

#define EXPECTED_IPV4 "192.168.1.111"
#define EXPECTED_IPV6 "2001:4998:0:1::1007"

int checkAddress(const char *expected, int ai_family,
        const ipv6_sockaddr *addr, const char*forwho) {
    if (NULL == expected && NULL == addr) {
        return 0;
    }

    if (NULL == expected) {
        return -1;
    }

    if (NULL == addr) {
        return -2;
    }

    const void *addr_s = NULL;
    /* get the IP address as string passed to this function */
    char ipstr[INET6_ADDRSTRLEN] = { 0, };
    if (ai_family == AF_INET) {
        /* IPv4 */
        const struct sockaddr_in *ipv4 = &(addr->sin);
        addr_s = (const void*) &(ipv4->sin_addr);
    } else {
        /* IPv6 */
        const struct sockaddr_in6 *ipv6 = &(addr->sin6);
        addr_s = (const void*) &(ipv6->sin6_addr);
    }

    if (NULL == inet_ntop(ai_family, addr_s, ipstr, sizeof(ipstr))) {
        return -3;
    }

    fprintf(stderr, "comparing %s to %s for %s\n", expected, ipstr, forwho);
    return strcmp(expected, ipstr);
}

int checkAddress(const char *expected, const struct addrinfo *addr, const char *forwho) {
    if (NULL == expected && NULL == addr) {
        return 0;
    }

    if (NULL == expected) {
        return -1;
    }

    if (NULL == addr) {
        return -2;
    }

    return checkAddress(expected, addr->ai_family,
            (const ipv6_sockaddr*) addr->ai_addr, forwho);
}

/*
 * Class:     com_yahoo_wildwest_PowersawValidator
 * Method:    validateIpv4
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL Java_com_yahoo_wildwest_PowersawValidator_validateIpv4(
        JNIEnv *, jclass, jlong address, jlong length) {
    fprintf(stderr, "calling validateIpv6\n");

    ipv6_sockaddr v6sa;
    memset(&v6sa, 0, sizeof(ipv6_sockaddr));
    unsafeToSockAddr(v6sa, address, length);
    return checkAddress(EXPECTED_IPV4, AF_INET, &v6sa,"validateIpv4");
}

/*
 * Class:     com_yahoo_wildwest_PowersawValidator
 * Method:    validateIpv6
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL Java_com_yahoo_wildwest_PowersawValidator_validateIpv6(
        JNIEnv *, jclass, jlong address, jlong length) {
    fprintf(stderr, "calling validateIpv6\n");

    ipv6_sockaddr v6sa;
    memset(&v6sa, 0, sizeof(ipv6_sockaddr));
    unsafeToSockAddr(v6sa, address, length);
    return checkAddress(EXPECTED_IPV6, AF_INET6, &v6sa,"validateIpv6");
}

/*
 * Class:     com_yahoo_wildwest_PowersawValidator
 * Method:    validateAddresses
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL Java_com_yahoo_wildwest_PowersawValidator_validateAddresses(
        JNIEnv *, jclass, jlong addresses, jlong length) {

    fprintf(stderr, "calling validateAddresses\n");

    ScopedAddrInfo aiScope;
    if (!allocAddrInfo(aiScope, addresses, length)) {
        return -2;
    }

    int ret;

    // check the first address
    ret = checkAddress(EXPECTED_IPV4, aiScope.get()->ai_family,
            (const ipv6_sockaddr*) aiScope.get()->ai_addr,"validateAddresses:validateIpv4");

    if (0 != ret) {
        return ret;
    }

    // should not be lazy and loop all of them.
    // that would be way better testing.
    if (NULL != aiScope.get()->ai_next) {
        addrinfo *next = aiScope.get()->ai_next;
        ret = checkAddress(EXPECTED_IPV6, next->ai_family,
                (const ipv6_sockaddr*) next->ai_addr,"validateAddresses:validateIpv6");

        if (0 != ret) {
            return ret;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_FUNCTION_CONSTANT_HH
#define DUNE_STUFF_FUNCTION_CONSTANT_HH

#include <dune/stuff/common/parameter/tree.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimCols, int rangeDimRows >
class FunctionConstantBase
  : public FunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimCols, rangeDimRows >
  , public TimedependentFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimCols, rangeDimRows >
{
  typedef FunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimCols, rangeDimRows > BaseType;
public:
  typedef typename BaseType::DomainFieldType  DomainFieldType;
  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType       DomainType;
  typedef typename BaseType::RangeFieldType   RangeFieldType;
  static const unsigned int                   dimRangeCols = BaseType::dimRangeCols;
  static const unsigned int                   dimRangeRows = BaseType::dimRangeRows;
  typedef typename BaseType::RangeType        RangeType;

  FunctionConstantBase(const RangeFieldType& constant)
    : constant_(constant)
  {}

  FunctionConstantBase(const RangeType& constant)
    : constant_(constant)
  {}

  static const std::string id()
  {
    return BaseType::id() + ".constant";
  }

  virtual int order() const
  {
    return 0;
  }

  virtual std::string name() const
  {
    return "function.constant";
  }

  virtual void evaluate(const DomainType& /*arg*/, RangeType& ret) const
  {
    ret = constant_;
  }

  virtual void evaluate(const DomainType& /*arg*/, const double& /*t*/, RangeType& ret) const
  {
    ret = constant_;
  }

private:
  const RangeType constant_;
}; // class FunctionConstantBase

// forward, to allow for specialization
template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimCols, int rangeDimRows = 1 >
class FunctionConstant
{
public:
  FunctionConstant() = delete;
}; // class FunctionConstant

template< class DomainFieldImp, int domainDim, class RangeFieldImp >
class FunctionConstant< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
  : public FunctionConstantBase< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
{
  typedef FunctionConstantBase< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >  BaseType;
public:
  typedef FunctionConstant< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >      ThisType;

  typedef typename BaseType::RangeFieldType RangeFieldType;
  typedef typename BaseType::RangeType      RangeType;

  FunctionConstant(const RangeType& constant)
    : BaseType(constant)
  {}

  static Dune::ParameterTree createSampleDescription(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["value"] = "1.0";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  } // ... createSampleDescription(...)

  static ThisType* create(const DSC::ExtendedParameterTree description)
  {
    return new ThisType(description.get< RangeFieldType >("value", RangeFieldType(0)));
  } // ... create(...)
}; // class FunctionConstant< ..., 1 >

} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTION_CONSTANT_HH
<commit_msg>[function.constant] added another constructor<commit_after>#ifndef DUNE_STUFF_FUNCTION_CONSTANT_HH
#define DUNE_STUFF_FUNCTION_CONSTANT_HH

#include <dune/stuff/common/parameter/tree.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimCols, int rangeDimRows >
class FunctionConstantBase
  : public FunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimCols, rangeDimRows >
  , public TimedependentFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimCols, rangeDimRows >
{
  typedef FunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimCols, rangeDimRows > BaseType;
public:
  typedef typename BaseType::DomainFieldType  DomainFieldType;
  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType       DomainType;
  typedef typename BaseType::RangeFieldType   RangeFieldType;
  static const unsigned int                   dimRangeCols = BaseType::dimRangeCols;
  static const unsigned int                   dimRangeRows = BaseType::dimRangeRows;
  typedef typename BaseType::RangeType        RangeType;

  FunctionConstantBase(const RangeFieldType& constant)
    : constant_(constant)
  {}

  FunctionConstantBase(const RangeType& constant)
    : constant_(constant)
  {}

  static const std::string id()
  {
    return BaseType::id() + ".constant";
  }

  virtual int order() const
  {
    return 0;
  }

  virtual std::string name() const
  {
    return "function.constant";
  }

  virtual void evaluate(const DomainType& /*arg*/, RangeType& ret) const
  {
    ret = constant_;
  }

  virtual void evaluate(const DomainType& /*arg*/, const double& /*t*/, RangeType& ret) const
  {
    ret = constant_;
  }

private:
  const RangeType constant_;
}; // class FunctionConstantBase

// forward, to allow for specialization
template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimCols, int rangeDimRows = 1 >
class FunctionConstant
{
public:
  FunctionConstant() = delete;
}; // class FunctionConstant

template< class DomainFieldImp, int domainDim, class RangeFieldImp >
class FunctionConstant< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
  : public FunctionConstantBase< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
{
  typedef FunctionConstantBase< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >  BaseType;
public:
  typedef FunctionConstant< DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >      ThisType;

  typedef typename BaseType::RangeFieldType RangeFieldType;
  typedef typename BaseType::RangeType      RangeType;

  FunctionConstant(const RangeFieldType& constant)
    : BaseType(constant)
  {}

  FunctionConstant(const RangeType& constant)
    : BaseType(constant)
  {}

  static Dune::ParameterTree createSampleDescription(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["value"] = "1.0";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  } // ... createSampleDescription(...)

  static ThisType* create(const DSC::ExtendedParameterTree description)
  {
    return new ThisType(description.get< RangeFieldType >("value", RangeFieldType(0)));
  } // ... create(...)
}; // class FunctionConstant< ..., 1 >

} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTION_CONSTANT_HH
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------*\
 *                                OpenSG                                     *
 *                                                                           *
 *                                                                           *
 *               Copyright (C) 2000-2006 by the OpenSG Forum                 *
 *                                                                           *
 *                            www.opensg.org                                 *
 *                                                                           *
 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * This library is distributed in the hope that it will be useful, but       *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#include <cstdlib>
#include <cstdio>

#include <OSGConfig.h>

#include "OSGCSMTrackball.h"
#include "OSGWindow.h"

OSG_BEGIN_NAMESPACE

// Documentation for this class is emitted in the
// OSGCSMTrackballBase.cpp file.
// To modify it, please change the .fcd file (OSGCSMTrackball.fcd) and
// regenerate the base file.

/***************************************************************************\
 *                           Class variables                               *
\***************************************************************************/

/***************************************************************************\
 *                           Class methods                                 *
\***************************************************************************/

void CSMTrackball::initMethod(InitPhase ePhase)
{
    Inherited::initMethod(ePhase);

    if(ePhase == TypeObject::SystemPost)
    {
    }
}

/***************************************************************************\
 *                           Instance methods                              *
\***************************************************************************/

/*-------------------------------------------------------------------------*\
 -  private                                                                 -
\*-------------------------------------------------------------------------*/

/*----------------------- constructors & destructors ----------------------*/

CSMTrackball::CSMTrackball(void) :
     Inherited    (  ),
    _oTrackball   (  ),
    _iLastX       (-1),
    _iLastY       (-1),
    _iMouseButtons( 0)

{
    _oTrackball.setStartPosition(0, 0, 10, true);
    _oTrackball.setTranslationScale(1.f);

    _oTrackball.setMode            (Trackball::OSGObject);
    _oTrackball.setSum             (true                );
    _oTrackball.setTranslationMode (Trackball::OSGFree  );
}

CSMTrackball::CSMTrackball(const CSMTrackball &source) :
     Inherited    (source),
    _oTrackball   (      ),
    _iLastX       (-1    ),
    _iLastY       (-1    ),
    _iMouseButtons( 0    )

{
    _oTrackball.setStartPosition(0, 0, 10, true);
    _oTrackball.setTranslationScale(1.f);

    _oTrackball.setMode            (Trackball::OSGObject);
    _oTrackball.setSum             (true                );
    _oTrackball.setTranslationMode (Trackball::OSGFree  );
}

CSMTrackball::~CSMTrackball(void)
{
}

/*----------------------------- class specific ----------------------------*/

void CSMTrackball::changed(ConstFieldMaskArg whichField,
                           UInt32            origin,
                           BitVector         details)
{
    if(0x0000 != (whichField & MouseDataFieldMask))
    {
        const MouseData &mData = _sfMouseData.getValue();

        if((0x0000 != (mData.getModifier() & _sfModifierMask.getValue())) ||
           (_sfProcessing.getValue() == true))
        {
            if(mData.getButton() != -1)
            {
                if(mData.getState() == MouseData::ButtonDown)
                {
                    switch(mData.getButton())
                    {
                        case MouseData::LeftButton :
                            break;

                        case MouseData::MiddleButton :
                            _oTrackball.setAutoPosition(true);
                            break;

                        case MouseData::RightButton :
                            _oTrackball.setAutoPositionNeg(true);
                            break;
                    }

                    _iMouseButtons |= 1 << mData.getButton();

                    editSFProcessing()->setValue(true);
                }
                else
                {
                    switch(mData.getButton())
                    {
                        case MouseData::LeftButton :
                            break;

                        case MouseData::MiddleButton :
                            _oTrackball.setAutoPosition(false);
                            break;

                        case MouseData::RightButton :
                            _oTrackball.setAutoPositionNeg(false);
                            break;
                    }

                    _iMouseButtons &= ~(1 << mData.getButton());

                    editSFProcessing()->setValue(false);
                }
            }
            else
            {
                if(_sfProcessing.getValue() == true)
                {
                    Real32 a,b,c,d;

                    if(mData.getMode() == MouseData::RelValues)
                    {
                        a = 0.f;
                        b = 0.f;

                        c = mData.getX();
                        d = mData.getY();
                    }
                    else
                    {
                        Real32 w = mData.getWindow()->getWidth ();
                        Real32 h = mData.getWindow()->getHeight();

                        Real32 x = mData.getX();
                        Real32 y = mData.getY();

                        a = -2.0 * (_iLastX / w - 0.5);
                        b = -2.0 * (0.5 - _iLastY / h);
                        c = -2.0 * (  x / w - 0.5   );
                        d = -2.0 * (0.5 - y / h     );

                        fprintf(stderr, "%f %f - %f %f\n", x, c, y, d);
                    }

                    if(_iMouseButtons & (1 << MouseData::LeftButton))
                    {
                        _oTrackball.updateRotation(a, b, c, d);
                    }
                    else if(_iMouseButtons & (1 << MouseData::MiddleButton))
                    {
                        _oTrackball.updatePosition(a, b, c, d);
                    }
                    else if(_iMouseButtons & (1 << MouseData::RightButton))
                    {
                        _oTrackball.updatePositionNeg(a, b, c, d);
                    }

                    editSFMatrixResult()->setValue(
                            _oTrackball.getFullTrackballMatrix());
                }
            }

            _iLastX = mData.getX();
            _iLastY = mData.getY();
        }
    }

    if(0x0000 != (whichField & ReferencePositionFieldMask))
    {
        _oTrackball.setStartPosition(_sfReferencePosition.getValue()[0],
                                     _sfReferencePosition.getValue()[1],
                                     _sfReferencePosition.getValue()[2],
                                      true                             );

        editSFMatrixResult()->setValue(_oTrackball.getFullTrackballMatrix());
    }

    if(0x0000 != (whichField & ReferenceMatrixFieldMask))
    {
        Matrix m;

        m.setValue(&(_sfReferenceMatrix.getValue()[0][0]));

        Quaternion so;
        Vec3f      s;
        Vec3f      trans;
        Quaternion ro;
        Vec3f      cnt;

        cnt[0] = _sfTransformCenter.getValue()[0];
        cnt[1] = _sfTransformCenter.getValue()[1];
        cnt[2] = _sfTransformCenter.getValue()[2];

        m.getTransform(trans, ro, s, so, cnt);

        _oTrackball.setStartRotation(ro, true);

        ro.invert();
        ro.multVec(trans, trans);

        _oTrackball.setStartPosition(trans[0],
                                     trans[1],
                                     trans[2],
                                     true);

        editSFMatrixResult()->setValue(_oTrackball.getFullTrackballMatrix());
    }

    if(0x0000 != (whichField & TransformCenterFieldMask))
    {
        _oTrackball.setRotationCenter(_sfTransformCenter.getValue());
    }

    if(0x0000 != (whichField & WorldDiagFieldMask))
    {
        _oTrackball.setTranslationScale(((_sfWorldDiag.getValue()[0] +
                                          _sfWorldDiag.getValue()[1] +
                                          _sfWorldDiag.getValue()[2]) / 5.f) *
                                        _sfTranslationScaleFactor.getValue());
    }

#if 0
    if(0x0000 != (whichField & ResetFieldMask))
    {
        _oTrackball.reset();

        VSC::beginEdit(this, MatrixResultFieldMask);
        {
            _sfMatrixResult.setValue(_oTrackball.getFullTrackballMatrix());
        }
        VSC::endEdit  (this, MatrixResultFieldMask);
    }
#endif

    Inherited::changed(whichField, origin, details);
}

void CSMTrackball::dump(      UInt32    ,
                         const BitVector ) const
{
    SLOG << "Dump CSMTrackball NI" << std::endl;
}

OSG_END_NAMESPACE
<commit_msg>fixed: removed noise<commit_after>/*---------------------------------------------------------------------------*\
 *                                OpenSG                                     *
 *                                                                           *
 *                                                                           *
 *               Copyright (C) 2000-2006 by the OpenSG Forum                 *
 *                                                                           *
 *                            www.opensg.org                                 *
 *                                                                           *
 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * This library is distributed in the hope that it will be useful, but       *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#include <cstdlib>
#include <cstdio>

#include <OSGConfig.h>

#include "OSGCSMTrackball.h"
#include "OSGWindow.h"

OSG_BEGIN_NAMESPACE

// Documentation for this class is emitted in the
// OSGCSMTrackballBase.cpp file.
// To modify it, please change the .fcd file (OSGCSMTrackball.fcd) and
// regenerate the base file.

/***************************************************************************\
 *                           Class variables                               *
\***************************************************************************/

/***************************************************************************\
 *                           Class methods                                 *
\***************************************************************************/

void CSMTrackball::initMethod(InitPhase ePhase)
{
    Inherited::initMethod(ePhase);

    if(ePhase == TypeObject::SystemPost)
    {
    }
}

/***************************************************************************\
 *                           Instance methods                              *
\***************************************************************************/

/*-------------------------------------------------------------------------*\
 -  private                                                                 -
\*-------------------------------------------------------------------------*/

/*----------------------- constructors & destructors ----------------------*/

CSMTrackball::CSMTrackball(void) :
     Inherited    (  ),
    _oTrackball   (  ),
    _iLastX       (-1),
    _iLastY       (-1),
    _iMouseButtons( 0)

{
    _oTrackball.setStartPosition(0, 0, 10, true);
    _oTrackball.setTranslationScale(1.f);

    _oTrackball.setMode            (Trackball::OSGObject);
    _oTrackball.setSum             (true                );
    _oTrackball.setTranslationMode (Trackball::OSGFree  );
}

CSMTrackball::CSMTrackball(const CSMTrackball &source) :
     Inherited    (source),
    _oTrackball   (      ),
    _iLastX       (-1    ),
    _iLastY       (-1    ),
    _iMouseButtons( 0    )

{
    _oTrackball.setStartPosition(0, 0, 10, true);
    _oTrackball.setTranslationScale(1.f);

    _oTrackball.setMode            (Trackball::OSGObject);
    _oTrackball.setSum             (true                );
    _oTrackball.setTranslationMode (Trackball::OSGFree  );
}

CSMTrackball::~CSMTrackball(void)
{
}

/*----------------------------- class specific ----------------------------*/

void CSMTrackball::changed(ConstFieldMaskArg whichField,
                           UInt32            origin,
                           BitVector         details)
{
    if(0x0000 != (whichField & MouseDataFieldMask))
    {
        const MouseData &mData = _sfMouseData.getValue();

        if((0x0000 != (mData.getModifier() & _sfModifierMask.getValue())) ||
           (_sfProcessing.getValue() == true))
        {
            if(mData.getButton() != -1)
            {
                if(mData.getState() == MouseData::ButtonDown)
                {
                    switch(mData.getButton())
                    {
                        case MouseData::LeftButton :
                            break;

                        case MouseData::MiddleButton :
                            _oTrackball.setAutoPosition(true);
                            break;

                        case MouseData::RightButton :
                            _oTrackball.setAutoPositionNeg(true);
                            break;
                    }

                    _iMouseButtons |= 1 << mData.getButton();

                    editSFProcessing()->setValue(true);
                }
                else
                {
                    switch(mData.getButton())
                    {
                        case MouseData::LeftButton :
                            break;

                        case MouseData::MiddleButton :
                            _oTrackball.setAutoPosition(false);
                            break;

                        case MouseData::RightButton :
                            _oTrackball.setAutoPositionNeg(false);
                            break;
                    }

                    _iMouseButtons &= ~(1 << mData.getButton());

                    editSFProcessing()->setValue(false);
                }
            }
            else
            {
                if(_sfProcessing.getValue() == true)
                {
                    Real32 a,b,c,d;

                    if(mData.getMode() == MouseData::RelValues)
                    {
                        a = 0.f;
                        b = 0.f;

                        c = mData.getX();
                        d = mData.getY();
                    }
                    else
                    {
                        Real32 w = mData.getWindow()->getWidth ();
                        Real32 h = mData.getWindow()->getHeight();

                        Real32 x = mData.getX();
                        Real32 y = mData.getY();

                        a = -2.0 * (_iLastX / w - 0.5);
                        b = -2.0 * (0.5 - _iLastY / h);
                        c = -2.0 * (  x / w - 0.5   );
                        d = -2.0 * (0.5 - y / h     );
                    }

                    if(_iMouseButtons & (1 << MouseData::LeftButton))
                    {
                        _oTrackball.updateRotation(a, b, c, d);
                    }
                    else if(_iMouseButtons & (1 << MouseData::MiddleButton))
                    {
                        _oTrackball.updatePosition(a, b, c, d);
                    }
                    else if(_iMouseButtons & (1 << MouseData::RightButton))
                    {
                        _oTrackball.updatePositionNeg(a, b, c, d);
                    }

                    editSFMatrixResult()->setValue(
                            _oTrackball.getFullTrackballMatrix());
                }
            }

            _iLastX = mData.getX();
            _iLastY = mData.getY();
        }
    }

    if(0x0000 != (whichField & ReferencePositionFieldMask))
    {
        _oTrackball.setStartPosition(_sfReferencePosition.getValue()[0],
                                     _sfReferencePosition.getValue()[1],
                                     _sfReferencePosition.getValue()[2],
                                      true                             );

        editSFMatrixResult()->setValue(_oTrackball.getFullTrackballMatrix());
    }

    if(0x0000 != (whichField & ReferenceMatrixFieldMask))
    {
        Matrix m;

        m.setValue(&(_sfReferenceMatrix.getValue()[0][0]));

        Quaternion so;
        Vec3f      s;
        Vec3f      trans;
        Quaternion ro;
        Vec3f      cnt;

        cnt[0] = _sfTransformCenter.getValue()[0];
        cnt[1] = _sfTransformCenter.getValue()[1];
        cnt[2] = _sfTransformCenter.getValue()[2];

        m.getTransform(trans, ro, s, so, cnt);

        _oTrackball.setStartRotation(ro, true);

        ro.invert();
        ro.multVec(trans, trans);

        _oTrackball.setStartPosition(trans[0],
                                     trans[1],
                                     trans[2],
                                     true);

        editSFMatrixResult()->setValue(_oTrackball.getFullTrackballMatrix());
    }

    if(0x0000 != (whichField & TransformCenterFieldMask))
    {
        _oTrackball.setRotationCenter(_sfTransformCenter.getValue());
    }

    if(0x0000 != (whichField & WorldDiagFieldMask))
    {
        _oTrackball.setTranslationScale(((_sfWorldDiag.getValue()[0] +
                                          _sfWorldDiag.getValue()[1] +
                                          _sfWorldDiag.getValue()[2]) / 5.f) *
                                        _sfTranslationScaleFactor.getValue());
    }

#if 0
    if(0x0000 != (whichField & ResetFieldMask))
    {
        _oTrackball.reset();

        VSC::beginEdit(this, MatrixResultFieldMask);
        {
            _sfMatrixResult.setValue(_oTrackball.getFullTrackballMatrix());
        }
        VSC::endEdit  (this, MatrixResultFieldMask);
    }
#endif

    Inherited::changed(whichField, origin, details);
}

void CSMTrackball::dump(      UInt32    ,
                         const BitVector ) const
{
    SLOG << "Dump CSMTrackball NI" << std::endl;
}

OSG_END_NAMESPACE
<|endoftext|>


<commit_before>/*!
 * \file SU2_SOL.cpp
 * \brief Main file for the solution export/conversion code (SU2_SOL).
 * \author Aerospace Design Laboratory (Stanford University) <http://su2.stanford.edu>.
 * \version 3.0.0 "eagle"
 *
 * SU2, Copyright (C) 2012-2014 Aerospace Design Laboratory (ADL).
 *
 * SU2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * SU2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
 */

#include "../include/SU2_SOL.hpp"

using namespace std;

int main(int argc, char *argv[]) {
	/*--- Variable definitions ---*/
	unsigned short iZone, nZone;
	unsigned long iExtIter, nExtIter;
	ofstream ConvHist_file;
	char file_name[200];
	int rank = MASTER_NODE;
  int size = SINGLE_NODE;

#ifndef NO_MPI
	/*--- MPI initialization, and buffer setting ---*/
#ifdef WINDOWS
	MPI_Init(&argc,&argv);
	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
	MPI_Comm_size(MPI_COMM_WORLD,&size);
#else
	MPI::Init(argc, argv);
	rank = MPI::COMM_WORLD.Get_rank();
	size = MPI::COMM_WORLD.Get_size();
#endif
#endif

	/*--- Pointer to different structures that will be used throughout the entire code ---*/
	COutput *output = NULL;
	CGeometry **geometry = NULL;
	CSolver **solver = NULL;
	CConfig **config = NULL;

	/*--- Definition of the containers per zones ---*/
	solver = new CSolver*[MAX_ZONES];
	config = new CConfig*[MAX_ZONES];
	geometry = new CGeometry *[MAX_ZONES];

	/*--- Only one zone is allowed ---*/
	nZone = 1;

	for (iZone = 0; iZone < nZone; iZone++) {

		/*--- Definition of the configuration class per zones ---*/
		if (argc == 2) config[iZone] = new CConfig(argv[1], SU2_SOL, iZone, nZone, 0, VERB_HIGH);
		else { strcpy (file_name, "default.cfg"); config[iZone] = new CConfig(file_name, SU2_SOL,
                                                                          iZone, nZone, 0, VERB_HIGH); }

#ifndef NO_MPI
		/*--- Change the name of the input-output files for a parallel computation ---*/
		config[iZone]->SetFileNameDomain(rank+1);
#endif

		/*--- Definition of the geometry class and open the mesh file ---*/
		geometry[iZone] = new CPhysicalGeometry(config[iZone], iZone+1, nZone);

    /*--- Create the vertex structure (required for MPI) ---*/
    if (rank == MASTER_NODE) cout << "Identify vertices." <<endl;
    geometry[iZone]->SetVertex(config[iZone]);

    /*--- Perform the non-dimensionalization for the flow equations using the
     specified reference values. ---*/

		config[iZone]->SetNondimensionalization(geometry[iZone]->GetnDim(), iZone);

  }

#ifndef NO_MPI
  /*--- Synchronization point after the geometrical definition subroutine ---*/
#ifdef WINDOWS
	MPI_Barrier(MPI_COMM_WORLD);
#else
	MPI::COMM_WORLD.Barrier();
#endif
#endif

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solution Postprocessing -----------------------" << endl;

#ifndef NO_MPI
  /*--- Synchronization point after the solution subroutine ---*/
#ifdef WINDOWS
	MPI_Barrier(MPI_COMM_WORLD);
#else
	MPI::COMM_WORLD.Barrier();
#endif
#endif

	/*--- Definition of the output class (one for all the zones) ---*/
	output = new COutput();

  /*---  Check whether this is an unsteady simulation, and call the
   solution merging routines accordingly.---*/

  if (config[ZONE_0]->GetWrt_Unsteady()) {

    /*--- Unsteady simulation: merge all unsteady time steps. First,
     find the frequency and total number of files to write. ---*/

    double Physical_dt, Physical_t;
    unsigned long iExtIter = 0;
    bool StopCalc = false;

    /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
    if (config[ZONE_0]->GetWrt_Unsteady() && config[ZONE_0]->GetRestart())
      iExtIter = config[ZONE_0]->GetUnst_RestartIter();

    while (iExtIter < config[ZONE_0]->GetnExtIter()) {

      /*--- Check several conditions in order to merge the correct time step files. ---*/
      Physical_dt = config[ZONE_0]->GetDelta_UnstTime();
      Physical_t  = (iExtIter+1)*Physical_dt;
      if (Physical_t >=  config[ZONE_0]->GetTotal_UnstTime())
        StopCalc = true;

      if ((iExtIter+1 == config[ZONE_0]->GetnExtIter()) ||
          ((iExtIter % config[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
           !((config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
             (config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
          (StopCalc) ||
          (((config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
            (config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
           ((iExtIter == 0) || (iExtIter % config[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {

        /*--- Set the current iteration number in the config class. ---*/
        config[ZONE_0]->SetExtIter(iExtIter);

        /*--- Read in the restart file for this time step ---*/
        for (iZone = 0; iZone < nZone; iZone++) {

          /*--- Either instantiate the solution class or load a restart file. ---*/
          if (iExtIter == 0 || (config[ZONE_0]->GetRestart() && iExtIter == config[ZONE_0]->GetUnst_RestartIter()))
            solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], MESH_0);
          else
            solver[iZone]->LoadRestart(geometry, &solver, config[iZone], int(MESH_0));
        }

            if (rank == MASTER_NODE)
          cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
        output->SetBaselineResult_Files(solver, geometry, config, iExtIter, nZone);
      }

      iExtIter++;
      if (StopCalc) break;
    }

  } else if (config[ZONE_0]->GetUnsteady_Simulation() == TIME_SPECTRAL) {

	  /*--- Time-spectral simulation: merge files for each time instance (each zone). ---*/
	  unsigned short nTimeSpectral = config[ZONE_0]->GetnTimeInstances();
	  unsigned short iTimeSpectral;
	  for (iTimeSpectral = 0; iTimeSpectral < nTimeSpectral; iTimeSpectral++) {

		  /*--- Set the current instance number in the config class to "ExtIter." ---*/
		  config[ZONE_0]->SetExtIter(iTimeSpectral);

		  /*--- Read in the restart file for this time step ---*/
		  /*--- N.B. In SU2_SOL, nZone != nTimeInstances ---*/
		  for (iZone = 0; iZone < nZone; iZone++) {

			  /*--- Either instantiate the solution class or load a restart file. ---*/
			  if (iTimeSpectral == 0)
				  solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], MESH_0);
			  else
				  solver[iZone]->LoadRestart(geometry, &solver, config[iZone], int(MESH_0));
		  }

		  /*--- Print progress in solution writing to the screen. ---*/
		  if (rank == MASTER_NODE) {
			  cout << "Writing the volume solution for time instance " << iTimeSpectral << "." << endl;
		  }

		  output->SetBaselineResult_Files(solver, geometry, config, iTimeSpectral, nZone);
	  }
  } else {

	  /*--- Steady simulation: merge the single solution file. ---*/

	  for (iZone = 0; iZone < nZone; iZone++) {
		  /*--- Definition of the solution class ---*/
		  solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], MESH_0);
	  }

	  output->SetBaselineResult_Files(solver, geometry, config, 0, nZone);

  }

#ifndef NO_MPI
  /*--- Finalize MPI parallelization ---*/
#ifdef WINDOWS
  MPI_Finalize();
#else
  MPI::Finalize();
#endif
#endif

  /*--- End solver ---*/
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_SOL) ------------------------" << endl << endl;

  return EXIT_SUCCESS;
}
<commit_msg>Fixed SU2_SOL so that for unsteady restarts it doesn't require you to write a solution at every iteration<commit_after>/*!
 * \file SU2_SOL.cpp
 * \brief Main file for the solution export/conversion code (SU2_SOL).
 * \author Aerospace Design Laboratory (Stanford University) <http://su2.stanford.edu>.
 * \version 3.0.0 "eagle"
 *
 * SU2, Copyright (C) 2012-2014 Aerospace Design Laboratory (ADL).
 *
 * SU2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * SU2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
 */

#include "../include/SU2_SOL.hpp"

using namespace std;

int main(int argc, char *argv[]) {
	/*--- Variable definitions ---*/
	unsigned short iZone, nZone;
	ofstream ConvHist_file;
	char file_name[200];
	int rank = MASTER_NODE;
  int size = SINGLE_NODE;

#ifndef NO_MPI
	/*--- MPI initialization, and buffer setting ---*/
#ifdef WINDOWS
	MPI_Init(&argc,&argv);
	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
	MPI_Comm_size(MPI_COMM_WORLD,&size);
#else
	MPI::Init(argc, argv);
	rank = MPI::COMM_WORLD.Get_rank();
	size = MPI::COMM_WORLD.Get_size();
#endif
#endif

	/*--- Pointer to different structures that will be used throughout the entire code ---*/
	COutput *output = NULL;
	CGeometry **geometry = NULL;
	CSolver **solver = NULL;
	CConfig **config = NULL;

	/*--- Definition of the containers per zones ---*/
	solver = new CSolver*[MAX_ZONES];
	config = new CConfig*[MAX_ZONES];
	geometry = new CGeometry *[MAX_ZONES];

	/*--- Only one zone is allowed ---*/
	nZone = 1;

	for (iZone = 0; iZone < nZone; iZone++) {

		/*--- Definition of the configuration class per zones ---*/
		if (argc == 2) config[iZone] = new CConfig(argv[1], SU2_SOL, iZone, nZone, 0, VERB_HIGH);
		else { strcpy (file_name, "default.cfg"); config[iZone] = new CConfig(file_name, SU2_SOL,
                                                                          iZone, nZone, 0, VERB_HIGH); }

#ifndef NO_MPI
		/*--- Change the name of the input-output files for a parallel computation ---*/
		config[iZone]->SetFileNameDomain(rank+1);
#endif

		/*--- Definition of the geometry class and open the mesh file ---*/
		geometry[iZone] = new CPhysicalGeometry(config[iZone], iZone+1, nZone);

    /*--- Create the vertex structure (required for MPI) ---*/
    if (rank == MASTER_NODE) cout << "Identify vertices." <<endl;
    geometry[iZone]->SetVertex(config[iZone]);

    /*--- Perform the non-dimensionalization for the flow equations using the
     specified reference values. ---*/

		config[iZone]->SetNondimensionalization(geometry[iZone]->GetnDim(), iZone);

  }

#ifndef NO_MPI
  /*--- Synchronization point after the geometrical definition subroutine ---*/
#ifdef WINDOWS
	MPI_Barrier(MPI_COMM_WORLD);
#else
	MPI::COMM_WORLD.Barrier();
#endif
#endif

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solution Postprocessing -----------------------" << endl;

#ifndef NO_MPI
  /*--- Synchronization point after the solution subroutine ---*/
#ifdef WINDOWS
	MPI_Barrier(MPI_COMM_WORLD);
#else
	MPI::COMM_WORLD.Barrier();
#endif
#endif

	/*--- Definition of the output class (one for all the zones) ---*/
	output = new COutput();

  /*---  Check whether this is an unsteady simulation, and call the
   solution merging routines accordingly.---*/

  if (config[ZONE_0]->GetWrt_Unsteady()) {

    /*--- Unsteady simulation: merge all unsteady time steps. First,
     find the frequency and total number of files to write. ---*/

    double Physical_dt, Physical_t;
    unsigned long iExtIter = 0;
    bool StopCalc = false;
    bool SolutionInstantiated = false;

    /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
    if (config[ZONE_0]->GetWrt_Unsteady() && config[ZONE_0]->GetRestart())
      iExtIter = config[ZONE_0]->GetUnst_RestartIter();

    while (iExtIter < config[ZONE_0]->GetnExtIter()) {

      /*--- Check several conditions in order to merge the correct time step files. ---*/
      Physical_dt = config[ZONE_0]->GetDelta_UnstTime();
      Physical_t  = (iExtIter+1)*Physical_dt;
      if (Physical_t >=  config[ZONE_0]->GetTotal_UnstTime())
        StopCalc = true;

      if ((iExtIter+1 == config[ZONE_0]->GetnExtIter()) ||
          ((iExtIter % config[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
           !((config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
             (config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
          (StopCalc) ||
          (((config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
            (config[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
           ((iExtIter == 0) || (iExtIter % config[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {

        /*--- Set the current iteration number in the config class. ---*/
        config[ZONE_0]->SetExtIter(iExtIter);

        /*--- Read in the restart file for this time step ---*/
        for (iZone = 0; iZone < nZone; iZone++) {

          /*--- Either instantiate the solution class or load a restart file. ---*/
          if (SolutionInstantiated == false && (iExtIter == 0 ||
              (config[ZONE_0]->GetRestart() && (iExtIter == config[ZONE_0]->GetUnst_RestartIter() ||
                                                iExtIter % config[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                                                iExtIter+1 == config[ZONE_0]->GetnExtIter())))) {
            solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], MESH_0);
            SolutionInstantiated = true;
          }
          else
            solver[iZone]->LoadRestart(geometry, &solver, config[iZone], int(MESH_0));
        }

            if (rank == MASTER_NODE)
          cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
        output->SetBaselineResult_Files(solver, geometry, config, iExtIter, nZone);
      }

      iExtIter++;
      if (StopCalc) break;
    }

  } else if (config[ZONE_0]->GetUnsteady_Simulation() == TIME_SPECTRAL) {

	  /*--- Time-spectral simulation: merge files for each time instance (each zone). ---*/
	  unsigned short nTimeSpectral = config[ZONE_0]->GetnTimeInstances();
	  unsigned short iTimeSpectral;
	  for (iTimeSpectral = 0; iTimeSpectral < nTimeSpectral; iTimeSpectral++) {

		  /*--- Set the current instance number in the config class to "ExtIter." ---*/
		  config[ZONE_0]->SetExtIter(iTimeSpectral);

		  /*--- Read in the restart file for this time step ---*/
		  /*--- N.B. In SU2_SOL, nZone != nTimeInstances ---*/
		  for (iZone = 0; iZone < nZone; iZone++) {

			  /*--- Either instantiate the solution class or load a restart file. ---*/
			  if (iTimeSpectral == 0)
				  solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], MESH_0);
			  else
				  solver[iZone]->LoadRestart(geometry, &solver, config[iZone], int(MESH_0));
		  }

		  /*--- Print progress in solution writing to the screen. ---*/
		  if (rank == MASTER_NODE) {
			  cout << "Writing the volume solution for time instance " << iTimeSpectral << "." << endl;
		  }

		  output->SetBaselineResult_Files(solver, geometry, config, iTimeSpectral, nZone);
	  }
  } else {

	  /*--- Steady simulation: merge the single solution file. ---*/

	  for (iZone = 0; iZone < nZone; iZone++) {
		  /*--- Definition of the solution class ---*/
		  solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], MESH_0);
	  }

	  output->SetBaselineResult_Files(solver, geometry, config, 0, nZone);

  }

#ifndef NO_MPI
  /*--- Finalize MPI parallelization ---*/
#ifdef WINDOWS
  MPI_Finalize();
#else
  MPI::Finalize();
#endif
#endif

  /*--- End solver ---*/
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_SOL) ------------------------" << endl << endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "graph.hpp"
#include <stack>
#include <queue>
#include <algorithm>

#define N 32

using namespace std;

shared_ptr<Vertex> Graph::getVertex(std::string name) const {
  auto it = this->vertices.begin();
  for (; it != this->vertices.end(); it++) {
    if ((*it)->getName() == name) break;
  }
  return (it != this->vertices.end()) ? *it : nullptr;

}

Graph::Graph(vector<tuple<string, int>> vertices,
	     vector<tuple<string, string, int>> edges,
	     bool directed=false) {

  this->directed = directed; 	// Is the graph directed?

  // Build the vertices
  for (auto it = vertices.begin(); it != vertices.end(); it++)
    this->vertices.push_back(make_shared<Vertex>(get<1>(*it), get<0>(*it)));

  for (auto it = edges.begin(); it != edges.end(); it++)
    this->edges.push_back(make_shared<Edge>(get<2>(*it),
				       Graph::getVertex(get<0>(*it)),
				       Graph::getVertex(get<1>(*it))));
  // Now make the adjacency list for the vertices
  for (auto it = this->vertices.begin(); it != this->vertices.end(); it++) {
    vector<shared_ptr<Edge>> ie;
    for (auto eit = this->edges.begin(); eit != this->edges.end(); eit++) {
      if ((*it)->getName() == (*eit)->second()->getName()
	  || (*it)->getName() == (*eit)->first()->getName())
	ie.push_back(*eit);
    }
    (*it)->setIEdges(ie);
  }
}

shared_ptr<Vertex> Edge::opposite(string v) {
  if (v == this->first()->getName())
    return this->second();
  else return this->first();
}

vector<shared_ptr<Vertex>> Vertex::neighbors() {
  vector<shared_ptr<Vertex>> ret;
  for (auto it = this->incidentEdges.begin(); it != this->incidentEdges.end(); it++) {
    ret.push_back((*it)->opposite(this->getName()));
  }
  return ret;
}

void print(shared_ptr<Vertex> v) {
  cout << " name: " << v->getName() << endl;
}

// DFS for the graph with a function.
template<typename F>
static void doDFS(Graph g, shared_ptr<Vertex> start, F fun) {
  stack<shared_ptr<Vertex>> s;
  s.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> n = s.top();
      // Print the name of the node
      fun(n); // XXX: Look this is a lambda (functor in C++ parlance)
	      // from the argument.
      s.pop(); 			// Very bad stack interface of C++!
      n->setVisited(true);
      vector<shared_ptr<Vertex>> vns = n->neighbors();
      for (auto it = vns.begin(); it != vns.end(); it++) {
	if (!(*it)->getVisited()) {
	  s.push(*it);
	  (*it)->setVisited(true);
	}
      }
    } while (!s.empty());

  g.resetVisited();
}

// Topological sort in a directed graph
template<void (*fun)(shared_ptr<Vertex>)>
static void topological_sort(Graph g) {
  if (!g.getDirected()) return;

  // First make the degree for the vertex.
  queue<shared_ptr<Vertex>> start_vertices;
  vector<shared_ptr<Vertex>> mvertices = g.getVertices();
  for (auto it = mvertices.begin(); it != mvertices.end(); ++it) {
    vector<shared_ptr<Edge>> ves = (*it)->getIEdges();
    for (auto eit = ves.begin(); eit != ves.end(); ++eit) {
      // Increment your degree if you are the second in the incident-edge
      if ((*eit)->second()->getName() == (*it)->getName())
	(*it)->degree += 1;
    }
    if ((*it)->degree == 0) start_vertices.push(g.getVertex((*it)->getName()));
  }
  // Now we can start going through and doing the actual topological sort.
  do
    {
      // Process vertices
      shared_ptr<Vertex> el = start_vertices.front();
      start_vertices.pop(); 	// C++'s horrible API!
      fun(el); // XXX: Look this is a function pointer from the
	       // template argument.

      // Get all its neighbors and if their degree is 0, then push
      // them onto the queue.
      vector<shared_ptr<Vertex>> eln = el->neighbors();
      for (auto it = eln.begin(); it != eln.end(); ++it) {
	(*it)->degree -= 1;
	if ((*it)->degree == 0) start_vertices.push(*it);
      }
    } while (!start_vertices.empty());

}

vector<shared_ptr<Vertex>> mst (shared_ptr<Vertex> p, vector<shared_ptr<Vertex>> gvs) {
  vector<shared_ptr<Vertex>> ret;
  // XXX: Don't forget to remove the parent from the gvs
  auto it = gvs.begin();
  vector<decltype(it)> vits;
  for (; it != gvs.end(); ++it){
    if ((*it)->dist.second->getName() == p->getName()) {
      vits.push_back(it);
      ret.push_back(*it);
    }
  }

  // Now delete the indices from gvs.
  for (auto it = vits.begin(); it != vits.end(); ++it)
    gvs.erase(*it);

  return ret;
}

// XXX: shortest path and MST together
vector<shared_ptr<Vertex>> sp_mst(Graph g, shared_ptr<Vertex> start) {
  // We need to use a priority queue.

  // Declare a pq with a comparator.
  auto comp = [](const shared_ptr<Vertex> e1,
		 const shared_ptr<Vertex> e2){
    return e1->dist.first > e2->dist.first;
  };
  priority_queue<shared_ptr<Vertex>,
		 vector<shared_ptr<Vertex>>,
		 decltype(comp)> pq(comp);
  pq.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> me = pq.top();
      vector<shared_ptr<Edge>> ie = me->getIEdges();
      pq.pop(); 		// remove the top from the pq.
      // Expand the distance for each neighbor.
      for(shared_ptr<Edge> x : ie) {
	shared_ptr<Vertex> men = x->opposite(me->getName());
	unsigned xw = x->getWeight();
	if (!men->getVisited() && men->dist.first > me->dist.first + xw) {
	  men->dist.first = me->dist.first+xw;
	  men->dist.second = me;
	  pq.push(men); 	// FIXME: can add same vertex again!
	}
      }
      me->setVisited(true);
    } while (!pq.empty());

  // Build the minimum spanning tree
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Vertex>> q;
  q.push_back (start);

  // remove start from gvs.
  auto it = gvs.begin();
  for ( ; it != gvs.end(); ++it)
    if ((*it) == start) break;
  // remove it from gvs.
  gvs.erase(it);

  unsigned counter = 0;
  for (; counter < q.size(); ++counter) {
    auto nn = mst(q[counter], gvs);
    for (auto x: nn)
      q.push_back(x);
  }
  return q;

}

// XXX: Independent sets (dual of cliques).
vector<shared_ptr<Vertex>> independent_sets (Graph g){
  vector<shared_ptr<Vertex>> ret {};
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Edge>> ges = g.getEdges();
  unsigned pcount = 0;
  for (unsigned i = (2 << (gvs.size() - 1))-1; i >=1 ; --i) {
    bitset<N> bb(i);  		// FIXME: This is very annoying in C++
    vector<shared_ptr<Vertex>> fe;
    // Now just get the length of bits that we need.
    bool possibly_return = true;
    unsigned ccount = 0;
    for (int j = gvs.size()-1; j >= 0; --j)
      if (j) {
	++ccount;
	// Now get the edge's opposite and check.
	for (auto it = ges.begin(); it != ges.end(); ++it) {
	  if ((*it)->first()->getName() == gvs[j]->getName()
	      || (*it)->second()->getName() == gvs[j]->getName()) {
	    if (find(gvs.begin(), gvs.end(),
		     (*it)->opposite(gvs[j]->getName())) == gvs.end()) {
	      possibly_return = false;
	      break;
	    }
	  }
	}
	fe.push_back(gvs[j]);
      }
    // Now check for intersection.
    if(possibly_return && ccount > pcount)
      ret = fe;
  }
  return ret;
}

int main(void)
{
  // Test program.
  vector<tuple<string, int>> vertices = {make_tuple("a", 1), make_tuple("b", 2),
					 make_tuple("c", 3), make_tuple("d", 4)};
  vector<tuple<string, string, int>> edges = {make_tuple("a", "b", 5), make_tuple("a", "c", 1),
					      make_tuple("a", "d", 4), make_tuple("c", "d", 2),
					      make_tuple("d", "b", 3)};

  // This is the graph.
  Graph g(vertices, edges, false);
  vector<shared_ptr<Vertex>> mv = g.getVertices();

  // Print the graph using dfs and a std::copy_backward(std::begin(container), std::end(container), std::end(container));

  cout  << "DFS" << endl;
  // Here lambda is most likely also inlined.
  doDFS(g, g.getVertex("a"), [](shared_ptr<Vertex> x) -> void {cout << x->getName() << endl;});

  // make the graph directed.
  g.setDirected(true);

  // Do topological sort.
  cout  << "Topological sort" << endl;
  // Here print should be inlined -- passing print as a function pointer
  // at compile time as a template argument.
  topological_sort<print>(g);

  // Dijkstra's shortest path and minimum spanning tree together
  vector<shared_ptr<Vertex>> tree = sp_mst(g, g.getVertex("a"));
  cout << "Done mst" << "\n";

  // Print the tree
  for (auto x : tree)
    cout << x->getName() << " ";
  cout << "\n";

  // Independent sets
  independent_sets(g);

  return 0;
}
<commit_msg>Something wrong in the result of independent algorithm, needs to be fixed.<commit_after>#include "graph.hpp"
#include <stack>
#include <queue>
#include <algorithm>

#define N 32

using namespace std;

shared_ptr<Vertex> Graph::getVertex(std::string name) const {
  auto it = this->vertices.begin();
  for (; it != this->vertices.end(); it++) {
    if ((*it)->getName() == name) break;
  }
  return (it != this->vertices.end()) ? *it : nullptr;

}

Graph::Graph(vector<tuple<string, int>> vertices,
	     vector<tuple<string, string, int>> edges,
	     bool directed=false) {

  this->directed = directed; 	// Is the graph directed?

  // Build the vertices
  for (auto it = vertices.begin(); it != vertices.end(); it++)
    this->vertices.push_back(make_shared<Vertex>(get<1>(*it), get<0>(*it)));

  for (auto it = edges.begin(); it != edges.end(); it++)
    this->edges.push_back(make_shared<Edge>(get<2>(*it),
				       Graph::getVertex(get<0>(*it)),
				       Graph::getVertex(get<1>(*it))));
  // Now make the adjacency list for the vertices
  for (auto it = this->vertices.begin(); it != this->vertices.end(); it++) {
    vector<shared_ptr<Edge>> ie;
    for (auto eit = this->edges.begin(); eit != this->edges.end(); eit++) {
      if ((*it)->getName() == (*eit)->second()->getName()
	  || (*it)->getName() == (*eit)->first()->getName())
	ie.push_back(*eit);
    }
    (*it)->setIEdges(ie);
  }
}

shared_ptr<Vertex> Edge::opposite(string v) {
  if (v == this->first()->getName())
    return this->second();
  else return this->first();
}

vector<shared_ptr<Vertex>> Vertex::neighbors() {
  vector<shared_ptr<Vertex>> ret;
  for (auto it = this->incidentEdges.begin(); it != this->incidentEdges.end(); it++) {
    ret.push_back((*it)->opposite(this->getName()));
  }
  return ret;
}

void print(shared_ptr<Vertex> v) {
  cout << " name: " << v->getName() << endl;
}

// DFS for the graph with a function.
template<typename F>
static void doDFS(Graph g, shared_ptr<Vertex> start, F fun) {
  stack<shared_ptr<Vertex>> s;
  s.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> n = s.top();
      // Print the name of the node
      fun(n); // XXX: Look this is a lambda (functor in C++ parlance)
	      // from the argument.
      s.pop(); 			// Very bad stack interface of C++!
      n->setVisited(true);
      vector<shared_ptr<Vertex>> vns = n->neighbors();
      for (auto it = vns.begin(); it != vns.end(); it++) {
	if (!(*it)->getVisited()) {
	  s.push(*it);
	  (*it)->setVisited(true);
	}
      }
    } while (!s.empty());

  g.resetVisited();
}

// Topological sort in a directed graph
template<void (*fun)(shared_ptr<Vertex>)>
static void topological_sort(Graph g) {
  if (!g.getDirected()) return;

  // First make the degree for the vertex.
  queue<shared_ptr<Vertex>> start_vertices;
  vector<shared_ptr<Vertex>> mvertices = g.getVertices();
  for (auto it = mvertices.begin(); it != mvertices.end(); ++it) {
    vector<shared_ptr<Edge>> ves = (*it)->getIEdges();
    for (auto eit = ves.begin(); eit != ves.end(); ++eit) {
      // Increment your degree if you are the second in the incident-edge
      if ((*eit)->second()->getName() == (*it)->getName())
	(*it)->degree += 1;
    }
    if ((*it)->degree == 0) start_vertices.push(g.getVertex((*it)->getName()));
  }
  // Now we can start going through and doing the actual topological sort.
  do
    {
      // Process vertices
      shared_ptr<Vertex> el = start_vertices.front();
      start_vertices.pop(); 	// C++'s horrible API!
      fun(el); // XXX: Look this is a function pointer from the
	       // template argument.

      // Get all its neighbors and if their degree is 0, then push
      // them onto the queue.
      vector<shared_ptr<Vertex>> eln = el->neighbors();
      for (auto it = eln.begin(); it != eln.end(); ++it) {
	(*it)->degree -= 1;
	if ((*it)->degree == 0) start_vertices.push(*it);
      }
    } while (!start_vertices.empty());

}

vector<shared_ptr<Vertex>> mst (shared_ptr<Vertex> p, vector<shared_ptr<Vertex>> gvs) {
  vector<shared_ptr<Vertex>> ret;
  // XXX: Don't forget to remove the parent from the gvs
  auto it = gvs.begin();
  vector<decltype(it)> vits;
  for (; it != gvs.end(); ++it){
    if ((*it)->dist.second->getName() == p->getName()) {
      vits.push_back(it);
      ret.push_back(*it);
    }
  }

  // Now delete the indices from gvs.
  for (auto it = vits.begin(); it != vits.end(); ++it)
    gvs.erase(*it);

  return ret;
}

// XXX: shortest path and MST together
vector<shared_ptr<Vertex>> sp_mst(Graph g, shared_ptr<Vertex> start) {
  // We need to use a priority queue.
  start->dist.first = 0;

  // Declare a pq with a comparator.
  auto comp = [](const shared_ptr<Vertex> e1,
		 const shared_ptr<Vertex> e2){
    return e1->dist.first > e2->dist.first;
  };
  priority_queue<shared_ptr<Vertex>,
		 vector<shared_ptr<Vertex>>,
		 decltype(comp)> pq(comp);
  pq.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> me = pq.top();
      vector<shared_ptr<Edge>> ie = me->getIEdges();
      pq.pop(); 		// remove the top from the pq.
      // Expand the distance for each neighbor.
      for(shared_ptr<Edge> x : ie) {
	shared_ptr<Vertex> men = x->opposite(me->getName());
	unsigned xw = x->getWeight();
	if (!men->getVisited() && men->dist.first > me->dist.first + xw) {
	  men->dist.first = me->dist.first+xw;
	  men->dist.second = me;
	  pq.push(men); 	// FIXME: can add same vertex again!
	}
      }
      me->setVisited(true);
    } while (!pq.empty());

  // Build the minimum spanning tree
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Vertex>> q;
  q.push_back (start);

  // remove start from gvs.
  auto it = gvs.begin();
  for ( ; it != gvs.end(); ++it)
    if ((*it) == start) break;
  // remove it from gvs.
  gvs.erase(it);

  unsigned counter = 0;
  for (; counter < q.size(); ++counter) {
    auto nn = mst(q[counter], gvs);
    for (auto x: nn)
      q.push_back(x);
  }
  return q;

}

// XXX: Independent sets (dual of cliques).
vector<shared_ptr<Vertex>> independent_sets (Graph g){
  vector<shared_ptr<Vertex>> ret {};
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Edge>> ges = g.getEdges();
  unsigned pcount = 0;
  for (unsigned i = (2 << (gvs.size() - 1))-1; i >=1 ; --i) {
    bitset<N> bb(i);  		// FIXME: This is very annoying in C++
    vector<shared_ptr<Vertex>> fe;
    // Now just get the length of bits that we need.
    bool possibly_return = true;
    unsigned ccount = 0;
    for (int j = gvs.size()-1; j >= 0; --j)
      if (j) {
	++ccount;
	// Now get the edge's opposite and check.
	for (auto it = ges.begin(); it != ges.end(); ++it) {
	  if ((*it)->first()->getName() == gvs[j]->getName()
	      || (*it)->second()->getName() == gvs[j]->getName()) {
	    if (find(gvs.begin(), gvs.end(),
		     (*it)->opposite(gvs[j]->getName())) == gvs.end()) {
	      possibly_return = false;
	      break;
	    }
	  }
	}
	fe.push_back(gvs[j]);
      }
    // Now check for intersection.
	if(possibly_return && ccount > pcount) {
		ret = fe;
		pcount = ccount;
	}
  }
  return ret;
}

int main(void)
{
  // Test program.
  vector<tuple<string, int>> vertices = {make_tuple("a", 1), make_tuple("b", 2),
					 make_tuple("c", 3), make_tuple("d", 4)};
  vector<tuple<string, string, int>> edges = {make_tuple("a", "b", 5), make_tuple("a", "c", 1),
					      make_tuple("a", "d", 4), make_tuple("c", "d", 2),
					      make_tuple("d", "b", 3)};

  // This is the graph.
  Graph g(vertices, edges, false);
  vector<shared_ptr<Vertex>> mv = g.getVertices();

  // Print the graph using dfs and a std::copy_backward(std::begin(container), std::end(container), std::end(container));

  cout  << "DFS" << endl;
  // Here lambda is most likely also inlined.
  doDFS(g, g.getVertex("a"), [](shared_ptr<Vertex> x) -> void {cout << x->getName() << endl;});

  // make the graph directed.
  g.setDirected(true);

  // Do topological sort.
  cout  << "Topological sort" << endl;
  // Here print should be inlined -- passing print as a function pointer
  // at compile time as a template argument.
  topological_sort<print>(g);

  // Dijkstra's shortest path and minimum spanning tree together
  vector<shared_ptr<Vertex>> tree = sp_mst(g, g.getVertex("a"));
  cout << "Done mst" << "\n";

  // Print the tree
  for (auto x : tree)
    cout << x->getName() << " ";
  cout << "\n";

  // Independent sets
  vector<shared_ptr<Vertex>> s = independent_sets(g);
  for (auto x: s)
    cout << x->getName() << " ";
  cout << "\n";

  return 0;
}
<|endoftext|>