<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "ansiescapecodehandler.h"
#include "outputformatter.h"
#include "theme/theme.h"

#include <QPlainTextEdit>
#include <QTextCursor>

namespace Utils {

namespace Internal {

class OutputFormatterPrivate
{
public:
    OutputFormatterPrivate()
        : plainTextEdit(0)
        , formats(0)
        , escapeCodeHandler(new AnsiEscapeCodeHandler)
        , overwriteOutput(false)
    {
    }

    ~OutputFormatterPrivate()
    {
        delete[] formats;
        delete escapeCodeHandler;
    }

    QPlainTextEdit *plainTextEdit;
    QTextCharFormat *formats;
    QFont font;
    QTextCursor cursor;
    AnsiEscapeCodeHandler *escapeCodeHandler;
    bool overwriteOutput;
};

} // namespace Internal

OutputFormatter::OutputFormatter()
    : d(new Internal::OutputFormatterPrivate)
{
}

OutputFormatter::~OutputFormatter()
{
    delete d;
}

QPlainTextEdit *OutputFormatter::plainTextEdit() const
{
    return d->plainTextEdit;
}

void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
{
    d->plainTextEdit = plainText;
    d->cursor = plainText ? plainText->textCursor() : QTextCursor();
    initFormats();
}

void OutputFormatter::appendMessage(const QString &text, OutputFormat format)
{
    appendMessage(text, d->formats[format]);
}

void OutputFormatter::appendMessage(const QString &text, const QTextCharFormat &format)
{
    if (!d->cursor.atEnd())
        d->cursor.movePosition(QTextCursor::End);

    foreach (const FormattedText &output, parseAnsi(text, format)) {
        int startPos = 0;
        int crPos = -1;
        while ((crPos = output.text.indexOf(QLatin1Char('\r'), startPos)) >= 0)  {
            append(d->cursor, output.text.mid(startPos, crPos - startPos), output.format);
            startPos = crPos + 1;
            d->overwriteOutput = true;
        }
        if (startPos < output.text.count())
            append(d->cursor, output.text.mid(startPos), output.format);
    }
}

QTextCharFormat OutputFormatter::charFormat(OutputFormat format) const
{
    return d->formats[format];
}

QList<FormattedText> OutputFormatter::parseAnsi(const QString &text, const QTextCharFormat &format)
{
    return d->escapeCodeHandler->parseText(FormattedText(text, format));
}

void OutputFormatter::append(QTextCursor &cursor, const QString &text,
                             const QTextCharFormat &format)
{
    if (d->overwriteOutput) {
        cursor.clearSelection();
        cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
        d->overwriteOutput = false;
    }
    cursor.insertText(text, format);
}

void OutputFormatter::clearLastLine()
{
    if (!d->cursor.atEnd())
        d->cursor.movePosition(QTextCursor::End);
    d->cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
    d->cursor.removeSelectedText();
}

void OutputFormatter::initFormats()
{
    if (!plainTextEdit())
        return;

    QFont boldFont = d->font;
    boldFont.setBold(true);

    d->formats = new QTextCharFormat[NumberOfFormats];

    Theme *theme = creatorTheme();

    // NormalMessageFormat
    d->formats[NormalMessageFormat].setFont(boldFont);
    d->formats[NormalMessageFormat].setForeground(theme->color(Theme::OutputFormatter_NormalMessageTextColor));

    // ErrorMessageFormat
    d->formats[ErrorMessageFormat].setFont(boldFont);
    d->formats[ErrorMessageFormat].setForeground(theme->color(Theme::OutputFormatter_ErrorMessageTextColor));

    // StdOutFormat
    d->formats[StdOutFormat].setFont(d->font);
    d->formats[StdOutFormat].setForeground(theme->color(Theme::OutputFormatter_StdOutTextColor));
    d->formats[StdOutFormatSameLine] = d->formats[StdOutFormat];

    // StdErrFormat
    d->formats[StdErrFormat].setFont(d->font);
    d->formats[StdErrFormat].setForeground(theme->color(Theme::OutputFormatter_StdErrTextColor));
    d->formats[StdErrFormatSameLine] = d->formats[StdErrFormat];

    d->formats[DebugFormat].setFont(d->font);
    d->formats[DebugFormat].setForeground(theme->color(Theme::OutputFormatter_DebugTextColor));
}

void OutputFormatter::handleLink(const QString &href)
{
    Q_UNUSED(href);
}

QFont OutputFormatter::font() const
{
    return d->font;
}

void OutputFormatter::setFont(const QFont &font)
{
    d->font = font;
    initFormats();
}

void OutputFormatter::flush()
{
    d->escapeCodeHandler->endFormatScope();
}

} // namespace Utils
<commit_msg>Utils: Remove unneeded double indirection in OutputFormatter<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "ansiescapecodehandler.h"
#include "outputformatter.h"
#include "theme/theme.h"

#include <QPlainTextEdit>
#include <QTextCursor>

namespace Utils {

namespace Internal {

class OutputFormatterPrivate
{
public:
    OutputFormatterPrivate()
        : plainTextEdit(0), overwriteOutput(false)
    {}

    QPlainTextEdit *plainTextEdit;
    QTextCharFormat formats[NumberOfFormats];
    QFont font;
    QTextCursor cursor;
    AnsiEscapeCodeHandler escapeCodeHandler;
    bool overwriteOutput;
};

} // namespace Internal

OutputFormatter::OutputFormatter()
    : d(new Internal::OutputFormatterPrivate)
{
}

OutputFormatter::~OutputFormatter()
{
    delete d;
}

QPlainTextEdit *OutputFormatter::plainTextEdit() const
{
    return d->plainTextEdit;
}

void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
{
    d->plainTextEdit = plainText;
    d->cursor = plainText ? plainText->textCursor() : QTextCursor();
    initFormats();
}

void OutputFormatter::appendMessage(const QString &text, OutputFormat format)
{
    appendMessage(text, d->formats[format]);
}

void OutputFormatter::appendMessage(const QString &text, const QTextCharFormat &format)
{
    if (!d->cursor.atEnd())
        d->cursor.movePosition(QTextCursor::End);

    foreach (const FormattedText &output, parseAnsi(text, format)) {
        int startPos = 0;
        int crPos = -1;
        while ((crPos = output.text.indexOf(QLatin1Char('\r'), startPos)) >= 0)  {
            append(d->cursor, output.text.mid(startPos, crPos - startPos), output.format);
            startPos = crPos + 1;
            d->overwriteOutput = true;
        }
        if (startPos < output.text.count())
            append(d->cursor, output.text.mid(startPos), output.format);
    }
}

QTextCharFormat OutputFormatter::charFormat(OutputFormat format) const
{
    return d->formats[format];
}

QList<FormattedText> OutputFormatter::parseAnsi(const QString &text, const QTextCharFormat &format)
{
    return d->escapeCodeHandler.parseText(FormattedText(text, format));
}

void OutputFormatter::append(QTextCursor &cursor, const QString &text,
                             const QTextCharFormat &format)
{
    if (d->overwriteOutput) {
        cursor.clearSelection();
        cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
        d->overwriteOutput = false;
    }
    cursor.insertText(text, format);
}

void OutputFormatter::clearLastLine()
{
    if (!d->cursor.atEnd())
        d->cursor.movePosition(QTextCursor::End);
    d->cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
    d->cursor.removeSelectedText();
}

void OutputFormatter::initFormats()
{
    if (!plainTextEdit())
        return;

    QFont boldFont = d->font;
    boldFont.setBold(true);

    Theme *theme = creatorTheme();

    // NormalMessageFormat
    d->formats[NormalMessageFormat].setFont(boldFont);
    d->formats[NormalMessageFormat].setForeground(theme->color(Theme::OutputFormatter_NormalMessageTextColor));

    // ErrorMessageFormat
    d->formats[ErrorMessageFormat].setFont(boldFont);
    d->formats[ErrorMessageFormat].setForeground(theme->color(Theme::OutputFormatter_ErrorMessageTextColor));

    // StdOutFormat
    d->formats[StdOutFormat].setFont(d->font);
    d->formats[StdOutFormat].setForeground(theme->color(Theme::OutputFormatter_StdOutTextColor));
    d->formats[StdOutFormatSameLine] = d->formats[StdOutFormat];

    // StdErrFormat
    d->formats[StdErrFormat].setFont(d->font);
    d->formats[StdErrFormat].setForeground(theme->color(Theme::OutputFormatter_StdErrTextColor));
    d->formats[StdErrFormatSameLine] = d->formats[StdErrFormat];

    d->formats[DebugFormat].setFont(d->font);
    d->formats[DebugFormat].setForeground(theme->color(Theme::OutputFormatter_DebugTextColor));
}

void OutputFormatter::handleLink(const QString &href)
{
    Q_UNUSED(href);
}

QFont OutputFormatter::font() const
{
    return d->font;
}

void OutputFormatter::setFont(const QFont &font)
{
    d->font = font;
    initFormats();
}

void OutputFormatter::flush()
{
    d->escapeCodeHandler.endFormatScope();
}

} // namespace Utils
<|endoftext|>


<commit_before>// NOTE: Breadboard code --- can refactor into nice bits later.  This is
// not meant to be final in any way, but I'd like to lay as much out here
// and see what it looks like before we go making fancy classes to do
// stuff and realize we did something stupid.
//
// The MPI environment needs to be sectioned away in a singleton that can
//  work even if the MPI isn't present.  I have code that can do this with
//  minimal confusion.
// It would probably be nice to have some kind of coherent logging here but
//  I haven't thought hard about it.  I would like to not have to depend
//  on anything external, unless there is a compelling reason.  Like there
//  are some drop-in header-only logging things we could use.
// Since this is in MPI the logging either has to know that (which would
//  be easy to mess up) or dead simple (like one per MPI task).
// Bunch of cut-n-pasted stuff for reading header stuff.  This should be
//  sectioned off into an IO manager, etc.  Also should not come from header?
// The image math looks clunky, I had better looking stuff in an earlier
//  iteration of C3.  I am not opposed to extending the containers
//  to have more math semantics, but I want it done cleanly.
// Probably using OpenMP to iterate over HDUs is enough work per thread to
//  get a payoff.  We are probably looking at 1-2 MPI tasks per edison node.
//  More than that is not enough memory and we seem to peg the I/O.
// IO interface through CFITSIO needs to have traits to map types.

#include <iostream>
#include <map>
#include <sstream>

#include <fitsio.h>
#include <mpi.h>

#include "C3.hh"
#include "DECam.hh"

// Convert MPI error status into an exception.

