<commit_before>//-----------------------------------------------------------------------------
// name: sig_gen.cpp
// desc: real-time waveforms!
//
// author: Nikhil Goel (nmgoel@stanford.edu)
//   date: fall 2015, Music256a taught by Ge Wang (righteous!)
//   uses: RtAudio by Gary Scavone
//-----------------------------------------------------------------------------
#include "RtAudio.h"
#include <math.h>
#include <iostream>
#include <cstdlib>
using namespace std;

/* ----------------------#defines-------------------- */

// A sample is a discrete time signal derived from a continuous signal
#define SAMPLE double

// RtAudio's data format type. Normalized between +- 1
#define MY_FORMAT RTAUDIO_FLOAT64

// Sample Rate = (avg. # of samples)/second = 1/T, where T is sampling interval
#define MY_SRATE 44100

// number of channels
#define MY_CHANNELS 2

#define MY_PIE 3.14159265358979

// amplitude definitions
#define MAX_AMP 1.0
#define MIN_AMP -1.0
#define BASELINE 0

// a width multiplier to elongate the sound of the waves
#define WIDTH_MULTIPLIER 1

/* ----------------------globals--------------------- */

// frequency
SAMPLE g_freq = 440;

// sample number
SAMPLE g_t = 0;

// wave width (default square wave)
SAMPLE g_width = 0.5;

// type of signal requested by user, enumerated in function determine_signal
int g_sig = 0;

// --input flag
bool flag = false;

/*---------------------------------------------------- */

/*
 * @funtion audio_callback The RtAudioCallback function.
 * @param outputBuffer Pointer to the buffer that holds the output.
 * @param inputBuffer Pointer to the buffer that holds the input.
 * @param numFrames The number of sample frames held by input buffer
          and written to output buffer.
 * @param streamTime The number of seconds (double) that the signal streams.
 * @param status Notifies if there is an output/input overflow/underflow.
 * @param data Pointer to optional data provided by the client
          when opening the stream (default = NULL).
 * @return Zero to maintain normal stream. One to stop the stream and drain the
           output buffer. Two to abort the stream immediately.
 */
int audio_callback(void *outputBuffer, void *inputBuffer, unsigned int numFrames,
     double streamTime, RtAudioStreamStatus status, void *data) {

         // Fundamental period of the wave.
         double period = 1 / g_freq;

         // Difference between period and the width. Used by the right part of a saw tooth.
         double rmdr = period - (g_width * period);

         // Difference in value between consecutive samples for the left portion of the saw.
         double left_sample_step = (MAX_AMP * 2) / (g_width * period);

         // Difference in value between consecutive samples for the right portion of the saw.
         double right_sample_step = (MAX_AMP * 2) / rmdr;

         // stderr prints info and err messages (info about callback here)
         cerr << ".";

         // outputBuffer points to array of SAMPLEs
         SAMPLE *buffer = (SAMPLE *) outputBuffer;
         SAMPLE *ibuffer = (SAMPLE *) inputBuffer;

         for (int i = 0; i < numFrames; i++)
         {
            // Position of the current sample relative to the current wave period.
            double sample_pos = fmod(g_t / MY_SRATE, period);

            /* Create different waveforms based on user input by first generating a signal in the
             * even-indexed slots of the buffer. */
            switch(g_sig) {

                // sine
                case 1:
                    buffer[i * MY_CHANNELS] = sin(2 * MY_PIE * g_freq * g_t / MY_SRATE);
                    break;

                // saw
                case 2:

                    /* Produces left portion of saw wave (pos. slope). Steps up the left portion's
                       hypotenuse with values based on the current sample position. */
                    if (sample_pos <= g_width * period) {
                        buffer[i * MY_CHANNELS] = left_sample_step * sample_pos;
                    }

                    /* Produces right portion of saw wave (neg. slope). Steps down the right portion's
                       hypotenuse. Uses the difference of the period and the current position. */
                    else {
                        buffer[i * MY_CHANNELS] = right_sample_step * (period - sample_pos);
                    }
                    break;

                // pulse
                case 3:

                    /* (Sample % period) <= delay time of the wave.
                     * Produces rectangular wave above the baseline. */
                    if (sample_pos <= g_width * period) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    }

                    /* (Sample % period) >= delay time of the wave.
                     * Produces rectangular wave below the baseline. */
                    else if (sample_pos >= g_width * period) {
                        buffer[i * MY_CHANNELS] = MIN_AMP;
                    }
                    break;

                // noise
                case 4:
                    buffer[i * MY_CHANNELS] = (rand() % 100) / 10;
                    break;

                // impulse train
                case 5:

                    // signal sample shoots an impulse at the given frequency's fundamental period
                    if (fmod(g_t, round(period * MY_SRATE)) == 0) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    } else {
                        buffer[i * MY_CHANNELS] = BASELINE;
                    }
                    break;

                // if none of the above, stop the stream immediately.
                default:
                    return 2;

                // one ring to modulate them all (multiplies audio input by wave)
                if (flag) {
                    buffer[i * MY_CHANNELS] *= ibuffer[i * MY_CHANNELS];
                }
            }

             // copy signal into odd-indexed slots of the buffer
             for(int j = 1; j < MY_CHANNELS; j++)
                 buffer[i * MY_CHANNELS + j] = buffer[i * MY_CHANNELS];

             // increment sample number
             g_t += 1.0;
         }
         return 0;
}

/*
 * @funtion determine_signal Returns an integer based on the type of command given.
            Allows me to easily use a switch statement in the audio callback function
            for the different waveforms.
 * @param argc Number of command line arguments.
 * @param argv Array of strings containing command line arguments.
 */
int determine_signal(int argc, const char *type) {

    string arg = string(type);

    // sine
    if (arg == "--sine") {
        return 1;
    }

    // saw
    else if (arg == "--saw"){
        return 2;
    }

    // pulse
    else if (arg == "--pulse"){
        return 3;
    }

    // noise
    else if (arg == "--noise"){
        return 4;
    }

    //impulse
    else if (arg == "--impulse") {
        return 5;
    }

    // arg is some other input not defined by this program
    else {
        cout << "Must provide a valid type of waveform. --sine, --saw, --noise, --pulse, --impulse." << endl;
        return -1;
    }
}

/*
 * @funtion check_args Provides error-checking and robustness on command line arguments given by a user.
 * @param argc Number of command line arguments.
 * @param arg Array of strings containing command line arguments.
 * @return -1 if any errors. Returns integer between and including 1 and 5 if there the args are properly formed.
 */
int check_args(int argc, const char* argv[]) {

    char *endptr = 0;

        // error: ./sig_gen with no additional arguments
        if (argc <= 1) {
            cout << "Not enough arguments. Must at least give type of wave." << endl;
            cout << "Input should be of form ./sig_gen [type] [frequency] [width] --input ... ";
            cout << "where [frequency], [width], and --input are optional." << endl;
            return -1;
        }

        // check second argument: type
        if (argc > 1) {
            g_sig = determine_signal(argc, argv[1]);
            if (g_sig == -1) return g_sig;

            if (argc == 2) {
                cout << "No frequency given. Using 440Hz as default frequency." << endl;
                cout << "No width given. Using 0.5 as default width." << endl;
            }
        }

        // check third argument: frequency
        if (argc > 2) {

            // check for input flag
            if (strcmp(argv[2], "--input") == 0) {
                flag = true;
                cout << "No frequency given. Using 440Hz as default frequency." << endl;
            }

            // check for frequency
            else {
                g_freq = strtod(argv[2], &endptr);
                if (*endptr != '\0' || endptr == argv[2] || g_freq <= 0) {
                    cout << "The frequency you entered is not a double above 0." << endl;
                    return -1;
                }
            }

            // no width given, use default width
            cout << "No width given. Using 0.5 as default width." << endl;
        }

        // check fourth argument: width
        if (argc > 3) {

            // check for input flag
            if (strcmp(argv[3], "--input") == 0) {
                flag = true;
            }

            // check width
            else {
                g_width = strtod(argv[3], &endptr);
                if ((*endptr != '\0' || endptr == argv[3]) || (g_width >= 1.0 || g_width <= 0)) {
                    cout << "The width must be a double in the range (0, 1)." << endl;
                    return -1;
                }
            }
        }

        // check fifth argument: can only be input flag
        if (argc > 4) {
            if (strcmp(argv[4], "--input") == 0) {
                flag = true;
            } else {
                cout << "--input is the only acceptable flag after the frequency and width arguments." << endl;
                cout << "Proceeding with no input functionality." << endl;
            }
        }

        // error: more than five arguments
        if (argc > 5) cout << "Ignoring extraneous arguments..." << endl;

        return g_sig;
}

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

    // checks the command line args and determines the desired signal
    if ((g_sig = check_args(argc, argv)) == -1) exit(1);

    // instantiate RtAudio object
    RtAudio *audio = new RtAudio(RtAudio::MACOSX_CORE);

    // apply the width mutliplier (1 by default)
    g_width *= WIDTH_MULTIPLIER;

    // frame size
    unsigned int bufferFrames = 512;
    unsigned int bufferBytes = 0;

    // check for audio devices
    if(audio->getDeviceCount() < 1)
    {
        cout << "no audio devices found!" << endl;
        exit(1);
    }

    // let RtAudio print messages to stderr.
    audio->showWarnings(true);

    // set input and output parameters
    RtAudio::StreamParameters iParams, oParams;
    iParams.deviceId = audio->getDefaultInputDevice();
    iParams.nChannels = MY_CHANNELS;
    iParams.firstChannel = 0;
    oParams.deviceId = audio->getDefaultOutputDevice();
    oParams.nChannels = MY_CHANNELS;
    oParams.firstChannel = 0;

    // #############testing purposes############
    printf("%u\n", iParams.deviceId);
    printf("%u\n", audio->getDeviceCount());

    // create stream options
    RtAudio::StreamOptions options;

    try {
        // open a stream
        audio->openStream(&oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames,
            &audio_callback, (void *) &bufferBytes, &options);
    }
    catch(RtError& e)
    {
        cout << e.getMessage() << endl;
        exit(1);
    }

    // compute
    bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE);

    // test RtAudio functionality for reporting latency.
    cout << "stream latency: " << audio->getStreamLatency() << " frames" << endl;

    // go for it
    try {
        // start stream
        audio->startStream();

        // get input
        char input;
        std::cout << "running... press <enter> to quit (buffer frames: " << bufferFrames << ")" << endl;
        std::cin.get(input);

        // stop the stream.
        audio->stopStream();
    }
    catch(RtError& e)
    {
        // print error message
        cout << e.getMessage() << endl;
        goto cleanup;
    }

    cleanup:
        // close if open
        if(audio->isStreamOpen())
            audio->closeStream();

    return 0;
}
<commit_msg>input not yet functional. macbook air input not recognized<commit_after>//-----------------------------------------------------------------------------
// name: sig_gen.cpp
// desc: real-time waveforms!
//
// author: Nikhil Goel (nmgoel@stanford.edu)
//   date: fall 2015, Music256a taught by Ge Wang (righteous!)
//   uses: RtAudio by Gary Scavone
//-----------------------------------------------------------------------------
#include "RtAudio.h"
#include <math.h>
#include <iostream>
#include <cstdlib>
using namespace std;

