<commit_before>#include <iostream>
#include <cmath>
#include <limits>
#include <vector>
#include <fstream>

/* PHYSICAL CONSTANTS */

constexpr double e = 1.60217657e-19;   // Coulombs
constexpr double k_B = 1.3806488e-23;  // Joules per Kelvin

/* USER CONFIGURATION */

/* Temperature */
constexpr double temp = 4.2;  // Kelvin

/* Dot orbital energies */
constexpr double single_electron_energies[] = {
    0.0*e, 0.01*e, 0.02*e, 0.03*e, 0.04*e, 0.05*e, 0.06*e, 0.07*e
};  // Joules

/* Tunnel widths (by dot level) */
constexpr double source_widths[] {
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

constexpr double drain_widths[] {
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

/* Dot-system capacitances */
constexpr double gate_capacitance =   1e-19;  // Farads
constexpr double source_capacitance = 1e-18;  // Farads
constexpr double drain_capacitance =  1e-18;  // Farads
constexpr double extra_capacitance =  1e-19;  // Farads

/* Voltage-space to be explored */
constexpr double v_g_min = -0.3;  // Volts
constexpr double v_g_max = 6.1;  // Volts
constexpr int v_g_steps = 200;  // (y axis resolution)

constexpr double v_sd_min = -0.21;  // Volts
constexpr double v_sd_max = 0.21;  // Volts
constexpr int v_sd_steps = 200;  // (x axis resolution)

/* Electronic properties of leads (s: source; d: drain) */
constexpr double source_dos (double energy) {
    if (energy > 0.0) {
        // Do nothing. (Suppress 'unused' warning.)
    }
    return 1;
}
constexpr double d_fermi_energy = 0.0*e;  // Joules

constexpr double drain_dos (double energy) {
    if (energy > 0.0) {
        // Do nothing. (Suppress 'unused' warning.)
    }
    return 1;
}
constexpr double s_fermi_energy = 0.0*e;  // Joules

/* Semiclassical simulation properties */
constexpr double h = 1e-1;  // Runge-Kutta evolution step size
constexpr double convergence_criterion = 1e-5;

/* COMPILE-TIME CALCULATIONS */

constexpr int n_levels = sizeof(single_electron_energies)
                         /sizeof(single_electron_energies[0]);

constexpr int n_source_rates = sizeof(source_widths)
                               /sizeof(source_widths[0]);

constexpr int n_drain_rates = sizeof(drain_widths)
                               /sizeof(drain_widths[0]);

static_assert(n_levels == n_source_rates && n_levels == n_drain_rates,
              "Wrong number of tunnelling rates inputted by user.");

constexpr double total_capacitance = gate_capacitance + source_capacitance
                                     + drain_capacitance + extra_capacitance;

/* TYPES */

typedef struct {
    double gate;
    double sd;  // Source-drain
} v_pair;

typedef unsigned long cfg;
constexpr cfg n_configs = 1 << n_levels;  // 2^n_levels

typedef struct {
    cfg to;    // Row
    cfg from;  // Column
    double value;
} matrix_elem;

typedef double mu_spectrum[n_levels];
typedef mu_spectrum mu_container[n_configs];
// TODO: typedef double mu_container[occupied][level][occ_num];
// Should do this. Otherwise there are many redundant mu calculations.

typedef double weights[n_configs];

/* BINARY REPRESENTATION OF CONFIGURATIONS */

bool occupied (cfg config, int level) {
    return (config >> level) & 1;
}

int sum_occupation (cfg config) {
    int sum = 0;
    for (int level = 0; level < n_levels; ++level)
        sum += (int)occupied(config, level);
    return sum;
}

cfg flipped_occupation (cfg config, int level) {
    return config ^ (1 << level);
}

/* THE PHYSICS */

/* Thermodynamics */

double fermi (double energy, double chem_pot) {
    double exponent = (energy - chem_pot)/(k_B*temp);
    if (exponent > log(std::numeric_limits<double>::max()))
        return 0.0;
    else if (exponent < log(std::numeric_limits<double>::min()))
        return 1.0;
    else
        return 1.0/(exp(exponent) + 1);
}

/* Energy shifts in leads owing to applied bias */

constexpr double s_shift (double energy, double v_sd) {
    return energy - e*v_sd/2.0;
}

constexpr double d_shift (double energy, double v_sd) {
    return energy + e*v_sd/2.0;
}

/* Tunnel rates */

double in_from_source (double mu, double v_sd, int level) {
    return source_widths[level]
           * source_dos(mu - s_shift(0.0, v_sd))
           * fermi(mu, s_shift(s_fermi_energy, v_sd));
}

double in_from_drain (double mu, double v_sd, int level) {
    return drain_widths[level]
           * drain_dos(mu - d_shift(0.0, v_sd))
           * fermi(mu, d_shift(d_fermi_energy, v_sd));
}

double out_to_source (double mu, double v_sd, int level) {
    return source_widths[level]
           * source_dos(mu - s_shift(0.0, v_sd))
           * (1 - fermi(mu, s_shift(s_fermi_energy, v_sd)));
}

double out_to_drain (double mu, double v_sd, int level) {
    return drain_widths[level]
           * drain_dos(mu - d_shift(0.0, v_sd))
           * (1 - fermi(mu, d_shift(d_fermi_energy, v_sd)));
}

double current_through_level (double mu, bool occupied, double v_sd, int level)
{
    if (occupied)
        return -e*(out_to_drain(mu, v_sd, level)
                   - out_to_source(mu, v_sd, level));
    else
        return -e*(in_from_source(mu, v_sd, level)
                   - in_from_drain(mu, v_sd, level));
}

/* Charging energy (constant interaction) */

double chemical_potential (bool occupied, double single_electron_energy,
                           int n_electrons_on_dot, v_pair voltage) {

    return single_electron_energy
           + ((e/total_capacitance)
             *((n_electrons_on_dot + (occupied ? -1 : 1)*0.5)*e
                - gate_capacitance*voltage.gate
                - (source_capacitance - drain_capacitance)*voltage.sd/2.0));
}

/* Rate matrix elements (Beenakker rate equations) */

matrix_elem diag (cfg config, mu_spectrum spectrum, double v_sd) {
    double value = 0.0;
    for (int level = 0; level < n_levels; ++level) {
        auto mu = spectrum[level];
        if (occupied(config, level))
            value -= (out_to_source(mu, v_sd, level)
                      + out_to_drain(mu, v_sd, level));
        else
            value -= (in_from_source(mu, v_sd, level)
                      + in_from_drain(mu, v_sd, level));
    }
    return { config, config, value };
}

matrix_elem offdiag (cfg to, cfg from, int level, double mu, double v_sd) {
    double value;
    if (occupied(from, level))
        value = out_to_source(mu, v_sd, level)
                + out_to_drain(mu, v_sd, level);
    else
        value = in_from_source(mu, v_sd, level)
                + in_from_drain(mu, v_sd, level);
    return { to, from, value };
}

/* MISCELLANEOUS HELPER */

v_pair voltage_pair_from_index (int index) {
    /*
     * This function is defined such that we iterate through voltage-space
     * like so:
     *
     *        ┌┐┌┐┌┐┌┐┌finish
     *        │││││││││
     *        │││││││││
     *   start┘└┘└┘└┘└┘
     *
     * where y: gate voltage; x: source-drain voltage. In this way, we ensure
     * our weights guesses will mostly be almost correct.
     */
    v_pair voltage;

    if ((int)floor((double)index/(double)v_g_steps) % 2 == 0)
        voltage.gate = v_g_min
                       + ((index % v_g_steps)
                          *(v_g_max - v_g_min)/(double)v_g_steps);
    else
        voltage.gate = v_g_max
                       - (((index % v_g_steps) + 1)
                          *(v_g_max - v_g_min)/(double)v_g_steps);

    voltage.sd = v_sd_min
                   + (floor((double)index/(double)v_g_steps)
                      *(v_sd_max - v_sd_min)/(double)(v_sd_steps));

    return voltage;
}

/* THE SIMULATION */

int main () {

    std::ofstream outfile ("output.csv", std::ofstream::out);
    // outfile << n_levels << "\n";  // Needed for visualization later.

    /* 'Guess' that the dot is initially empty; w = { 1.0, 0.0, 0.0, ... }. */
    weights guess = { 1.0 };

    /* Iterate through points in voltage-space. */
    for (int voltage_index = 0;
         voltage_index < v_g_steps*v_sd_steps;
         ++voltage_index) {

        /* Choose a point in voltage-space. */
        auto voltage = voltage_pair_from_index(voltage_index);
        outfile << voltage.gate << " ; " << voltage.sd;
        std::cout << "v_g:" << voltage.gate << " ; "
                  << "v_sd:" << voltage.sd;

        /* For each possible config, find all the chemical potentials. */
        mu_container mu;
        for (cfg config = 0; config < n_configs; ++config) {
            for (int level = 0; level < n_levels; ++level) {
                mu[config][level] = chemical_potential(
                    occupied(config, level), single_electron_energies[level],
                    sum_occupation(config), voltage);
            }
        }

        /* Generate the rate matrix M. */
        // Use a std::vector because we might decide later to make more matrix
        // elements non-zero, e.g. for radiative decay.
        std::vector<matrix_elem> matrix;
        // TODO: Store just one row of the matrix in memory.
        for (cfg to = 0; to < n_configs; ++to) {
            // TODO: Only store matrix elements greater than some tolerance.
            // For "to" on the following line only, read "away".
            matrix.push_back(diag(to, mu[to], voltage.sd));
            for (int level = 0; level < n_levels; ++level) {
                cfg from = flipped_occupation(to, level);
                matrix.push_back(
                    offdiag(to, from, level, mu[from][level], voltage.sd));
            }
        }

        /* Iterate on dw/dt = M w until steady state is found. */
        bool converged = false;
        int cycles = 0;
        while (!converged) {
            ++cycles;
            converged = true;  // To be &&'d.
            /* Runge-Kutta (RK4) iteration happens here. */
            double k_1[n_configs] = { 0.0 };
            cfg elem = 0;  // This is a summation variable.
            for (cfg config = 0; config < n_configs; ++config) {
                // We assume that matrix elements are ordered by value of
                // matrix[elem].to (as below).
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_1[config] += matrix[elem].value*guess[matrix[elem].from];
                    ++elem;
                }
            }
            double k_2[n_configs] = { 0.0 };
            elem = 0;  // Reset summation variable.
            for (cfg config = 0; config < n_configs; ++config) {
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_2[config] += matrix[elem].value
                                   * (guess[matrix[elem].from]
                                      + (k_1[matrix[elem].from] * h/2.0));
                    ++elem;
                }
            }
            double k_3[n_configs] = { 0.0 };
            elem = 0;
            for (cfg config = 0; config < n_configs; ++config) {
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_3[config] += matrix[elem].value
                                   * (guess[matrix[elem].from]
                                      + (k_2[matrix[elem].from] * h/2.0));
                    ++elem;
                }
            }
            double k_4[n_configs] = { 0.0 };
            elem = 0;
            for (cfg config = 0; config < n_configs; ++config) {
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_4[config] += matrix[elem].value
                                   * (guess[matrix[elem].from]
                                      + (k_3[matrix[elem].from] * h));
                    ++elem;
                }
            }
            for (cfg config = 0; config < n_configs; ++config) {
                double increment = (k_1[config]
                                    + 2*k_2[config]
                                    + 2*k_3[config]
                                    + k_4[config])
                                   * h/6.0;
                guess[config] += increment;
                converged = converged && (increment < convergence_criterion);
            }
        }
        std::cout << " ; " << cycles << " cycles\n";

        /* Find weighted-average current and write it to file. */
        double current = 0.0;
        for (cfg config = 0; config < n_configs; ++config) {
            for (int level = 0; level < n_levels; ++level) {
                current += guess[config]*current_through_level(
                    mu[config][level], occupied(config, level),
                    voltage.sd, level);
            }
        }
        outfile << " ; " << current/e;

        // for (cfg config = 0; config < n_configs; ++config) {
        //     if (guess[config] > 1e-5)
        //         outfile << " ; "<< config << " ; " << guess[config];
        // }

        /* Write weights vector to file for later viewing. */
        for (cfg config = 0; config < n_configs; ++config) {
            outfile << " ; " << guess[config];
        }

        outfile << "\n";
    }
}
<commit_msg>Allocate weights and mu container on heap<commit_after>#include <iostream>
#include <cmath>
#include <limits>
#include <vector>
#include <fstream>