void assert_mpi_status( const int mpi_status )
{
    if( mpi_status == MPI_SUCCESS ) return;

    int error_class;
    MPI_Error_class( mpi_status, &error_class );

    char error_string[ MPI_MAX_ERROR_STRING ];
    int length;
    MPI_Error_string( mpi_status, error_string, &length );

    std::stringstream ss;
    ss << "MPI error code " << mpi_status;
    ss << " | error class " << error_class;
    ss << " | "             << error_string;

    throw C3::Exception( ss.str() );
}

// Convert CFITSIO error status into an exception.

void assert_cfitsio_status( const int cfitsio_status )
{
    if( cfitsio_status == 0 ) return;

    char message[ FLEN_STATUS ];
    fits_get_errstatus( cfitsio_status, message );

    std::stringstream ss;
    ss << message;

    throw C3::Exception( ss.str() );
}

//

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

    // Initialize MPI environment.

    int mpi_status;
    mpi_status = MPI_Init( &argc, &argv );
    assert_mpi_status( mpi_status );

    int mpi_size;
    mpi_status = MPI_Comm_size( MPI_COMM_WORLD, &mpi_size );
    assert_mpi_status( mpi_status );

    int mpi_rank;
    mpi_status = MPI_Comm_rank( MPI_COMM_WORLD, &mpi_rank );
    assert_mpi_status( mpi_status );

    // Need to load up our assets (bias, flats, cross-talk model, etc.)
    // TODO

    // Main loop over exposures, round-robin over MPI task.

    for( size_t arg = 1 + mpi_rank; arg < argc; arg += mpi_size )
    {

        // Open FITS file.

        int cfitsio_status = 0;

        fitsfile* fptr = 0;
        fits_open_file( &fptr, argv[ arg ], READONLY, &cfitsio_status );
        assert_cfitsio_status( cfitsio_status );

        // Number of HDUs.

        int numhdus = 0;
        fits_get_num_hdus( fptr, &numhdus, &cfitsio_status );
        assert_cfitsio_status( cfitsio_status );

        // Load remaining HDUs into the exposure.

        std::vector< C3::Image< float > > exposure; // or std::map< std::string, C3::Image< float >* >, whatevz

        for( int hdunum = 1; hdunum < numhdus; ++ hdunum )
        {

            // Move to the next HDU.

            int hdutype = IMAGE_HDU;
            fits_movrel_hdu( fptr, 1, &hdutype, &cfitsio_status );
            assert_cfitsio_status( cfitsio_status );

            // DATASEC.

            size_t d_imin, d_imax, d_jmin, d_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "DATASEC", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> d_imin >> tmp >> d_imax >> tmp >> d_jmin >> tmp >> d_jmax;
                d_imin -= 1;
                d_jmin -= 1;
            }

            // DATASEC A.

            size_t da_imin, da_imax, da_jmin, da_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "DATASECA", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> da_imin >> tmp >> da_imax >> tmp >> da_jmin >> tmp >> da_jmax;
                da_imin -= 1;
                da_jmin -= 1;
            }

            // BIASSEC A.

            size_t ba_imin, ba_imax, ba_jmin, ba_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "BIASSECA", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> ba_imin >> tmp >> ba_imax >> tmp >> ba_jmin >> tmp >> ba_jmax;
                ba_imin -= 1;
                ba_jmin -= 1;
            }

            // DATASEC B.

            size_t db_imin, db_imax, db_jmin, db_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "DATASECB", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> db_imin >> tmp >> db_imax >> tmp >> db_jmin >> tmp >> db_jmax;
                db_imin -= 1;
                db_jmin -= 1;
            }

            // BIASSEC B.

            size_t bb_imin, bb_imax, bb_jmin, bb_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "BIASSECB", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> bb_imin >> tmp >> bb_imax >> tmp >> bb_jmin >> tmp >> bb_jmax;
                bb_imin -= 1;
                bb_jmin -= 1;
            }

            // Image parameters.

            int  maxdim = 2;
            int  bitpix = 0;
            int  naxis  = 0;
            long naxes[ 2 ] = { 0, 0 };

            fits_get_img_param( fptr, maxdim, &bitpix, &naxis, naxes, &cfitsio_status );
            assert_cfitsio_status( cfitsio_status );

            // Create empty image.

            C3::Image< float > image = C3::Image< float >::create( naxes[ 0 ], naxes[ 1 ] );

            // Fill image.

            int     datatype  = TFLOAT; //C3::Traits< T >::cfitsio_type;
            long    firstelem = 1;
            long    nelements = naxes[ 0 ] * naxes[ 1 ];
            float   nulval    = 0;
            int     anynul    = 0;

            fits_read_img( fptr, datatype, firstelem, nelements, &nulval, image._data, &anynul, &cfitsio_status );
            assert_cfitsio_status( cfitsio_status );

            // Overscan subtraction.

            C3::View< float > dataseca  = C3::View< float >::create( image, da_imin, da_imax - da_imin, da_jmin, da_jmax - da_jmin );
            C3::View< float > biasseca  = C3::View< float >::create( image, ba_imin, ba_imax - ba_imin, ba_jmin, ba_jmax - ba_jmin );
            dataseca -= C3::Reduce< C3::Median, C3::View< float >, C3::Column< float > >::compute( biasseca );

            C3::View< float > datasecb = C3::View< float >::create( image, db_imin, db_imax - db_imin, db_jmin, db_jmax - db_jmin );
            C3::View< float > biassecb = C3::View< float >::create( image, bb_imin, bb_imax - bb_imin, bb_jmin, bb_jmax - bb_jmin );
            datasecb -= C3::Reduce< C3::Median, C3::View< float >, C3::Column< float > >::compute( biassecb );

            // New image from the view.

            C3::View< float >  datasec = C3::View< float >::create( image, d_imin, d_imax - d_imin, d_jmin, d_jmax - d_jmin );
            C3::Image< float > trimmed = C3::Image< float >::create( datasec.ncols(), datasec.nrows() );
            trimmed = datasec;
            exposure.push_back( trimmed );

        }

        // Close FITS file.

        fits_close_file( fptr, &cfitsio_status );
        assert_cfitsio_status( cfitsio_status );

        if( mpi_rank == 0 ) std::cerr << argv[ arg ] << std::endl; // tmp

        // now do more stuff, subtract bias, flat field, etc...

    }

    // Goodbye.

    mpi_status = MPI_Finalize();
    return 0;

}
<commit_msg>Going to be re-done soon anyway.<commit_after>// NOTE: Breadboard code --- can refactor into nice bits later.  This is
// not meant to be final in any way, but I'd like to lay as much out here
// and see what it looks like before we go making fancy classes to do
// stuff and realize we did something stupid.
//
// The MPI environment needs to be sectioned away in a singleton that can
//  work even if the MPI isn't present.  I have code that can do this with
//  minimal confusion.
// It would probably be nice to have some kind of coherent logging here but
//  I haven't thought hard about it.  I would like to not have to depend
//  on anything external, unless there is a compelling reason.  Like there
//  are some drop-in header-only logging things we could use.
// Since this is in MPI the logging either has to know that (which would
//  be easy to mess up) or dead simple (like one per MPI task).
// Bunch of cut-n-pasted stuff for reading header stuff.  This should be
//  sectioned off into an IO manager, etc.  Also should not come from header?
// The image math looks clunky, I had better looking stuff in an earlier
//  iteration of C3.  I am not opposed to extending the containers
//  to have more math semantics, but I want it done cleanly.
// Probably using OpenMP to iterate over HDUs is enough work per thread to
//  get a payoff.  We are probably looking at 1-2 MPI tasks per edison node.
//  More than that is not enough memory and we seem to peg the I/O.
// IO interface through CFITSIO needs to have traits to map types.

#include <iostream>
#include <map>
#include <sstream>
#include <vector>

#include <fitsio.h>
#include <mpi.h>

#include "C3.hh"
#include "DECam.hh"

// Convert MPI error status into an exception.

void assert_mpi_status( const int mpi_status )
{
    if( mpi_status == MPI_SUCCESS ) return;

    int error_class;
    MPI_Error_class( mpi_status, &error_class );

    char error_string[ MPI_MAX_ERROR_STRING ];
    int length;
    MPI_Error_string( mpi_status, error_string, &length );

    std::stringstream ss;
    ss << "MPI error code " << mpi_status;
    ss << " | error class " << error_class;
    ss << " | "             << error_string;

    throw C3::Exception( ss.str() );
}

// Convert CFITSIO error status into an exception.

void assert_cfitsio_status( const int cfitsio_status )
{
    if( cfitsio_status == 0 ) return;

    char message[ FLEN_STATUS ];
    fits_get_errstatus( cfitsio_status, message );

    std::stringstream ss;
    ss << message;

    throw C3::Exception( ss.str() );
}