/* ----------------------#defines-------------------- */

// A sample is a discrete time signal derived from a continuous signal
#define SAMPLE double

// RtAudio's data format type. Normalized between +- 1
#define MY_FORMAT RTAUDIO_FLOAT64

// Sample Rate = (avg. # of samples)/second = 1/T, where T is sampling interval
#define MY_SRATE 44100

// number of channels
#define MY_CHANNELS 2

#define MY_PIE 3.14159265358979

// amplitude definitions
#define MAX_AMP 1.0
#define MIN_AMP -1.0
#define BASELINE 0

// a width multiplier to elongate the sound of the waves
#define WIDTH_MULTIPLIER 1

/* ----------------------globals--------------------- */

// frequency
SAMPLE g_freq = 440;

// sample number
SAMPLE g_t = 0;

// wave width (default square wave)
SAMPLE g_width = 0.5;

// type of signal requested by user, enumerated in function determine_signal
int g_sig = 0;

// --input flag
bool flag = false;

/*---------------------------------------------------- */

/*
 * @funtion audio_callback The RtAudioCallback function.
 * @param outputBuffer Pointer to the buffer that holds the output.
 * @param inputBuffer Pointer to the buffer that holds the input.
 * @param numFrames The number of sample frames held by input buffer
          and written to output buffer.
 * @param streamTime The number of seconds (double) that the signal streams.
 * @param status Notifies if there is an output/input overflow/underflow.
 * @param data Pointer to optional data provided by the client
          when opening the stream (default = NULL).
 * @return Zero to maintain normal stream. One to stop the stream and drain the
           output buffer. Two to abort the stream immediately.
 */
int audio_callback(void *outputBuffer, void *inputBuffer, unsigned int numFrames,
     double streamTime, RtAudioStreamStatus status, void *data) {

         // Fundamental period of the wave.
         double period = 1 / g_freq;

         // Difference between period and the width. Used by the right part of a saw tooth.
         double rmdr = period - (g_width * period);

         // Difference in value between consecutive samples for the left portion of the saw.
         double left_sample_step = (MAX_AMP * 2) / (g_width * period);

         // Difference in value between consecutive samples for the right portion of the saw.
         double right_sample_step = (MAX_AMP * 2) / rmdr;

         // stderr prints info and err messages (info about callback here)
         cerr << ".";

         // outputBuffer points to array of SAMPLEs
         SAMPLE *buffer = (SAMPLE *) outputBuffer;
         SAMPLE *ibuffer = (SAMPLE *) inputBuffer;

         for (int i = 0; i < numFrames; i++)
         {
            // Position of the current sample relative to the current wave period.
            double sample_pos = fmod(g_t / MY_SRATE, period);

            /* Create different waveforms based on user input by first generating a signal in the
             * even-indexed slots of the buffer. */
            switch(g_sig) {

                // sine
                case 1:
                    buffer[i * MY_CHANNELS] = sin(2 * MY_PIE * g_freq * g_t / MY_SRATE);
                    break;

                // saw
                case 2:

                    /* Produces left portion of saw wave (pos. slope). Steps up the left portion's
                       hypotenuse with values based on the current sample position. */
                    if (sample_pos <= g_width * period) {
                        buffer[i * MY_CHANNELS] = left_sample_step * sample_pos;
                    }

                    /* Produces right portion of saw wave (neg. slope). Steps down the right portion's
                       hypotenuse. Uses the difference of the period and the current position. */
                    else {
                        buffer[i * MY_CHANNELS] = right_sample_step * (period - sample_pos);
                    }
                    break;

                // pulse
                case 3:

                    /* (Sample % period) <= delay time of the wave.
                     * Produces rectangular wave above the baseline. */
                    if (sample_pos <= g_width * period) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    }

                    /* (Sample % period) >= delay time of the wave.
                     * Produces rectangular wave below the baseline. */
                    else if (sample_pos >= g_width * period) {
                        buffer[i * MY_CHANNELS] = MIN_AMP;
                    }
                    break;

                // noise
                case 4:
                    buffer[i * MY_CHANNELS] = (rand() % 100) / 10;
                    break;

                // impulse train
                case 5:

                    // signal sample shoots an impulse at the given frequency's fundamental period
                    if (fmod(g_t, round(period * MY_SRATE)) == 0) {
                        buffer[i * MY_CHANNELS] = MAX_AMP;
                    } else {
                        buffer[i * MY_CHANNELS] = BASELINE;
                    }
                    break;

                // if none of the above, stop the stream immediately.
                default:
                    return 2;

                // one ring to modulate them all (multiplies audio input by wave)
                if (flag) {
                    buffer[i * MY_CHANNELS] *= ibuffer[i * MY_CHANNELS];
                }
            }

             // copy signal into odd-indexed slots of the buffer
             for(int j = 1; j < MY_CHANNELS; j++)
                 buffer[i * MY_CHANNELS + j] = buffer[i * MY_CHANNELS];

             // increment sample number
             g_t += 1.0;
         }
         return 0;
}

/*
 * @funtion determine_signal Returns an integer based on the type of command given.
            Allows me to easily use a switch statement in the audio callback function
            for the different waveforms.
 * @param argc Number of command line arguments.
 * @param argv Array of strings containing command line arguments.
 */
int determine_signal(int argc, const char *type) {

    string arg = string(type);

    // sine
    if (arg == "--sine") {
        return 1;
    }

    // saw
    else if (arg == "--saw"){
        return 2;
    }

    // pulse
    else if (arg == "--pulse"){
        return 3;
    }

    // noise
    else if (arg == "--noise"){
        return 4;
    }

    //impulse
    else if (arg == "--impulse") {
        return 5;
    }

    // arg is some other input not defined by this program
    else {
        cout << "Must provide a valid type of waveform. --sine, --saw, --noise, --pulse, --impulse." << endl;
        return -1;
    }
}

/*
 * @funtion check_args Provides error-checking and robustness on command line arguments given by a user.
 * @param argc Number of command line arguments.
 * @param arg Array of strings containing command line arguments.
 * @return -1 if any errors. Returns integer between and including 1 and 5 if there the args are properly formed.
 */
int check_args(int argc, const char* argv[]) {

    char *endptr = 0;

        // error: ./sig_gen with no additional arguments
        if (argc <= 1) {
            cout << "Not enough arguments. Must at least give type of wave." << endl;
            cout << "Input should be of form ./sig_gen [type] [frequency] [width] --input ... ";
            cout << "where [frequency], [width], and --input are optional." << endl;
            return -1;
        }

        // check second argument: type
        if (argc > 1) {
            g_sig = determine_signal(argc, argv[1]);
            if (g_sig == -1) return g_sig;

            if (argc == 2) {
                cout << "No frequency given. Using 440Hz as default frequency." << endl;
                cout << "No width given. Using 0.5 as default width." << endl;
            }
        }

        // check third argument: frequency
        if (argc > 2) {

            // check for input flag
            if (strcmp(argv[2], "--input") == 0) {
                flag = true;
                cout << "No frequency given. Using 440Hz as default frequency." << endl;
            }

            // check for frequency
            else {
                g_freq = strtod(argv[2], &endptr);
                if (*endptr != '\0' || endptr == argv[2] || g_freq <= 0) {
                    cout << "The frequency you entered is not a double above 0." << endl;
                    return -1;
                }
            }

            // no width given, use default width
            cout << "No width given. Using 0.5 as default width." << endl;
        }

        // check fourth argument: width
        if (argc > 3) {

            // check for input flag
            if (strcmp(argv[3], "--input") == 0) {
                flag = true;
            }

            // check width
            else {
                g_width = strtod(argv[3], &endptr);
                if ((*endptr != '\0' || endptr == argv[3]) || (g_width >= 1.0 || g_width <= 0)) {
                    cout << "The width must be a double in the range (0, 1)." << endl;
                    return -1;
                }
            }
        }

        // check fifth argument: can only be input flag
        if (argc > 4) {
            if (strcmp(argv[4], "--input") == 0) {
                flag = true;
            } else {
                cout << "--input is the only acceptable flag after the frequency and width arguments." << endl;
                cout << "Proceeding with no input functionality." << endl;
            }
        }

        // error: more than five arguments
        if (argc > 5) cout << "Ignoring extraneous arguments..." << endl;

        return g_sig;
}

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

    // checks the command line args and determines the desired signal
    if ((g_sig = check_args(argc, argv)) == -1) exit(1);

    // instantiate RtAudio object
    RtAudio *audio = new RtAudio(RtAudio::MACOSX_CORE);

    // apply the width mutliplier (1 by default)
    g_width *= WIDTH_MULTIPLIER;

    // frame size
    unsigned int bufferFrames = 512;
    unsigned int bufferBytes = 0;

    // check for audio devices
    if(audio->getDeviceCount() < 1)
    {
        cout << "no audio devices found!" << endl;
        exit(1);
    }

    // let RtAudio print messages to stderr.
    audio->showWarnings(true);

    // set input and output parameters
    RtAudio::StreamParameters iParams, oParams;
    iParams.deviceId = audio->getDefaultInputDevice();
    iParams.nChannels = MY_CHANNELS;
    iParams.firstChannel = 0;
    oParams.deviceId = audio->getDefaultOutputDevice();
    oParams.nChannels = MY_CHANNELS;
    oParams.firstChannel = 0;

    // create stream options
    RtAudio::StreamOptions options;

    try {
        // open a stream
        audio->openStream(&oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames,
            &audio_callback, (void *) &bufferBytes, &options);
    }
    catch(RtError& e)
    {
        cout << e.getMessage() << endl;
        exit(1);
    }

    // compute
    bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE);

    // test RtAudio functionality for reporting latency.
    cout << "stream latency: " << audio->getStreamLatency() << " frames" << endl;

    // go for it
    try {
        // start stream
        audio->startStream();

        // get input
        char input;
        std::cout << "running... press <enter> to quit (buffer frames: " << bufferFrames << ")" << endl;
        std::cin.get(input);

        // stop the stream.
        audio->stopStream();
    }
    catch(RtError& e)
    {
        // print error message
        cout << e.getMessage() << endl;
        goto cleanup;
    }

    cleanup:
        // close if open
        if(audio->isStreamOpen())
            audio->closeStream();

    return 0;
}
<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_LA_CONTAINER_DYNAMICVECTOR_HH
#define DUNE_PYMOR_LA_CONTAINER_DYNAMICVECTOR_HH

#include <memory>

#include <dune/common/dynvector.hh>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <dune/common/dynmatrix.hh>
#pragma GCC diagnostic pop
#include <dune/common/float_cmp.hh>

#include "interfaces.hh"