/* PHYSICAL CONSTANTS */

constexpr double e = 1.60217657e-19;   // Coulombs
constexpr double k_B = 1.3806488e-23;  // Joules per Kelvin

/* USER CONFIGURATION */

/* Temperature */
constexpr double temp = 4.2;  // Kelvin

/* Dot orbital energies */
constexpr double single_electron_energies[] = {
    0.0*e, 0.01*e, 0.02*e, 0.03*e, 0.04*e, 0.05*e, 0.06*e, 0.07*e
};  // Joules

/* Tunnel widths (by dot level) */
constexpr double source_widths[] {
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

constexpr double drain_widths[] {
    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

/* Dot-system capacitances */
constexpr double gate_capacitance =   1e-19;  // Farads
constexpr double source_capacitance = 1e-18;  // Farads
constexpr double drain_capacitance =  1e-18;  // Farads
constexpr double extra_capacitance =  1e-19;  // Farads

/* Voltage-space to be explored */
constexpr double v_g_min = -0.3;  // Volts
constexpr double v_g_max = 6.1;  // Volts
constexpr int v_g_steps = 200;  // (y axis resolution)

constexpr double v_sd_min = -0.21;  // Volts
constexpr double v_sd_max = 0.21;  // Volts
constexpr int v_sd_steps = 200;  // (x axis resolution)

/* Electronic properties of leads (s: source; d: drain) */
constexpr double source_dos (double energy) {
    if (energy > 0.0) {
        // Do nothing. (Suppress 'unused' warning.)
    }
    return 1;
}
constexpr double d_fermi_energy = 0.0*e;  // Joules

constexpr double drain_dos (double energy) {
    if (energy > 0.0) {
        // Do nothing. (Suppress 'unused' warning.)
    }
    return 1;
}
constexpr double s_fermi_energy = 0.0*e;  // Joules

/* Semiclassical simulation properties */
constexpr double h = 1e-1;  // Runge-Kutta evolution step size
constexpr double convergence_criterion = 1e-5;

/* COMPILE-TIME CALCULATIONS */

constexpr int n_levels = sizeof(single_electron_energies)
                         /sizeof(single_electron_energies[0]);

constexpr int n_source_rates = sizeof(source_widths)
                               /sizeof(source_widths[0]);

constexpr int n_drain_rates = sizeof(drain_widths)
                               /sizeof(drain_widths[0]);

static_assert(n_levels == n_source_rates && n_levels == n_drain_rates,
              "Wrong number of tunnelling rates inputted by user.");

constexpr double total_capacitance = gate_capacitance + source_capacitance
                                     + drain_capacitance + extra_capacitance;

/* TYPES */

typedef struct {
    double gate;
    double sd;  // Source-drain
} v_pair;

typedef unsigned long cfg;
constexpr cfg n_configs = 1 << n_levels;  // 2^n_levels

typedef struct {
    cfg to;    // Row
    cfg from;  // Column
    double value;
} matrix_elem;

typedef double mu_spectrum[n_levels];
// TODO: typedef double mu_container[occupied][level][occ_num];
// Should do this. Otherwise there are many redundant mu calculations.

/* BINARY REPRESENTATION OF CONFIGURATIONS */

bool occupied (cfg config, int level) {
    return (config >> level) & 1;
}

int sum_occupation (cfg config) {
    int sum = 0;
    for (int level = 0; level < n_levels; ++level)
        sum += (int)occupied(config, level);
    return sum;
}

cfg flipped_occupation (cfg config, int level) {
    return config ^ (1 << level);
}

/* THE PHYSICS */

/* Thermodynamics */

double fermi (double energy, double chem_pot) {
    double exponent = (energy - chem_pot)/(k_B*temp);
    if (exponent > log(std::numeric_limits<double>::max()))
        return 0.0;
    else if (exponent < log(std::numeric_limits<double>::min()))
        return 1.0;
    else
        return 1.0/(exp(exponent) + 1);
}

/* Energy shifts in leads owing to applied bias */

constexpr double s_shift (double energy, double v_sd) {
    return energy - e*v_sd/2.0;
}

constexpr double d_shift (double energy, double v_sd) {
    return energy + e*v_sd/2.0;
}

/* Tunnel rates */

double in_from_source (double mu, double v_sd, int level) {
    return source_widths[level]
           * source_dos(mu - s_shift(0.0, v_sd))
           * fermi(mu, s_shift(s_fermi_energy, v_sd));
}

double in_from_drain (double mu, double v_sd, int level) {
    return drain_widths[level]
           * drain_dos(mu - d_shift(0.0, v_sd))
           * fermi(mu, d_shift(d_fermi_energy, v_sd));
}

double out_to_source (double mu, double v_sd, int level) {
    return source_widths[level]
           * source_dos(mu - s_shift(0.0, v_sd))
           * (1 - fermi(mu, s_shift(s_fermi_energy, v_sd)));
}

double out_to_drain (double mu, double v_sd, int level) {
    return drain_widths[level]
           * drain_dos(mu - d_shift(0.0, v_sd))
           * (1 - fermi(mu, d_shift(d_fermi_energy, v_sd)));
}

double current_through_level (double mu, bool occupied, double v_sd, int level)
{
    if (occupied)
        return -e*(out_to_drain(mu, v_sd, level)
                   - out_to_source(mu, v_sd, level));
    else
        return -e*(in_from_source(mu, v_sd, level)
                   - in_from_drain(mu, v_sd, level));
}

/* Charging energy (constant interaction) */

double chemical_potential (bool occupied, double single_electron_energy,
                           int n_electrons_on_dot, v_pair voltage) {

    return single_electron_energy
           + ((e/total_capacitance)
             *((n_electrons_on_dot + (occupied ? -1 : 1)*0.5)*e
                - gate_capacitance*voltage.gate
                - (source_capacitance - drain_capacitance)*voltage.sd/2.0));
}

/* Rate matrix elements (Beenakker rate equations) */

matrix_elem diag (cfg config, mu_spectrum spectrum, double v_sd) {
    double value = 0.0;
    for (int level = 0; level < n_levels; ++level) {
        auto mu = spectrum[level];
        if (occupied(config, level))
            value -= (out_to_source(mu, v_sd, level)
                      + out_to_drain(mu, v_sd, level));
        else
            value -= (in_from_source(mu, v_sd, level)
                      + in_from_drain(mu, v_sd, level));
    }
    return { config, config, value };
}

matrix_elem offdiag (cfg to, cfg from, int level, double mu, double v_sd) {
    double value;
    if (occupied(from, level))
        value = out_to_source(mu, v_sd, level)
                + out_to_drain(mu, v_sd, level);
    else
        value = in_from_source(mu, v_sd, level)
                + in_from_drain(mu, v_sd, level);
    return { to, from, value };
}

/* MISCELLANEOUS HELPER */

v_pair voltage_pair_from_index (int index) {
    /*
     * This function is defined such that we iterate through voltage-space
     * like so:
     *
     *        ┌┐┌┐┌┐┌┐┌finish
     *        │││││││││
     *        │││││││││
     *   start┘└┘└┘└┘└┘
     *
     * where y: gate voltage; x: source-drain voltage. In this way, we ensure
     * our weights guesses will mostly be almost correct.
     */
    v_pair voltage;

    if ((int)floor((double)index/(double)v_g_steps) % 2 == 0)
        voltage.gate = v_g_min
                       + ((index % v_g_steps)
                          *(v_g_max - v_g_min)/(double)v_g_steps);
    else
        voltage.gate = v_g_max
                       - (((index % v_g_steps) + 1)
                          *(v_g_max - v_g_min)/(double)v_g_steps);

    voltage.sd = v_sd_min
                   + (floor((double)index/(double)v_g_steps)
                      *(v_sd_max - v_sd_min)/(double)(v_sd_steps));

    return voltage;
}

/* THE SIMULATION */

int main () {

    std::ofstream outfile ("output.csv", std::ofstream::out);
    // outfile << n_levels << "\n";  // Needed for visualization later.

    /* 'Guess' that the dot is initially empty; w = { 1.0, 0.0, 0.0, ... }. */
    std::vector<double> guess (n_configs);
    guess[0] = 1;

    /* Iterate through points in voltage-space. */
    for (int voltage_index = 0;
         voltage_index < v_g_steps*v_sd_steps;
         ++voltage_index) {

        /* Choose a point in voltage-space. */
        auto voltage = voltage_pair_from_index(voltage_index);
        outfile << voltage.gate << " ; " << voltage.sd;
        std::cout << "v_g:" << voltage.gate << " ; "
                  << "v_sd:" << voltage.sd;

        /* For each possible config, find all the chemical potentials. */
        std::vector<mu_spectrum> mu (n_configs);
        for (cfg config = 0; config < n_configs; ++config) {
            for (int level = 0; level < n_levels; ++level) {
                mu[config][level] = chemical_potential(
                    occupied(config, level), single_electron_energies[level],
                    sum_occupation(config), voltage);
            }
        }

        /* Generate the rate matrix M. */
        // Use a std::vector because we might decide later to make more matrix
        // elements non-zero, e.g. for radiative decay.
        std::vector<matrix_elem> matrix;
        // TODO: Store just one row of the matrix in memory.
        for (cfg to = 0; to < n_configs; ++to) {
            // TODO: Only store matrix elements greater than some tolerance.
            // For "to" on the following line only, read "away".
            matrix.push_back(diag(to, mu[to], voltage.sd));
            for (int level = 0; level < n_levels; ++level) {
                cfg from = flipped_occupation(to, level);
                matrix.push_back(
                    offdiag(to, from, level, mu[from][level], voltage.sd));
            }
        }

        /* Iterate on dw/dt = M w until steady state is found. */
        bool converged = false;
        int cycles = 0;
        while (!converged) {
            ++cycles;
            converged = true;  // To be &&'d.
            /* Runge-Kutta (RK4) iteration happens here. */
            double k_1[n_configs] = { 0.0 };
            cfg elem = 0;  // This is a summation variable.
            for (cfg config = 0; config < n_configs; ++config) {
                // We assume that matrix elements are ordered by value of
                // matrix[elem].to (as below).
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_1[config] += matrix[elem].value*guess[matrix[elem].from];
                    ++elem;
                }
            }
            double k_2[n_configs] = { 0.0 };
            elem = 0;  // Reset summation variable.
            for (cfg config = 0; config < n_configs; ++config) {
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_2[config] += matrix[elem].value
                                   * (guess[matrix[elem].from]
                                      + (k_1[matrix[elem].from] * h/2.0));
                    ++elem;
                }
            }
            double k_3[n_configs] = { 0.0 };
            elem = 0;
            for (cfg config = 0; config < n_configs; ++config) {
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_3[config] += matrix[elem].value
                                   * (guess[matrix[elem].from]
                                      + (k_2[matrix[elem].from] * h/2.0));
                    ++elem;
                }
            }
            double k_4[n_configs] = { 0.0 };
            elem = 0;
            for (cfg config = 0; config < n_configs; ++config) {
                while (elem < matrix.size() && matrix[elem].to == config) {
                    k_4[config] += matrix[elem].value
                                   * (guess[matrix[elem].from]
                                      + (k_3[matrix[elem].from] * h));
                    ++elem;
                }
            }
            for (cfg config = 0; config < n_configs; ++config) {
                double increment = (k_1[config]
                                    + 2*k_2[config]
                                    + 2*k_3[config]
                                    + k_4[config])
                                   * h/6.0;
                guess[config] += increment;
                converged = converged && (increment < convergence_criterion);
            }
        }
        std::cout << " ; " << cycles << " cycles\n";

        /* Find weighted-average current and write it to file. */
        double current = 0.0;
        for (cfg config = 0; config < n_configs; ++config) {
            for (int level = 0; level < n_levels; ++level) {
                current += guess[config]*current_through_level(
                    mu[config][level], occupied(config, level),
                    voltage.sd, level);
            }
        }
        outfile << " ; " << current/e;

        // for (cfg config = 0; config < n_configs; ++config) {
        //     if (guess[config] > 1e-5)
        //         outfile << " ; "<< config << " ; " << guess[config];
        // }

        /* Write weights vector to file for later viewing. */
        for (cfg config = 0; config < n_configs; ++config) {
            outfile << " ; " << guess[config];
        }

        outfile << "\n";
    }
}
<|endoftext|>