//

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

    // Initialize MPI environment.

    int mpi_status;
    mpi_status = MPI_Init( &argc, &argv );
    assert_mpi_status( mpi_status );

    int mpi_size;
    mpi_status = MPI_Comm_size( MPI_COMM_WORLD, &mpi_size );
    assert_mpi_status( mpi_status );

    int mpi_rank;
    mpi_status = MPI_Comm_rank( MPI_COMM_WORLD, &mpi_rank );
    assert_mpi_status( mpi_status );

    // Need to load up our assets (bias, flats, cross-talk model, etc.)
    // TODO

    // Main loop over exposures, round-robin over MPI task.

    for( size_t arg = 1 + mpi_rank; arg < argc; arg += mpi_size )
    {

        // Open FITS file.

        int cfitsio_status = 0;

        fitsfile* fptr = 0;
        fits_open_file( &fptr, argv[ arg ], READONLY, &cfitsio_status );
        assert_cfitsio_status( cfitsio_status );

        // Number of HDUs.

        int numhdus = 0;
        fits_get_num_hdus( fptr, &numhdus, &cfitsio_status );
        assert_cfitsio_status( cfitsio_status );

        // Load remaining HDUs into the exposure.

        std::vector< C3::Image< float > > exposure; // or std::map< std::string, C3::Image< float >* >, whatevz

        for( int hdunum = 1; hdunum < numhdus; ++ hdunum )
        {

            // Move to the next HDU.

            int hdutype = IMAGE_HDU;
            fits_movrel_hdu( fptr, 1, &hdutype, &cfitsio_status );
            assert_cfitsio_status( cfitsio_status );

            // DATASEC.

            size_t d_imin, d_imax, d_jmin, d_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "DATASEC", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> d_imin >> tmp >> d_imax >> tmp >> d_jmin >> tmp >> d_jmax;
                d_imin -= 1;
                d_jmin -= 1;
            }

            // DATASEC A.

            size_t da_imin, da_imax, da_jmin, da_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "DATASECA", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> da_imin >> tmp >> da_imax >> tmp >> da_jmin >> tmp >> da_jmax;
                da_imin -= 1;
                da_jmin -= 1;
            }

            // BIASSEC A.

            size_t ba_imin, ba_imax, ba_jmin, ba_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "BIASSECA", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> ba_imin >> tmp >> ba_imax >> tmp >> ba_jmin >> tmp >> ba_jmax;
                ba_imin -= 1;
                ba_jmin -= 1;
            }

            // DATASEC B.

            size_t db_imin, db_imax, db_jmin, db_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "DATASECB", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> db_imin >> tmp >> db_imax >> tmp >> db_jmin >> tmp >> db_jmax;
                db_imin -= 1;
                db_jmin -= 1;
            }

            // BIASSEC B.

            size_t bb_imin, bb_imax, bb_jmin, bb_jmax;

            {
                char buffer[ FLEN_VALUE ];

                fits_read_key( fptr, TSTRING, "BIASSECB", buffer, 0, &cfitsio_status );
                assert_cfitsio_status( cfitsio_status );

                char tmp;
                std::stringstream ss( buffer );
                ss >> tmp >> bb_imin >> tmp >> bb_imax >> tmp >> bb_jmin >> tmp >> bb_jmax;
                bb_imin -= 1;
                bb_jmin -= 1;
            }

            // Image parameters.

            int  maxdim = 2;
            int  bitpix = 0;
            int  naxis  = 0;
            long naxes[ 2 ] = { 0, 0 };

            fits_get_img_param( fptr, maxdim, &bitpix, &naxis, naxes, &cfitsio_status );
            assert_cfitsio_status( cfitsio_status );

            // Create empty image.

            C3::Image< float > image = C3::Image< float >::create( naxes[ 0 ], naxes[ 1 ] );

            // Fill image.

            int     datatype  = TFLOAT; //C3::Traits< T >::cfitsio_type;
            long    firstelem = 1;
            long    nelements = naxes[ 0 ] * naxes[ 1 ];
            float   nulval    = 0;
            int     anynul    = 0;

            fits_read_img( fptr, datatype, firstelem, nelements, &nulval, image._data, &anynul, &cfitsio_status );
            assert_cfitsio_status( cfitsio_status );

            // Overscan subtraction.

            C3::View< float > dataseca  = C3::View< float >::create( image, da_imin, da_imax - da_imin, da_jmin, da_jmax - da_jmin );
            C3::View< float > biasseca  = C3::View< float >::create( image, ba_imin, ba_imax - ba_imin, ba_jmin, ba_jmax - ba_jmin );
            dataseca -= C3::Reduce< C3::Median, C3::View< float >, C3::Column< float > >::compute( biasseca );

            C3::View< float > datasecb = C3::View< float >::create( image, db_imin, db_imax - db_imin, db_jmin, db_jmax - db_jmin );
            C3::View< float > biassecb = C3::View< float >::create( image, bb_imin, bb_imax - bb_imin, bb_jmin, bb_jmax - bb_jmin );
            datasecb -= C3::Reduce< C3::Median, C3::View< float >, C3::Column< float > >::compute( biassecb );

            // New image from the view.

            C3::View< float >  datasec = C3::View< float >::create( image, d_imin, d_imax - d_imin, d_jmin, d_jmax - d_jmin );
            C3::Image< float > trimmed = C3::Image< float >::create( datasec.ncols(), datasec.nrows() );
            trimmed = datasec;
            exposure.push_back( trimmed );

        }

        // Close FITS file.

        fits_close_file( fptr, &cfitsio_status );
        assert_cfitsio_status( cfitsio_status );

        if( mpi_rank == 0 ) std::cerr << argv[ arg ] << std::endl; // tmp

        // now do more stuff, subtract bias, flat field, etc...

    }

    // Goodbye.

    mpi_status = MPI_Finalize();
    return 0;

}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "Function.hpp"
#include "GlobalContext.hpp"

#include "mtac/call_graph.hpp"
#include "mtac/Program.hpp"
#include "mtac/Function.hpp"

using namespace eddic;

mtac::call_graph::~call_graph(){
    for(auto& node_key : nodes){
        auto& node = node_key.second;

        for(auto& edge : node->in_edges){
            edge->source = nullptr;
            edge->target = nullptr;
        }

        for(auto& edge : node->out_edges){
            edge->source = nullptr;
            edge->target = nullptr;
        }

        node->in_edges.clear();
        node->out_edges.clear();
    }
}

mtac::call_graph_node_p mtac::call_graph::node(eddic::Function& function){
    auto it = nodes.find(function.mangled_name());

    if(it == nodes.end()){
        auto node = std::make_shared<mtac::call_graph_node>(function);
        nodes[function.mangled_name()] = node;
        return node;
    }

    return it->second;
}

mtac::call_graph_edge_p mtac::call_graph::edge(eddic::Function& source, eddic::Function& target){
    auto source_node = node(source);
    auto target_node = node(target);

    for(auto& edge : source_node->out_edges){
        if(edge->target == target_node){
            return edge;
        }
    }

    return nullptr;
}

void mtac::call_graph::add_edge(eddic::Function& source, eddic::Function& target){
    auto edge = this->edge(source, target);

    if(!edge){
        auto source_node = node(source);
        auto target_node = node(target);

        edge = std::make_shared<mtac::call_graph_edge>(source_node, target_node);

        source_node->out_edges.push_back(edge);
        target_node->in_edges.push_back(edge);
    }

    ++edge->count;
}

void compute_reachable(mtac::Reachable& reachable, mtac::call_graph_node_p node){
    if(reachable.find(node->function) == reachable.end()){
        reachable.insert(node->function);

        for(auto& edge : node->out_edges){
            if(edge->count > 0){
                compute_reachable(reachable, edge->target);
            }
        }
    }
}

void mtac::call_graph::compute_reachable(){
    eddic_assert(entry, "The call graph must be built before computing reachable");

    release_reachable();

    ::compute_reachable(reachable, entry);
}

void mtac::call_graph::release_reachable(){
    reachable.clear();
}

bool mtac::call_graph::is_reachable(eddic::Function& function){
    return reachable.find(function) != reachable.end();
}

void mtac::build_call_graph(mtac::Program& program){
    timing_timer timer(program.context->timing(), "build_cg");

    auto& cg = program.call_graph;

    for(auto& function : program){
        for(auto& block : function){
            for(auto& quadruple : block){
                if(quadruple.op == mtac::Operator::CALL){
                    cg.add_edge(function.definition(), quadruple.function());
                }
            }
        }

        if(function.is_main()){
            cg.entry = cg.node(function.definition());
        }
    }
}

void post_dfs_visit(mtac::call_graph_node_p& node, std::vector<std::reference_wrapper<eddic::Function>>& order){
    for(auto& edge : node->out_edges){
        if(edge->target->function != node->function){
            post_dfs_visit(edge->target, order);
        }
    }

    order.push_back(node->function);
}

std::vector<std::reference_wrapper<eddic::Function>> mtac::call_graph::topological_order(){
    std::vector<std::reference_wrapper<eddic::Function>> order;

    post_dfs_visit(entry, order);

    return order;
}
<commit_msg>Fix call_graph -> cg<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "Function.hpp"
#include "GlobalContext.hpp"

#include "mtac/call_graph.hpp"
#include "mtac/Program.hpp"
#include "mtac/Function.hpp"

using namespace eddic;

mtac::call_graph::~call_graph(){
    for(auto& node_key : nodes){
        auto& node = node_key.second;

        for(auto& edge : node->in_edges){
            edge->source = nullptr;
            edge->target = nullptr;
        }

        for(auto& edge : node->out_edges){
            edge->source = nullptr;
            edge->target = nullptr;
        }

        node->in_edges.clear();
        node->out_edges.clear();
    }
}

mtac::call_graph_node_p mtac::call_graph::node(eddic::Function& function){
    auto it = nodes.find(function.mangled_name());

    if(it == nodes.end()){
        auto node = std::make_shared<mtac::call_graph_node>(function);
        nodes[function.mangled_name()] = node;
        return node;
    }

    return it->second;
}

mtac::call_graph_edge_p mtac::call_graph::edge(eddic::Function& source, eddic::Function& target){
    auto source_node = node(source);
    auto target_node = node(target);

    for(auto& edge : source_node->out_edges){
        if(edge->target == target_node){
            return edge;
        }
    }

    return nullptr;
}

void mtac::call_graph::add_edge(eddic::Function& source, eddic::Function& target){
    auto edge = this->edge(source, target);

    if(!edge){
        auto source_node = node(source);
        auto target_node = node(target);

        edge = std::make_shared<mtac::call_graph_edge>(source_node, target_node);

        source_node->out_edges.push_back(edge);
        target_node->in_edges.push_back(edge);
    }

    ++edge->count;
}

void compute_reachable(mtac::Reachable& reachable, mtac::call_graph_node_p node){
    if(reachable.find(node->function) == reachable.end()){
        reachable.insert(node->function);

        for(auto& edge : node->out_edges){
            if(edge->count > 0){
                compute_reachable(reachable, edge->target);
            }
        }
    }
}

void mtac::call_graph::compute_reachable(){
    eddic_assert(entry, "The call graph must be built before computing reachable");

    release_reachable();

    ::compute_reachable(reachable, entry);
}

void mtac::call_graph::release_reachable(){
    reachable.clear();
}

bool mtac::call_graph::is_reachable(eddic::Function& function){
    return reachable.find(function) != reachable.end();
}

void mtac::build_call_graph(mtac::Program& program){
    timing_timer timer(program.context->timing(), "build_cg");

    auto& cg = program.cg;

    for(auto& function : program){
        for(auto& block : function){
            for(auto& quadruple : block){
                if(quadruple.op == mtac::Operator::CALL){
                    cg.add_edge(function.definition(), quadruple.function());
                }
            }
        }

        if(function.is_main()){
            cg.entry = cg.node(function.definition());
        }
    }
}

void post_dfs_visit(mtac::call_graph_node_p& node, std::vector<std::reference_wrapper<eddic::Function>>& order){
    for(auto& edge : node->out_edges){
        if(edge->target->function != node->function){
            post_dfs_visit(edge->target, order);
        }
    }

    order.push_back(node->function);
}

std::vector<std::reference_wrapper<eddic::Function>> mtac::call_graph::topological_order(){
    std::vector<std::reference_wrapper<eddic::Function>> order;

    post_dfs_visit(entry, order);

    return order;
}
<|endoftext|>


<commit_before>#include "evaluator.h"
#include "mugen_exception.h"
#include "character.h"
#include "mugen_animation.h"
#include "ast/all.h"
#include <math.h>

/* TODO:
 * 1. Change RuntimeValue into an object that stores pointers so that the
 * overhead of copying values is not so high.
 * 2. 1 necessitates garbage collection. Implement precise mark/sweep.
 * 3. Convert interpreter into a compiler. Refresher
 *   (define intepreter (lambda (env) (lambda (input) (eval env input))))
 *   (define compiler (lambda (input) (let ([compiled (compile input)])
 *                       (lambda (env) (eval env compiled)))))
 * 4. Implement simple optimizations: constant folding, dead code elimintation.
 */