namespace Dune {
namespace Pymor {

namespace Operators {

template< class ScalarImp >
class DuneDynamic;

template< class ScalarImp >
class DuneDynamicInverse;

}

namespace LA {

template< class ScalarImp = double >
class DuneDynamicVector;

template< class ScalarImp = double >
class DuneDynamicVectorTraits
{
public:
  typedef ScalarImp                         ScalarType;
  typedef DuneDynamicVector< ScalarType >   derived_type;
  typedef Dune::DynamicVector< ScalarType > BackendType;
};

/**
 * \brief An implementation of Dune::Pymor::LA::VectorInterface using Dune::DynamicVector< double >.
 *
 * \see   Dune::Pymor::LA::VectorInterface
 */
template< class ScalarImp >
class DuneDynamicVector
  : public Dune::Pymor::LA::VectorInterface< DuneDynamicVectorTraits< ScalarImp > >
  , public ProvidesBackend< DuneDynamicVectorTraits< ScalarImp > >
{
  typedef Dune::Pymor::LA::VectorInterface< DuneDynamicVectorTraits< ScalarImp > > BaseType;
public:
  typedef DuneDynamicVectorTraits< ScalarImp >  Traits;
  typedef typename Traits::derived_type         ThisType;
  typedef typename Traits::ScalarType           ScalarType;
  typedef typename Traits::BackendType          BackendType;

  DuneDynamicVector(const int size = 0, const ScalarType value = ScalarType(0));

  /**
   * \attention This class takes ownership of backend_ptr!
   */
  DuneDynamicVector(BackendType* backend_ptr);

  DuneDynamicVector(std::unique_ptr< BackendType >&& backend_ptr);

  DuneDynamicVector(const ThisType& other) = delete;

  ThisType& operator=(const ThisType& other) = delete;

  DuneDynamicVector(ThisType&& source);

  ThisType& operator=(ThisType&& source);

  ThisType copy() const;

  unsigned int dim() const;

  bool has_equal_shape(const ThisType& other) const;

  bool almost_equal(const ThisType& other,
                    const ScalarType epsilon = Dune::FloatCmp::DefaultEpsilon< ScalarType >::value()) const;

  using BaseType::almost_equal;

  void scal(const ScalarType& alpha);

  void axpy(const ScalarType& alpha, const ThisType& xx) throw (Exception::sizes_do_not_match);

  using BaseType::axpy;

  ScalarType dot(const ThisType& other) const throw (Exception::sizes_do_not_match);

  using BaseType::dot;

  ScalarType l1_norm() const;

  ScalarType l2_norm() const;

  ScalarType sup_norm() const;

  std::vector< ScalarType > components(const std::vector< int >& component_indices) const
    throw (Exception::sizes_do_not_match, Exception::index_out_of_range);

  std::vector< ScalarType > amax() const;

  void add(const ThisType& other, ThisType& result) const throw (Exception::sizes_do_not_match);

  using BaseType::add;

  void iadd(const ThisType& other) throw (Exception::sizes_do_not_match);

  using BaseType::iadd;

  void sub(const ThisType& other, ThisType& result) const throw (Exception::sizes_do_not_match);

  using BaseType::sub;

  void isub(const ThisType& other) throw (Exception::sizes_do_not_match);

  using BaseType::isub;

  BackendType& backend();

  const BackendType& backend() const;

private:
  static int assert_is_not_negative(const int ii) throw (Exception::index_out_of_range);

  friend class Operators::DuneDynamic< ScalarType >;
  friend class Operators::DuneDynamicInverse< ScalarType >;

  std::unique_ptr< BackendType > backend_;
}; // class DuneDynamicVector

template< class ScalarImp = double >
class DuneDynamicMatrix;

template< class ScalarImp = double >
class DuneDynamicMatrixTraits
{
public:
  typedef ScalarImp                         ScalarType;
  typedef DuneDynamicMatrix< ScalarType >   derived_type;
  typedef Dune::DynamicMatrix< ScalarType > BackendType;
};

template< class ScalarImp >
class DuneDynamicMatrix
  : public Dune::Pymor::LA::MatrixInterface< DuneDynamicMatrixTraits< ScalarImp > >
{
public:
  typedef DuneDynamicMatrixTraits< ScalarImp >  Traits;
  typedef typename Traits::derived_type         ThisType;
  typedef typename Traits::ScalarType           ScalarType;
  typedef typename Traits::BackendType          BackendType;

public:
  DuneDynamicMatrix(const int rr = 0, const int cc = 0, const ScalarType value = ScalarType(0));

  /**
   * \attention This class takes ownership of backend_ptr!
   */
  DuneDynamicMatrix(BackendType* backend_ptr);

  DuneDynamicMatrix(std::unique_ptr< BackendType >&& backend_ptr);

  DuneDynamicMatrix(const ThisType& other) = delete;

  ThisType& operator=(const ThisType& other) = delete;

  DuneDynamicMatrix(ThisType&& source);

  ThisType& operator=(ThisType&& source);

  ThisType copy() const;

  unsigned int dim_source() const;

  unsigned int dim_range() const;

  bool has_equal_shape(const ThisType& other) const;

  void scal(const ScalarType& alpha);

  void axpy(const ScalarType& alpha, const ThisType& x) throw (Exception::sizes_do_not_match);

  BackendType& backend();

  const BackendType& backend() const;

private:
  static int assert_is_not_negative(const int ii) throw (Exception::index_out_of_range);

  friend class Operators::DuneDynamic< ScalarType >;
  friend class Operators::DuneDynamicInverse< ScalarType >;

  std::unique_ptr< BackendType > backend_;
}; // class DuneDynamicMatrix

template< class S >
static DuneDynamicVector< S > createContainer(const DuneDynamicVector< S >&, const size_t size)
{
  return DuneDynamicVector< S >(size, S(1));
}

template< class S >
static DuneDynamicMatrix< S > createContainer(const DuneDynamicMatrix< S >&, const size_t size)
{
  typedef Dune::DynamicMatrix< S > BackendType;
  BackendType* matrix = new BackendType(size, size, S(0));
  for (size_t ii = 0; ii < size; ++ii)
    matrix->operator[](ii)[ii] = S(1);
  return DuneDynamicMatrix< S >(matrix);
}

} // namespace LA
} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_LA_CONTAINER_DYNAMICVECTOR_HH
<commit_msg>[la.container.dunedynamic]<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_LA_CONTAINER_DYNAMICVECTOR_HH
#define DUNE_PYMOR_LA_CONTAINER_DYNAMICVECTOR_HH

#include <memory>

#include <dune/common/dynvector.hh>
#include <dune/stuff/common/disable_warnings.hh>
  #include <dune/common/dynmatrix.hh>
#include <dune/stuff/common/reenable_warnings.hh>
#include <dune/common/float_cmp.hh>

#include "interfaces.hh"

namespace Dune {
namespace Pymor {

namespace Operators {

template< class ScalarImp >
class DuneDynamic;

template< class ScalarImp >
class DuneDynamicInverse;

}

namespace LA {

template< class ScalarImp = double >
class DuneDynamicVector;

template< class ScalarImp = double >
class DuneDynamicVectorTraits
{
public:
  typedef ScalarImp                         ScalarType;
  typedef DuneDynamicVector< ScalarType >   derived_type;
  typedef Dune::DynamicVector< ScalarType > BackendType;
};

/**
 * \brief An implementation of Dune::Pymor::LA::VectorInterface using Dune::DynamicVector< double >.
 *
 * \see   Dune::Pymor::LA::VectorInterface
 */
template< class ScalarImp >
class DuneDynamicVector
  : public Dune::Pymor::LA::VectorInterface< DuneDynamicVectorTraits< ScalarImp > >
  , public ProvidesBackend< DuneDynamicVectorTraits< ScalarImp > >
{
  typedef Dune::Pymor::LA::VectorInterface< DuneDynamicVectorTraits< ScalarImp > > BaseType;
public:
  typedef DuneDynamicVectorTraits< ScalarImp >  Traits;
  typedef typename Traits::derived_type         ThisType;
  typedef typename Traits::ScalarType           ScalarType;
  typedef typename Traits::BackendType          BackendType;

  DuneDynamicVector(const int size = 0, const ScalarType value = ScalarType(0));

  /**
   * \attention This class takes ownership of backend_ptr!
   */
  DuneDynamicVector(BackendType* backend_ptr);

  DuneDynamicVector(std::unique_ptr< BackendType >&& backend_ptr);

  DuneDynamicVector(const ThisType& other) = delete;

  ThisType& operator=(const ThisType& other) = delete;

  DuneDynamicVector(ThisType&& source);

  ThisType& operator=(ThisType&& source);

  ThisType copy() const;

  unsigned int dim() const;

  bool has_equal_shape(const ThisType& other) const;

  bool almost_equal(const ThisType& other,
                    const ScalarType epsilon = Dune::FloatCmp::DefaultEpsilon< ScalarType >::value()) const;

  using BaseType::almost_equal;

  void scal(const ScalarType& alpha);

  void axpy(const ScalarType& alpha, const ThisType& xx) throw (Exception::sizes_do_not_match);

  using BaseType::axpy;

  ScalarType dot(const ThisType& other) const throw (Exception::sizes_do_not_match);

  using BaseType::dot;

  ScalarType l1_norm() const;

  ScalarType l2_norm() const;

  ScalarType sup_norm() const;

  std::vector< ScalarType > components(const std::vector< int >& component_indices) const
    throw (Exception::sizes_do_not_match, Exception::index_out_of_range);

  std::vector< ScalarType > amax() const;

  void add(const ThisType& other, ThisType& result) const throw (Exception::sizes_do_not_match);

  using BaseType::add;

  void iadd(const ThisType& other) throw (Exception::sizes_do_not_match);

  using BaseType::iadd;

  void sub(const ThisType& other, ThisType& result) const throw (Exception::sizes_do_not_match);

  using BaseType::sub;

  void isub(const ThisType& other) throw (Exception::sizes_do_not_match);

  using BaseType::isub;

  BackendType& backend();

  const BackendType& backend() const;

private:
  static int assert_is_not_negative(const int ii) throw (Exception::index_out_of_range);

  friend class Operators::DuneDynamic< ScalarType >;
  friend class Operators::DuneDynamicInverse< ScalarType >;

  std::unique_ptr< BackendType > backend_;
}; // class DuneDynamicVector

template< class ScalarImp = double >
class DuneDynamicMatrix;

template< class ScalarImp = double >
class DuneDynamicMatrixTraits
{
public:
  typedef ScalarImp                         ScalarType;
  typedef DuneDynamicMatrix< ScalarType >   derived_type;
  typedef Dune::DynamicMatrix< ScalarType > BackendType;
};

template< class ScalarImp >
class DuneDynamicMatrix
  : public Dune::Pymor::LA::MatrixInterface< DuneDynamicMatrixTraits< ScalarImp > >
{
public:
  typedef DuneDynamicMatrixTraits< ScalarImp >  Traits;
  typedef typename Traits::derived_type         ThisType;
  typedef typename Traits::ScalarType           ScalarType;
  typedef typename Traits::BackendType          BackendType;

public:
  DuneDynamicMatrix(const int rr = 0, const int cc = 0, const ScalarType value = ScalarType(0));

  /**
   * \attention This class takes ownership of backend_ptr!
   */
  DuneDynamicMatrix(BackendType* backend_ptr);

  DuneDynamicMatrix(std::unique_ptr< BackendType >&& backend_ptr);

  DuneDynamicMatrix(const ThisType& other) = delete;

  ThisType& operator=(const ThisType& other) = delete;

  DuneDynamicMatrix(ThisType&& source);

  ThisType& operator=(ThisType&& source);

  ThisType copy() const;

  unsigned int dim_source() const;

  unsigned int dim_range() const;

  bool has_equal_shape(const ThisType& other) const;

  void scal(const ScalarType& alpha);

  void axpy(const ScalarType& alpha, const ThisType& x) throw (Exception::sizes_do_not_match);

  BackendType& backend();

  const BackendType& backend() const;

private:
  static int assert_is_not_negative(const int ii) throw (Exception::index_out_of_range);

  friend class Operators::DuneDynamic< ScalarType >;
  friend class Operators::DuneDynamicInverse< ScalarType >;

  std::unique_ptr< BackendType > backend_;
}; // class DuneDynamicMatrix

template< class S >
static DuneDynamicVector< S > createContainer(const DuneDynamicVector< S >&, const size_t size)
{
  return DuneDynamicVector< S >(size, S(1));
}

template< class S >
static DuneDynamicMatrix< S > createContainer(const DuneDynamicMatrix< S >&, const size_t size)
{
  typedef Dune::DynamicMatrix< S > BackendType;
  BackendType* matrix = new BackendType(size, size, S(0));
  for (size_t ii = 0; ii < size; ++ii)
    matrix->operator[](ii)[ii] = S(1);
  return DuneDynamicMatrix< S >(matrix);
}

} // namespace LA
} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_LA_CONTAINER_DYNAMICVECTOR_HH
<|endoftext|>


<commit_before>#pragma once
#include <list>
#include <functional>

namespace wheel
{
    using namespace std;