<commit_before>b9a2c478-4b02-11e5-b369-28cfe9171a43<commit_msg>TODO: Add a beter commit message<commit_after>b9b1458c-4b02-11e5-83e1-28cfe9171a43<|endoftext|>


<commit_before>8a5ec905-ad58-11e7-8320-ac87a332f658<commit_msg>add file<commit_after>8adc294c-ad58-11e7-add3-ac87a332f658<|endoftext|>


<commit_before>//===============================================================================
//  iSpectraSampler
//===============================================================================
//
//  Zhi Qiu & Chun Shen
//    qiu.24@asc.ohio-state.edu
//    shen.201@asc.ohio-state.edu
//
//        Date: 03/2012
// Version info written in the main function.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <ctime>
#include <string>
#include <sstream>
#include <math.h>
#include <vector>
#include <sys/time.h>
#include <stdlib.h>

#include "main.h"
#include "ParameterReader.h"
#include "Table.h"
#include "readindata.h"
#include "emissionfunction.h"
#include "arsenal.h"

using namespace std;

int main(int argc, char** argv)
{
   cout << endl
        << "                  iSpectraSampler                " << endl
        << endl
        << "  Ver 2.0.0.0  ---- Zhi Qiu & Chun Shen, 04/2012 " << endl;
   cout << endl << "**********************************************************" << endl;
   display_logo(3); // Hail to the king~
   cout << endl << "**********************************************************" << endl << endl;

   // Chun's input reading process
   string path="results";

   //load freeze out information
   int FO_length = 0;
   ostringstream decdatfile;
   cout << " -- Loading the decoupling data....";
   decdatfile << path << "/decdat2.dat";
   FO_length=get_filelength(decdatfile.str().c_str());
   cout <<" cells number: " <<  FO_length << endl;

   //read the data arrays for the decoupling information
   FO_surf* FOsurf_ptr = new FO_surf[FO_length];
   for(int i=0; i<FO_length; i++)
     for(int j=0; j<Maxparticle; j++)
         FOsurf_ptr[i].particle_mu[j] = 0.0e0;
   read_decdat(path, FO_length, FOsurf_ptr);

   //read the positions of the freeze out surface
   read_surfdat(path, FO_length, FOsurf_ptr);

   //read the chemical potential on the freeze out surface
   int N_stableparticle;
   ifstream particletable("EOS/EOS_particletable.dat");
   particletable >> N_stableparticle;
   double** particle_mu = new double* [N_stableparticle];
   for(int i=0; i<N_stableparticle; i++)
     particle_mu[i] = new double [FO_length];
   if(N_stableparticle >0)
   {
      read_decdat_mu(path, FO_length, N_stableparticle, particle_mu);
   }

   //read particle resonance decay table
   particle_info *particle = new particle_info [Maxparticle];
   for (int i=0; i<Maxparticle; i++) particle[i].decays=0; // to avoid infinite loop
   int Nparticle=read_resonance(particle);
   cout <<"particle number: " << Nparticle << endl;
   if(N_stableparticle >0)
   {
      cout << " -- EOS is partically chemical equilibrium " << endl;
      calculate_particle_mu(Nparticle, FOsurf_ptr, FO_length, particle, particle_mu);
   }
   else
   {
      cout << " -- EOS is chemical equilibrium. " << endl;
      for(int i=0; i<Nparticle; i++)
        for(int j=0; j<FO_length; j++)
           FOsurf_ptr[i].particle_mu[j] = 0.0e0;
   }
   cout << endl << " -- Read in data finished!" << endl << endl;

   // Next, Zhi's turn...

   // First other parameters; Zhi's style
   ParameterReader paraRdr;
   paraRdr.readFromFile("parameters.dat");
   paraRdr.readFromArguments(argc, argv);
   //paraRdr.echo();

   // init random seed from system time
   timeval a;
   gettimeofday(&a, 0);
   long randomSeed=paraRdr.getVal("randomSeed");
   if (randomSeed<0) randomSeed=a.tv_usec; // randomSeed<0 means to use CPU clock
   srand48(randomSeed);

   Table chosen_particles("EOS/chosen_particles.dat"); // skip others except for these particle
   Table pT_tab("tables/pT_gauss_table.dat"); // pt position and weight table
   Table phi_tab("tables/phi_gauss_table.dat"); // phi position and weight table
   Table eta_tab("tables/eta_gauss_table_20_full.dat"); // eta uniform dist table
   EmissionFunctionArray efa(&chosen_particles, &pT_tab, &phi_tab, &eta_tab, particle, Nparticle, FOsurf_ptr, FO_length, &paraRdr);

   efa.shell();
   //efa.combine_samples_to_OSCAR();
}
<commit_msg>iSS fixed one typo<commit_after>//===============================================================================
//  iSpectraSampler
//===============================================================================
//
//  Zhi Qiu & Chun Shen
//    qiu.24@asc.ohio-state.edu
//    shen.201@asc.ohio-state.edu
//
//        Date: 03/2012
// Version info written in the main function.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <ctime>
#include <string>
#include <sstream>
#include <math.h>
#include <vector>
#include <sys/time.h>
#include <stdlib.h>

#include "main.h"
#include "ParameterReader.h"
#include "Table.h"
#include "readindata.h"
#include "emissionfunction.h"
#include "arsenal.h"

using namespace std;