using namespace std;

namespace Mugen{

string toString(const RuntimeValue & value){
    if (value.isString()){
        return value.getStringValue();
    }
    throw MugenException("Not a string");
}

double toNumber(const RuntimeValue & value){
    if (value.isDouble()){
        return value.getDoubleValue();
    }
    if (value.isBool()){
        if (value.getBoolValue()){
            return 1;
        } else {
            return 0;
        }
    }
    throw MugenException("Not a number");
}

bool toBool(const RuntimeValue & value){
    if (value.isBool()){
        return value.getBoolValue();
    }
    if (value.isDouble()){
        return value.getDoubleValue() != 0;
    }
    throw MugenException("Not a bool");
}

/* a meta-circular evaluator! */
class Evaluator: public Ast::Walker {
public:
    Evaluator(const Environment & environment):
        environment(environment){
        }

    const Environment & environment;
    RuntimeValue result;

    /* value1 == value2 */
    RuntimeValue same(const RuntimeValue & value1, const RuntimeValue & value2){
        switch (value1.type){
            case RuntimeValue::ListOfString : {
                switch (value2.type){
                    case RuntimeValue::String : {
                        const vector<string> & strings = value1.strings_value;
                        for (vector<string>::const_iterator it = strings.begin(); it != strings.end(); it++){
                            const string & check = *it;
                            if (check == value2.string_value){
                                return RuntimeValue(true);
                            }
                        }
                        return RuntimeValue(false);
                    }
                }
                break;
            }
            case RuntimeValue::String : {
                switch (value2.type){
                    case RuntimeValue::ListOfString : {
                        return same(value2, value1);
                    }
                    case RuntimeValue::String : {
                        return toString(value1) == toString(value2);
                    }
                }
                break;
            }
            case RuntimeValue::Double : {
                switch (value2.type){
                    case RuntimeValue::Double : {
                        double epsilon = 0.0000001;
                        return RuntimeValue(fabs(value1.getDoubleValue() - value2.getDoubleValue()) < epsilon);
                    }
                }
                break;
            }
        }

        return RuntimeValue(false);
    }

    RuntimeValue evaluate(const Ast::Value * value){
        return Mugen::evaluate(value, environment);
    }

    RuntimeValue evalIdentifier(const Ast::Identifier & identifier){
        if (identifier == "command"){
            return RuntimeValue(environment.getCommands());
        }

        if (identifier == "anim"){
            return RuntimeValue(environment.getCharacter().getAnimation());
        }

        if (identifier == "alive"){
            /* FIXME */
            return RuntimeValue(true);
        }

        if (identifier == "p2statetype"){
            /* FIXME */
            return RuntimeValue(0);
        }

        if (identifier == "animtime"){
            return RuntimeValue(environment.getCharacter().getCurrentAnimation()->animationTime());
        }

        if (identifier == "animelem"){
            /* FIXME! */
            return RuntimeValue(0);
        }

        if (identifier == "time"){
            return RuntimeValue(environment.getCharacter().getStateTime());
        }

        if (identifier == "A"){
            return RuntimeValue(string("A"));
        }

        if (identifier == "S"){
            /* states are just strings */
            return RuntimeValue(string("S"));
        }

        if (identifier == "C"){
            return RuntimeValue(string("C"));
        }

        if (identifier == "L"){
            return RuntimeValue(string("L"));
        }

        if (identifier == "statetype"){
            return RuntimeValue(environment.getCharacter().getStateType());
        }

        /* true if the player has control */
        if (identifier == "ctrl"){
            return RuntimeValue(environment.getCharacter().hasControl());
        }

        if (identifier == "stateno"){
            return RuntimeValue(environment.getCharacter().getCurrentState());
        }

        if (identifier == "power"){
            return RuntimeValue(environment.getCharacter().getPower());
        }

        if (identifier == "velocity.walk.back.x"){
            return RuntimeValue(environment.getCharacter().getWalkBackX());
        }

        if (identifier == "velocity.walk.fwd.x"){
            return RuntimeValue(environment.getCharacter().getWalkForwardX());
        }

        if (identifier == "velocity.run.fwd.x"){
            return RuntimeValue(environment.getCharacter().getRunForwardX());
        }

        if (identifier == "velocity.jump.neu.x"){
            return RuntimeValue(environment.getCharacter().getNeutralJumpingX());
        }

        if (identifier == "velocity.jump.y"){
            return RuntimeValue(environment.getCharacter().getNeutralJumpingY());
        }

        if (identifier == "prevstateno"){
            return RuntimeValue(environment.getCharacter().getPreviousState());
        }

        if (identifier == "velocity.run.back.x"){
            return RuntimeValue(environment.getCharacter().getRunBackX());
        }

        if (identifier == "velocity.run.back.y"){
            return RuntimeValue(environment.getCharacter().getRunBackY());
        }

        if (identifier == "velocity.jump.back.x"){
            return RuntimeValue(environment.getCharacter().getJumpBack());
        }

        if (identifier == "velocity.jump.fwd.x"){
            return RuntimeValue(environment.getCharacter().getJumpForward());
        }

        if (identifier == "velocity.runjump.fwd.x"){
            return RuntimeValue(environment.getCharacter().getRunJumpForward());
        }

        ostringstream out;
        out << "Unknown identifier '" << identifier.toString() << "'";
        throw MugenException(out.str());
    }

    virtual void onIdenfitier(const Ast::Identifier & identifier){
        result = evalIdentifier(identifier);
    }

    RuntimeValue evalKeyword(const Ast::Keyword & keyword){
        if (keyword == "vel x"){
            return RuntimeValue(environment.getCharacter().getXVelocity());
        }

        if (keyword == "vel y"){
            return RuntimeValue(environment.getCharacter().getYVelocity());
        }

        if (keyword == "pos y"){
            return RuntimeValue(-environment.getCharacter().getYPosition());
        }

        if (keyword == "p2bodydist x"){
            /* FIXME */
            return RuntimeValue(0);
        }

        ostringstream out;
        out << "Unknown keyword '" << keyword.toString() << "'";
        throw MugenException(out.str());
    }

    virtual void onKeyword(const Ast::Keyword & keyword){
        result = evalKeyword(keyword);
    }

    RuntimeValue evalString(const Ast::String & string_value){
        string out;
        string_value >> out;
        return RuntimeValue(out);
    }

    virtual void onString(const Ast::String & string){
        result = evalString(string);
    }

    RuntimeValue evalFunction(const Ast::Function & function){
        if (function == "const"){
            return evaluate(function.getArg1());
        }

        if (function == "abs"){
            return RuntimeValue(fabs(toNumber(evaluate(function.getArg1()))));
        }

        if (function == "var"){
            int index = (int) toNumber(evaluate(function.getArg1()));
            Ast::Value * value = environment.getCharacter().getVariable(index);
            if (value == 0){
                ostringstream out;
                out << "No variable for index " << index;
                throw MugenException(out.str());
            }
            return evaluate(value);
        }

        if (function == "sysvar"){
            int index = (int) toNumber(evaluate(function.getArg1()));
            Ast::Value * value = environment.getCharacter().getSystemVariable(index);
            if (value == 0){
                ostringstream out;
                out << "No system variable for index " << index;
                throw MugenException(out.str());
            }
            return evaluate(value);
        }

        if (function == "ifelse"){
            if (toBool(evaluate(function.getArg1()))){
                return evaluate(function.getArg2());
            } else {
                return evaluate(function.getArg3());
            }
        }

        if (function == "selfanimexist"){
            int animation = (int) toNumber(evaluate(function.getArg1()));
            return RuntimeValue(environment.getCharacter().hasAnimation(animation));
        }

        /* Gets the animation-time elapsed since the start of a specified element
         * of the current animation action. Useful for synchronizing events to
         * elements of an animation action.
         *
         * (reminder: first element of an action is element 1, not 0)
         */
        if (function == "animelemtime"){
            /* FIXME */
            return RuntimeValue(0);
        }

        ostringstream out;
        out << "Unknown function '" << function.toString() << "'";
        throw MugenException(out.str());
    }

    virtual void onFunction(const Ast::Function & string){
        result = evalFunction(string);
    }

    RuntimeValue evalNumber(const Ast::Number & number){
        double x;
        number >> x;
        return RuntimeValue(x);
    }

    virtual void onNumber(const Ast::Number & number){
        result = evalNumber(number);
    }

    virtual RuntimeValue evalExpressionInfix(const Ast::ExpressionInfix & expression){
        Global::debug(1) << "Evaluate expression " << expression.toString() << endl;
        using namespace Ast;
        switch (expression.getExpressionType()){
            case ExpressionInfix::Or : {
                return RuntimeValue(toBool(evaluate(expression.getLeft())) ||
                                    toBool(evaluate(expression.getRight())));
            }
            case ExpressionInfix::XOr : {
                return RuntimeValue(toBool(evaluate(expression.getLeft())) ^
                                    toBool(evaluate(expression.getRight())));
            }
            case ExpressionInfix::And : {
                return RuntimeValue(toBool(evaluate(expression.getLeft())) &&
                                    toBool(evaluate(expression.getRight())));
            }
            case ExpressionInfix::BitwiseOr : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) |
                                    (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::BitwiseXOr : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) ^
                                    (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::BitwiseAnd : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) &
                                    (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Assignment : {
                /* FIXME: is this needed? */
                break;
            }
            case ExpressionInfix::Equals : {
                return same(evaluate(expression.getLeft()), evaluate(expression.getRight()));
                break;
            }
            case ExpressionInfix::Unequals : {
                return RuntimeValue(!toBool(same(evaluate(expression.getLeft()), evaluate(expression.getRight()))));
            }
            case ExpressionInfix::GreaterThanEquals : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) >= toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::GreaterThan : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) > toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::LessThanEquals : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) <= toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::LessThan : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) < toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Add : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) + toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Subtract : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) - toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Multiply : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) * toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Divide : {
                /* FIXME: catch divide by 0 */
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) / toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Modulo : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) % (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Power : {
                return RuntimeValue(pow(toNumber(evaluate(expression.getLeft())), toNumber(evaluate(expression.getRight()))));
            }
        }

        ostringstream out;
        out << "Unknown expression: " << expression.toString();
        throw MugenException(out.str());
    }

    virtual void onExpressionInfix(const Ast::ExpressionInfix & expression){
        result = evalExpressionInfix(expression);
    }

    RuntimeValue evalExpressionUnary(const Ast::ExpressionUnary & expression){
        switch (expression.getExpressionType()){
            case Ast::ExpressionUnary::Not : {
                return RuntimeValue(!toBool(evaluate(expression.getExpression())));
            }
            case Ast::ExpressionUnary::Minus : {
                return RuntimeValue(-toNumber(evaluate(expression.getExpression())));
            }
            case Ast::ExpressionUnary::Negation : {
                return RuntimeValue(~(int)toNumber(evaluate(expression.getExpression())));
            }
        }

        ostringstream out;
        out << "Unknown expression: " << expression.toString();
        throw MugenException(out.str());
    }

    virtual void onExpressionUnary(const Ast::ExpressionUnary & expression){
        result = evalExpressionUnary(expression);
    }
};