    template<class signature> struct signal;

    template<class... args> struct signal<void(args...)>
    {
        typedef function<void(args...)> slot_type;
        typedef typename list<slot_type>::iterator connection;
        list<slot_type> slots;
        connection begin() { return slots.begin(); }
        connection end() { return slots.end(); }
        connection operator+=(slot_type slot) { return slots.insert(slots.end(), slot); }
        connection connect(slot_type slot, connection c) { return slots.insert(c, slot); }
        connection operator-=(connection c) { return slots.erase(c); }
        void clear() { slots.clear(); }
        void operator()(args... a) { for(auto& s : slots) s(a...); }
    };
}
<commit_msg>Minor change in signal support<commit_after>#pragma once
#include <list>
#include <functional>

namespace wheel
{
    using namespace std;

    template<class signature> struct signal;

    template<class... args> struct signal<void(args...)>
    {
		using slot = function<void(args...)>;
		using connection = typename list<slot>::iterator;
		list<slot> slots;
        connection begin() { return slots.begin(); }
        connection end() { return slots.end(); }
		connection operator+=(slot fn) { return slots.insert(slots.end(), fn); }
		connection connect(slot fn, connection c) { return slots.insert(c, fn); }
        connection operator-=(connection c) { return slots.erase(c); }
        void clear() { slots.clear(); }
        void operator()(args... a) { for(auto& s : slots) s(a...); }
    };
}
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "libjoynr/joynr-messaging/dispatcher/ReceivedMessageRunnable.h"

#include <cassert>

#include "joynr/CallContextStorage.h"
#include "joynr/Dispatcher.h"
#include "joynr/Message.h"
#include "joynr/ImmutableMessage.h"

namespace joynr
{

ReceivedMessageRunnable::ReceivedMessageRunnable(std::shared_ptr<ImmutableMessage> message,
                                                 Dispatcher& dispatcher)
        : Runnable(),
          ObjectWithDecayTime(message->getExpiryDate()),
          message(std::move(message)),
          dispatcher(dispatcher)
{
    JOYNR_LOG_TRACE(logger(),
                    "Creating ReceivedMessageRunnable for message: {}",
                    this->message->toLogMessage());
}

void ReceivedMessageRunnable::shutdown()
{
}

void ReceivedMessageRunnable::run()
{
    if (!message) {
        return;
    }

    const std::string& messageType = message->getType();

    JOYNR_LOG_TRACE(logger(),
                    "Running ReceivedMessageRunnable for message type: {}, msg ID: {}",
                    messageType,
                    message->getId());
    if (isExpired()) {
        JOYNR_LOG_DEBUG(
                logger(), "Dropping ReceivedMessageRunnable message, because it is expired: ");
        return;
    }

    JOYNR_LOG_TRACE(logger(), "Setting callContext principal to: {}", message->getCreator());
    CallContext callContext;
    callContext.setPrincipal(message->getCreator());
    CallContextStorage::set(std::move(callContext));

    if (messageType == Message::VALUE_MESSAGE_TYPE_REQUEST()) {
        dispatcher.handleRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_REPLY()) {
        dispatcher.handleReplyReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_ONE_WAY()) {
        dispatcher.handleOneWayRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REQUEST()) {
        dispatcher.handleSubscriptionRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_BROADCAST_SUBSCRIPTION_REQUEST()) {
        dispatcher.handleBroadcastSubscriptionRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_MULTICAST_SUBSCRIPTION_REQUEST()) {
        dispatcher.handleMulticastSubscriptionRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REPLY()) {
        dispatcher.handleSubscriptionReplyReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_MULTICAST()) {
        dispatcher.handleMulticastReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_PUBLICATION()) {
        dispatcher.handlePublicationReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_SUBSCRIPTION_STOP()) {
        dispatcher.handleSubscriptionStopReceived(std::move(message));
    } else {
        JOYNR_LOG_ERROR(logger(), "unknown message type: {}", messageType);
    }

    CallContextStorage::invalidate();
    JOYNR_LOG_TRACE(logger(), "Invalidating call context.");
}

} // namespace joynr
<commit_msg>[C++] include CallContext.h in ReceivedMessageRunnable.cpp<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "libjoynr/joynr-messaging/dispatcher/ReceivedMessageRunnable.h"

#include <cassert>

#include "joynr/CallContext.h"
#include "joynr/CallContextStorage.h"
#include "joynr/Dispatcher.h"
#include "joynr/ImmutableMessage.h"
#include "joynr/Message.h"

namespace joynr
{

ReceivedMessageRunnable::ReceivedMessageRunnable(std::shared_ptr<ImmutableMessage> message,
                                                 Dispatcher& dispatcher)
        : Runnable(),
          ObjectWithDecayTime(message->getExpiryDate()),
          message(std::move(message)),
          dispatcher(dispatcher)
{
    JOYNR_LOG_TRACE(logger(),
                    "Creating ReceivedMessageRunnable for message: {}",
                    this->message->toLogMessage());
}

void ReceivedMessageRunnable::shutdown()
{
}

void ReceivedMessageRunnable::run()
{
    if (!message) {
        return;
    }

    const std::string& messageType = message->getType();

    JOYNR_LOG_TRACE(logger(),
                    "Running ReceivedMessageRunnable for message type: {}, msg ID: {}",
                    messageType,
                    message->getId());
    if (isExpired()) {
        JOYNR_LOG_DEBUG(
                logger(), "Dropping ReceivedMessageRunnable message, because it is expired: ");
        return;
    }

    JOYNR_LOG_TRACE(logger(), "Setting callContext principal to: {}", message->getCreator());
    CallContext callContext;
    callContext.setPrincipal(message->getCreator());
    CallContextStorage::set(std::move(callContext));

    if (messageType == Message::VALUE_MESSAGE_TYPE_REQUEST()) {
        dispatcher.handleRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_REPLY()) {
        dispatcher.handleReplyReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_ONE_WAY()) {
        dispatcher.handleOneWayRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REQUEST()) {
        dispatcher.handleSubscriptionRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_BROADCAST_SUBSCRIPTION_REQUEST()) {
        dispatcher.handleBroadcastSubscriptionRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_MULTICAST_SUBSCRIPTION_REQUEST()) {
        dispatcher.handleMulticastSubscriptionRequestReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REPLY()) {
        dispatcher.handleSubscriptionReplyReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_MULTICAST()) {
        dispatcher.handleMulticastReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_PUBLICATION()) {
        dispatcher.handlePublicationReceived(std::move(message));
    } else if (messageType == Message::VALUE_MESSAGE_TYPE_SUBSCRIPTION_STOP()) {
        dispatcher.handleSubscriptionStopReceived(std::move(message));
    } else {
        JOYNR_LOG_ERROR(logger(), "unknown message type: {}", messageType);
    }

    CallContextStorage::invalidate();
    JOYNR_LOG_TRACE(logger(), "Invalidating call context.");
}

} // namespace joynr
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <algorithm>

//	Nicolas Fry
//	COP3503
//	Programming Assignment 1
//	Circular Linked List
//

template<class T>
class CircleLL
{
	public:
		CircleLL();
		void Insert(int index, const T &data);
		void PrintLL() const;
		int size() const;
		void PrintAtElement(int index) const;
		T getElement(int index) const;
		void RemoveAtIndex(int index);
		~CircleLL();

	private:
		struct node
		{
			//next node
			node* next;
			bool isRoot;
			T data;
		};