int main(int argc, char** argv)
{
   cout << endl
        << "                  iSpectraSampler                " << endl
        << endl
        << "  Ver 2.0.0.0  ---- Zhi Qiu & Chun Shen, 04/2012 " << endl;
   cout << endl << "**********************************************************" << endl;
   display_logo(3); // Hail to the king~
   cout << endl << "**********************************************************" << endl << endl;

   // Chun's input reading process
   string path="results";

   //load freeze out information
   int FO_length = 0;
   ostringstream decdatfile;
   cout << " -- Loading the decoupling data....";
   decdatfile << path << "/decdat2.dat";
   FO_length=get_filelength(decdatfile.str().c_str());
   cout <<" cells number: " <<  FO_length << endl;

   //read the data arrays for the decoupling information
   FO_surf* FOsurf_ptr = new FO_surf[FO_length];
   for(int i=0; i<FO_length; i++)
     for(int j=0; j<Maxparticle; j++)
         FOsurf_ptr[i].particle_mu[j] = 0.0e0;
   read_decdat(path, FO_length, FOsurf_ptr);

   //read the positions of the freeze out surface
   read_surfdat(path, FO_length, FOsurf_ptr);

   //read the chemical potential on the freeze out surface
   int N_stableparticle;
   ifstream particletable("EOS/EOS_particletable.dat");
   particletable >> N_stableparticle;
   double** particle_mu = new double* [N_stableparticle];
   for(int i=0; i<N_stableparticle; i++)
     particle_mu[i] = new double [FO_length];
   if(N_stableparticle >0)
   {
      read_decdat_mu(path, FO_length, N_stableparticle, particle_mu);
   }

   //read particle resonance decay table
   particle_info *particle = new particle_info [Maxparticle];
   for (int i=0; i<Maxparticle; i++) particle[i].decays=0; // to avoid infinite loop
   int Nparticle=read_resonance(particle);
   cout <<"particle number: " << Nparticle << endl;
   if(N_stableparticle >0)
   {
      cout << " -- EOS is partically chemical equilibrium " << endl;
      calculate_particle_mu(Nparticle, FOsurf_ptr, FO_length, particle, particle_mu);
   }
   else
   {
      cout << " -- EOS is chemical equilibrium. " << endl;
      for(int i=0; i<Nparticle; i++)
        for(int j=0; j<FO_length; j++)
           FOsurf_ptr[j].particle_mu[i] = 0.0e0;
   }
   cout << endl << " -- Read in data finished!" << endl << endl;

   // Next, Zhi's turn...

   // First other parameters; Zhi's style
   ParameterReader paraRdr;
   paraRdr.readFromFile("parameters.dat");
   paraRdr.readFromArguments(argc, argv);
   //paraRdr.echo();

   // init random seed from system time
   timeval a;
   gettimeofday(&a, 0);
   long randomSeed=paraRdr.getVal("randomSeed");
   if (randomSeed<0) randomSeed=a.tv_usec; // randomSeed<0 means to use CPU clock
   srand48(randomSeed);

   Table chosen_particles("EOS/chosen_particles.dat"); // skip others except for these particle
   Table pT_tab("tables/pT_gauss_table.dat"); // pt position and weight table
   Table phi_tab("tables/phi_gauss_table.dat"); // phi position and weight table
   Table eta_tab("tables/eta_gauss_table_20_full.dat"); // eta uniform dist table
   EmissionFunctionArray efa(&chosen_particles, &pT_tab, &phi_tab, &eta_tab, particle, Nparticle, FOsurf_ptr, FO_length, &paraRdr);

   efa.shell();
   //efa.combine_samples_to_OSCAR();
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <chrono>
#include "mame/emu.h"
#include "src/delegate.h"
#include "mame/devdelegate.h"

class running_machine
{
public:
	running_machine() {}
};

// Declare some functions of varying complexity...
void SimpleStaticFunction(running_machine &, int num) {
	printf("In SimpleStaticFunction. Num=%d\n", num);
}

void SimpleVoidFunction(running_machine &) {
	printf("In SimpleVoidFunction with no parameters.\n");
}

class CBaseClass {
protected:
	const char *m_name;
public:
	CBaseClass(const char *name) : m_name(name) {}
	virtual ~CBaseClass() { }
	void SimpleMemberFunction(int num) {
		printf("In SimpleMemberFunction in %s. Num=%d\n", m_name, num);
	}
	int SimpleMemberFunctionReturnsInt(int num) {
		printf("In SimpleMemberFunction in %s. Num=%d\n", m_name, num); return -1;
	}
	void ConstMemberFunction(int num) const {
		printf("In ConstMemberFunction in %s. Num=%d\n", m_name, num);
	}
	virtual void SimpleVirtualFunction(int num) {
		printf("In SimpleVirtualFunction in %s. Num=%d\n", m_name, num);
	}
	static void StaticMemberFunction(running_machine &, int num) {
		printf("In StaticMemberFunction. Num=%d\n", num);
	}
};

class COtherClass {
	double rubbish; // to ensure this class has non-zero size.
public:
	virtual ~COtherClass() { }
	virtual void UnusedVirtualFunction(void) { }
	virtual void TrickyVirtualFunction(int num) = 0;
};

class VeryBigClass {
	int letsMakeThingsComplicated[400];
};

// This declaration ensures that we get a convoluted class heirarchy.
class CDerivedClass : public VeryBigClass, virtual public COtherClass, virtual public CBaseClass
{
	double m_somemember[8];
public:
	CDerivedClass() : CBaseClass("Base of Derived") { m_somemember[0] = 1.2345; }
	void SimpleDerivedFunction(int num) { printf("In SimpleDerived. num=%d\n", num); }
	virtual void AnotherUnusedVirtualFunction(int) {}
	virtual void TrickyVirtualFunction(int num) override {
		printf("In Derived TrickyMemberFunction. Num=%d\n", num);
	}
};

class MyClass
{
public:
	MyClass() { i = 0; }
	virtual ~MyClass() { }

	void docount2(int j) { i += j; }
	virtual void docount(int j) { i+=j; }
	int get() { return i; }
private:
	int i;
};

class MyClass2 : public MyClass
{
public:
	MyClass2() : MyClass() { }
	virtual ~MyClass2() { }
	virtual void docount(int) {  }
};

#define FUNC(x) &x, #x

typedef delegate<void(void)> VoidDelegate;
typedef delegate<void(int)> MyDelegate;

typedef device_delegate<int()> read_line_delegate;
typedef device_delegate<void(int)> write_line_delegate;

template<class _FunctionClass>
void dump_mfp(_FunctionClass *object, void (_FunctionClass::*mfp)(int num))
{
	unsigned long *ptr = (unsigned long *)&mfp;
	int size = sizeof(mfp) / sizeof(*ptr);
	(object->*mfp)(1);
	printf("Size = %d bytes:\n", (int)sizeof(mfp));
	for (int i = 0; i < size; i++)
		printf("  %08X\n", (std::uint32_t)ptr[i]);
}

template<class _FunctionClass>
void dump_addr(const char *, _FunctionClass *, void (_FunctionClass::*)(int))
{
	//printf("%s Addr = %08x\n", text, (void*)(object->*mfp));
}

void dump_vtable(const char *name, void *ptr)
{
	void **vtable = *reinterpret_cast<void ***>(ptr);
	printf("%s: vtable @ %p = %p %p %p %p\n", name, *vtable, vtable[0], vtable[1], vtable[2], vtable[3]);
}

int main(int, char**)
{
#if defined(__clang__)
	printf("Clang version: %d.%d.%d\n", __clang_major__, __clang_minor__, __clang_patchlevel__);
#elif defined(_MSC_VER)
	printf("MSC_VER version: %d\n", _MSC_VER);
#elif defined(__GNUC__)
	printf("GCC version: %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#else
	printf("Unknown compiler\n");
#endif //

#if defined(__arm__) || defined(_M_ARM)
	printf("ARM\n");
#elif defined(__aarch64__)
	printf("ARM 64bit\n");
#elif defined(__MIPSEL__) || defined(__mips_isa_rev)
	printf("MIPS\n");
#elif defined(__mips64)
	printf("MIPS 64bit\n");
#elif defined(_M_PPC) || defined(__powerpc__)
	printf("PPC\n");
#elif defined(__powerpc64__)
	printf("PPC 64bit\n");
#elif defined(__i386__) || defined(_M_IX86)
	printf("Intel x86\n");
#elif defined(__x86_64__) || defined(_M_X64)
	printf("Intel x64\n");
#else
	printf("Unknown CPU\n");
#endif //
	printf("Pointer size %d\n", (int)sizeof(void *));

#if USE_DELEGATE_TYPE==DELEGATE_TYPE_COMPATIBLE
	printf("Using slow compatible delegates\n");
#elif USE_DELEGATE_TYPE==DELEGATE_TYPE_INTERNAL
	printf("Using fast internal GCC/CLANG delegates\n");
#elif USE_DELEGATE_TYPE==DELEGATE_TYPE_MSVC
	printf("Using fast internal MSVC delegates\n");
#endif

	running_machine machine;
	MyDelegate funclist[12]; // delegates are initialized to empty
	CBaseClass a("Base A");
	CBaseClass b("Base B");
	CDerivedClass c;
	CDerivedClass d;

	dump_vtable("A", &a);
	dump_vtable("D", &d);

	dump_mfp(&a, &CBaseClass::SimpleMemberFunction);
	dump_mfp(&a, &CBaseClass::SimpleVirtualFunction);

	dump_mfp(&d, &CDerivedClass::SimpleDerivedFunction);
	dump_mfp(&d, &CDerivedClass::TrickyVirtualFunction);

	dump_addr("CBaseClass::SimpleMemberFunction",&a, &CBaseClass::SimpleMemberFunction);
	dump_addr("CBaseClass::SimpleVirtualFunction",&b, &CBaseClass::SimpleVirtualFunction);
	dump_addr("CDerivedClass::TrickyVirtualFunction",&c, &CDerivedClass::TrickyVirtualFunction);
	dump_addr("CDerivedClass::SimpleDerivedFunction",&c, &CDerivedClass::SimpleDerivedFunction);
	// Binding a simple member function
	printf("funclist[0] = MyDelegate(FUNC(CBaseClass::SimpleMemberFunction), &a);\n");
	funclist[0] = MyDelegate(FUNC(CBaseClass::SimpleMemberFunction), &a);

	// You can also bind static (free) functions
	printf("funclist[1] = MyDelegate(FUNC(SimpleStaticFunction),&machine);\n");
	funclist[1] = MyDelegate(FUNC(SimpleStaticFunction),&machine);
	// and static member functions
	printf("funclist[2] = MyDelegate(FUNC(CBaseClass::StaticMemberFunction), &machine);\n");
	funclist[2] = MyDelegate(FUNC(CBaseClass::StaticMemberFunction), &machine);
	// and virtual member functions
	printf("funclist[3] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction), &b);\n");
	funclist[3] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction), &b);
	printf("funclist[4] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction),(CBaseClass *)&d);\n");
	funclist[4] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction),(CBaseClass *)&d);
	printf("funclist[5] = MyDelegate(FUNC(CDerivedClass::TrickyVirtualFunction),&c);\n");
	funclist[5] = MyDelegate(FUNC(CDerivedClass::TrickyVirtualFunction),&c);
	printf("funclist[6] = MyDelegate(FUNC(COtherClass::TrickyVirtualFunction),(COtherClass*)&c);\n");
	funclist[6] = MyDelegate(FUNC(COtherClass::TrickyVirtualFunction),(COtherClass*)&c);
	printf("funclist[7] = MyDelegate(FUNC(CDerivedClass::SimpleDerivedFunction),&c);\n");
	funclist[7] = MyDelegate(FUNC(CDerivedClass::SimpleDerivedFunction),&c);
	fflush(stdout);
	for (int i = 0; i<8; i++) {
		if (!funclist[i].isnull()) {
			funclist[i](i);
			fflush(stdout);
		}
	}

	printf("Checking devdelegates:\n");

	device_t root("root");
	device_t sub1("sub1");
	device_t sub2("sub2");
	root.add_device("sub1", &sub1);
	root.add_device("sub2", &sub2);

	write_line_delegate write_del = write_line_delegate(FUNC(device_t::write), &root);
	read_line_delegate read_del = read_line_delegate(FUNC(device_t::read), &root);
	write_del(100);
	printf("read_line_delegate : %d\n", read_del());

	write_line_delegate sub1_write_del = write_line_delegate(FUNC(device_t::write), "sub1", (device_t*)nullptr);
	read_line_delegate sub1_read_del = read_line_delegate(FUNC(device_t::read), "sub1", (device_t*)nullptr);
	sub1_write_del.bind_relative_to(root);
	sub1_read_del.bind_relative_to(root);
	sub1_write_del(200);

	printf("read_line_delegate sub 1: %d\n", sub1_read_del());

	typedef delegate<void(int j)> driver_callback_delegate;
	MyClass2 mc;
	driver_callback_delegate md = driver_callback_delegate(FUNC(MyClass2::docount), static_cast<MyClass2 *>(&mc));

	printf("Benchmarking virtual call : ");
	{
		auto before = std::chrono::high_resolution_clock::now(); ;
		for (int i = 0; i < 100000000; i++)
		{
			md(i);
		}
		auto after = std::chrono::high_resolution_clock::now(); ;
		auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(after - before);
		printf("%ld\n", elapsed.count());
	}

	printf("Done\n");
	return 0;

}

<commit_msg>added std::bind tests measurement<commit_after>#include <stdio.h>
#include <chrono>
#include "mame/emu.h"
#include "src/delegate.h"
#include "mame/devdelegate.h"
#include <functional>

class running_machine
{
public:
	running_machine() {}
};

// Declare some functions of varying complexity...
void SimpleStaticFunction(running_machine &, int num) {
	printf("In SimpleStaticFunction. Num=%d\n", num);
}

void SimpleVoidFunction(running_machine &) {
	printf("In SimpleVoidFunction with no parameters.\n");
}

class CBaseClass {
protected:
	const char *m_name;
public:
	CBaseClass(const char *name) : m_name(name) {}
	virtual ~CBaseClass() { }
	void SimpleMemberFunction(int num) {
		printf("In SimpleMemberFunction in %s. Num=%d\n", m_name, num);
	}
	int SimpleMemberFunctionReturnsInt(int num) {
		printf("In SimpleMemberFunction in %s. Num=%d\n", m_name, num); return -1;
	}
	void ConstMemberFunction(int num) const {
		printf("In ConstMemberFunction in %s. Num=%d\n", m_name, num);
	}
	virtual void SimpleVirtualFunction(int num) {
		printf("In SimpleVirtualFunction in %s. Num=%d\n", m_name, num);
	}
	static void StaticMemberFunction(running_machine &, int num) {
		printf("In StaticMemberFunction. Num=%d\n", num);
	}
};

class COtherClass {
	double rubbish; // to ensure this class has non-zero size.
public:
	virtual ~COtherClass() { }
	virtual void UnusedVirtualFunction(void) { }
	virtual void TrickyVirtualFunction(int num) = 0;
};

class VeryBigClass {
	int letsMakeThingsComplicated[400];
};

// This declaration ensures that we get a convoluted class heirarchy.
class CDerivedClass : public VeryBigClass, virtual public COtherClass, virtual public CBaseClass
{
	double m_somemember[8];
public:
	CDerivedClass() : CBaseClass("Base of Derived") { m_somemember[0] = 1.2345; }
	void SimpleDerivedFunction(int num) { printf("In SimpleDerived. num=%d\n", num); }
	virtual void AnotherUnusedVirtualFunction(int) {}
	virtual void TrickyVirtualFunction(int num) override {
		printf("In Derived TrickyMemberFunction. Num=%d\n", num);
	}
};

class MyClass
{
public:
	MyClass() { i = 0; }
	virtual ~MyClass() { }

	void docount2(int j) { i += j; }
	virtual void docount(int j) { i+=j; }
	int get() { return i; }
private:
	int i;
};

class MyClass2 : public MyClass
{
public:
	MyClass2() : MyClass() { }
	virtual ~MyClass2() { }
	virtual void docount(int) {  }
};

#define FUNC(x) &x, #x

typedef delegate<void(void)> VoidDelegate;
typedef delegate<void(int)> MyDelegate;

typedef device_delegate<int()> read_line_delegate;
typedef device_delegate<void(int)> write_line_delegate;

template<class _FunctionClass>
void dump_mfp(_FunctionClass *object, void (_FunctionClass::*mfp)(int num))
{
	unsigned long *ptr = (unsigned long *)&mfp;
	int size = sizeof(mfp) / sizeof(*ptr);
	(object->*mfp)(1);
	printf("Size = %d bytes:\n", (int)sizeof(mfp));
	for (int i = 0; i < size; i++)
		printf("  %08X\n", (std::uint32_t)ptr[i]);
}

template<class _FunctionClass>
void dump_addr(const char *, _FunctionClass *, void (_FunctionClass::*)(int))
{
	//printf("%s Addr = %08x\n", text, (void*)(object->*mfp));
}

void dump_vtable(const char *name, void *ptr)
{
	void **vtable = *reinterpret_cast<void ***>(ptr);
	printf("%s: vtable @ %p = %p %p %p %p\n", name, *vtable, vtable[0], vtable[1], vtable[2], vtable[3]);
}