RuntimeValue evaluate(const Ast::Value * value, const Environment & environment){
    try{
        Evaluator eval(environment);
        value->walk(eval);
        return eval.result;
    } catch (const MugenException & e){
        ostringstream out;
        out << "Error while evaluating expression `" << value->toString() << "': " << e.getReason();
        throw MugenException(out.str());
    }
}

}
<commit_msg>start to add hitdef stuff<commit_after>#include "evaluator.h"
#include "mugen_exception.h"
#include "character.h"
#include "mugen_animation.h"
#include "ast/all.h"
#include <math.h>

/* TODO:
 * 1. Change RuntimeValue into an object that stores pointers so that the
 * overhead of copying values is not so high.
 * 2. 1 necessitates garbage collection. Implement precise mark/sweep.
 * 3. Convert interpreter into a compiler. Refresher
 *   (define intepreter (lambda (env) (lambda (input) (eval env input))))
 *   (define compiler (lambda (input) (let ([compiled (compile input)])
 *                       (lambda (env) (eval env compiled)))))
 * 4. Implement simple optimizations: constant folding, dead code elimintation.
 */

using namespace std;

namespace Mugen{

string toString(const RuntimeValue & value){
    if (value.isString()){
        return value.getStringValue();
    }
    throw MugenException("Not a string");
}

double toNumber(const RuntimeValue & value){
    if (value.isDouble()){
        return value.getDoubleValue();
    }
    if (value.isBool()){
        if (value.getBoolValue()){
            return 1;
        } else {
            return 0;
        }
    }
    throw MugenException("Not a number");
}

bool toBool(const RuntimeValue & value){
    if (value.isBool()){
        return value.getBoolValue();
    }
    if (value.isDouble()){
        return value.getDoubleValue() != 0;
    }
    throw MugenException("Not a bool");
}

/* a meta-circular evaluator! */
class Evaluator: public Ast::Walker {
public:
    Evaluator(const Environment & environment):
        environment(environment){
        }

    const Environment & environment;
    RuntimeValue result;

    /* value1 == value2 */
    RuntimeValue same(const RuntimeValue & value1, const RuntimeValue & value2){
        switch (value1.type){
            case RuntimeValue::ListOfString : {
                switch (value2.type){
                    case RuntimeValue::String : {
                        const vector<string> & strings = value1.strings_value;
                        for (vector<string>::const_iterator it = strings.begin(); it != strings.end(); it++){
                            const string & check = *it;
                            if (check == value2.string_value){
                                return RuntimeValue(true);
                            }
                        }
                        return RuntimeValue(false);
                    }
                }
                break;
            }
            case RuntimeValue::String : {
                switch (value2.type){
                    case RuntimeValue::ListOfString : {
                        return same(value2, value1);
                    }
                    case RuntimeValue::String : {
                        return toString(value1) == toString(value2);
                    }
                }
                break;
            }
            case RuntimeValue::Double : {
                switch (value2.type){
                    case RuntimeValue::Double : {
                        double epsilon = 0.0000001;
                        return RuntimeValue(fabs(value1.getDoubleValue() - value2.getDoubleValue()) < epsilon);
                    }
                }
                break;
            }
        }

        return RuntimeValue(false);
    }

    RuntimeValue evaluate(const Ast::Value * value){
        return Mugen::evaluate(value, environment);
    }

    RuntimeValue evalIdentifier(const Ast::Identifier & identifier){
        if (identifier == "command"){
            return RuntimeValue(environment.getCommands());
        }

        if (identifier == "anim"){
            return RuntimeValue(environment.getCharacter().getAnimation());
        }

        if (identifier == "alive"){
            /* FIXME */
            return RuntimeValue(true);
        }

        if (identifier == "p2statetype"){
            /* FIXME */
            return RuntimeValue(0);
        }

        if (identifier == "animtime"){
            return RuntimeValue(environment.getCharacter().getCurrentAnimation()->animationTime());
        }

        if (identifier == "animelem"){
            /* FIXME! */
            return RuntimeValue(0);
        }

        if (identifier == "hitshakeover"){
            /* FIXME */
            return RuntimeValue(1);
        }

        if (identifier == "hitover"){
            /* FIXME */
            return RuntimeValue(1);
        }

        if (identifier == "hitfall"){
            /* FIXME */
            return RuntimeValue(0);
        }

        if (identifier == "time"){
            return RuntimeValue(environment.getCharacter().getStateTime());
        }

        if (identifier == "A"){
            return RuntimeValue(string("A"));
        }

        if (identifier == "S"){
            /* states are just strings */
            return RuntimeValue(string("S"));
        }

        if (identifier == "C"){
            return RuntimeValue(string("C"));
        }

        if (identifier == "L"){
            return RuntimeValue(string("L"));
        }

        if (identifier == "statetype"){
            return RuntimeValue(environment.getCharacter().getStateType());
        }

        /* true if the player has control */
        if (identifier == "ctrl"){
            return RuntimeValue(environment.getCharacter().hasControl());
        }

        if (identifier == "stateno"){
            return RuntimeValue(environment.getCharacter().getCurrentState());
        }

        if (identifier == "power"){
            return RuntimeValue(environment.getCharacter().getPower());
        }

        if (identifier == "velocity.walk.back.x"){
            return RuntimeValue(environment.getCharacter().getWalkBackX());
        }

        if (identifier == "velocity.walk.fwd.x"){
            return RuntimeValue(environment.getCharacter().getWalkForwardX());
        }

        if (identifier == "velocity.run.fwd.x"){
            return RuntimeValue(environment.getCharacter().getRunForwardX());
        }

        if (identifier == "velocity.jump.neu.x"){
            return RuntimeValue(environment.getCharacter().getNeutralJumpingX());
        }

        if (identifier == "velocity.jump.y"){
            return RuntimeValue(environment.getCharacter().getNeutralJumpingY());
        }

        if (identifier == "prevstateno"){
            return RuntimeValue(environment.getCharacter().getPreviousState());
        }

        if (identifier == "velocity.run.back.x"){
            return RuntimeValue(environment.getCharacter().getRunBackX());
        }

        if (identifier == "velocity.run.back.y"){
            return RuntimeValue(environment.getCharacter().getRunBackY());
        }

        if (identifier == "velocity.jump.back.x"){
            return RuntimeValue(environment.getCharacter().getJumpBack());
        }

        if (identifier == "velocity.jump.fwd.x"){
            return RuntimeValue(environment.getCharacter().getJumpForward());
        }

        if (identifier == "velocity.runjump.fwd.x"){
            return RuntimeValue(environment.getCharacter().getRunJumpForward());
        }

        ostringstream out;
        out << "Unknown identifier '" << identifier.toString() << "'";
        throw MugenException(out.str());
    }

    virtual void onIdenfitier(const Ast::Identifier & identifier){
        result = evalIdentifier(identifier);
    }

    RuntimeValue evalKeyword(const Ast::Keyword & keyword){
        if (keyword == "vel x"){
            return RuntimeValue(environment.getCharacter().getXVelocity());
        }

        if (keyword == "vel y"){
            return RuntimeValue(environment.getCharacter().getYVelocity());
        }

        if (keyword == "pos y"){
            return RuntimeValue(-environment.getCharacter().getYPosition());
        }

        if (keyword == "p2bodydist x"){
            /* FIXME */
            return RuntimeValue(0);
        }

        ostringstream out;
        out << "Unknown keyword '" << keyword.toString() << "'";
        throw MugenException(out.str());
    }

    virtual void onKeyword(const Ast::Keyword & keyword){
        result = evalKeyword(keyword);
    }

    RuntimeValue evalString(const Ast::String & string_value){
        string out;
        string_value >> out;
        return RuntimeValue(out);
    }

    virtual void onString(const Ast::String & string){
        result = evalString(string);
    }

    RuntimeValue evalFunction(const Ast::Function & function){
        if (function == "const"){
            return evaluate(function.getArg1());
        }

        if (function == "abs"){
            return RuntimeValue(fabs(toNumber(evaluate(function.getArg1()))));
        }

        if (function == "var"){
            int index = (int) toNumber(evaluate(function.getArg1()));
            Ast::Value * value = environment.getCharacter().getVariable(index);
            if (value == 0){
                ostringstream out;
                out << "No variable for index " << index;
                throw MugenException(out.str());
            }
            return evaluate(value);
        }

        if (function == "gethitvar"){
            if (function.getArg1() == 0){
                throw MugenException("No argument given to gethitvar");
            }
            string var = function.getArg1()->toString();
            if (var == "xveladd"){
            } else if (var == "yveladd"){
            } else if (var == "type"){
            } else if (var == "animtype"){
            } else if (var == "airtype"){
            } else if (var == "groundtype"){
            } else if (var == "damage"){
            } else if (var == "hitcount"){
            } else if (var == "fallcount"){
            } else if (var == "hitshaketime"){
            } else if (var == "hittime"){
            } else if (var == "slidetime"){
            } else if (var == "ctrltime"){
            } else if (var == "recovertime"){
            } else if (var == "xoff"){
            } else if (var == "yoff"){
            } else if (var == "zoff"){
            } else if (var == "xvel"){
            } else if (var == "yvel"){
            } else if (var == "yaccel"){
            } else if (var == "hitid"){
            } else if (var == "chainid"){
            } else if (var == "guarded"){
            } else if (var == "fall"){
            } else if (var == "fall.damage"){
            } else if (var == "fall.xvel"){
            } else if (var == "fall.yvel"){
            } else if (var == "fall.recover"){
            } else if (var == "fall.time"){
            } else if (var == "fall.recovertime"){
            }

            throw MugenException("Unknown gethitvar variable " + var);
        }

        if (function == "sysvar"){
            int index = (int) toNumber(evaluate(function.getArg1()));
            Ast::Value * value = environment.getCharacter().getSystemVariable(index);
            if (value == 0){
                ostringstream out;
                out << "No system variable for index " << index;
                throw MugenException(out.str());
            }
            return evaluate(value);
        }

        if (function == "ifelse"){
            if (toBool(evaluate(function.getArg1()))){
                return evaluate(function.getArg2());
            } else {
                return evaluate(function.getArg3());
            }
        }

        if (function == "selfanimexist"){
            int animation = (int) toNumber(evaluate(function.getArg1()));
            return RuntimeValue(environment.getCharacter().hasAnimation(animation));
        }

        /* Gets the animation-time elapsed since the start of a specified element
         * of the current animation action. Useful for synchronizing events to
         * elements of an animation action.
         *
         * (reminder: first element of an action is element 1, not 0)
         */
        if (function == "animelemtime"){
            /* FIXME */
            return RuntimeValue(0);
        }

        ostringstream out;
        out << "Unknown function '" << function.toString() << "'";
        throw MugenException(out.str());
    }