		node *root;
		node *last;
};

//constructor
template<class T>
CircleLL<T>::CircleLL()
{
	root = 0;		//initialize root and last pointers to null
	last = 0;
}

//Destructor implementation
template<class T>
CircleLL<T>::~CircleLL()
{
	int fullsize = size();	//Figure out size and deallocate each memory address
	node * toDelete;
	int i = 0;
	while(i++ < fullsize)
	{
		toDelete = root;
		root = root->next;
		delete toDelete;
	}
}

//insert T data to index index
template<class T>
void CircleLL<T>::Insert(int index, const T &data)
{

	//Case 1: List is empty
	if(root == 0)
	{
		root = new node;
		root->isRoot = true;
		root->data = data;

		//point the next portion back to itself
		root->next = root;
		last = root;
		return;
	}

	//List is not empty so create node;
	node * toBeAdded = new node;
	toBeAdded->data = data;

	//Case 2: Want to insert at position 0 aka root
	//    	endNode ----> root
	//		endNode ----> tobeadded(new root) ------>  (old root)
	//made index % size() + 1 because we may want to tack on a element to the end,
	//anything after end will loop around
	if(index == 0 || index % (size()+1) == 0)
	{

		//Point new root to original root
		toBeAdded->isRoot = true;
		toBeAdded->next = root;

		//Switch root to no longer be root
		root->isRoot = false;

		//new root is toBeAdded, and tell last node to point to new root
		root = toBeAdded;
		last->next = root;

		return;
	}

	//Case 3: Want to insert at nth position
	//Traverse to position
	node * current = root;
	int n = 0;
	while(n++ < index-1)
	{
		current = current->next;
	}

	//if inserting at the end, declare it to be the last element
	if(index % size() == 0)
	{
		last = toBeAdded;
	}

	//Insert it in
	toBeAdded->next = current->next;
	current->next = toBeAdded;

}

template<class T>
void CircleLL<T>::PrintLL() const
{

	if(size() == 0)
	{
		std::cout << "No items in list" << std::endl;
		return;
	}

	node *current = root;

	//Create string stream
	std::stringstream ss;
	ss<< '[';
	do
	{
		ss <<  current->data <<",";

		current = current->next;
	}
	while(current->isRoot != true);

	std::string toPrint = ss.str().substr(0, ss.str().size()-1);
	std::cout << toPrint << "]" << std:: endl;
}

template<class T>
int CircleLL<T>::size() const
{
	if(root == 0)
		return 0;

	node * current = root;

	int count = 0;
	do
	{
		count++;
		current=current->next;
	}
	while(current->isRoot != true);
	return count;
}

template<class T>
void CircleLL<T>::PrintAtElement(int index) const
{
	std::cout << getElement(index) << std:: endl;
}

template<class T>
T CircleLL<T>::getElement(int index) const
{
	if(size() == 0)
	{
		std::cout << "No items in list" << std::endl;
		return NULL;
	}

	node *current = root;

	int i = 0;
	while(i++ < index)
	{
		current = current->next;
	}

	return current->data;
}

template<class T>
void CircleLL<T>::RemoveAtIndex(int index)
{
	//Case 1: List is empty
	if(root == 0)
	{
		std::cout << "Nothing to remove! List is empty" << std::endl;
		return;
	}

	//if removing last element in the list, delete root and null out first and last pointers
	if(size() == 1)
	{
		delete root;
		root = 0;
		last = 0;
		return;
	}

	node * toDelete;

	//Case 2: Want to remove at position 0 aka root
	//    	endNode ----> root ----> indexOfRoot+1
	//		endNode ----> indexOfRoot+1 (new root)
	if(index == 0 || index % size() == 0)
	{
		//std::cout << "Deleting root!" << std:: endl;
		//std::cout << "Last's data " << last->data << std::endl;
		//std::cout << "Last->next's data " << last->next->data << std::endl;
		//std::cout << "Root's data " << root->data << std::endl;
		last->next = root->next;
		root->next->isRoot = true;

		//store root in temp pointer which will be deleted
		toDelete = root;
		root = root->next;
		delete toDelete;

		return;
	}

	//Case 3: Want to delete at nth position
	//Traverse to position
	node * current = root;
	int n = 0;

	while(n++ < index-1)
	{
		//std::cout << "Data: " << current->data << std:: endl;
		current = current->next;
	}

	//if deleting at the end, reassign the last element
	if((index + 1)  % size() == 0)
	{
		//std:: cout << "index: " << index << std:: endl;
		//std:: cout << "size: " << size() << std:: endl;
		//std:: cout << "index % size()-1: " << (index % size()-1) << std::endl;
		//std::cout << "Reassigning last node to node with data "<< current->data << std::endl;
		last = current;
	}

	//Remove it
	toDelete = current->next;
	//std::cout << "Deleting node: " << toDelete->data << std::endl;
	current->next = current->next->next;
	delete toDelete;
}

/*
19
I 1 0
I 2 1
I 3 2
I 4 3
I 5 4
I 6 5
I 7 6
I 8 7
I 9 8
I 10 9
I 0 2
D 5
J 3 2 34 23 22
*/<commit_msg>Modified CircleLL to make it more accessable, also corrected bug<commit_after>#include <iostream>
#include <sstream>
#include <algorithm>

//	Nicolas Fry
//	COP3503
//	Programming Assignment 1
//	Circular Linked List
//

template<class T>
class CircleLL
{
	public:
		CircleLL();
		void Insert(int index, const T &data);
		void PrintLL() const;
		int size() const;
		void PrintAtElement(int index) const;
		T getElementValue(int index) const;
		typename CircleLL<T>::node* getElement(int index) const;
		void RemoveAtIndex(int index);
		bool isRoot(int index) const;
		~CircleLL();

	private:
		struct node
		{
			//next node
			node* next;
			bool isRoot;
			T data;
		};

		node *root;
		node *last;
};

//constructor
template<class T>
CircleLL<T>::CircleLL()
{
	root = 0;		//initialize root and last pointers to null
	last = 0;
}

//Destructor implementation
template<class T>
CircleLL<T>::~CircleLL()
{
	int fullsize = size();	//Figure out size and deallocate each memory address
	node * toDelete;
	int i = 0;
	while(i++ < fullsize)
	{
		toDelete = root;
		root = root->next;
		delete toDelete;
	}
}

//insert T data to index index
template<class T>
void CircleLL<T>::Insert(int index, const T &data)
{

	//Case 1: List is empty
	if(root == 0)
	{
		root = new node;
		root->isRoot = true;
		root->data = data;

		//point the next portion back to itself
		root->next = root;
		last = root;
		return;
	}

	//List is not empty so create node;
	node * toBeAdded = new node;
	toBeAdded->data = data;

	//Case 2: Want to insert at position 0 aka root
	//    	endNode ----> root
	//		endNode ----> tobeadded(new root) ------>  (old root)
	//made index % size() + 1 because we may want to tack on a element to the end,
	//anything after end will loop around
	if(index == 0 || index % (size()+1) == 0)
	{

		//Point new root to original root
		toBeAdded->isRoot = true;
		toBeAdded->next = root;

		//Switch root to no longer be root
		root->isRoot = false;

		//new root is toBeAdded, and tell last node to point to new root
		root = toBeAdded;
		last->next = root;

		return;
	}

	//we know at this point that the node will not be root,
	toBeAdded->isRoot = false;

	//Case 3: Want to insert at nth position
	//Traverse to position
	node * current = root;
	int n = 0;
	while(n++ < index-1)
	{
		current = current->next;
	}

	//if inserting at the end, declare it to be the last element
	if(index % size() == 0)
	{
		last = toBeAdded;
	}

	//Insert it in
	toBeAdded->next = current->next;
	current->next = toBeAdded;

}

template<class T>
void CircleLL<T>::PrintLL() const
{

	if(size() == 0)
	{
		std::cout << "No items in list" << std::endl;
		return;
	}

	node *current = root;

	//Create string stream
	std::stringstream ss;
	ss<< '[';
	do
	{
		ss <<  current->data <<",";

		current = current->next;
	}
	while(current->isRoot != true);

	std::string toPrint = ss.str().substr(0, ss.str().size()-1);
	std::cout << toPrint << "]" << std:: endl;
}

template<class T>
int CircleLL<T>::size() const
{
	if(root == 0)
		return 0;

	node * current = root;

	int count = 0;
	do
	{
		count++;
		current=current->next;
	}
	while(current->isRoot != true);
	return count;
}

template<class T>
void CircleLL<T>::PrintAtElement(int index) const
{
	std::cout << getElementValue(index) << std::endl;
}

template<class T>
T CircleLL<T>::getElementValue(int index) const
{
	return getElement(index)->data;
}

template<class T>
typename CircleLL<T>::node* CircleLL<T>::getElement(int index) const
{
	if(size() == 0)
	{
		std::cout << "No items in list" << std::endl;
		return NULL;
	}

	node *current = root;

	int i = 0;
	while(i++ < index)
	{
		current = current->next;
	}

	return current;
}

template<class T>
void CircleLL<T>::RemoveAtIndex(int index)
{
	//Case 1: List is empty
	if(root == 0)
	{
		std::cout << "Nothing to remove! List is empty" << std::endl;
		return;
	}

	//if removing last element in the list, delete root and null out first and last pointers
	if(size() == 1)
	{
		delete root;
		root = 0;
		last = 0;
		return;
	}

	node * toDelete;

	//Case 2: Want to remove at position 0 aka root
	//    	endNode ----> root ----> indexOfRoot+1
	//		endNode ----> indexOfRoot+1 (new root)
	if(index == 0 || index % size() == 0)
	{
		//std::cout << "Deleting root!" << std:: endl;
		//std::cout << "Last's data " << last->data << std::endl;
		//std::cout << "Last->next's data " << last->next->data << std::endl;
		//std::cout << "Root's data " << root->data << std::endl;
		last->next = root->next;
		root->next->isRoot = true;

		//store root in temp pointer which will be deleted
		toDelete = root;
		root = root->next;
		delete toDelete;

		return;
	}

	//Case 3: Want to delete at nth position
	//Traverse to position
	node * current = root;
	int n = 0;

	while(n++ < index-1)
	{
		//std::cout << "Data: " << current->data << std:: endl;
		current = current->next;
	}

	//if deleting at the end, reassign the last element
	if((index + 1)  % size() == 0)
	{
		//std:: cout << "index: " << index << std:: endl;
		//std:: cout << "size: " << size() << std:: endl;
		//std:: cout << "index % size()-1: " << (index % size()-1) << std::endl;
		//std::cout << "Reassigning last node to node with data "<< current->data << std::endl;
		last = current;
	}

	//Remove it
	toDelete = current->next;
	//std::cout << "Deleting node: " << toDelete->data << std::endl;
	current->next = current->next->next;
	delete toDelete;
}

template<class T>
bool CircleLL<T>::isRoot(int index) const
{
	return getElement(index)->isRoot;
}

/*
19
I 1 0
I 2 1
I 3 2
I 4 3
I 5 4
I 6 5
I 7 6
I 8 7
I 9 8
I 10 9
I 0 2
D 5
J 3 2 34 23 22
*/<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    enum idx {start = 0, end = 1, height = 2};
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        return ComputeSkylineInInterval(buildings, 0, buildings.size());
    }

    // Divide and Conquer.
    vector<vector<int>> ComputeSkylineInInterval(const vector<vector<int>>& buildings,
                                                 int left_endpoint, int right_endpoint) {
        if (right_endpoint - left_endpoint <= 1) {  // 0 or 1 skyline, just copy it.
            return {buildings.cbegin() + left_endpoint,
                buildings.cbegin() + right_endpoint};
        }
        int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
        auto left_skyline = ComputeSkylineInInterval(buildings, left_endpoint, mid);
        auto right_skyline = ComputeSkylineInInterval(buildings, mid, right_endpoint);
        return MergeSkylines(left_skyline, right_skyline);
    }