int main(int, char**)
{
#if defined(__clang__)
	printf("Clang version: %d.%d.%d\n", __clang_major__, __clang_minor__, __clang_patchlevel__);
#elif defined(_MSC_VER)
	printf("MSC_VER version: %d\n", _MSC_VER);
#elif defined(__GNUC__)
	printf("GCC version: %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#else
	printf("Unknown compiler\n");
#endif //

#if defined(__arm__) || defined(_M_ARM)
	printf("ARM\n");
#elif defined(__aarch64__)
	printf("ARM 64bit\n");
#elif defined(__MIPSEL__) || defined(__mips_isa_rev)
	printf("MIPS\n");
#elif defined(__mips64)
	printf("MIPS 64bit\n");
#elif defined(_M_PPC) || defined(__powerpc__)
	printf("PPC\n");
#elif defined(__powerpc64__)
	printf("PPC 64bit\n");
#elif defined(__i386__) || defined(_M_IX86)
	printf("Intel x86\n");
#elif defined(__x86_64__) || defined(_M_X64)
	printf("Intel x64\n");
#else
	printf("Unknown CPU\n");
#endif //
	printf("Pointer size %d\n", (int)sizeof(void *));

#if USE_DELEGATE_TYPE==DELEGATE_TYPE_COMPATIBLE
	printf("Using slow compatible delegates\n");
#elif USE_DELEGATE_TYPE==DELEGATE_TYPE_INTERNAL
	printf("Using fast internal GCC/CLANG delegates\n");
#elif USE_DELEGATE_TYPE==DELEGATE_TYPE_MSVC
	printf("Using fast internal MSVC delegates\n");
#endif

	running_machine machine;
	MyDelegate funclist[12]; // delegates are initialized to empty
	CBaseClass a("Base A");
	CBaseClass b("Base B");
	CDerivedClass c;
	CDerivedClass d;

	dump_vtable("A", &a);
	dump_vtable("D", &d);

	dump_mfp(&a, &CBaseClass::SimpleMemberFunction);
	dump_mfp(&a, &CBaseClass::SimpleVirtualFunction);

	dump_mfp(&d, &CDerivedClass::SimpleDerivedFunction);
	dump_mfp(&d, &CDerivedClass::TrickyVirtualFunction);

	dump_addr("CBaseClass::SimpleMemberFunction",&a, &CBaseClass::SimpleMemberFunction);
	dump_addr("CBaseClass::SimpleVirtualFunction",&b, &CBaseClass::SimpleVirtualFunction);
	dump_addr("CDerivedClass::TrickyVirtualFunction",&c, &CDerivedClass::TrickyVirtualFunction);
	dump_addr("CDerivedClass::SimpleDerivedFunction",&c, &CDerivedClass::SimpleDerivedFunction);
	// Binding a simple member function
	printf("funclist[0] = MyDelegate(FUNC(CBaseClass::SimpleMemberFunction), &a);\n");
	funclist[0] = MyDelegate(FUNC(CBaseClass::SimpleMemberFunction), &a);

	// You can also bind static (free) functions
	printf("funclist[1] = MyDelegate(FUNC(SimpleStaticFunction),&machine);\n");
	funclist[1] = MyDelegate(FUNC(SimpleStaticFunction),&machine);
	// and static member functions
	printf("funclist[2] = MyDelegate(FUNC(CBaseClass::StaticMemberFunction), &machine);\n");
	funclist[2] = MyDelegate(FUNC(CBaseClass::StaticMemberFunction), &machine);
	// and virtual member functions
	printf("funclist[3] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction), &b);\n");
	funclist[3] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction), &b);
	printf("funclist[4] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction),(CBaseClass *)&d);\n");
	funclist[4] = MyDelegate(FUNC(CBaseClass::SimpleVirtualFunction),(CBaseClass *)&d);
	printf("funclist[5] = MyDelegate(FUNC(CDerivedClass::TrickyVirtualFunction),&c);\n");
	funclist[5] = MyDelegate(FUNC(CDerivedClass::TrickyVirtualFunction),&c);
	printf("funclist[6] = MyDelegate(FUNC(COtherClass::TrickyVirtualFunction),(COtherClass*)&c);\n");
	funclist[6] = MyDelegate(FUNC(COtherClass::TrickyVirtualFunction),(COtherClass*)&c);
	printf("funclist[7] = MyDelegate(FUNC(CDerivedClass::SimpleDerivedFunction),&c);\n");
	funclist[7] = MyDelegate(FUNC(CDerivedClass::SimpleDerivedFunction),&c);
	fflush(stdout);
	for (int i = 0; i<8; i++) {
		if (!funclist[i].isnull()) {
			funclist[i](i);
			fflush(stdout);
		}
	}

	printf("Checking devdelegates:\n");

	device_t root("root");
	device_t sub1("sub1");
	device_t sub2("sub2");
	root.add_device("sub1", &sub1);
	root.add_device("sub2", &sub2);

	write_line_delegate write_del = write_line_delegate(FUNC(device_t::write), &root);
	read_line_delegate read_del = read_line_delegate(FUNC(device_t::read), &root);
	write_del(100);
	printf("read_line_delegate : %d\n", read_del());

	write_line_delegate sub1_write_del = write_line_delegate(FUNC(device_t::write), "sub1", (device_t*)nullptr);
	read_line_delegate sub1_read_del = read_line_delegate(FUNC(device_t::read), "sub1", (device_t*)nullptr);
	sub1_write_del.bind_relative_to(root);
	sub1_read_del.bind_relative_to(root);
	sub1_write_del(200);

	printf("read_line_delegate sub 1: %d\n", sub1_read_del());

	typedef delegate<void(int j)> driver_callback_delegate;
	MyClass2 mc;
	driver_callback_delegate md = driver_callback_delegate(FUNC(MyClass2::docount), static_cast<MyClass2 *>(&mc));

	printf("Benchmarking virtual call : ");
	{
		auto before = std::chrono::high_resolution_clock::now(); ;
		for (int i = 0; i < 100000000; i++)
		{
			md(i);
		}
		auto after = std::chrono::high_resolution_clock::now(); ;
		auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(after - before);
		printf("%ld\n", elapsed.count());
	}

	using namespace std::placeholders;

	auto bindFunc = std::bind(&MyClass2::docount, &mc, _1);

	printf("Benchmarking std::bind call : ");
	{
		auto before = std::chrono::high_resolution_clock::now(); ;
		for (int i = 0; i < 100000000; i++)
		{
			bindFunc(i);
		}
		auto after = std::chrono::high_resolution_clock::now(); ;
		auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(after - before);
		printf("%ld\n", elapsed.count());
	}

	printf("Done\n");
	return 0;

}

<|endoftext|>


<commit_before>bacba50a-2747-11e6-a7a6-e0f84713e7b8<commit_msg>fixed bug<commit_after>badaf275-2747-11e6-994d-e0f84713e7b8<|endoftext|>


<commit_before>/*
Copyright 2016-2017 Daniil Gentili
(https://daniil.it)
This file is part of php-libtgvoip.
php-libtgvoip is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
The PWRTelegram API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with php-libtgvoip.
If not, see <http://www.gnu.org/licenses/>.
*/

#include <phpcpp.h>
#include <string.h>
#include <wchar.h>
#include <map>
#include <string>
#include <vector>
#include "libtgvoip/VoIPServerConfig.h"
#include "libtgvoip/VoIPController.h"
#include "libtgvoip/NetworkSocket.h"
#include "libtgvoip/logging.cpp"
#include "libtgvoip/VoIPController.cpp"
#include "libtgvoip/BufferInputStream.cpp"
#include "libtgvoip/BufferOutputStream.cpp"
#include "libtgvoip/BlockingQueue.cpp"
#include "libtgvoip/MediaStreamItf.cpp"
#include "libtgvoip/OpusEncoder.cpp"
#include "libtgvoip/JitterBuffer.cpp"
#include "libtgvoip/OpusDecoder.cpp"
#include "libtgvoip/BufferPool.cpp"
#include "libtgvoip/EchoCanceller.cpp"
#include "libtgvoip/CongestionControl.cpp"
#include "libtgvoip/VoIPServerConfig.cpp"
#include "libtgvoip/NetworkSocket.cpp"
#include "libtgvoip/os/posix/NetworkSocketPosix.cpp"

#include "libtgvoip/audio/AudioInput.cpp"
#include "libtgvoip/audio/AudioOutput.cpp"

#include "audio/AudioInputPHP.h"
#include "audio/AudioOutputPHP.h"

using namespace tgvoip;
using namespace tgvoip::audio;

class VoIP : public Php::Base {
public:

    void __construct(Php::Parameters &params) {
        setStateMethod = params[0];
        madeline = params[3];
        current_call = params[4];
        params[1]["call"] = static_cast<void*>(this);
        params[2]["call"] = static_cast<void*>(this);
        inst=new VoIPController(params[1], params[2]);
        inst->implData = static_cast<void*>(this);
        inst->SetStateCallback([](tgvoip::VoIPController *controller, int state) {
	    	static_cast<VoIP*>(controller->implData)->updateConnectionState(controller, state);
    	});

    }

    void start() {
        inst->Start();
    }

    void connect() {
        inst->Connect();
    }
    void setEncryptionKey(Php::Parameters &params) {

        char* key = strdup(params[0]);
        inst->SetEncryptionKey(key, (bool) params[1]);
        free(key);
    }

    void setRemoteEndpoints(Php::Parameters &params) {

        size_t len=(size_t) params[0].size();
        //voip_endpoint_t* eps=(voip_endpoint_t *) malloc(sizeof(voip_endpoint_t)*len);
        std::vector<Endpoint> eps;
        uint i;

        for(i=0; i<len; i++) {
            std::string ip = params[0][i]["ip"];
            std::string ipv6 = params[0][i]["ipv6"];
            std::string peer_tag = params[0][i]["peer_tag"];

            tgvoip::IPv4Address v4addr(ip);
            tgvoip::IPv6Address v6addr("::0");
            unsigned char pTag[16];

            if(ipv6 != ""){
                v6addr=IPv6Address(ipv6);
            }

            if(peer_tag != "") {
                memcpy(pTag, peer_tag.c_str(), 17);
            }

            eps.push_back(Endpoint(params[0][i]["id"], (int32_t)params[0][i]["port"], v4addr, v6addr, EP_TYPE_UDP_RELAY, pTag));

        }
        inst->SetRemoteEndpoints(eps, params[1]);

    }

    void release() {
        delete inst;
    }

    void writeFrames(Php::Parameters &params) {
        AudioInputPHP* in=(AudioInputPHP*)(intptr_t)inst;
        in->writeFrames(params);
    }

    Php::Value readFrames() {
        AudioOutputPHP* out=(AudioOutputPHP*)(intptr_t)inst;
        return out->readFrames();
    }

    Php::Value getDebugString() {
        char buf[10240];
        inst->GetDebugString(buf, 10240);
        return buf;
    }

    void setNetworkType(Php::Parameters &params) {
        inst->SetNetworkType(params[0]);
    }

    void setMicMute(Php::Parameters &params) {
        inst->SetMicMute(params[0]);
    }
    // jdouble recvTimeout, jdouble initTimeout, jint dataSavingMode, jboolean enableAEC, jboolean enableNS, jboolean enableAGC, jstring logFilePath
    void setConfig(Php::Parameters &params) {
        voip_config_t cfg;
        cfg.recv_timeout=params[0];
        cfg.init_timeout=params[1];
        cfg.data_saving=params[2];
        cfg.enableAEC=params[3];
        cfg.enableNS=params[4];
        cfg.enableAGC=params[5];
        if (params.size() == 7) {
            strncpy(cfg.logFilePath, params[6], sizeof(cfg.logFilePath));
            cfg.logFilePath[sizeof(cfg.logFilePath) - 1] = 0;
        } else {
            memset(cfg.logFilePath, 0, sizeof(cfg.logFilePath));
        }

        if (params.size() == 8) {
            strncpy(cfg.statsDumpFilePath, params[7], sizeof(cfg.statsDumpFilePath));
            cfg.statsDumpFilePath[sizeof(cfg.statsDumpFilePath) - 1] = 0;
        } else {
            memset(cfg.statsDumpFilePath, 0, sizeof(cfg.statsDumpFilePath));
        }
        inst->SetConfig(&cfg);
    }

    void debugCtl(Php::Parameters &params) {
        inst->DebugCtl(params[0], params[1]);
    }

    Php::Value getVersion() {
        return VoIPController::GetVersion();
    }

    Php::Value getPreferredRelayID() {
        return inst->GetPreferredRelayID();
    }

    Php::Value getLastError() {
        return inst->GetLastError();
    }