    virtual void onFunction(const Ast::Function & string){
        result = evalFunction(string);
    }

    RuntimeValue evalNumber(const Ast::Number & number){
        double x;
        number >> x;
        return RuntimeValue(x);
    }

    virtual void onNumber(const Ast::Number & number){
        result = evalNumber(number);
    }

    virtual RuntimeValue evalExpressionInfix(const Ast::ExpressionInfix & expression){
        Global::debug(1) << "Evaluate expression " << expression.toString() << endl;
        using namespace Ast;
        switch (expression.getExpressionType()){
            case ExpressionInfix::Or : {
                return RuntimeValue(toBool(evaluate(expression.getLeft())) ||
                                    toBool(evaluate(expression.getRight())));
            }
            case ExpressionInfix::XOr : {
                return RuntimeValue(toBool(evaluate(expression.getLeft())) ^
                                    toBool(evaluate(expression.getRight())));
            }
            case ExpressionInfix::And : {
                return RuntimeValue(toBool(evaluate(expression.getLeft())) &&
                                    toBool(evaluate(expression.getRight())));
            }
            case ExpressionInfix::BitwiseOr : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) |
                                    (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::BitwiseXOr : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) ^
                                    (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::BitwiseAnd : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) &
                                    (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Assignment : {
                /* FIXME: is this needed? */
                break;
            }
            case ExpressionInfix::Equals : {
                return same(evaluate(expression.getLeft()), evaluate(expression.getRight()));
                break;
            }
            case ExpressionInfix::Unequals : {
                return RuntimeValue(!toBool(same(evaluate(expression.getLeft()), evaluate(expression.getRight()))));
            }
            case ExpressionInfix::GreaterThanEquals : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) >= toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::GreaterThan : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) > toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::LessThanEquals : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) <= toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::LessThan : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) < toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Add : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) + toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Subtract : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) - toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Multiply : {
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) * toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Divide : {
                /* FIXME: catch divide by 0 */
                return RuntimeValue(toNumber(evaluate(expression.getLeft())) / toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Modulo : {
                return RuntimeValue((int)toNumber(evaluate(expression.getLeft())) % (int)toNumber(evaluate(expression.getRight())));
            }
            case ExpressionInfix::Power : {
                return RuntimeValue(pow(toNumber(evaluate(expression.getLeft())), toNumber(evaluate(expression.getRight()))));
            }
        }

        ostringstream out;
        out << "Unknown expression: " << expression.toString();
        throw MugenException(out.str());
    }

    virtual void onExpressionInfix(const Ast::ExpressionInfix & expression){
        result = evalExpressionInfix(expression);
    }

    RuntimeValue evalExpressionUnary(const Ast::ExpressionUnary & expression){
        switch (expression.getExpressionType()){
            case Ast::ExpressionUnary::Not : {
                return RuntimeValue(!toBool(evaluate(expression.getExpression())));
            }
            case Ast::ExpressionUnary::Minus : {
                return RuntimeValue(-toNumber(evaluate(expression.getExpression())));
            }
            case Ast::ExpressionUnary::Negation : {
                return RuntimeValue(~(int)toNumber(evaluate(expression.getExpression())));
            }
        }

        ostringstream out;
        out << "Unknown expression: " << expression.toString();
        throw MugenException(out.str());
    }

    virtual void onExpressionUnary(const Ast::ExpressionUnary & expression){
        result = evalExpressionUnary(expression);
    }
};

RuntimeValue evaluate(const Ast::Value * value, const Environment & environment){
    try{
        Evaluator eval(environment);
        value->walk(eval);
        return eval.result;
    } catch (const MugenException & e){
        ostringstream out;
        out << "Error while evaluating expression `" << value->toString() << "': " << e.getReason();
        throw MugenException(out.str());
    }
}

}
<|endoftext|>


<commit_before>// CS3230-PA1-DE
// Multiplication of 2 n-digit integers.
// Naive O(n^2) multiplication algorithm (Karatsuba + Long Multiplication)
// Name: Tay Yang Shun

#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include <sstream>
#include <math.h>
#include <stdint.h>

using namespace std;

#define     FOR(i,s,e)      for(int64_t (i) = (s); (i) <  (e); ++(i))
#define     REP(i,n)        FOR(i,0,n)
#define     FORE(i,s,e)     for(int64_t (i) = (s); (i) <= (e); ++(i))

const string        Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char          RADIX_POINT = '.';
const int64_t       CHUNK_SIZE = 8;
const int64_t       MAXSIZE = 130000;
const int64_t       CUT_OFF = 300;
const int64_t       CHUNK_BASE = pow(10, CHUNK_SIZE);

long getMemoryUsage() {
    struct rusage usage;
    if(0 == getrusage(RUSAGE_SELF, &usage)) {
        return usage.ru_maxrss / 1000; // bytes
    } else {
        return 0;
    }
}

inline int64_t valueOf(char x){ // integer value of a digit
    if ('0' <= x and x <= '9') return x - '0';
    if ('A' <= x and x <= 'Z') return x - 'A' +10;
    return 255;
};

int64_t A[MAXSIZE], B[MAXSIZE], *temp, *res;

// Trim unnecessary zeros and radix point
string trim(string aStr){
    string X = aStr;
    //leading zeros:
    while(X.length()>1 and X[0] == '0'and X[1] != RADIX_POINT) X.erase(0,1); //000.001

    //trailing zeros and radix point:
    if (X.find(RADIX_POINT) != string::npos) {
        while (X.length() >= 1 and X[X.length()-1] == '0') {
            X.erase(X.length()-1,1);//0.010; 1.000
        }
        if (X.length() >= 1 and X[X.length()-1] == RADIX_POINT) {
            X.erase(X.length()-1);//123.
        }
        if (X[0] == RADIX_POINT) {
            X = "0" + X; // insert "0" into ".123"
        }
    };
    if (X == "") X = "0";
    return X;
};

// Convert string into array of integer:
// A[0] stores length of the number;
// Digits are stored in reverse order, example:
// X = "123456789"
// A = {3,6789,2345,1};
void convert2IntArr(string X, int64_t *A){

    X = trim(X);
    int64_t len = X.length() / CHUNK_SIZE;
    int64_t rem = (X.length() % CHUNK_SIZE);
    int64_t padLength;
    if (rem > 0) {
        padLength = CHUNK_SIZE - rem;
        for (int64_t i = 0; i < padLength; i++) {
            X = "0" + X;
        }
        len += 1;
    }
    A[0] = len;
    int64_t j = 1;
    for (int64_t i = X.length()-1; i >= 0; i-=CHUNK_SIZE) {
        int64_t num = 0;
        for (int64_t k = 0; k < CHUNK_SIZE; k++) {
            num += valueOf(X[i-k]) * pow(10, k);
        }
        A[j] = num;
        j++;
    }
}

string numberToString(int64_t number) {
    string s = "";
    if (number == 0) {
        return "0";
    } else {
        while (number > 0) {
            int64_t digit = number % 10;
            s = Digits[digit] + s;
            number /= 10;
        }
        return s;
    }
}

// Convert an array A to string:
string convertIntArr2Str(int64_t *A){
    string result = "";
    int64_t len = A[0];

    for (int64_t i = len; i >= 1; i--) {
        string s = numberToString(A[i]);
        int64_t currLen = s.length();
        for (int64_t j = 0; j < CHUNK_SIZE - currLen; j++) {
            s = "0" + s;
        }
        result += s;
    }
    return trim(result);
};

// Adding two arrays with offset: USEFUL for karatsuba algorithm!!
// A = A + B * base^offset
inline void add(int64_t *A, int64_t *B, int64_t offset, int64_t base){
    int64_t lenA = A[0], lenB = B[0];
    int64_t carry = 0;
    int64_t i = 1;
    offset++;

    int64_t b;
    while (i <= lenB or carry > 0) {
        if (offset > lenA) {
            A[offset] = 0;
        }
        if (i > lenB) {
            b = 0;
        } else {
            b = B[i];
        }

        carry = A[offset] + b + carry;
        A[offset] = carry % base;
        carry = carry >= base ? 1 : 0;

        i++;
        offset++;
    };

    offset--;
    while (offset > 1 and A[offset] == 0) {
        offset--;
    }
    if (offset > lenA) {
        A[0] = offset;
    }
};

inline void addFast(int64_t *A, int64_t *B, int64_t *C, int64_t offset, int64_t base){
    int64_t lenA = A[0], lenB = B[0];
    int64_t carry = 0;
    int64_t i = 1;
    int64_t firstOffset = offset * 2 + 1;

    int64_t b;
    while (i <= lenB or carry > 0) {
        if (firstOffset > lenA) {
            A[firstOffset] = 0;
        }
        if (i > lenB) {
            b = 0;
        } else {
            b = B[i];
        }

        carry = A[firstOffset] + b + carry;
        A[firstOffset] = carry % base;
        carry = carry >= base ? 1 : 0;

        i++;
        firstOffset++;
    };

    firstOffset--;
    while (firstOffset > 1 and A[firstOffset] == 0) {
        firstOffset--;
    }
    if (firstOffset > lenA) {
        A[0] = firstOffset;
    }

    // Second
    lenA = A[0];
    int64_t lenC = C[0];
    carry = 0;
    i = 1;
    int64_t c;
    offset++;

    while (i <= lenC or carry > 0) {
        if (offset > lenA) {
            A[offset] = 0;
        }
        if (i > lenC) {
            c = 0;
        } else {
            c = C[i];
        }

        carry = A[offset] + c + carry;
        A[offset] = carry % base;
        carry = carry >= base ? 1 : 0;

        i++;
        offset++;
    };

    offset--;
    while (offset > 1 and A[offset] == 0) {
        offset--;
    }
    if (offset > lenA) {
        A[0] = offset;
    }
};

inline void subtract(int64_t *A, int64_t *B, int64_t base) {
    // A = A - B
    // Requirement: A > B
    int64_t lenA = A[0];
    int64_t lenB = B[0];
    for (int64_t i = 1; i <= lenB; i++) {
        if (A[i] < B[i]) {
            int64_t j = i + 1;
            while (A[j] == 0) {
                A[j] = base - 1;
                j++;
            }
            A[j] -= 1;
            int64_t temp = A[i];
            A[i] = base + A[i] - B[i];
        } else {
            A[i] -= B[i];
        }
    }
    while (lenA > 1 and A[lenA] == 0) {
        lenA--;
    }
    A[0] = lenA;
};