    // Merge Sort
    vector<vector<int>> MergeSkylines(vector<vector<int>>& left_skyline, vector<vector<int>>& right_skyline) {
        int i = 0, j = 0;
        vector<vector<int>> merged;

        while (i < left_skyline.size() && j < right_skyline.size()) {
            if (left_skyline[i][end] < right_skyline[j][start]) {
                merged.emplace_back(left_skyline[i++]);
            } else if (right_skyline[j][end] < left_skyline[i][start]) {
                merged.emplace_back(right_skyline[j++]);
            } else if (left_skyline[i][start] <= right_skyline[j][start]) {
                MergeIntersectSkylines(merged, left_skyline[i], i,
                                       right_skyline[j], j);
            } else {  // left_skyline[i][start] > right_skyline[j][start].
                MergeIntersectSkylines(merged, right_skyline[j], j,
                                       left_skyline[i], i);
            }
        }

        // Insert the remaining skylines.
        merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
        merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
        return merged;
    }

    // a[start] <= b[start]
    void MergeIntersectSkylines(vector<vector<int>>& merged, vector<int>& a, int& a_idx,
                                vector<int>& b, int& b_idx) {
        if (a[end] <= b[end]) {
            if (a[height] > b[height]) {  // |aaa|
                if (b[end] != a[end]) {   // |abb|b
                    merged.emplace_back(a), ++a_idx;
                    b[start] = a[end];
                } else {        // aaa
                    ++b_idx;    // abb
                }
            } else if (a[height] == b[height]) { // abb
                b[start] = a[start], ++a_idx;    // abb
            } else {  // a[height] < b[height].
                if (a[start] != b[start]) {                                           //    bb
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});  // |a|bb
                }
                ++a_idx;
            }
        } else {  // a[end] > b[end].
            if (a[height] >= b[height]) {  // aaaa
                ++b_idx;                   // abba
            } else {
                //    |bb|
                // |a||bb|a
                if (a[start] != b[start]) {
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});
                }
                a[start] = b[end];
                merged.emplace_back(b), ++b_idx;
            }
        }
    }
};
<commit_msg>update<commit_after>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    enum {start = 0, end = 1, height = 2};
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        return ComputeSkylineInInterval(buildings, 0, buildings.size());
    }

    // Divide and Conquer.
    vector<vector<int>> ComputeSkylineInInterval(const vector<vector<int>>& buildings,
                                                 int left_endpoint, int right_endpoint) {
        if (right_endpoint - left_endpoint <= 1) {  // 0 or 1 skyline, just copy it.
            return {buildings.cbegin() + left_endpoint,
                buildings.cbegin() + right_endpoint};
        }
        int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
        auto left_skyline = ComputeSkylineInInterval(buildings, left_endpoint, mid);
        auto right_skyline = ComputeSkylineInInterval(buildings, mid, right_endpoint);
        return MergeSkylines(left_skyline, right_skyline);
    }

    // Merge Sort
    vector<vector<int>> MergeSkylines(vector<vector<int>>& left_skyline, vector<vector<int>>& right_skyline) {
        int i = 0, j = 0;
        vector<vector<int>> merged;

        while (i < left_skyline.size() && j < right_skyline.size()) {
            if (left_skyline[i][end] < right_skyline[j][start]) {
                merged.emplace_back(left_skyline[i++]);
            } else if (right_skyline[j][end] < left_skyline[i][start]) {
                merged.emplace_back(right_skyline[j++]);
            } else if (left_skyline[i][start] <= right_skyline[j][start]) {
                MergeIntersectSkylines(merged, left_skyline[i], i,
                                       right_skyline[j], j);
            } else {  // left_skyline[i][start] > right_skyline[j][start].
                MergeIntersectSkylines(merged, right_skyline[j], j,
                                       left_skyline[i], i);
            }
        }

        // Insert the remaining skylines.
        merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
        merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
        return merged;
    }

    // a[start] <= b[start]
    void MergeIntersectSkylines(vector<vector<int>>& merged, vector<int>& a, int& a_idx,
                                vector<int>& b, int& b_idx) {
        if (a[end] <= b[end]) {
            if (a[height] > b[height]) {  // |aaa|
                if (b[end] != a[end]) {   // |abb|b
                    merged.emplace_back(a), ++a_idx;
                    b[start] = a[end];
                } else {        // aaa
                    ++b_idx;    // abb
                }
            } else if (a[height] == b[height]) { // abb
                b[start] = a[start], ++a_idx;    // abb
            } else {  // a[height] < b[height].
                if (a[start] != b[start]) {                                           //    bb
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});  // |a|bb
                }
                ++a_idx;
            }
        } else {  // a[end] > b[end].
            if (a[height] >= b[height]) {  // aaaa
                ++b_idx;                   // abba
            } else {
                //    |bb|
                // |a||bb|a
                if (a[start] != b[start]) {
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});
                }
                a[start] = b[end];
                merged.emplace_back(b), ++b_idx;
            }
        }
    }
};
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/init.h>
#include <shogun/features/SparseFeatures.h>
#include <shogun/features/Subset.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

const int32_t num_vectors=6;
const int32_t dim_features=6;

void check_transposed(CSparseFeatures<int32_t>* features)
{
	CSparseFeatures<int32_t>* transposed=features->get_transposed();
	CSparseFeatures<int32_t>* double_transposed=transposed->get_transposed();

	for (index_t i=0; i<features->get_num_vectors(); ++i)
	{
		SGSparseVector<int32_t> orig_vec=features->get_sparse_feature_vector(i);
		SGSparseVector<int32_t> new_vec=
				double_transposed->get_sparse_feature_vector(i);

		for (index_t j=0; j<dim_features; j++)
			ASSERT(orig_vec.features[j].entry==new_vec.features[j].entry);

		/* not necessary since feature matrix is in memory. for documentation */
		features->free_sparse_feature_vector(orig_vec, i);
		double_transposed->free_sparse_feature_vector(new_vec, i);
	}

	SG_UNREF(transposed);
	SG_UNREF(double_transposed);
}

int main(int argc, char **argv)
{
	init_shogun(&print_message, &print_message, &print_message);
	const int32_t num_subset_idx=CMath::random(1, num_vectors);

	/* create feature data matrix */
	SGMatrix<int32_t> data(dim_features, num_vectors);

	/* fill matrix with random data */
	for (index_t i=0; i<num_vectors*dim_features; ++i)
		data.matrix[i]=CMath::random(1, 9);

	/* create sparse features */
	CSparseFeatures<int32_t>* features=new CSparseFeatures<int32_t>(data);

	/* print dense feature matrix */
	CMath::display_matrix(data.matrix, data.num_rows, data.num_cols,
			"dense feature matrix");

	/* create subset indices */
	SGVector<index_t> subset_idx(CMath::randperm(num_subset_idx),
			num_subset_idx);

	/* print subset indices */
	CMath::display_vector(subset_idx.vector, subset_idx.vlen, "subset indices");

	/* apply subset to features */
	SG_SPRINT("\n-------------------\n"
	"applying subset to features\n"
	"-------------------\n");
	features->set_subset(new CSubset(subset_idx));

	/* do some stuff do check and output */
	ASSERT(features->get_num_vectors()==num_subset_idx);
	SG_SPRINT("features->get_num_vectors(): %d\n", features->get_num_vectors());

	/* check get_Transposed method */
	SG_SPRINT("checking transpose...");
	check_transposed(features);
	SG_SPRINT("does work\n");

	for (index_t i=0; i<features->get_num_vectors(); ++i)
	{
		SGSparseVector<int32_t> vec=features->get_sparse_feature_vector(i);
		SG_SPRINT("sparse_vector[%d]=", i);
		for (index_t j=0; j<vec.num_feat_entries; ++j)
		{
			SG_SPRINT("%d", vec.features[j].entry);
			if (j<vec.num_feat_entries-1)
				SG_SPRINT(",");
		}

		SG_SPRINT("\n");

		for (index_t j=0; j<vec.num_feat_entries; ++j)
		{
			int32_t a=vec.features[j].entry;
			index_t ind=features->subset_idx_conversion(i)*num_vectors+j;
			int32_t	b=data.matrix[ind];
			ASSERT(a==b);
		}

		features->free_sparse_feature_vector(vec, i);
	}

	/* remove features subset */
	SG_SPRINT("\n-------------------\n"
	"removing subset from features\n"
	"-------------------\n");
	features->remove_subset();

	/* do some stuff do check and output */
	ASSERT(features->get_num_vectors()==num_vectors);
	SG_SPRINT("features->get_num_vectors(): %d\n", features->get_num_vectors());

	/* check get_Transposed method */
	SG_SPRINT("checking transpose...");
	check_transposed(features);
	SG_SPRINT("does work\n");

	for (index_t i=0; i<features->get_num_vectors(); ++i)
	{
		SGSparseVector<int32_t> vec=features->get_sparse_feature_vector(i);
		SG_SPRINT("sparse_vector[%d]=", i);
		for (index_t j=0; j<vec.num_feat_entries; ++j)
		{
			SG_SPRINT("%d", vec.features[j].entry);
			if (j<vec.num_feat_entries-1)
				SG_SPRINT(",");
		}

		SG_SPRINT("\n");

		for (index_t j=0; j<vec.num_feat_entries; ++j)
			ASSERT(vec.features[j].entry==data.matrix[i*num_vectors+j]);

		features->free_sparse_feature_vector(vec, i);
	}

	SG_UNREF(features);
	SG_FREE(data.matrix);

	exit_shogun();

	return 0;
}

<commit_msg>applied changes of new subset system<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/init.h>
#include <shogun/features/SparseFeatures.h>
#include <shogun/features/Subset.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

const int32_t num_vectors=6;
const int32_t dim_features=6;

void check_transposed(CSparseFeatures<int32_t>* features)
{
	CSparseFeatures<int32_t>* transposed=features->get_transposed();
	CSparseFeatures<int32_t>* double_transposed=transposed->get_transposed();

	for (index_t i=0; i<features->get_num_vectors(); ++i)
	{
		SGSparseVector<int32_t> orig_vec=features->get_sparse_feature_vector(i);
		SGSparseVector<int32_t> new_vec=
				double_transposed->get_sparse_feature_vector(i);

		for (index_t j=0; j<dim_features; j++)
			ASSERT(orig_vec.features[j].entry==new_vec.features[j].entry);

		/* not necessary since feature matrix is in memory. for documentation */
		features->free_sparse_feature_vector(orig_vec, i);
		double_transposed->free_sparse_feature_vector(new_vec, i);
	}

	SG_UNREF(transposed);
	SG_UNREF(double_transposed);
}