    Php::Value getStats() {
        voip_stats_t _stats;
        inst->GetStats(&_stats);
        Php::Array stats;
        stats["bytesSentWifi"] = (int64_t)_stats.bytesSentWifi;
        stats["bytesSentMobile"] = (int64_t)_stats.bytesSentMobile;
        stats["bytesRecvdWifi"] = (int64_t)_stats.bytesRecvdWifi;
        stats["bytesRecvdMobile"] = (int64_t)_stats.bytesRecvdMobile;
        return stats;
    }

    void setSharedConfig(Php::Parameters &params) {
        ServerConfig::GetSharedInstance()->Update(params[0]);
    }

    Php::Value getDebugLog() {
        return inst->GetDebugLog();
    }

    void updateConnectionState(VoIPController* cntrlr, int state) {
        setStateMethod(this, state);
    }
private:

    VoIPController* inst;
    Php::Value setStateMethod;
    Php::Value madeline;
    Php::Value current_call;

};

extern "C" {

    /**
     *  Function that is called by PHP right after the PHP process
     *  has started, and that returns an address of an internal PHP
     *  strucure with all the details and features of your extension
     *
     *  @return void*   a pointer to an address that is understood by PHP
     */
    PHPCPP_EXPORT void *get_module()
    {
        // static(!) Php::Extension object that should stay in memory
        // for the entire duration of the process (that's why it's static)
        static Php::Extension extension("php-libtgvoip", "1.0");

        // description of the class so that PHP knows which methods are accessible
        Php::Class<VoIP> voip("VoIP");
        voip.method<&VoIP::__construct> ("__construct", {
            Php::ByVal("setStateCallable", Php::Type::Callable),
            Php::ByVal("inputCallables", Php::Type::Array),
            Php::ByVal("outputCallables", Php::Type::Array),
            Php::ByRef("madelineProto", Php::Type::Object),
            Php::ByRef("currentCall", Php::Type::Array),
        });
        voip.method<&VoIP::setEncryptionKey> ("setEncryptionKey", {
            Php::ByVal("key", Php::Type::String),
            Php::ByVal("isOutgoing", Php::Type::Bool),
        });
        voip.method<&VoIP::setNetworkType> ("setNetworkType", {
            Php::ByVal("type", Php::Type::Numeric),
        });
        voip.method<&VoIP::setMicMute> ("setMicMute", {
            Php::ByVal("type", Php::Type::Bool),
        });
        voip.method<&VoIP::debugCtl> ("debugCtl", {
            Php::ByVal("request", Php::Type::Numeric),
            Php::ByVal("param", Php::Type::Numeric),
        });
        voip.method<&VoIP::setConfig> ("setConfig", { // jdouble recvTimeout, jdouble initTimeout, jint dataSavingMode, jboolean enableAEC, jboolean enableNS, jboolean enableAGC, jstring logFilePath
            Php::ByVal("recvTimeout", Php::Type::Float),
            Php::ByVal("initTimeout", Php::Type::Float),
            Php::ByVal("dataSavingMode", Php::Type::Bool),
            Php::ByVal("enableAEC", Php::Type::Bool),
            Php::ByVal("enableNS", Php::Type::Bool),
            Php::ByVal("enableAGC", Php::Type::Bool),
            Php::ByVal("logFilePath", Php::Type::String, false),
            Php::ByVal("statsDumpFilePath", Php::Type::String, false),
        });
        voip.method<&VoIP::setSharedConfig> ("setSharedConfig", {
            Php::ByVal("config", Php::Type::Array)
        });
        voip.method<&VoIP::setRemoteEndpoints> ("setRemoteEndpoints", {
            Php::ByVal("endpoints", Php::Type::Array),
            Php::ByVal("allowP2P", Php::Type::Bool)
        });
        voip.method<&VoIP::getDebugLog> ("getDebugLog");
        voip.method<&VoIP::getLastError> ("getLastError");
        voip.method<&VoIP::getPreferredRelayID> ("getPreferredRelayID");
        voip.method<&VoIP::getVersion> ("getVersion");
        voip.method<&VoIP::getDebugString> ("getDebugString");
        voip.method<&VoIP::getStats> ("getStats");
        voip.method<&VoIP::release> ("release");
        voip.method<&VoIP::start> ("start");
        voip.method<&VoIP::connect> ("connect");

        voip.method<&VoIP::readFrames> ("readFrames");
        voip.method<&VoIP::writeFrames> ("writeFrames", {
            Php::ByVal("frames", Php::Type::String)
        });

        voip.constant("STATE_READY_TO_INIT", 0);
        voip.constant("STATE_WAIT_INIT", 1);
        voip.constant("STATE_WAIT_INIT_ACK", 2);
        voip.constant("STATE_ESTABLISHED", 3);
        voip.constant("STATE_FAILED", 4);

        voip.constant("TGVOIP_ERROR_UNKNOWN", 0);
        voip.constant("TGVOIP_ERROR_INCOMPATIBLE", 1);
        voip.constant("TGVOIP_ERROR_TIMEOUT", 2);
        voip.constant("TGVOIP_ERROR_AUDIO_IO", 3);

        voip.constant("NET_TYPE_UNKNOWN", 0);
        voip.constant("NET_TYPE_GPRS", 1);
        voip.constant("NET_TYPE_EDGE", 2);
        voip.constant("NET_TYPE_3G", 3);
        voip.constant("NET_TYPE_HSPA", 4);
        voip.constant("NET_TYPE_LTE", 5);
        voip.constant("NET_TYPE_WIFI", 6);
        voip.constant("NET_TYPE_ETHERNET", 7);
        voip.constant("NET_TYPE_OTHER_HIGH_SPEED", 8);
        voip.constant("NET_TYPE_OTHER_LOW_SPEED", 9);
        voip.constant("NET_TYPE_DIALUP", 10);
        voip.constant("NET_TYPE_OTHER_MOBILE", 11);

        Php::Namespace danog("danog");
        Php::Namespace MadelineProto("MadelineProto");

        MadelineProto.add(std::move(voip));
        danog.add(std::move(MadelineProto));
        extension.add(std::move(danog));

        return extension;
    }
}
<commit_msg>WTF is wrong with C strings<commit_after>/*
Copyright 2016-2017 Daniil Gentili
(https://daniil.it)
This file is part of php-libtgvoip.
php-libtgvoip is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
The PWRTelegram API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with php-libtgvoip.
If not, see <http://www.gnu.org/licenses/>.
*/

#include <phpcpp.h>
#include <string.h>
#include <wchar.h>
#include <map>
#include <string>
#include <vector>
#include "libtgvoip/VoIPServerConfig.h"
#include "libtgvoip/VoIPController.h"
#include "libtgvoip/NetworkSocket.h"
#include "libtgvoip/logging.cpp"
#include "libtgvoip/VoIPController.cpp"
#include "libtgvoip/BufferInputStream.cpp"
#include "libtgvoip/BufferOutputStream.cpp"
#include "libtgvoip/BlockingQueue.cpp"
#include "libtgvoip/MediaStreamItf.cpp"
#include "libtgvoip/OpusEncoder.cpp"
#include "libtgvoip/JitterBuffer.cpp"
#include "libtgvoip/OpusDecoder.cpp"
#include "libtgvoip/BufferPool.cpp"
#include "libtgvoip/EchoCanceller.cpp"
#include "libtgvoip/CongestionControl.cpp"
#include "libtgvoip/VoIPServerConfig.cpp"
#include "libtgvoip/NetworkSocket.cpp"
#include "libtgvoip/os/posix/NetworkSocketPosix.cpp"

#include "libtgvoip/audio/AudioInput.cpp"
#include "libtgvoip/audio/AudioOutput.cpp"

#include "audio/AudioInputPHP.h"
#include "audio/AudioOutputPHP.h"

using namespace tgvoip;
using namespace tgvoip::audio;

class VoIP : public Php::Base {
public:

    void __construct(Php::Parameters &params) {
        setStateMethod = params[0];
        madeline = params[3];
        current_call = params[4];
        params[1]["call"] = static_cast<void*>(this);
        params[2]["call"] = static_cast<void*>(this);
        inst=new VoIPController(params[1], params[2]);
        inst->implData = static_cast<void*>(this);
        inst->SetStateCallback([](tgvoip::VoIPController *controller, int state) {
	    	static_cast<VoIP*>(controller->implData)->updateConnectionState(controller, state);
    	});

    }

    void start() {
        inst->Start();
    }

    void connect() {
        inst->Connect();
    }
    void setEncryptionKey(Php::Parameters &params) {

        char* key = strdup(params[0]);
        inst->SetEncryptionKey(key, (bool) params[1]);
        free(key);
    }

    void setRemoteEndpoints(Php::Parameters &params) {

        size_t len=(size_t) params[0].size();
        //voip_endpoint_t* eps=(voip_endpoint_t *) malloc(sizeof(voip_endpoint_t)*len);
        std::vector<Endpoint> eps;
        uint i;

        for(i=0; i<len; i++) {
            std::string ip = params[0][i]["ip"];
            std::string ipv6 = params[0][i]["ipv6"];
            std::string peer_tag = params[0][i]["peer_tag"];

            tgvoip::IPv4Address v4addr(ip);
            tgvoip::IPv6Address v6addr("::0");
            unsigned char pTag[16];

            if(ipv6 != ""){
                v6addr=IPv6Address(ipv6);
            }

            if(peer_tag != "") {
                memcpy(pTag, peer_tag.c_str(), 16);
            }

            eps.push_back(Endpoint(params[0][i]["id"], (int32_t)params[0][i]["port"], v4addr, v6addr, EP_TYPE_UDP_RELAY, pTag));

        }
        inst->SetRemoteEndpoints(eps, params[1]);

    }

    void release() {
        delete inst;
    }

    void writeFrames(Php::Parameters &params) {
        AudioInputPHP* in=(AudioInputPHP*)(intptr_t)inst;
        in->writeFrames(params);
    }

    Php::Value readFrames() {
        AudioOutputPHP* out=(AudioOutputPHP*)(intptr_t)inst;
        return out->readFrames();
    }

    Php::Value getDebugString() {
        char buf[10240];
        inst->GetDebugString(buf, 10240);
        return buf;
    }

    void setNetworkType(Php::Parameters &params) {
        inst->SetNetworkType(params[0]);
    }

    void setMicMute(Php::Parameters &params) {
        inst->SetMicMute(params[0]);
    }
    // jdouble recvTimeout, jdouble initTimeout, jint dataSavingMode, jboolean enableAEC, jboolean enableNS, jboolean enableAGC, jstring logFilePath
    void setConfig(Php::Parameters &params) {
        voip_config_t cfg;
        cfg.recv_timeout=params[0];
        cfg.init_timeout=params[1];
        cfg.data_saving=params[2];
        cfg.enableAEC=params[3];
        cfg.enableNS=params[4];
        cfg.enableAGC=params[5];
        if (params.size() == 7) {
            strncpy(cfg.logFilePath, params[6], sizeof(cfg.logFilePath));
            cfg.logFilePath[sizeof(cfg.logFilePath) - 1] = 0;
        } else {
            memset(cfg.logFilePath, 0, sizeof(cfg.logFilePath));
        }

        if (params.size() == 8) {
            strncpy(cfg.statsDumpFilePath, params[7], sizeof(cfg.statsDumpFilePath));
            cfg.statsDumpFilePath[sizeof(cfg.statsDumpFilePath) - 1] = 0;
        } else {
            memset(cfg.statsDumpFilePath, 0, sizeof(cfg.statsDumpFilePath));
        }
        inst->SetConfig(&cfg);
    }

    void debugCtl(Php::Parameters &params) {
        inst->DebugCtl(params[0], params[1]);
    }

    Php::Value getVersion() {
        return VoIPController::GetVersion();
    }

    Php::Value getPreferredRelayID() {
        return inst->GetPreferredRelayID();
    }

    Php::Value getLastError() {
        return inst->GetLastError();
    }

    Php::Value getStats() {
        voip_stats_t _stats;
        inst->GetStats(&_stats);
        Php::Array stats;
        stats["bytesSentWifi"] = (int64_t)_stats.bytesSentWifi;
        stats["bytesSentMobile"] = (int64_t)_stats.bytesSentMobile;
        stats["bytesRecvdWifi"] = (int64_t)_stats.bytesRecvdWifi;
        stats["bytesRecvdMobile"] = (int64_t)_stats.bytesRecvdMobile;
        return stats;
    }