inline void subtractFast(int64_t *A, int64_t *B, int64_t *C, int64_t base) {
    // A = A - B - C
    // Requirement: A > B
    int64_t lenA = A[0];
    int64_t lenB = B[0];
    int64_t lenC = C[0];

    int64_t j;
    for (int64_t i = 1; i <= lenB; i++) {
        if (A[i] < B[i]) {
            j = i + 1;
            while (A[j] == 0) {
                A[j] = base - 1;
                j++;
            }
            A[j] -= 1;
            A[i] = base + A[i] - B[i];
        } else {
            A[i] -= B[i];
        }
    }

    for (int64_t i = 1; i <= lenC; i++) {
        if (A[i] < C[i]) {
            j = i + 1;
            while (A[j] == 0) {
                A[j] = base - 1;
                j++;
            }
            A[j] -= 1;
            A[i] = base + A[i] - C[i];
        } else {
            A[i] -= C[i];
        }
    }

    while (lenA > 1 and A[lenA] == 0) {
        lenA--;
    }
    A[0] = lenA;
};

// Faster multiplication:
// res = A * B;
inline int64_t* mulTwoArrays(int64_t *A, int64_t *B, int64_t base) {
    int64_t lenA = A[0];
    int64_t lenB = B[0];

    res = new int64_t[MAXSIZE];
    temp = new int64_t[MAXSIZE];

    REP(i, A[0]+2) res[i] = temp[i] = 0;

    FORE(i, 1, lenA)
    FORE(j, 1, lenB) {
        temp[i+j-1] += A[i] * B[j];
    };

    int64_t lenR = lenA + lenB + 1;
    int64_t carry = 0;
    FORE(i, 1, lenR) {
        carry += temp[i];
        res[i] = carry % base;
        carry  = carry / base;
    };

    while (lenR>1 and res[lenR] == 0) {
        lenR--;
    }
    res[0] = lenR;
    delete[] temp;

    return res;
};

inline void splitAt(int64_t *input, int64_t *high, int64_t *low, int64_t R) {
    int64_t lenInput = input[0];

    for (int64_t i = 1; i <= R; i++) {
        low[i] = (i <= lenInput) ? input[i] : 0;
    }
    low[0] = (lenInput <= R) ? lenInput : R;

    for (int64_t i = 1; i <= R; i++) {
        high[i] = (i <= lenInput) ? input[i+R] : 0;
    }
    high[0] = (lenInput - R > 0) ? lenInput - R : 0;

};

int64_t* karatsuba(int64_t *A, int64_t *B, int64_t base) {
    int64_t lenA = A[0];
    int64_t lenB = B[0];

    if (lenA < CUT_OFF or lenB < CUT_OFF) {
        return mulTwoArrays(A, B, base);
    }

    int64_t R = ((lenA > lenB ? lenA : lenB)+1) / 2;

    int64_t highX[R+2];
    int64_t lowX[R+2];
    int64_t highY[R+2];
    int64_t lowY[R+2];
    splitAt(A, highX, lowX, R);
    splitAt(B, highY, lowY, R);

    int64_t *z0 = karatsuba(lowX, lowY, base);
    int64_t *z2 = karatsuba(highX, highY, base);

    add(lowX, highX, 0, base);
    add(lowY, highY, 0, base);

    int64_t *z1 = karatsuba(lowX, lowY, base);

    subtractFast(z1, z0, z2, base);
    addFast(z0, z2, z1, R, base);

    delete[] z1;
    delete[] z2;
    return z0;
}

int main() {
    int64_t T;
    string V, M, P;
    int64_t base;

    cin >> T;
    FORE(t, 1, T) {
        cin >> base;
        cin >> V >> M;

        convert2IntArr(V, A);
        convert2IntArr(M, B);
        string s = convertIntArr2Str(karatsuba(A, B, CHUNK_BASE));
        cout << s << endl;
    };
    // cout << "Memory used: " << getMemoryUsage() << " KB" << endl;
    return 0;
}
<commit_msg>[PA1] Optimize split<commit_after>// CS3230-PA1-DE
// Multiplication of 2 n-digit integers.
// Naive O(n^2) multiplication algorithm (Karatsuba + Long Multiplication)
// Name: Tay Yang Shun

#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include <sstream>
#include <math.h>
#include <stdint.h>

using namespace std;

#define     FOR(i,s,e)      for(int64_t (i) = (s); (i) <  (e); ++(i))
#define     REP(i,n)        FOR(i,0,n)
#define     FORE(i,s,e)     for(int64_t (i) = (s); (i) <= (e); ++(i))

const string        Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char          RADIX_POINT = '.';
const int64_t       CHUNK_SIZE = 8;
const int64_t       MAXSIZE = 130000;
const int64_t       CUT_OFF = 300;
const int64_t       CHUNK_BASE = pow(10, CHUNK_SIZE);

long getMemoryUsage() {
    struct rusage usage;
    if(0 == getrusage(RUSAGE_SELF, &usage)) {
        return usage.ru_maxrss / 1000; // bytes
    } else {
        return 0;
    }
}

inline int64_t valueOf(char x){ // integer value of a digit
    if ('0' <= x and x <= '9') return x - '0';
    if ('A' <= x and x <= 'Z') return x - 'A' +10;
    return 255;
};

int64_t A[MAXSIZE], B[MAXSIZE], *temp, *res;

// Trim unnecessary zeros and radix point
string trim(string aStr){
    string X = aStr;
    //leading zeros:
    while(X.length()>1 and X[0] == '0'and X[1] != RADIX_POINT) X.erase(0,1); //000.001

    //trailing zeros and radix point:
    if (X.find(RADIX_POINT) != string::npos) {
        while (X.length() >= 1 and X[X.length()-1] == '0') {
            X.erase(X.length()-1,1);//0.010; 1.000
        }
        if (X.length() >= 1 and X[X.length()-1] == RADIX_POINT) {
            X.erase(X.length()-1);//123.
        }
        if (X[0] == RADIX_POINT) {
            X = "0" + X; // insert "0" into ".123"
        }
    };
    if (X == "") X = "0";
    return X;
};

// Convert string into array of integer:
// A[0] stores length of the number;
// Digits are stored in reverse order, example:
// X = "123456789"
// A = {3,6789,2345,1};
void convert2IntArr(string X, int64_t *A){

    X = trim(X);
    int64_t len = X.length() / CHUNK_SIZE;
    int64_t rem = (X.length() % CHUNK_SIZE);
    int64_t padLength;
    if (rem > 0) {
        padLength = CHUNK_SIZE - rem;
        for (int64_t i = 0; i < padLength; i++) {
            X = "0" + X;
        }
        len += 1;
    }
    A[0] = len;
    int64_t j = 1;
    for (int64_t i = X.length()-1; i >= 0; i-=CHUNK_SIZE) {
        int64_t num = 0;
        for (int64_t k = 0; k < CHUNK_SIZE; k++) {
            num += valueOf(X[i-k]) * pow(10, k);
        }
        A[j] = num;
        j++;
    }
}

string numberToString(int64_t number) {
    string s = "";
    if (number == 0) {
        return "0";
    } else {
        while (number > 0) {
            int64_t digit = number % 10;
            s = Digits[digit] + s;
            number /= 10;
        }
        return s;
    }
}

// Convert an array A to string:
string convertIntArr2Str(int64_t *A){
    string result = "";
    int64_t len = A[0];

    for (int64_t i = len; i >= 1; i--) {
        string s = numberToString(A[i]);
        int64_t currLen = s.length();
        for (int64_t j = 0; j < CHUNK_SIZE - currLen; j++) {
            s = "0" + s;
        }
        result += s;
    }
    return trim(result);
};

// Adding two arrays with offset: USEFUL for karatsuba algorithm!!
// A = A + B * base^offset
inline void add(int64_t *A, int64_t *B, int64_t offset, int64_t base){
    int64_t lenA = A[0], lenB = B[0];
    int64_t carry = 0;
    int64_t i = 1;
    offset++;

    int64_t b;
    while (i <= lenB or carry > 0) {
        if (offset > lenA) {
            A[offset] = 0;
        }
        if (i > lenB) {
            b = 0;
        } else {
            b = B[i];
        }

        carry = A[offset] + b + carry;
        A[offset] = carry % base;
        carry = carry >= base ? 1 : 0;

        i++;
        offset++;
    };

    offset--;
    while (offset > 1 and A[offset] == 0) {
        offset--;
    }
    if (offset > lenA) {
        A[0] = offset;
    }
};

inline void addFast(int64_t *A, int64_t *B, int64_t *C, int64_t offset, int64_t base){
    int64_t lenA = A[0], lenB = B[0];
    int64_t carry = 0;
    int64_t i = 1;
    int64_t firstOffset = offset * 2 + 1;

    int64_t b;
    while (i <= lenB or carry > 0) {
        if (firstOffset > lenA) {
            A[firstOffset] = 0;
        }
        if (i > lenB) {
            b = 0;
        } else {
            b = B[i];
        }

        carry = A[firstOffset] + b + carry;
        A[firstOffset] = carry % base;
        carry = carry >= base ? 1 : 0;

        i++;
        firstOffset++;
    };

    firstOffset--;
    while (firstOffset > 1 and A[firstOffset] == 0) {
        firstOffset--;
    }
    if (firstOffset > lenA) {
        A[0] = firstOffset;
    }

    // Second
    lenA = A[0];
    int64_t lenC = C[0];
    carry = 0;
    i = 1;
    int64_t c;
    offset++;

    while (i <= lenC or carry > 0) {
        if (offset > lenA) {
            A[offset] = 0;
        }
        if (i > lenC) {
            c = 0;
        } else {
            c = C[i];
        }

        carry = A[offset] + c + carry;
        A[offset] = carry % base;
        carry = carry >= base ? 1 : 0;

        i++;
        offset++;
    };

    offset--;
    while (offset > 1 and A[offset] == 0) {
        offset--;
    }
    if (offset > lenA) {
        A[0] = offset;
    }
};

inline void subtract(int64_t *A, int64_t *B, int64_t base) {
    // A = A - B
    // Requirement: A > B
    int64_t lenA = A[0];
    int64_t lenB = B[0];
    for (int64_t i = 1; i <= lenB; i++) {
        if (A[i] < B[i]) {
            int64_t j = i + 1;
            while (A[j] == 0) {
                A[j] = base - 1;
                j++;
            }
            A[j] -= 1;
            int64_t temp = A[i];
            A[i] = base + A[i] - B[i];
        } else {
            A[i] -= B[i];
        }
    }
    while (lenA > 1 and A[lenA] == 0) {
        lenA--;
    }
    A[0] = lenA;
};