int main(int argc, char **argv)
{
	init_shogun(&print_message, &print_message, &print_message);
	const int32_t num_subset_idx=CMath::random(1, num_vectors);

	/* create feature data matrix */
	SGMatrix<int32_t> data(dim_features, num_vectors);

	/* fill matrix with random data */
	for (index_t i=0; i<num_vectors*dim_features; ++i)
		data.matrix[i]=CMath::random(1, 9);

	/* create sparse features */
	CSparseFeatures<int32_t>* features=new CSparseFeatures<int32_t>(data);

	/* print dense feature matrix */
	CMath::display_matrix(data.matrix, data.num_rows, data.num_cols,
			"dense feature matrix");

	/* create subset indices */
	SGVector<index_t> subset_idx(CMath::randperm(num_subset_idx),
			num_subset_idx);

	/* print subset indices */
	CMath::display_vector(subset_idx.vector, subset_idx.vlen, "subset indices");

	/* apply subset to features */
	SG_SPRINT("\n-------------------\n"
	"applying subset to features\n"
	"-------------------\n");
	features->push_subset(new CSubset(subset_idx));

	/* do some stuff do check and output */
	ASSERT(features->get_num_vectors()==num_subset_idx);
	SG_SPRINT("features->get_num_vectors(): %d\n", features->get_num_vectors());

	/* check get_Transposed method */
	SG_SPRINT("checking transpose...");
	check_transposed(features);
	SG_SPRINT("does work\n");

	for (index_t i=0; i<features->get_num_vectors(); ++i)
	{
		SGSparseVector<int32_t> vec=features->get_sparse_feature_vector(i);
		SG_SPRINT("sparse_vector[%d]=", i);
		for (index_t j=0; j<vec.num_feat_entries; ++j)
		{
			SG_SPRINT("%d", vec.features[j].entry);
			if (j<vec.num_feat_entries-1)
				SG_SPRINT(",");
		}

		SG_SPRINT("\n");

		for (index_t j=0; j<vec.num_feat_entries; ++j)
		{
			int32_t a=vec.features[j].entry;
			index_t ind=features->subset_idx_conversion(i)*num_vectors+j;
			int32_t	b=data.matrix[ind];
			ASSERT(a==b);
		}

		features->free_sparse_feature_vector(vec, i);
	}

	/* remove features subset */
	SG_SPRINT("\n-------------------\n"
	"removing subset from features\n"
	"-------------------\n");
	features->remove_all_subsets();

	/* do some stuff do check and output */
	ASSERT(features->get_num_vectors()==num_vectors);
	SG_SPRINT("features->get_num_vectors(): %d\n", features->get_num_vectors());

	/* check get_Transposed method */
	SG_SPRINT("checking transpose...");
	check_transposed(features);
	SG_SPRINT("does work\n");

	for (index_t i=0; i<features->get_num_vectors(); ++i)
	{
		SGSparseVector<int32_t> vec=features->get_sparse_feature_vector(i);
		SG_SPRINT("sparse_vector[%d]=", i);
		for (index_t j=0; j<vec.num_feat_entries; ++j)
		{
			SG_SPRINT("%d", vec.features[j].entry);
			if (j<vec.num_feat_entries-1)
				SG_SPRINT(",");
		}

		SG_SPRINT("\n");

		for (index_t j=0; j<vec.num_feat_entries; ++j)
			ASSERT(vec.features[j].entry==data.matrix[i*num_vectors+j]);

		features->free_sparse_feature_vector(vec, i);
	}

	SG_UNREF(features);
	SG_FREE(data.matrix);

	exit_shogun();

	return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/uint32_t.h>
#include "imgui/imgui.h"

#include <bgfx/embedded_shader.h>

// embedded shaders
#include "vs_drawstress.bin.h"
#include "fs_drawstress.bin.h"

static const bgfx::EmbeddedShader s_embeddedShaders[] =
{
	BGFX_EMBEDDED_SHADER(vs_drawstress),
	BGFX_EMBEDDED_SHADER(fs_drawstress),

	BGFX_EMBEDDED_SHADER_END()
};

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	}

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

#if BX_PLATFORM_EMSCRIPTEN
static const int64_t highwm = 1000000/35;
static const int64_t lowwm  = 1000000/27;
#else
static const int64_t highwm = 1000000/65;
static const int64_t lowwm  = 1000000/57;
#endif // BX_PLATFORM_EMSCRIPTEN

class ExampleDrawStress : public entry::AppI
{
	void init(int _argc, char** _argv) BX_OVERRIDE
	{
		Args args(_argc, _argv);

		m_width  = 1280;
		m_height = 720;
		m_debug  = BGFX_DEBUG_TEXT;
		m_reset  = BGFX_RESET_NONE;

		m_autoAdjust = true;
		m_scrollArea = 0;
		m_dim        = 16;
		m_maxDim     = 40;
		m_transform  = 0;

		m_timeOffset = bx::getHPCounter();

		m_deltaTimeNs    = 0;
		m_deltaTimeAvgNs = 0;
		m_numFrames      = 0;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		const bgfx::Caps* caps = bgfx::getCaps();
		m_maxDim = (int32_t)bx::fpow(float(caps->limits.maxDrawCalls), 1.0f/3.0f);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x303030ff
				, 1.0f
				, 0
				);

		// Create vertex stream declaration.
		PosColorVertex::init();

		bgfx::RendererType::Enum type = bgfx::getRendererType();