    void setSharedConfig(Php::Parameters &params) {
        ServerConfig::GetSharedInstance()->Update(params[0]);
    }

    Php::Value getDebugLog() {
        return inst->GetDebugLog();
    }

    void updateConnectionState(VoIPController* cntrlr, int state) {
        setStateMethod(this, state);
    }
private:

    VoIPController* inst;
    Php::Value setStateMethod;
    Php::Value madeline;
    Php::Value current_call;

};

extern "C" {

    /**
     *  Function that is called by PHP right after the PHP process
     *  has started, and that returns an address of an internal PHP
     *  strucure with all the details and features of your extension
     *
     *  @return void*   a pointer to an address that is understood by PHP
     */
    PHPCPP_EXPORT void *get_module()
    {
        // static(!) Php::Extension object that should stay in memory
        // for the entire duration of the process (that's why it's static)
        static Php::Extension extension("php-libtgvoip", "1.0");

        // description of the class so that PHP knows which methods are accessible
        Php::Class<VoIP> voip("VoIP");
        voip.method<&VoIP::__construct> ("__construct", {
            Php::ByVal("setStateCallable", Php::Type::Callable),
            Php::ByVal("inputCallables", Php::Type::Array),
            Php::ByVal("outputCallables", Php::Type::Array),
            Php::ByRef("madelineProto", Php::Type::Object),
            Php::ByRef("currentCall", Php::Type::Array),
        });
        voip.method<&VoIP::setEncryptionKey> ("setEncryptionKey", {
            Php::ByVal("key", Php::Type::String),
            Php::ByVal("isOutgoing", Php::Type::Bool),
        });
        voip.method<&VoIP::setNetworkType> ("setNetworkType", {
            Php::ByVal("type", Php::Type::Numeric),
        });
        voip.method<&VoIP::setMicMute> ("setMicMute", {
            Php::ByVal("type", Php::Type::Bool),
        });
        voip.method<&VoIP::debugCtl> ("debugCtl", {
            Php::ByVal("request", Php::Type::Numeric),
            Php::ByVal("param", Php::Type::Numeric),
        });
        voip.method<&VoIP::setConfig> ("setConfig", { // jdouble recvTimeout, jdouble initTimeout, jint dataSavingMode, jboolean enableAEC, jboolean enableNS, jboolean enableAGC, jstring logFilePath
            Php::ByVal("recvTimeout", Php::Type::Float),
            Php::ByVal("initTimeout", Php::Type::Float),
            Php::ByVal("dataSavingMode", Php::Type::Bool),
            Php::ByVal("enableAEC", Php::Type::Bool),
            Php::ByVal("enableNS", Php::Type::Bool),
            Php::ByVal("enableAGC", Php::Type::Bool),
            Php::ByVal("logFilePath", Php::Type::String, false),
            Php::ByVal("statsDumpFilePath", Php::Type::String, false),
        });
        voip.method<&VoIP::setSharedConfig> ("setSharedConfig", {
            Php::ByVal("config", Php::Type::Array)
        });
        voip.method<&VoIP::setRemoteEndpoints> ("setRemoteEndpoints", {
            Php::ByVal("endpoints", Php::Type::Array),
            Php::ByVal("allowP2P", Php::Type::Bool)
        });
        voip.method<&VoIP::getDebugLog> ("getDebugLog");
        voip.method<&VoIP::getLastError> ("getLastError");
        voip.method<&VoIP::getPreferredRelayID> ("getPreferredRelayID");
        voip.method<&VoIP::getVersion> ("getVersion");
        voip.method<&VoIP::getDebugString> ("getDebugString");
        voip.method<&VoIP::getStats> ("getStats");
        voip.method<&VoIP::release> ("release");
        voip.method<&VoIP::start> ("start");
        voip.method<&VoIP::connect> ("connect");

        voip.method<&VoIP::readFrames> ("readFrames");
        voip.method<&VoIP::writeFrames> ("writeFrames", {
            Php::ByVal("frames", Php::Type::String)
        });

        voip.constant("STATE_READY_TO_INIT", 0);
        voip.constant("STATE_WAIT_INIT", 1);
        voip.constant("STATE_WAIT_INIT_ACK", 2);
        voip.constant("STATE_ESTABLISHED", 3);
        voip.constant("STATE_FAILED", 4);

        voip.constant("TGVOIP_ERROR_UNKNOWN", 0);
        voip.constant("TGVOIP_ERROR_INCOMPATIBLE", 1);
        voip.constant("TGVOIP_ERROR_TIMEOUT", 2);
        voip.constant("TGVOIP_ERROR_AUDIO_IO", 3);

        voip.constant("NET_TYPE_UNKNOWN", 0);
        voip.constant("NET_TYPE_GPRS", 1);
        voip.constant("NET_TYPE_EDGE", 2);
        voip.constant("NET_TYPE_3G", 3);
        voip.constant("NET_TYPE_HSPA", 4);
        voip.constant("NET_TYPE_LTE", 5);
        voip.constant("NET_TYPE_WIFI", 6);
        voip.constant("NET_TYPE_ETHERNET", 7);
        voip.constant("NET_TYPE_OTHER_HIGH_SPEED", 8);
        voip.constant("NET_TYPE_OTHER_LOW_SPEED", 9);
        voip.constant("NET_TYPE_DIALUP", 10);
        voip.constant("NET_TYPE_OTHER_MOBILE", 11);

        Php::Namespace danog("danog");
        Php::Namespace MadelineProto("MadelineProto");

        MadelineProto.add(std::move(voip));
        danog.add(std::move(MadelineProto));
        extension.add(std::move(danog));

        return extension;
    }
}
<|endoftext|>


<commit_before>7eb77957-ad5c-11e7-962c-ac87a332f658<commit_msg>new flies<commit_after>7f2a8842-ad5c-11e7-bab5-ac87a332f658<|endoftext|>


<commit_before>#include "SpFS.hpp"
#include <iostream>

using namespace SpFS;

int main()
{
	FileSystem sys;
	sys.create("partition.sys");
	Directory* root = sys.getRoot();

	Directory* home = new Directory("home");
	Directory* poney = new Directory("poney");

	File* bashrc = new File(".bashrc");
	bashrc->append("[ -f .bash_aliases ] && . .bash_aliases");

	root->addNode(home);
	home->addNode(poney);
	poney->addNode(bashrc);

	std::cout << root->serialize() << std::endl;
}
<commit_msg>deleted unused file<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <utility>
#include <cstdio>
#include <cstdint>
#include <cstdlib>
extern "C" {
#include <lightning.h>
}

enum Opcode {
    OP_NOP,
    OP_PUSH,
    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_CALL,
};
const char *trans_opcode(int op) {
    switch (op) {
    case OP_NOP:
        return "NOP";
    case OP_PUSH:
        return "PUSH";
    case OP_ADD:
        return "ADD";
    case OP_SUB:
        return "SUB";
    case OP_MUL:
        return "MUL";
    case OP_DIV:
        return "DIV";
    case OP_CALL:
        return "CALL";
    default:
        return "unknown";
    }

}

struct Instruction {
    uint8_t op;
    union {
        int    ival;
        double dval;
        struct {
            uint32_t fidx;
            uint32_t nargs;
        } callop;
    };

    Instruction(Opcode op) : op(op) {}
    Instruction(Opcode op, int ival) : op(op), ival(ival) {}
    Instruction(Opcode op, double dval) : op(op), dval(dval) {}
    Instruction(Opcode op, uint32_t function_idx, uint32_t nargs)
        : op(op) { callop.fidx = function_idx; callop.nargs = nargs; }
};

void _JIT_stack_push(jit_state_t *_jit, int reg, int *sp) {
    jit_stxi_d(*sp, JIT_FP, reg);
    *sp += sizeof(double);
}

void _JIT_stack_pop(jit_state_t *_jit, int reg, int *sp) {
    *sp -= sizeof(double);
    jit_ldxi_d(reg, JIT_FP, *sp);
}

typedef std::pair<int, double> Result;

template<typename T, typename R>
void* evil_cast(R(T::*f)(uint32_t, const double*))
{
    union
    {
        R(T::*pf)(uint32_t, const double*);
        void* p;
    };
    pf = f;
    return p;
}

// TODO: implement
struct MyEnv {
    Result myFunc(/*void *self,*/ uint32_t nargs, const double *stack) {
        printf("inside MyEnv::myFunc: %p\n", this);
        return std::make_pair(0, stack[0] + stack[1]);
    }
};

//typedef Result (*Callback)(void *, uint32_t, const double*);
typedef void* Callback;

struct Translator {
    virtual ~Translator() {}
    virtual Callback lookup(uint32_t function_idx)=0;
};

struct DummyTranslator : public Translator {

    virtual ~DummyTranslator() {}
    Callback lookup(uint32_t function_idx) override {
        //#pragma GCC diagnostic ignored "-Wpmf-conversions"
        switch (function_idx) {
        case 1:
            return evil_cast(&MyEnv::myFunc);
        default:
            throw std::runtime_error("Unknown function index!");
        }
        //#pragma GCC diagnostic pop
    }
};

typedef std::vector<Instruction> Program;

class JIT {
public:
    JIT() : _jit(jit_new_state()), func_(nullptr) {}

    ~JIT() {
        jit_destroy_state();
    }