inline void subtractFast(int64_t *A, int64_t *B, int64_t *C, int64_t base) {
    // A = A - B - C
    // Requirement: A > B
    int64_t lenA = A[0];
    int64_t lenB = B[0];
    int64_t lenC = C[0];

    int64_t j;
    for (int64_t i = 1; i <= lenB; i++) {
        if (A[i] < B[i]) {
            j = i + 1;
            while (A[j] == 0) {
                A[j] = base - 1;
                j++;
            }
            A[j] -= 1;
            A[i] = base + A[i] - B[i];
        } else {
            A[i] -= B[i];
        }
    }

    for (int64_t i = 1; i <= lenC; i++) {
        if (A[i] < C[i]) {
            j = i + 1;
            while (A[j] == 0) {
                A[j] = base - 1;
                j++;
            }
            A[j] -= 1;
            A[i] = base + A[i] - C[i];
        } else {
            A[i] -= C[i];
        }
    }

    while (lenA > 1 and A[lenA] == 0) {
        lenA--;
    }
    A[0] = lenA;
};

// Faster multiplication:
// res = A * B;
inline int64_t* mulTwoArrays(int64_t *A, int64_t *B, int64_t base) {
    int64_t lenA = A[0];
    int64_t lenB = B[0];

    res = new int64_t[MAXSIZE];
    temp = new int64_t[MAXSIZE];

    REP(i, A[0]+2) res[i] = temp[i] = 0;

    FORE(i, 1, lenA)
    FORE(j, 1, lenB) {
        temp[i+j-1] += A[i] * B[j];
    };

    int64_t lenR = lenA + lenB + 1;
    int64_t carry = 0;
    FORE(i, 1, lenR) {
        carry += temp[i];
        res[i] = carry % base;
        carry  = carry / base;
    };

    while (lenR>1 and res[lenR] == 0) {
        lenR--;
    }
    res[0] = lenR;
    delete[] temp;

    return res;
};

inline void splitAt(int64_t *input, int64_t *high, int64_t *low, int64_t R) {
    int64_t lenInput = input[0];

    for (int64_t i = 1; i <= R; i++) {
        low[i] = (i <= lenInput) ? input[i] : 0;
        high[i] = (i <= lenInput) ? input[i+R] : 0;
    }
    low[0] = (lenInput <= R) ? lenInput : R;
    high[0] = (lenInput - R > 0) ? lenInput - R : 0;
};

int64_t* karatsuba(int64_t *A, int64_t *B, int64_t base) {
    int64_t lenA = A[0];
    int64_t lenB = B[0];

    if (lenA < CUT_OFF or lenB < CUT_OFF) {
        return mulTwoArrays(A, B, base);
    }

    int64_t R = ((lenA > lenB ? lenA : lenB)+1) / 2;

    int64_t highX[R+2];
    int64_t lowX[R+2];
    int64_t highY[R+2];
    int64_t lowY[R+2];
    splitAt(A, highX, lowX, R);
    splitAt(B, highY, lowY, R);

    int64_t *z0 = karatsuba(lowX, lowY, base);
    int64_t *z2 = karatsuba(highX, highY, base);

    add(lowX, highX, 0, base);
    add(lowY, highY, 0, base);

    int64_t *z1 = karatsuba(lowX, lowY, base);

    subtractFast(z1, z0, z2, base);
    addFast(z0, z2, z1, R, base);

    delete[] z1;
    delete[] z2;
    return z0;
}

int main() {
    int64_t T;
    string V, M, P;
    int64_t base;

    cin >> T;
    FORE(t, 1, T) {
        cin >> base;
        cin >> V >> M;

        convert2IntArr(V, A);
        convert2IntArr(M, B);
        string s = convertIntArr2Str(karatsuba(A, B, CHUNK_BASE));
        cout << s << endl;
    };
    // cout << "Memory used: " << getMemoryUsage() << " KB" << endl;
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>updated Aff_op to be created when it is actually possible to create it.  Change required by solver change for NKA creation time<commit_after><|endoftext|>


<commit_before>/******************************************************
 * cpu_tests.cpp - cpu unit tests
 * created 140204 jonathan howard (j@hovverd.com)
 ******************************************************/

#include "gtest/gtest.h"

#include "utils.h"
#include "cpu.h"
#include "opcodes.h"

TEST(OpCode, IsCorrectSize)
{
    ASSERT_TRUE(sizeof(INSTR_Arithmatic) == 4);
    ASSERT_TRUE(sizeof(INSTR_Register) == 4);
    ASSERT_TRUE(sizeof(INSTR_Immediate) == 4);
    ASSERT_TRUE(sizeof(INSTR_Flow) == 4);
    ASSERT_TRUE(sizeof(INSTR_Branch) == 4);
}
<commit_msg>CPU properly initializes registers<commit_after>/******************************************************
 * cpu_tests.cpp - cpu unit tests
 * created 140204 jonathan howard (j@hovverd.com)
 ******************************************************/

#include "gtest/gtest.h"

#include "utils.h"
#include "cpu.h"
#include "opcodes.h"

TEST(OpCode, IsCorrectSize)
{
    ASSERT_TRUE(sizeof(INSTR_Arithmatic) == 4);
    ASSERT_TRUE(sizeof(INSTR_Register) == 4);
    ASSERT_TRUE(sizeof(INSTR_Immediate) == 4);
    ASSERT_TRUE(sizeof(INSTR_Flow) == 4);
    ASSERT_TRUE(sizeof(INSTR_Branch) == 4);
}

TEST(CPU_Fetch, InitializesToNULL)
{
    CPU * cpu = new CPU();
    ASSERT_EQ(*R(cpu, -2), NULL);
}

<|endoftext|>


<commit_before><commit_msg>Added a simple gamma correction node - allows for "tonemapping" that doesn't influence black levels<commit_after><|endoftext|>


<commit_before>#pragma once

#include <depthai-shared/common/optional.hpp>
#include <nlohmann/json.hpp>

namespace dai {

/**
 * Specify properties for VideoEncoder such as profile, bitrate, ...
 */
struct VideoEncoderProperties {
    /**
     * Rate control mode specifies if constant or variable bitrate should be used (H264 / H265)
     */
    enum class RateControlMode : int { CBR, VBR };

    /**
     * Encoding profile, H264 (AVC), H265 (HEVC) or MJPEG
     */
    enum class Profile : int { H264_BASELINE, H264_HIGH, H264_MAIN, H265_MAIN, MJPEG };
    /**
     * Specifies preferred bitrate (in bit/s) of compressed output bitstream in CBR mode
     *
     * "0" for automatic computation, based on input resolution and FPS:
     * 720p30: 4Mbps, 1080p30: 8.5Mbps, 1440p30: 14Mbps, 2160p30: 20Mbps
     */
    std::int32_t bitrate = 0;
    /**
     * Every x number of frames a keyframe will be inserted
     */
    std::int32_t keyframeFrequency = 30;
    /**
     * Specifies maximum bitrate (in bit/s) of compressed output bitstream in CBR mode
     *
     * "0" to follow `bitrate` setting
     */
    std::int32_t maxBitrate = 0;
    /**
     * Specifies number of B frames to be inserted
     */
    std::int32_t numBFrames = 0;
    /**
     * This options specifies how many frames are available in this node's pool.
     * Helps when receiver is slow at consuming.
     *
     * Value "0" indicates automatic number of frames assignment
     */
    std::uint32_t numFramesPool = 0;
    /**
     * Encoding profile, H264, H265 or MJPEG
     */
    Profile profile = Profile::H264_BASELINE;
    /**
     * Value between 0-100% (approximates quality)
     */
    std::int32_t quality = 80;
    /**
     * Lossless mode ([M]JPEG only)
     */
    bool lossless = false;
    /**
     * Rate control mode specifies if constant or variable bitrate should be used (H264 / H265)
     */
    RateControlMode rateCtrlMode = RateControlMode::CBR;
    /**
     * Frame rate
     */
    float frameRate = 30.0f;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(VideoEncoderProperties,
                                   bitrate,
                                   keyframeFrequency,
                                   maxBitrate,
                                   numBFrames,
                                   numFramesPool,
                                   profile,
                                   quality,
                                   lossless,
                                   rateCtrlMode,
                                   frameRate);

}  // namespace dai
<commit_msg>make clangformat<commit_after>#pragma once

#include <depthai-shared/common/optional.hpp>
#include <nlohmann/json.hpp>

namespace dai {

/**
 * Specify properties for VideoEncoder such as profile, bitrate, ...
 */
struct VideoEncoderProperties {
    /**
     * Rate control mode specifies if constant or variable bitrate should be used (H264 / H265)
     */
    enum class RateControlMode : int { CBR, VBR };

    /**
     * Encoding profile, H264 (AVC), H265 (HEVC) or MJPEG
     */
    enum class Profile : int { H264_BASELINE, H264_HIGH, H264_MAIN, H265_MAIN, MJPEG };
    /**
     * Specifies preferred bitrate (in bit/s) of compressed output bitstream in CBR mode
     *
     * "0" for automatic computation, based on input resolution and FPS:
     * 720p30: 4Mbps, 1080p30: 8.5Mbps, 1440p30: 14Mbps, 2160p30: 20Mbps
     */
    std::int32_t bitrate = 0;
    /**
     * Every x number of frames a keyframe will be inserted
     */
    std::int32_t keyframeFrequency = 30;
    /**
     * Specifies maximum bitrate (in bit/s) of compressed output bitstream in CBR mode
     *
     * "0" to follow `bitrate` setting
     */
    std::int32_t maxBitrate = 0;
    /**
     * Specifies number of B frames to be inserted
     */
    std::int32_t numBFrames = 0;
    /**
     * This options specifies how many frames are available in this node's pool.
     * Helps when receiver is slow at consuming.
     *
     * Value "0" indicates automatic number of frames assignment
     */
    std::uint32_t numFramesPool = 0;
    /**
     * Encoding profile, H264, H265 or MJPEG
     */
    Profile profile = Profile::H264_BASELINE;
    /**
     * Value between 0-100% (approximates quality)
     */
    std::int32_t quality = 80;
    /**
     * Lossless mode ([M]JPEG only)
     */
    bool lossless = false;
    /**
     * Rate control mode specifies if constant or variable bitrate should be used (H264 / H265)
     */
    RateControlMode rateCtrlMode = RateControlMode::CBR;
    /**
     * Frame rate
     */
    float frameRate = 30.0f;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
    VideoEncoderProperties, bitrate, keyframeFrequency, maxBitrate, numBFrames, numFramesPool, profile, quality, lossless, rateCtrlMode, frameRate);

}  // namespace dai
<|endoftext|>