		// Create program from shaders.
		m_program = bgfx::createProgram(
				  bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress")
				, bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress")
				, true /* destroy shaders when program is destroyed */
				);

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
					  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
					, PosColorVertex::ms_decl
					);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );

		// Imgui.
		imguiCreate();
	}

	int shutdown() BX_OVERRIDE
	{
		// Cleanup.
		imguiDestroy();
		bgfx::destroyIndexBuffer(m_ibh);
		bgfx::destroyVertexBuffer(m_vbh);
		bgfx::destroyProgram(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() BX_OVERRIDE
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t hpFreq = bx::getHPFrequency();
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(hpFreq);
			const double toMs = 1000.0/freq;

			m_deltaTimeNs += frameTime*1000000/hpFreq;

			if (m_deltaTimeNs > 1000000)
			{
				m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames);

				if (m_autoAdjust)
				{
					if (m_deltaTimeAvgNs < highwm)
					{
						m_dim = bx::uint32_min(m_dim + 2, m_maxDim);
					}
					else if (m_deltaTimeAvgNs > lowwm)
					{
						m_dim = bx::uint32_max(m_dim - 1, 2);
					}
				}

				m_deltaTimeNs = 0;
				m_numFrames   = 0;
			}
			else
			{
				++m_numFrames;
			}

			float time = (float)( (now-m_timeOffset)/freq);

			imguiBeginFrame(m_mouseState.m_mx
					,  m_mouseState.m_my
					, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
					| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
					| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
					,  m_mouseState.m_mz
					, uint16_t(m_width)
					, uint16_t(m_height)
					);

			imguiBeginScrollArea("Settings", m_width - m_width / 4 - 10, 10, m_width / 4, m_height / 2, &m_scrollArea);
			imguiSeparatorLine();

			m_transform = imguiChoose(m_transform
					, "Rotate"
					, "No fragments"
					);
			imguiSeparatorLine();

			if (imguiCheck("Auto adjust", m_autoAdjust) )
			{
				m_autoAdjust ^= true;
			}

			imguiSlider("Dim", m_dim, 5, m_maxDim);
			imguiLabel("Draw calls: %d", m_dim*m_dim*m_dim);
			imguiLabel("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f);

			imguiSeparatorLine();
			const bgfx::Stats* stats = bgfx::getStats();
			imguiLabel("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq);
			imguiLabel("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq);
			imguiLabel("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs);
			imguiLabel("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs);

			imguiEndScrollArea();
			imguiEndFrame();

			float at[3] = { 0.0f, 0.0f, 0.0f };
			float eye[3] = { 0.0f, 0.0f, -35.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const bgfx::Caps* caps = bgfx::getCaps();
			float proj[16];
			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);

			// Set view and projection matrix for view 0.
			bgfx::setViewTransform(0, view, proj);

			// Set view 0 default viewport.
			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			// Use debug font to print information about this example.
			bgfx::dbgTextClear();
			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/17-drawstress");
			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Draw stress, maximizing number of draw calls.");
			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: %7.3f[ms]", double(frameTime)*toMs);

			float mtxS[16];
			const float scale = 0 == m_transform ? 0.25f : 0.0f;
			bx::mtxScale(mtxS, scale, scale, scale);

			const float step = 0.6f;
			float pos[3];
			pos[0] = -step*m_dim / 2.0f;
			pos[1] = -step*m_dim / 2.0f;
			pos[2] = -15.0;

			for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz)
			{
				for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy)
				{
					for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx)
					{
						float mtxR[16];
						bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f);

						float mtx[16];
						bx::mtxMul(mtx, mtxS, mtxR);

						mtx[12] = pos[0] + float(xx)*step;
						mtx[13] = pos[1] + float(yy)*step;
						mtx[14] = pos[2] + float(zz)*step;

						// Set model matrix for rendering.
						bgfx::setTransform(mtx);

						// Set vertex and index buffer.
						bgfx::setVertexBuffer(0, m_vbh);
						bgfx::setIndexBuffer(m_ibh);

						// Set render states.
						bgfx::setState(BGFX_STATE_DEFAULT);

						// Submit primitive for rendering to view 0.
						bgfx::submit(0, m_program);
					}
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	bool     m_autoAdjust;
	int32_t  m_scrollArea;
	int32_t  m_dim;
	int32_t  m_maxDim;
	uint32_t m_transform;

	int64_t  m_timeOffset;

	int64_t  m_deltaTimeNs;
	int64_t  m_deltaTimeAvgNs;
	int64_t  m_numFrames;

	bgfx::ProgramHandle m_program;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
};

ENTRY_IMPLEMENT_MAIN(ExampleDrawStress);
<commit_msg>17-drawstress: switched to imgui (#1171)<commit_after>/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/uint32_t.h>
#include "imgui/imgui.h"

#include <bgfx/embedded_shader.h>

// embedded shaders
#include "vs_drawstress.bin.h"
#include "fs_drawstress.bin.h"

static const bgfx::EmbeddedShader s_embeddedShaders[] =
{
	BGFX_EMBEDDED_SHADER(vs_drawstress),
	BGFX_EMBEDDED_SHADER(fs_drawstress),

	BGFX_EMBEDDED_SHADER_END()
};

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	}

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

#if BX_PLATFORM_EMSCRIPTEN
static const int64_t highwm = 1000000/35;
static const int64_t lowwm  = 1000000/27;
#else
static const int64_t highwm = 1000000/65;
static const int64_t lowwm  = 1000000/57;
#endif // BX_PLATFORM_EMSCRIPTEN

class ExampleDrawStress : public entry::AppI
{
	void init(int _argc, char** _argv) BX_OVERRIDE
	{
		Args args(_argc, _argv);

		m_width  = 1280;
		m_height = 720;
		m_debug  = BGFX_DEBUG_TEXT;
		m_reset  = BGFX_RESET_NONE;

		m_autoAdjust = true;
		m_scrollArea = 0;
		m_dim        = 16;
		m_maxDim     = 40;
		m_transform  = 0;

		m_timeOffset = bx::getHPCounter();

		m_deltaTimeNs    = 0;
		m_deltaTimeAvgNs = 0;
		m_numFrames      = 0;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		const bgfx::Caps* caps = bgfx::getCaps();
		m_maxDim = (int32_t)bx::fpow(float(caps->limits.maxDrawCalls), 1.0f/3.0f);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x303030ff
				, 1.0f
				, 0
				);

		// Create vertex stream declaration.
		PosColorVertex::init();

		bgfx::RendererType::Enum type = bgfx::getRendererType();

		// Create program from shaders.
		m_program = bgfx::createProgram(
				  bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress")
				, bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress")
				, true /* destroy shaders when program is destroyed */
				);

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
					  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
					, PosColorVertex::ms_decl
					);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );

		// Imgui.
		imguiCreate();
	}

	int shutdown() BX_OVERRIDE
	{
		// Cleanup.
		imguiDestroy();
		bgfx::destroyIndexBuffer(m_ibh);
		bgfx::destroyVertexBuffer(m_vbh);
		bgfx::destroyProgram(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() BX_OVERRIDE
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t hpFreq = bx::getHPFrequency();
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(hpFreq);
			const double toMs = 1000.0/freq;

			m_deltaTimeNs += frameTime*1000000/hpFreq;

			if (m_deltaTimeNs > 1000000)
			{
				m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames);

				if (m_autoAdjust)
				{
					if (m_deltaTimeAvgNs < highwm)
					{
						m_dim = bx::uint32_min(m_dim + 2, m_maxDim);
					}
					else if (m_deltaTimeAvgNs > lowwm)
					{
						m_dim = bx::uint32_max(m_dim - 1, 2);
					}
				}

				m_deltaTimeNs = 0;
				m_numFrames   = 0;
			}
			else
			{
				++m_numFrames;
			}

			float time = (float)( (now-m_timeOffset)/freq);

			imguiBeginFrame(m_mouseState.m_mx
					,  m_mouseState.m_my
					, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
					| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
					| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
					,  m_mouseState.m_mz
					, uint16_t(m_width)
					, uint16_t(m_height)
					);

			ImGui::SetNextWindowPos(ImVec2((float)m_width - (float)m_width / 4.0f - 10.0f, 10.0f) );
			ImGui::SetNextWindowSize(ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) );
			ImGui::Begin("Settings"
						 , NULL
						 , ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f)
						 , ImGuiWindowFlags_AlwaysAutoResize
						 );

			ImGui::RadioButton("Rotate",&m_transform,0);
			ImGui::RadioButton("No fragments",&m_transform,1);
			ImGui::Separator();

			ImGui::Checkbox("Auto adjust", &m_autoAdjust);

			ImGui::SliderInt("Dim", &m_dim, 5, m_maxDim);
			ImGui::Text("Draw calls: %d", m_dim*m_dim*m_dim);
			ImGui::Text("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f);

			ImGui::Separator();
			const bgfx::Stats* stats = bgfx::getStats();
			ImGui::Text("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq);
			ImGui::Text("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq);
			ImGui::Text("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs);
			ImGui::Text("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs);

			ImGui::End();

			imguiEndFrame();

			float at[3] = { 0.0f, 0.0f, 0.0f };
			float eye[3] = { 0.0f, 0.0f, -35.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const bgfx::Caps* caps = bgfx::getCaps();
			float proj[16];
			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);

			// Set view and projection matrix for view 0.
			bgfx::setViewTransform(0, view, proj);

			// Set view 0 default viewport.
			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			// Use debug font to print information about this example.
			bgfx::dbgTextClear();
			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/17-drawstress");
			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Draw stress, maximizing number of draw calls.");
			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: %7.3f[ms]", double(frameTime)*toMs);

			float mtxS[16];
			const float scale = 0 == m_transform ? 0.25f : 0.0f;
			bx::mtxScale(mtxS, scale, scale, scale);

			const float step = 0.6f;
			float pos[3];
			pos[0] = -step*m_dim / 2.0f;
			pos[1] = -step*m_dim / 2.0f;
			pos[2] = -15.0;

			for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz)
			{
				for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy)
				{
					for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx)
					{
						float mtxR[16];
						bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f);

						float mtx[16];
						bx::mtxMul(mtx, mtxS, mtxR);

						mtx[12] = pos[0] + float(xx)*step;
						mtx[13] = pos[1] + float(yy)*step;
						mtx[14] = pos[2] + float(zz)*step;

						// Set model matrix for rendering.
						bgfx::setTransform(mtx);

						// Set vertex and index buffer.
						bgfx::setVertexBuffer(0, m_vbh);
						bgfx::setIndexBuffer(m_ibh);

						// Set render states.
						bgfx::setState(BGFX_STATE_DEFAULT);

						// Submit primitive for rendering to view 0.
						bgfx::submit(0, m_program);
					}
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	bool     m_autoAdjust;
	int32_t  m_scrollArea;
	int32_t  m_dim;
	int32_t  m_maxDim;
	int32_t  m_transform;

	int64_t  m_timeOffset;

	int64_t  m_deltaTimeNs;
	int64_t  m_deltaTimeAvgNs;
	int64_t  m_numFrames;

	bgfx::ProgramHandle m_program;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
};

ENTRY_IMPLEMENT_MAIN(ExampleDrawStress);
<|endoftext|>


<commit_before>#include "serializer/log/lba/disk_extent.hpp"

#include "arch/arch.hpp"

lba_disk_extent_t::lba_disk_extent_t(extent_manager_t *_em, direct_file_t *file, file_account_t *io_account)
  : em(_em), data(new extent_t(em, file)), offset(data->offset), count(0)
{
    // Make sure that the size of the header is a multiple of the size of one entry, so that the
    // header doesn't prevent the entries from aligning with DEVICE_BLOCK_SIZE.
    rassert(divides(sizeof(lba_entry_t), offsetof(lba_extent_t, entries[0])));
    rassert(offsetof(lba_extent_t, entries[0]) == sizeof(lba_extent_t::header_t));

    lba_extent_t::header_t header;
    bzero(&header, sizeof(header));
    memcpy(header.magic, lba_magic, LBA_MAGIC_SIZE);
    data->append(&header, sizeof(header), io_account);
}

lba_disk_extent_t::lba_disk_extent_t(extent_manager_t *_em, direct_file_t *file, off64_t _offset, int _count)
    : em(_em), data(new extent_t(em, file, _offset, offsetof(lba_extent_t, entries[0]) + sizeof(lba_entry_t) * _count)), offset(_offset), count(_count)
{
}

void lba_disk_extent_t::add_entry(lba_entry_t entry, file_account_t *io_account) {
    // Make sure that entries will align with DEVICE_BLOCK_SIZE

    // TODO: This could just be a unit test.
    rassert(divides(DEVICE_BLOCK_SIZE, sizeof(lba_entry_t)));

    // Make sure that there is room
    rassert(data->amount_filled + sizeof(lba_entry_t) <= em->extent_size);

    data->append(&entry, sizeof(lba_entry_t), io_account);
    count++;
}

void lba_disk_extent_t::sync(file_account_t *io_account, extent_t::sync_callback_t *cb) {
    while (data->amount_filled % DEVICE_BLOCK_SIZE != 0) {
        add_entry(lba_entry_t::make_padding_entry(), io_account);
    }

    data->sync(cb);
}

void lba_disk_extent_t::read_step_1(read_info_t *info_out, extent_t::read_callback_t *cb) {
    info_out->buffer = malloc_aligned(em->extent_size, DEVICE_BLOCK_SIZE);
    info_out->count = count;
    data->read(0, sizeof(lba_extent_t) + sizeof(lba_entry_t) * count, info_out->buffer, cb);
}

void lba_disk_extent_t::read_step_2(read_info_t *info, in_memory_index_t *index) {
    lba_extent_t *extent = reinterpret_cast<lba_extent_t *>(info->buffer);
    rassert(memcmp(extent->header.magic, lba_magic, LBA_MAGIC_SIZE) == 0);

    for (int i = 0; i < info->count; i++) {
        lba_entry_t *e = &extent->entries[i];
        if (!lba_entry_t::is_padding(e)) {
            index->set_block_info(e->block_id, e->recency, e->offset);
        }
    }

    free(info->buffer);
}

<commit_msg>Switched the divides() call arguments around, they were backwards, in disk_extent.cc.<commit_after>#include "serializer/log/lba/disk_extent.hpp"

#include "arch/arch.hpp"

lba_disk_extent_t::lba_disk_extent_t(extent_manager_t *_em, direct_file_t *file, file_account_t *io_account)
  : em(_em), data(new extent_t(em, file)), offset(data->offset), count(0)
{
    // Make sure that the size of the header is a multiple of the size of one entry, so that the
    // header doesn't prevent the entries from aligning with DEVICE_BLOCK_SIZE.
    rassert(divides(sizeof(lba_entry_t), offsetof(lba_extent_t, entries[0])));
    rassert(offsetof(lba_extent_t, entries[0]) == sizeof(lba_extent_t::header_t));

    lba_extent_t::header_t header;
    bzero(&header, sizeof(header));
    memcpy(header.magic, lba_magic, LBA_MAGIC_SIZE);
    data->append(&header, sizeof(header), io_account);
}

lba_disk_extent_t::lba_disk_extent_t(extent_manager_t *_em, direct_file_t *file, off64_t _offset, int _count)
    : em(_em), data(new extent_t(em, file, _offset, offsetof(lba_extent_t, entries[0]) + sizeof(lba_entry_t) * _count)), offset(_offset), count(_count)
{
}

void lba_disk_extent_t::add_entry(lba_entry_t entry, file_account_t *io_account) {
    // Make sure that entries will align with DEVICE_BLOCK_SIZE

    // TODO(sam): This could just be a unit test.
    rassert(divides(sizeof(lba_entry_t), DEVICE_BLOCK_SIZE));

    // Make sure that there is room
    rassert(data->amount_filled + sizeof(lba_entry_t) <= em->extent_size);

    data->append(&entry, sizeof(lba_entry_t), io_account);
    count++;
}

void lba_disk_extent_t::sync(file_account_t *io_account, extent_t::sync_callback_t *cb) {
    while (data->amount_filled % DEVICE_BLOCK_SIZE != 0) {
        add_entry(lba_entry_t::make_padding_entry(), io_account);
    }

    data->sync(cb);
}

void lba_disk_extent_t::read_step_1(read_info_t *info_out, extent_t::read_callback_t *cb) {
    info_out->buffer = malloc_aligned(em->extent_size, DEVICE_BLOCK_SIZE);
    info_out->count = count;
    data->read(0, sizeof(lba_extent_t) + sizeof(lba_entry_t) * count, info_out->buffer, cb);
}

void lba_disk_extent_t::read_step_2(read_info_t *info, in_memory_index_t *index) {
    lba_extent_t *extent = reinterpret_cast<lba_extent_t *>(info->buffer);
    rassert(memcmp(extent->header.magic, lba_magic, LBA_MAGIC_SIZE) == 0);

    for (int i = 0; i < info->count; i++) {
        lba_entry_t *e = &extent->entries[i];
        if (!lba_entry_t::is_padding(e)) {
            index->set_block_info(e->block_id, e->recency, e->offset);
        }
    }

    free(info->buffer);
}

<|endoftext|>