    bool compile(const Program &program, Translator &trans, void *userdata) {
        jit_node_t *fn = jit_note(NULL, 0);
        jit_prolog();
        const int stack_base_offset = jit_allocai(32 * sizeof(double));
        int stack_top_idx = 0;

        auto &&stackPush = [&](int reg) {
            jit_stxi_d(stack_base_offset + stack_top_idx * sizeof(double), JIT_FP, reg);
            ++stack_top_idx;
        };

        auto &&stackPop = [&](int reg) {
            --stack_top_idx;
            jit_ldxi_d(reg, JIT_FP, stack_base_offset + stack_top_idx * sizeof(double));
            return reg;
        };

        size_t pc = 0;
        const size_t progsz = program.size();
        while (pc < progsz) {
            const Instruction &instr = program[pc];
            switch (instr.op) {
            case OP_NOP:
                break;
            case OP_PUSH:
                stackPush(JIT_F0);
                jit_movi_d(JIT_F0, instr.dval);
                break;
            case OP_ADD: {
                const int reg = stackPop(JIT_F1);
                jit_addr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_SUB: {
                const int reg = stackPop(JIT_F1);
                jit_subr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_MUL: {
                const int reg = stackPop(JIT_F1);
                jit_mulr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_DIV: {
                const int reg = stackPop(JIT_F1);
                jit_divr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_CALL: {
                stackPush(JIT_F0);
                const int sp = stack_top_idx - (instr.callop.nargs);
                jit_addi(JIT_R0, JIT_FP, stack_base_offset + sp * sizeof(double));

                jit_prepare();
                jit_pushargi((jit_word_t)userdata); // 1st arg: userdata
                jit_pushargi(instr.callop.nargs);   // 2nd arg: # of arguments
                jit_pushargr(JIT_R0);               // 3rd arg: pointer to args on stack

                auto &&cb = trans.lookup(instr.callop.fidx);
                jit_finishi(reinterpret_cast<jit_pointer_t>(cb));

                stack_top_idx -= instr.callop.nargs; // consume arguments on stack
                jit_retval_d(JIT_F0);
            }
                break;
            }

            ++pc;
        }

        jit_retr_d(JIT_F0);
        jit_epilog();

        (void)jit_emit();
        func_ = reinterpret_cast<JitFunction>(jit_address(fn));

        return true;
    }

    bool run() {
        result_ = func_();
        return true;
    }

    double result() const noexcept {
        return result_;
    }

    void disassemble() {
        jit_disassemble();
    }

    const char *error() const {
        return "TODO: implement";
    }

private:
    typedef double (*JitFunction)();

    jit_state_t *_jit; // DO NOT CHANGE NAME.  Satisfies req.s for GNU lightning macros
    JitFunction func_;
    double result_;
};

int main(int argc, char **argv) {
    Program program = {
        { OP_PUSH, 1234. },
        { OP_PUSH, 6666. },
        { OP_CALL, 1, 2  },
        { OP_PUSH, 4444. },
        { OP_SUB         },
        { OP_PUSH, 5555. },
        { OP_MUL         },
    };

    init_jit(argv[0]); // TODO: move to static function
    JIT jit;
    DummyTranslator trans;
    MyEnv env, env2, env3;

    if (!jit.compile(program, trans, &env)) {
        std::cerr << "Failed to compile program!" << std::endl;
        return 1;
    }

    if (!jit.run()) {
        std::cerr << "Error running program: " << jit.error() << std::endl;
        return 1;
    }

    std::cout << "\n\nProgram: \n";
    jit.disassemble();

    std::cout << "Result: " << jit.result() << std::endl;
    std::cout << "Expected: " << (((1234. + 6666.) - 4444.) * 5555.) << std::endl;

    finish_jit();

    return 0;
}
<commit_msg>Allow passing error message<commit_after>#include <iostream>
#include <vector>
#include <utility>
#include <cstdio>
#include <cstdint>
#include <cstdlib>
extern "C" {
#include <lightning.h>
}

enum Opcode {
    OP_NOP,
    OP_PUSH,
    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_CALL,
};
const char *trans_opcode(int op) {
    switch (op) {
    case OP_NOP:
        return "NOP";
    case OP_PUSH:
        return "PUSH";
    case OP_ADD:
        return "ADD";
    case OP_SUB:
        return "SUB";
    case OP_MUL:
        return "MUL";
    case OP_DIV:
        return "DIV";
    case OP_CALL:
        return "CALL";
    default:
        return "unknown";
    }

}

struct Instruction {
    uint8_t op;
    union {
        int    ival;
        double dval;
        struct {
            uint32_t fidx;
            uint32_t nargs;
        } callop;
    };

    Instruction(Opcode op) : op(op) {}
    Instruction(Opcode op, int ival) : op(op), ival(ival) {}
    Instruction(Opcode op, double dval) : op(op), dval(dval) {}
    Instruction(Opcode op, uint32_t function_idx, uint32_t nargs)
        : op(op) { callop.fidx = function_idx; callop.nargs = nargs; }
};

void _JIT_stack_push(jit_state_t *_jit, int reg, int *sp) {
    jit_stxi_d(*sp, JIT_FP, reg);
    *sp += sizeof(double);
}

void _JIT_stack_pop(jit_state_t *_jit, int reg, int *sp) {
    *sp -= sizeof(double);
    jit_ldxi_d(reg, JIT_FP, *sp);
}

typedef std::pair<int, double> Result;

template<typename T, typename R>
void* evil_cast(R(T::*f)(uint32_t, const double*, const char **error))
{
    union
    {
        R(T::*pf)(uint32_t, const double*, const char **error);
        void* p;
    };
    pf = f;
    return p;
}

// TODO: implement
struct MyEnv {
    MyEnv() : error_(nullptr) {}
    Result myFunc(/*void *self,*/ uint32_t nargs, const double *stack, const char **error) {
        *error = "this is a really bad error!";
        return std::make_pair(0, stack[0] + stack[1]);
    }
    const char *error_;
};

typedef void* Callback;

struct Translator {
    virtual ~Translator() {}
    virtual Callback lookup(uint32_t function_idx)=0;
};

struct DummyTranslator : public Translator {

    virtual ~DummyTranslator() {}
    Callback lookup(uint32_t function_idx) override {
        //#pragma GCC diagnostic ignored "-Wpmf-conversions"
        switch (function_idx) {
        case 1:
            return evil_cast(&MyEnv::myFunc);
        default:
            throw std::runtime_error("Unknown function index!");
        }
        //#pragma GCC diagnostic pop
    }
};

typedef std::vector<Instruction> Program;

class JIT {
public:
    JIT() : _jit(jit_new_state()), func_(nullptr) {}

    ~JIT() {
        jit_destroy_state();
    }

    template <class Environment>
    bool compile(const Program &program, Translator &trans, Environment &env) {
        jit_node_t *fn = jit_note(NULL, 0);
        jit_prolog();
        const int stack_base_offset = jit_allocai(32 * sizeof(double));
        int stack_top_idx = 0;

        auto &&stackPush = [&](int reg) {
            jit_stxi_d(stack_base_offset + stack_top_idx * sizeof(double), JIT_FP, reg);
            ++stack_top_idx;
        };

        auto &&stackPop = [&](int reg) {
            --stack_top_idx;
            jit_ldxi_d(reg, JIT_FP, stack_base_offset + stack_top_idx * sizeof(double));
            return reg;
        };

        size_t pc = 0;
        const size_t progsz = program.size();
        while (pc < progsz) {
            const Instruction &instr = program[pc];
            switch (instr.op) {
            case OP_NOP:
                break;
            case OP_PUSH:
                stackPush(JIT_F0);
                jit_movi_d(JIT_F0, instr.dval);
                break;
            case OP_ADD: {
                const int reg = stackPop(JIT_F1);
                jit_addr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_SUB: {
                const int reg = stackPop(JIT_F1);
                jit_subr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_MUL: {
                const int reg = stackPop(JIT_F1);
                jit_mulr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_DIV: {
                const int reg = stackPop(JIT_F1);
                jit_divr_d(JIT_F0, reg, JIT_F0);
            }
                break;
            case OP_CALL: {
                stackPush(JIT_F0);
                const int sp = stack_top_idx - (instr.callop.nargs);
                jit_addi(JIT_R0, JIT_FP, stack_base_offset + sp * sizeof(double));

                jit_prepare();
                jit_pushargi((jit_word_t)&env);       // 1st arg: userdata
                jit_pushargi(instr.callop.nargs);     // 2nd arg: # of arguments
                jit_pushargr(JIT_R0);                 // 3rd arg: pointer to args on stack
                jit_pushargi((jit_word_t)&env.error_); // 4th arg: pointer to error message

                auto &&cb = trans.lookup(instr.callop.fidx);
                jit_finishi(reinterpret_cast<jit_pointer_t>(cb));

                stack_top_idx -= instr.callop.nargs; // consume arguments on stack
                jit_retval_d(JIT_F0);
            }
                break;
            }

            ++pc;
        }

        jit_retr_d(JIT_F0);
        jit_epilog();

        (void)jit_emit();
        func_ = reinterpret_cast<JitFunction>(jit_address(fn));

        return true;
    }

    bool run() {
        result_ = func_();
        return true;
    }

    double result() const noexcept {
        return result_;
    }

    void disassemble() {
        jit_disassemble();
    }

    const char *error() const {
        return "TODO: implement";
    }

private:
    typedef double (*JitFunction)();

    jit_state_t *_jit; // DO NOT CHANGE NAME.  Satisfies req.s for GNU lightning macros
    JitFunction func_;
    double result_;
};

int main(int argc, char **argv) {
    Program program = {
        { OP_PUSH, 1234. },
        { OP_PUSH, 6666. },
        { OP_CALL, 1, 2  },
        { OP_PUSH, 4444. },
        { OP_SUB         },
        { OP_PUSH, 5555. },
        { OP_MUL         },
    };

    init_jit(argv[0]); // TODO: move to static function
    JIT jit;
    DummyTranslator trans;
    MyEnv env;

    if (!jit.compile(program, trans, env)) {
        std::cerr << "Failed to compile program!" << std::endl;
        return 1;
    }

    if (!jit.run()) {
        std::cerr << "Error running program: " << jit.error() << std::endl;
        return 1;
    }

    std::cout << "\n\nProgram: \n";
    jit.disassemble();

    std::cout << "Result: " << jit.result() << std::endl;
    std::cout << "Expected: " << (((1234. + 6666.) - 4444.) * 5555.) << std::endl;

    if (env.error_ != nullptr) {
        fprintf(stderr, "Error: %s\n", env.error_);
    }

    finish_jit();

    return 0;
}
<|endoftext|>


<commit_before>#include "ProfilingDataParser.h"
#include "RoutineListModel.h"
#include "View.h"
#include <QAbstractTableModel>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QFile>
#include <QDebug>
#include <QApplication>

int main(int argc, char *argv[])
{
    if (argc != 2) {
        qDebug() << "Usage:" << argv[0] << "<filename.json>";
        return 1;
    }
    QFile profile(argv[1]);
    if (!profile.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open" << argv[1];
        return 1;
    }
    QByteArray jsondata = profile.readAll();
    profile.close();

    QJsonDocument rawdata(QJsonDocument::fromJson(jsondata));
    if (!rawdata.isArray()) {
        // perhaps we got .html in, let's try to rip JSON from that
        QByteArray pattern("var rawData = JSON.parse('");
        int lineStart = jsondata.indexOf(pattern);
        if (lineStart != -1) {
            int lineEnd = jsondata.indexOf("\n", lineStart);
            if (lineEnd != -1) {
                // get the actual positions of the JSON string
                lineStart += pattern.length();
                lineEnd   -= 3;
                // cut the excess HTML on both sides
                jsondata.truncate(lineEnd);
                jsondata = jsondata.mid(lineStart);
            }
        }
    }
    rawdata = QJsonDocument::fromJson(jsondata);
    if (!rawdata.isArray()) {
        // if that didn't work either, we're screwed
        qDebug() << "Malformed input file";
        return 1;
    }
    QJsonArray arr = rawdata.array();
    if (!arr[0].isObject()) {
        qDebug() << "Malformed input file";
        return 1;
    }

    ProfilingDataParser pdp(arr);
    RoutineListModel rlm(0, pdp.buildRoutineList());
    QMap<QString, QVariant> ovm(pdp.buildOverviewData());

    QApplication app(argc, argv);

    View view;
    view.setRoutineModel(&rlm);
    view.setOverviewModel(&ovm);
    view.show();
    return app.exec();
}
<commit_msg>Show the QJsonParseError value if parsing fails.<commit_after>#include "ProfilingDataParser.h"
#include "RoutineListModel.h"
#include "View.h"
#include <QAbstractTableModel>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QFile>
#include <QDebug>
#include <QApplication>
#include <QJsonParseError>

int main(int argc, char *argv[])
{
    if (argc != 2) {
        qDebug() << "Usage:" << argv[0] << "<filename.[json,html]>";
        return 1;
    }
    QFile profile(argv[1]);
    if (!profile.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open" << argv[1];
        return 1;
    }
    QByteArray jsondata = profile.readAll();
    profile.close();

    if (profile.fileName().endsWith(".html", Qt::CaseInsensitive)) {
        // we got .html in, let's try to rip JSON from that
        QByteArray pattern("var rawData = JSON.parse('");
        int lineStart = jsondata.indexOf(pattern);
        if (lineStart != -1) {
            int lineEnd = jsondata.indexOf("\n", lineStart);
            if (lineEnd != -1) {
                // get the actual positions of the JSON string
                lineStart += pattern.length();
                lineEnd   -= 3;
                // cut the excess HTML on both sides
                jsondata.truncate(lineEnd);
                jsondata = jsondata.mid(lineStart);
            }
        }
    }
    QJsonParseError err;
    QJsonDocument rawdata(QJsonDocument::fromJson(jsondata, &err));
    if (!rawdata.isArray()) {
        qDebug() << "Malformed input file, top level isn't an array:" << err.errorString();
        return 1;
    }
    QJsonArray arr = rawdata.array();
    if (!arr[0].isObject()) {
        qDebug() << "Malformed input file, first element in array isn't an object:" << err.errorString();
        return 1;
    }

    ProfilingDataParser pdp(arr);
    RoutineListModel rlm(0, pdp.buildRoutineList());
    QMap<QString, QVariant> ovm(pdp.buildOverviewData());

    QApplication app(argc, argv);

    View view;
    view.setRoutineModel(&rlm);
    view.setOverviewModel(&ovm);
    view.show();
    return app.exec();
}
<|endoftext|>