<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <stdexcept>

#include "cppa/config.hpp"
#include "cppa/detail/demangle.hpp"

#ifdef CPPA_GCC
#include <cxxabi.h>
#endif

#include <stdlib.h>

namespace cppa { namespace detail {

std::string demangle(const char* decorated) {
    size_t size;
    int status;
    char* undecorated = abi::__cxa_demangle(decorated, nullptr, &size, &status);
    if (status != 0) {
        std::string error_msg = "Could not demangle type name ";
        error_msg += decorated;
        throw std::logic_error(error_msg);
    }
    std::string result; // the undecorated typeid name
    result.reserve(size);
    const char* cstr = undecorated;
    // filter unnecessary characters from undecorated
    char c = *cstr;
    while (c != '\0') {
        if (c == ' ') {
            char previous_c = result.empty() ? ' ' : *(result.rbegin());
            // get next non-space character
            for (c = *++cstr; c == ' '; c = *++cstr) { }
            if (c != '\0') {
                // skip whitespace unless it separates two alphanumeric
                // characters (such as in "unsigned int")
                if (isalnum(c) && isalnum(previous_c)) {
                    result += ' ';
                    result += c;
                }
                else {
                    result += c;
                }
                c = *++cstr;
            }
        }
        else {
            result += c;
            c = *++cstr;
        }
    }
    free(undecorated);
    return result;
}

} } // namespace cppa::detail
<commit_msg>fixed clang name demangling<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <stdexcept>

#include "cppa/config.hpp"
#include "cppa/detail/demangle.hpp"

#ifdef CPPA_GCC
#include <cxxabi.h>
#endif

#include <stdlib.h>

namespace cppa { namespace detail {

std::string demangle(const char* decorated) {
    size_t size;
    int status;
    char* undecorated = abi::__cxa_demangle(decorated, nullptr, &size, &status);
    if (status != 0) {
        std::string error_msg = "Could not demangle type name ";
        error_msg += decorated;
        throw std::logic_error(error_msg);
    }
    std::string result; // the undecorated typeid name
    result.reserve(size);
    const char* cstr = undecorated;
    // filter unnecessary characters from undecorated
    char c = *cstr;
    while (c != '\0') {
        if (c == ' ') {
            char previous_c = result.empty() ? ' ' : *(result.rbegin());
            // get next non-space character
            for (c = *++cstr; c == ' '; c = *++cstr) { }
            if (c != '\0') {
                // skip whitespace unless it separates two alphanumeric
                // characters (such as in "unsigned int")
                if (isalnum(c) && isalnum(previous_c)) {
                    result += ' ';
                    result += c;
                }
                else {
                    result += c;
                }
                c = *++cstr;
            }
        }
        else {
            result += c;
            c = *++cstr;
        }
    }
    free(undecorated);
#   ifdef __clang__
    // replace "std::__1::" with "std::" (fixes strange clang names)
    std::string needle = "std::__1::";
    std::string fixed_string = "std::";
    for (auto pos = result.find(needle); pos != std::string::npos; pos = result.find(needle)) {
        result.replace(pos, needle.size(), fixed_string);
    }
#   endif
    return result;
}

} } // namespace cppa::detail
<|endoftext|>


<commit_before>#include <array>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <math.h>
#include <omp.h>

#include <xmmintrin.h>
#include <pmmintrin.h>

#include "dijkstra.hpp"
#include "min_heap.hpp"
#include "universe.hpp"

#define AU_TO_M 149597870700.0
#define LY_TO_M 9460730472580800.0

#if defined(__AVX__)
#include <immintrin.h>
#define VECTOR_WIDTH 8
typedef __m256 vector_type;
#elif defined(__SSE__)
#define VECTOR_WIDTH 4
typedef __m128 vector_type;
#else
#error "Here's a nickel kid, buy yourself a real computer."
#endif

inline float __attribute__((always_inline)) entity_distance(Celestial *a, Celestial *b) {
    if (a->system != b->system) return INFINITY;

    float dx = a->x - b->x;
    float dy = a->y - b->y;
    float dz = a->z - b->z;

    return sqrt(dx * dx + dy * dy + dz * dz);
}

inline float __attribute__((always_inline)) system_distance(System *a, System *b) {
    float dx = a->x - b->x;
    float dy = a->y - b->y;
    float dz = a->z - b->z;

    return sqrt(dx * dx + dy * dy + dz * dz);
}

double get_time(double distance, double v_wrp) {
    double k_accel = v_wrp;
    double k_decel = (v_wrp / 3) < 2 ? (v_wrp / 3) : 2;

    double v_max_wrp = v_wrp * AU_TO_M;

    double d_accel = AU_TO_M;
    double d_decel = v_max_wrp / k_decel;

    double d_min = d_accel + d_decel;

    double cruise_time = 0;

    if (d_min > distance) {
        v_max_wrp = distance * k_accel * k_decel / (k_accel + k_decel);
    } else {
        cruise_time = (distance - d_min) / v_max_wrp;
    }

    double t_accel = log(v_max_wrp / k_accel) / k_accel;
    double t_decel = log(v_max_wrp / 100) / k_decel;

    return cruise_time + t_accel + t_decel;
}

Dijkstra::Dijkstra(Universe &u, Celestial *src, Celestial *dst, Parameters *parameters) : universe(u) {
    this->src = src;
    this->dst = dst;
    this->parameters = parameters;

    this->prev = new int[this->universe.entity_count];
    this->vist = new int[this->universe.entity_count];
    this->cost = new float[this->universe.entity_count];
    this->type = new enum movement_type[this->universe.entity_count];

    this->sys_x = new float[this->universe.system_count + VECTOR_WIDTH];
    this->sys_y = new float[this->universe.system_count + VECTOR_WIDTH];
    this->sys_z = new float[this->universe.system_count + VECTOR_WIDTH];

    this->fatigue = new float[this->universe.entity_count];
    this->reactivation = new float[this->universe.entity_count];

    this->queue = new MinHeap<float, int>(u.entity_count);

    for (int i = 0; i < this->universe.system_count; i++) {
        sys_x[i] = this->universe.systems[i].x;
        sys_y[i] = this->universe.systems[i].y;
        sys_z[i] = this->universe.systems[i].z;
    }

    for (int i = 0; i < this->universe.entity_count; i++) {

        vist[i] = i == src->seq_id ? 1 : 0;
        prev[i] = i == src->seq_id ? -2 : -1;
        type[i] = STRT;
        cost[i] = i == src->seq_id ? 0.0 : INFINITY;

        fatigue[i] = 0.0;
        reactivation[i] = 0.0;

        if (celestial_is_relevant(this->universe.entities[i])) {
            queue->insert(cost[i], i);
        }
    }
}

Dijkstra::~Dijkstra() {
    delete[] prev;
    delete[] cost;
    delete[] vist;
    delete[] type;

    delete[] sys_x;
    delete[] sys_y;
    delete[] sys_z;
}

bool Dijkstra::celestial_is_relevant(Celestial &c) {
    return c.is_relevant() || c.id == src->id || (dst && c.id == dst->id);
}

void Dijkstra::solve_w_set(Celestial *ent) {
    System *sys = ent->system;

    for (int i = 0; i < sys->entity_count; i++) {
        if (!celestial_is_relevant(sys->entities[i]) || ent == &sys->entities[i]) {
            continue;
        }

        update_administration(ent, &sys->entities[i], parameters->align_time + get_time(entity_distance(ent, &sys->entities[i]), parameters->warp_speed), WARP);
    }
}

void Dijkstra::solve_g_set(Celestial *ent) {
    if (ent->destination && parameters->gate_cost >= 0.0) {
        update_administration(ent, ent->destination, parameters->gate_cost, GATE);
    }
}

void Dijkstra::solve_r_set(Celestial *ent) {
    if (ent->bridge && isnan(parameters->jump_range)) {
        update_administration(ent, ent->bridge, system_distance(ent->system, ent->bridge->system) * (1 - parameters->jump_range_reduction), JUMP);
    }
}

void Dijkstra::solve_j_set(Celestial *ent) {
    vector_type x_vec, y_vec, z_vec;
    vector_type x_src_vec, y_src_vec, z_src_vec;

    System *jsys, *sys = ent->system;

    float distance;
    float range, range_sq;

    #if VECTOR_WIDTH == 4
    x_src_vec = _mm_set1_ps(sys->x);
    y_src_vec = _mm_set1_ps(sys->y);
    z_src_vec = _mm_set1_ps(sys->z);
    #elif VECTOR_WIDTH == 8
    x_src_vec = _mm256_set1_ps(sys->x);
    y_src_vec = _mm256_set1_ps(sys->y);
    z_src_vec = _mm256_set1_ps(sys->z);
    #endif

    if (!isnan((range = parameters->jump_range)) || !isnan((range = ent->jump_range))) {
        range_sq = pow(range * LY_TO_M, 2.0);

        #pragma omp for schedule(guided)
        for (int k = 0; k < this->universe.system_count; k += VECTOR_WIDTH) {
            #if VECTOR_WIDTH == 4
            x_vec = _mm_load_ps(sys_x + k);
            y_vec = _mm_load_ps(sys_y + k);
            z_vec = _mm_load_ps(sys_z + k);
            #elif VECTOR_WIDTH == 8
            x_vec = _mm256_loadu_ps(sys_x + k);
            y_vec = _mm256_loadu_ps(sys_y + k);
            z_vec = _mm256_loadu_ps(sys_z + k);
            #endif

            x_vec -= x_src_vec;
            y_vec -= y_src_vec;
            z_vec -= z_src_vec;

            x_vec = (x_vec * x_vec) + (y_vec * y_vec) + (z_vec * z_vec);

            for (int i = 0; i < VECTOR_WIDTH; i++) {
                if (x_vec[i] > range_sq ||
                    k + i >= this->universe.system_count ||
                    sys == (jsys = this->universe.systems + i + k) ||
                    jsys->security >= 0.5) continue;

                distance = sqrt(x_vec[i]) / LY_TO_M;

                for (int j = ((dst && jsys != dst->system) ? jsys->gates - jsys->entities : 0); j < jsys->entity_count; j++) {
                    update_administration(ent, &jsys->entities[j], distance * (1 - parameters->jump_range_reduction), JUMP);
                }
            }
        }
    }
}

void Dijkstra::update_administration(Celestial *a, Celestial *b, float ccost, enum movement_type ctype) {
    float dcost, cur_cost;

    if (ctype == JUMP) {
        if (parameters->fatigue_model == FATIGUE_IGNORE) {
            dcost = 10.0;
        } else if (parameters->fatigue_model == FATIGUE_REACTIVATION_COST) {
            dcost = 60 * (ccost + 1);
        } else if (parameters->fatigue_model == FATIGUE_FATIGUE_COST) {
            dcost = 600 * ccost;
        } else if (parameters->fatigue_model == FATIGUE_REACTIVATION_COUNTDOWN) {
            dcost = reactivation[a->seq_id] + 10.0;
        } else if (parameters->fatigue_model == FATIGUE_FATIGUE_COUNTDOWN) {
            dcost = fatigue[a->seq_id] + 10.0;
        } else {
            dcost = INFINITY;
        }
    } else {
        dcost = ccost;
    }

    cur_cost = cost[a->seq_id] + dcost;

    if (cur_cost <= cost[b->seq_id] && !vist[b->seq_id]) {
        #pragma omp critical
        {
            queue->decrease_raw(cur_cost, b->seq_id);
            prev[b->seq_id] = a->seq_id;
            cost[b->seq_id] = cur_cost;
            type[b->seq_id] = ctype;

            fatigue[b->seq_id] = std::max(fatigue[a->seq_id] - dcost, 0.f);
            reactivation[b->seq_id] = std::max(reactivation[a->seq_id] - dcost, 0.f);

            if (ctype == JUMP) {
                fatigue[b->seq_id] = std::min(60*60*24*7.f, std::max(fatigue[a->seq_id], 600.f) * (ccost + 1));
                reactivation[b->seq_id] = std::max(fatigue[a->seq_id] / 600, 60 * (ccost + 1));
            }
        }
    }
}

Route *Dijkstra::get_route() {
    if (!dst) throw 20;
    return get_route(dst);
}

Route *Dijkstra::get_route(Celestial *dst) {
    solve_internal();

    if (!vist[dst->seq_id]) throw 21;

    Route *route = new Route();

    route->loops = loops;
    route->cost = cost[dst->seq_id];

    for (int c = dst->seq_id; c != -2; c = prev[c]) {
        route->points.push_front((struct waypoint) {&this->universe.entities[c], type[c]});
    }

    return route;
}

std::map<Celestial *, float> *Dijkstra::get_all_distances() {
    solve_internal();

    std::map<Celestial *, float> *res = new std::map<Celestial *, float>();

    if (dst != NULL) throw 10;

    for (int i = 0; i < universe.entity_count; i++) {
        if (isfinite(cost[i])) {
            res->emplace(&universe.entities[i], cost[i]);
        }
    }

    return res;
}

void Dijkstra::solve_internal() {
    int tmp = -1;
    Celestial *ent;

    #pragma omp parallel num_threads(1)
    while (!queue->is_empty() && (!dst || !vist[dst->seq_id]) && (tmp == -1 || !isinf(cost[tmp]))) {
        #pragma omp master
        {
            tmp = queue->extract();
            ent = &this->universe.entities[tmp];
            vist[tmp] = 1;

            solve_w_set(ent);
            solve_g_set(ent);
            solve_r_set(ent);

            loops++;
        }

        #pragma omp barrier

        solve_j_set(ent);

        #pragma omp barrier
    }
}
<commit_msg>Gates are now disabled by setting NaN cost.<commit_after>#include <array>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <math.h>
#include <omp.h>

#include <xmmintrin.h>
#include <pmmintrin.h>

#include "dijkstra.hpp"
#include "min_heap.hpp"
#include "universe.hpp"

#define AU_TO_M 149597870700.0
#define LY_TO_M 9460730472580800.0

#if defined(__AVX__)
#include <immintrin.h>
#define VECTOR_WIDTH 8
typedef __m256 vector_type;
#elif defined(__SSE__)
#define VECTOR_WIDTH 4
typedef __m128 vector_type;
#else
#error "Here's a nickel kid, buy yourself a real computer."
#endif

inline float __attribute__((always_inline)) entity_distance(Celestial *a, Celestial *b) {
    if (a->system != b->system) return INFINITY;

    float dx = a->x - b->x;
    float dy = a->y - b->y;
    float dz = a->z - b->z;

    return sqrt(dx * dx + dy * dy + dz * dz);
}

inline float __attribute__((always_inline)) system_distance(System *a, System *b) {
    float dx = a->x - b->x;
    float dy = a->y - b->y;
    float dz = a->z - b->z;

    return sqrt(dx * dx + dy * dy + dz * dz);
}

double get_time(double distance, double v_wrp) {
    double k_accel = v_wrp;
    double k_decel = (v_wrp / 3) < 2 ? (v_wrp / 3) : 2;

    double v_max_wrp = v_wrp * AU_TO_M;

    double d_accel = AU_TO_M;
    double d_decel = v_max_wrp / k_decel;

    double d_min = d_accel + d_decel;

    double cruise_time = 0;

    if (d_min > distance) {
        v_max_wrp = distance * k_accel * k_decel / (k_accel + k_decel);
    } else {
        cruise_time = (distance - d_min) / v_max_wrp;
    }

    double t_accel = log(v_max_wrp / k_accel) / k_accel;
    double t_decel = log(v_max_wrp / 100) / k_decel;

    return cruise_time + t_accel + t_decel;
}

Dijkstra::Dijkstra(Universe &u, Celestial *src, Celestial *dst, Parameters *parameters) : universe(u) {
    this->src = src;
    this->dst = dst;
    this->parameters = parameters;

    this->prev = new int[this->universe.entity_count];
    this->vist = new int[this->universe.entity_count];
    this->cost = new float[this->universe.entity_count];
    this->type = new enum movement_type[this->universe.entity_count];

    this->sys_x = new float[this->universe.system_count + VECTOR_WIDTH];
    this->sys_y = new float[this->universe.system_count + VECTOR_WIDTH];
    this->sys_z = new float[this->universe.system_count + VECTOR_WIDTH];

    this->fatigue = new float[this->universe.entity_count];
    this->reactivation = new float[this->universe.entity_count];

    this->queue = new MinHeap<float, int>(u.entity_count);

    for (int i = 0; i < this->universe.system_count; i++) {
        sys_x[i] = this->universe.systems[i].x;
        sys_y[i] = this->universe.systems[i].y;
        sys_z[i] = this->universe.systems[i].z;
    }

    for (int i = 0; i < this->universe.entity_count; i++) {

        vist[i] = i == src->seq_id ? 1 : 0;
        prev[i] = i == src->seq_id ? -2 : -1;
        type[i] = STRT;
        cost[i] = i == src->seq_id ? 0.0 : INFINITY;

        fatigue[i] = 0.0;
        reactivation[i] = 0.0;

        if (celestial_is_relevant(this->universe.entities[i])) {
            queue->insert(cost[i], i);
        }
    }
}

Dijkstra::~Dijkstra() {
    delete[] prev;
    delete[] cost;
    delete[] vist;
    delete[] type;

    delete[] sys_x;
    delete[] sys_y;
    delete[] sys_z;
}

bool Dijkstra::celestial_is_relevant(Celestial &c) {
    return c.is_relevant() || c.id == src->id || (dst && c.id == dst->id);
}

void Dijkstra::solve_w_set(Celestial *ent) {
    System *sys = ent->system;

    for (int i = 0; i < sys->entity_count; i++) {
        if (!celestial_is_relevant(sys->entities[i]) || ent == &sys->entities[i]) {
            continue;
        }

        update_administration(ent, &sys->entities[i], parameters->align_time + get_time(entity_distance(ent, &sys->entities[i]), parameters->warp_speed), WARP);
    }
}

void Dijkstra::solve_g_set(Celestial *ent) {
    if (ent->destination && !isnan(parameters->gate_cost)) {
        update_administration(ent, ent->destination, parameters->gate_cost, GATE);
    }
}

void Dijkstra::solve_r_set(Celestial *ent) {
    if (ent->bridge && isnan(parameters->jump_range)) {
        update_administration(ent, ent->bridge, system_distance(ent->system, ent->bridge->system) * (1 - parameters->jump_range_reduction), JUMP);
    }
}

void Dijkstra::solve_j_set(Celestial *ent) {
    vector_type x_vec, y_vec, z_vec;
    vector_type x_src_vec, y_src_vec, z_src_vec;

    System *jsys, *sys = ent->system;

    float distance;
    float range, range_sq;

    #if VECTOR_WIDTH == 4
    x_src_vec = _mm_set1_ps(sys->x);
    y_src_vec = _mm_set1_ps(sys->y);
    z_src_vec = _mm_set1_ps(sys->z);
    #elif VECTOR_WIDTH == 8
    x_src_vec = _mm256_set1_ps(sys->x);
    y_src_vec = _mm256_set1_ps(sys->y);
    z_src_vec = _mm256_set1_ps(sys->z);
    #endif

    if (!isnan((range = parameters->jump_range)) || !isnan((range = ent->jump_range))) {
        range_sq = pow(range * LY_TO_M, 2.0);

        #pragma omp for schedule(guided)
        for (int k = 0; k < this->universe.system_count; k += VECTOR_WIDTH) {
            #if VECTOR_WIDTH == 4
            x_vec = _mm_load_ps(sys_x + k);
            y_vec = _mm_load_ps(sys_y + k);
            z_vec = _mm_load_ps(sys_z + k);
            #elif VECTOR_WIDTH == 8
            x_vec = _mm256_loadu_ps(sys_x + k);
            y_vec = _mm256_loadu_ps(sys_y + k);
            z_vec = _mm256_loadu_ps(sys_z + k);
            #endif

            x_vec -= x_src_vec;
            y_vec -= y_src_vec;
            z_vec -= z_src_vec;

            x_vec = (x_vec * x_vec) + (y_vec * y_vec) + (z_vec * z_vec);

            for (int i = 0; i < VECTOR_WIDTH; i++) {
                if (x_vec[i] > range_sq ||
                    k + i >= this->universe.system_count ||
                    sys == (jsys = this->universe.systems + i + k) ||
                    jsys->security >= 0.5) continue;

                distance = sqrt(x_vec[i]) / LY_TO_M;

                for (int j = ((dst && jsys != dst->system) ? jsys->gates - jsys->entities : 0); j < jsys->entity_count; j++) {
                    update_administration(ent, &jsys->entities[j], distance * (1 - parameters->jump_range_reduction), JUMP);
                }
            }
        }
    }
}

void Dijkstra::update_administration(Celestial *a, Celestial *b, float ccost, enum movement_type ctype) {
    float dcost, cur_cost;

    if (ctype == JUMP) {
        if (parameters->fatigue_model == FATIGUE_IGNORE) {
            dcost = 10.0;
        } else if (parameters->fatigue_model == FATIGUE_REACTIVATION_COST) {
            dcost = 60 * (ccost + 1);
        } else if (parameters->fatigue_model == FATIGUE_FATIGUE_COST) {
            dcost = 600 * ccost;
        } else if (parameters->fatigue_model == FATIGUE_REACTIVATION_COUNTDOWN) {
            dcost = reactivation[a->seq_id] + 10.0;
        } else if (parameters->fatigue_model == FATIGUE_FATIGUE_COUNTDOWN) {
            dcost = fatigue[a->seq_id] + 10.0;
        } else {
            dcost = INFINITY;
        }
    } else {
        dcost = ccost;
    }

    cur_cost = cost[a->seq_id] + dcost;

    if (cur_cost <= cost[b->seq_id] && !vist[b->seq_id]) {
        #pragma omp critical
        {
            queue->decrease_raw(cur_cost, b->seq_id);
            prev[b->seq_id] = a->seq_id;
            cost[b->seq_id] = cur_cost;
            type[b->seq_id] = ctype;

            fatigue[b->seq_id] = std::max(fatigue[a->seq_id] - dcost, 0.f);
            reactivation[b->seq_id] = std::max(reactivation[a->seq_id] - dcost, 0.f);

            if (ctype == JUMP) {
                fatigue[b->seq_id] = std::min(60*60*24*7.f, std::max(fatigue[a->seq_id], 600.f) * (ccost + 1));
                reactivation[b->seq_id] = std::max(fatigue[a->seq_id] / 600, 60 * (ccost + 1));
            }
        }
    }
}

Route *Dijkstra::get_route() {
    if (!dst) throw 20;
    return get_route(dst);
}

Route *Dijkstra::get_route(Celestial *dst) {
    solve_internal();

    if (!vist[dst->seq_id]) throw 21;

    Route *route = new Route();

    route->loops = loops;
    route->cost = cost[dst->seq_id];

    for (int c = dst->seq_id; c != -2; c = prev[c]) {
        route->points.push_front((struct waypoint) {&this->universe.entities[c], type[c]});
    }

    return route;
}

std::map<Celestial *, float> *Dijkstra::get_all_distances() {
    solve_internal();

    std::map<Celestial *, float> *res = new std::map<Celestial *, float>();

    if (dst != NULL) throw 10;

    for (int i = 0; i < universe.entity_count; i++) {
        if (isfinite(cost[i])) {
            res->emplace(&universe.entities[i], cost[i]);
        }
    }

    return res;
}

void Dijkstra::solve_internal() {
    int tmp = -1;
    Celestial *ent;

    #pragma omp parallel num_threads(1)
    while (!queue->is_empty() && (!dst || !vist[dst->seq_id]) && (tmp == -1 || !isinf(cost[tmp]))) {
        #pragma omp master
        {
            tmp = queue->extract();
            ent = &this->universe.entities[tmp];
            vist[tmp] = 1;

            solve_w_set(ent);
            solve_g_set(ent);
            solve_r_set(ent);

            loops++;
        }

        #pragma omp barrier

        solve_j_set(ent);

        #pragma omp barrier
    }
}
<|endoftext|>


<commit_before>#include "openmc/finalize.h"

#include "openmc/capi.h"
#include "openmc/constants.h"
#include "openmc/eigenvalue.h"
#include "openmc/geometry.h"
#include "openmc/message_passing.h"
#include "openmc/nuclide.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/timer.h"
#include "openmc/tallies/tally.h"

using namespace openmc;

// Functions defined in Fortran
extern "C" void free_memory();
extern "C" void reset_timers_f();

int openmc_finalize()
{
  // Clear results
  openmc_reset();

  // Reset global variables
  settings::assume_separate = false;
  settings::check_overlaps = false;
  settings::confidence_intervals = false;
  settings::create_fission_neutrons = true;
  settings::electron_treatment = ELECTRON_LED;
  settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0};
  settings::entropy_on = false;
  settings::gen_per_batch = 1;
  settings::index_entropy_mesh = -1;
  settings::index_ufs_mesh = -1;
  settings::legendre_to_tabular = true;
  settings::legendre_to_tabular_points = -1;
  settings::n_particles = -1;
  settings::output_summary = true;
  settings::output_tallies = true;
  settings::particle_restart_run = false;
  settings::photon_transport = false;
  settings::reduce_tallies = true;
  settings::res_scat_on = false;
  settings::res_scat_method = RES_SCAT_ARES;
  settings::res_scat_energy_min = 0.01;
  settings::res_scat_energy_max = 1000.0;
  settings::restart_run = false;
  settings::run_CE = true;
  settings::run_mode = -1;
  settings::dagmc = false;
  settings::source_latest = false;
  settings::source_separate = false;
  settings::source_write = true;
  settings::survival_biasing = false;
  settings::temperature_default = 293.6;
  settings::temperature_method = TEMPERATURE_NEAREST;
  settings::temperature_multipole = false;
  settings::temperature_range = {0.0, 0.0};
  settings::temperature_tolerance = 10.0;
  settings::trigger_on = false;
  settings::trigger_predict = false;
  settings::trigger_batch_interval = 1;
  settings::ufs_on = false;
  settings::urr_ptables_on = true;
  settings::verbosity = 7;
  settings::weight_cutoff = 0.25;
  settings::weight_survive = 1.0;
  settings::write_all_tracks = false;
  settings::write_initial_source = false;

  simulation::keff = 1.0;
  simulation::n_lost_particles = 0;
  simulation::satisfy_triggers = false;
  simulation::total_gen = 0;

  energy_max = {INFTY, INFTY};
  energy_min = {0.0, 0.0};
  n_tallies = 0;
  openmc_root_universe = -1;
  openmc_set_seed(DEFAULT_SEED);

  // Deallocate arrays
  free_memory();

  // Free all MPI types
#ifdef OPENMC_MPI
  MPI_Type_free(&mpi::bank);
#endif

  return 0;
}

int openmc_reset()
{
  for (int i = 1; i <= n_tallies; ++i) {
    openmc_tally_reset(i);
  }

  // Reset global tallies (can't really use global_tallies() right now because
  // it doesn't have any information about whether the underlying buffer was
  // allocated)
  n_realizations = 0;
  double* buffer = nullptr;
  openmc_global_tallies(&buffer);
  if (buffer) {
    for (int i = 0; i < 3*N_GLOBAL_TALLIES*3; ++i) {
      buffer[i] = 0.0;
    }
  }
  // auto gt = global_tallies();
  // std::fill(gt.begin(), gt.end(), 0.0);

  simulation::k_col_abs = 0.0;
  simulation::k_col_tra = 0.0;
  simulation::k_abs_tra = 0.0;
  k_sum = {0.0, 0.0};

  // Reset timers
  reset_timers();
  reset_timers_f();

  return 0;
}

int openmc_hard_reset()
{
  // Reset all tallies and timers
  openmc_reset();

  // Reset total generations and keff guess
  simulation::keff = 1.0;
  simulation::total_gen = 0;

  // Reset the random number generator state
  openmc_set_seed(DEFAULT_SEED);
  return 0;
}
<commit_msg>Fix resetting of global_tallies<commit_after>#include "openmc/finalize.h"

#include "openmc/capi.h"
#include "openmc/constants.h"
#include "openmc/eigenvalue.h"
#include "openmc/geometry.h"
#include "openmc/message_passing.h"
#include "openmc/nuclide.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/timer.h"
#include "openmc/tallies/tally.h"

using namespace openmc;

// Functions defined in Fortran
extern "C" void free_memory();
extern "C" void reset_timers_f();

int openmc_finalize()
{
  // Clear results
  openmc_reset();

  // Reset global variables
  settings::assume_separate = false;
  settings::check_overlaps = false;
  settings::confidence_intervals = false;
  settings::create_fission_neutrons = true;
  settings::electron_treatment = ELECTRON_LED;
  settings::energy_cutoff = {0.0, 1000.0, 0.0, 0.0};
  settings::entropy_on = false;
  settings::gen_per_batch = 1;
  settings::index_entropy_mesh = -1;
  settings::index_ufs_mesh = -1;
  settings::legendre_to_tabular = true;
  settings::legendre_to_tabular_points = -1;
  settings::n_particles = -1;
  settings::output_summary = true;
  settings::output_tallies = true;
  settings::particle_restart_run = false;
  settings::photon_transport = false;
  settings::reduce_tallies = true;
  settings::res_scat_on = false;
  settings::res_scat_method = RES_SCAT_ARES;
  settings::res_scat_energy_min = 0.01;
  settings::res_scat_energy_max = 1000.0;
  settings::restart_run = false;
  settings::run_CE = true;
  settings::run_mode = -1;
  settings::dagmc = false;
  settings::source_latest = false;
  settings::source_separate = false;
  settings::source_write = true;
  settings::survival_biasing = false;
  settings::temperature_default = 293.6;
  settings::temperature_method = TEMPERATURE_NEAREST;
  settings::temperature_multipole = false;
  settings::temperature_range = {0.0, 0.0};
  settings::temperature_tolerance = 10.0;
  settings::trigger_on = false;
  settings::trigger_predict = false;
  settings::trigger_batch_interval = 1;
  settings::ufs_on = false;
  settings::urr_ptables_on = true;
  settings::verbosity = 7;
  settings::weight_cutoff = 0.25;
  settings::weight_survive = 1.0;
  settings::write_all_tracks = false;
  settings::write_initial_source = false;

  simulation::keff = 1.0;
  simulation::n_lost_particles = 0;
  simulation::satisfy_triggers = false;
  simulation::total_gen = 0;

  energy_max = {INFTY, INFTY};
  energy_min = {0.0, 0.0};
  n_tallies = 0;
  openmc_root_universe = -1;
  openmc_set_seed(DEFAULT_SEED);

  // Deallocate arrays
  free_memory();

  // Free all MPI types
#ifdef OPENMC_MPI
  MPI_Type_free(&mpi::bank);
#endif

  return 0;
}

int openmc_reset()
{
  for (int i = 1; i <= n_tallies; ++i) {
    openmc_tally_reset(i);
  }

  // Reset global tallies (can't really use global_tallies() right now because
  // it doesn't have any information about whether the underlying buffer was
  // allocated)
  n_realizations = 0;
  double* buffer = nullptr;
  openmc_global_tallies(&buffer);
  if (buffer) {
    for (int i = 0; i < 3*N_GLOBAL_TALLIES; ++i) {
      buffer[i] = 0.0;
    }
  }

  simulation::k_col_abs = 0.0;
  simulation::k_col_tra = 0.0;
  simulation::k_abs_tra = 0.0;
  k_sum = {0.0, 0.0};

  // Reset timers
  reset_timers();
  reset_timers_f();

  return 0;
}

int openmc_hard_reset()
{
  // Reset all tallies and timers
  openmc_reset();

  // Reset total generations and keff guess
  simulation::keff = 1.0;
  simulation::total_gen = 0;

  // Reset the random number generator state
  openmc_set_seed(DEFAULT_SEED);
  return 0;
}
<|endoftext|>


<commit_before>#ifndef FLAT_MAP_H
#define FLAT_MAP_H

// Heavily inspired from https://stackoverflow.com/a/30938947, credits to
// Yakk - Adam Nevraum @ StackOverflow

#include <vector>
#include <utility>
#include <algorithm>

template<class Key, class Value, template<class...>class Storage=std::vector>
struct flat_map {
  using storage_t = Storage<std::pair<Key, Value>>;
  storage_t storage;

  using iterator=decltype(begin(std::declval<storage_t&>()));
  using const_iterator=decltype(begin(std::declval<const storage_t&>()));

  // Constructor
  flat_map() = default;
  flat_map(std::initializer_list<std::pair<Key,Value>> init) : storage(std::move(init)) { }

  // boilerplate:
  iterator begin() {
    using std::begin;
    return begin(storage);
  }
  const_iterator begin() const {
    using std::begin;
    return begin(storage);
  }
  const_iterator cbegin() const {
    using std::begin;
    return begin(storage);
  }
  iterator end() {
    using std::end;
    return end(storage);
  }
  const_iterator end() const {
    using std::end;
    return end(storage);
  }
  const_iterator cend() const {
    using std::end;
    return end(storage);
  }
  size_t size() const {
    return storage.size();
  }
  bool empty() const {
    return storage.empty();
  }
  // these only have to be valid if called:
  void reserve(size_t n) {
    storage.reserve(n);
  }
  size_t capacity() const {
    return storage.capacity();
  }
  // map-like interface:
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  Value& operator[](K&& k){
    auto it = find(k);
    if (it != end()) return it->v;
    storage.emplace_back( std::forward<K>(k), Value{} );
    return storage.back().v;
  }
private:
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  auto key_match( K& k ) {
    return [&k](const std::pair<Key, Value>& kv){
      return kv.first == k;
    };
  }
public:
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  iterator find(K&& k) {
    return std::find_if( begin(), end(), key_match(k) );
  }
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  const_iterator find(K&& k) const {
    return const_cast<flat_map*>(this)->find(k);
  }
  iterator erase(const_iterator it) {
    return storage.erase(it);
  }
  template<class P, class=std::enable_if_t<std::is_convertible<P,std::pair<Key, Value>>{}>>
  void insert( P&& value )
  {
    auto it = find(value.first);
    if (it == end())
      storage.emplace_back( std::forward<P>(value) );
    else
      it->second = value.second;
  }

  bool operator<(const flat_map &rhs) const
  {
    return storage < rhs.storage;
  }
};
#endif /* FLAT_MAP_H */
<commit_msg>Fix compilation<commit_after>#ifndef FLAT_MAP_H
#define FLAT_MAP_H

// Heavily inspired from https://stackoverflow.com/a/30938947, credits to
// Yakk - Adam Nevraum @ StackOverflow

#include <vector>
#include <utility>
#include <algorithm>

template<class Key, class Value, template<class...>class Storage=std::vector>
struct flat_map {
  using storage_t = Storage<std::pair<Key, Value>>;
  storage_t storage;

  using iterator=decltype(begin(std::declval<storage_t&>()));
  using const_iterator=decltype(begin(std::declval<const storage_t&>()));

  // Constructor
  flat_map() = default;
  flat_map(std::initializer_list<std::pair<Key,Value>> init) : storage(std::move(init)) { }

  // boilerplate:
  iterator begin() {
    using std::begin;
    return begin(storage);
  }
  const_iterator begin() const {
    using std::begin;
    return begin(storage);
  }
  const_iterator cbegin() const {
    using std::begin;
    return begin(storage);
  }
  iterator end() {
    using std::end;
    return end(storage);
  }
  const_iterator end() const {
    using std::end;
    return end(storage);
  }
  const_iterator cend() const {
    using std::end;
    return end(storage);
  }
  size_t size() const {
    return storage.size();
  }
  bool empty() const {
    return storage.empty();
  }
  // these only have to be valid if called:
  void reserve(size_t n) {
    storage.reserve(n);
  }
  size_t capacity() const {
    return storage.capacity();
  }
  // map-like interface:
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  Value& operator[](K&& k){
    auto it = find(k);
    if (it != end()) return it->second;
    storage.emplace_back( std::forward<K>(k), Value{} );
    return storage.back().second;
  }
private:
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  auto key_match( K& k ) {
    return [&k](const std::pair<Key, Value>& kv){
      return kv.first == k;
    };
  }
public:
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  iterator find(K&& k) {
    return std::find_if( begin(), end(), key_match(k) );
  }
  template<class K, class=std::enable_if_t<std::is_convertible<K, Key>{}>>
  const_iterator find(K&& k) const {
    return const_cast<flat_map*>(this)->find(k);
  }
  iterator erase(const_iterator it) {
    return storage.erase(it);
  }
  template<class P, class=std::enable_if_t<std::is_convertible<P,std::pair<Key, Value>>{}>>
  void insert( P&& value )
  {
    auto it = find(value.first);
    if (it == end())
      storage.emplace_back( std::forward<P>(value) );
    else
      it->second = value.second;
  }

  bool operator<(const flat_map &rhs) const
  {
    return storage < rhs.storage;
  }
};
#endif /* FLAT_MAP_H */
<|endoftext|>


<commit_before>#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/regex.hpp>
#include "factorio/mod-info.hpp"
#include <DA/exception.hpp>
#include <sstream>
#define AVHTTP_ENABLE_OPENSSL
#include <avhttp.hpp>
#ifdef DEBUG
	#include <iostream>
#endif
using namespace	boost::property_tree;
using avhttp::detail::escape_string;

namespace factorio
{
namespace mod
{
	std::string get_script(std::string html)
	try
	{
		ptree pt;
		std::stringstream ss(html);
		std::string json;
		while(std::getline(ss, json))
			if(json.find("window.__INITIAL_STATE__") != std::string::npos)
				break;
		json = json.substr(json.find('{'));
		json = json.substr(0, json.rfind('}') + 1);
		return json;
	}
	DA_CATCH_EXCEPTION
	ptree search(std::string name)
	try
	{
		using namespace std;
		stringstream ss;
		{
			std::string url = "https://mods.factorio.com/?q=";
			url += escape_string(name);

			boost::asio::io_service io;
			avhttp::http_stream h(io);
			h.open(url);

			ss << &h;
		}

		stringstream json(get_script(ss.str()));
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "search json:\n" << json.str();
		#endif
		ptree pt;
		read_json(json, pt);

		auto child = pt.get_child("mods.modsPages");
		for (const auto & i : child)
		{
			for (const auto & j : i.second)
			{
				if(j.second.get<string>("name") == name)
				{
					return j.second;
				}
			}
		}
		DA_THROW_EXCEPTION_1("Can't found mod");
	}
	DA_CATCH_EXCEPTION
	avhttp::url get_url(std::string name)
	try
	{
		auto pt = search(name);
		std::string result = "https://mods.factorio.com/mods/";
		result += escape_string(pt.get<std::string>("owner"));
		result += "/";
		result += escape_string(name);
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "mod url:" << result;
		#endif
		return result;
	}
	DA_CATCH_EXCEPTION

	ptree info::get_json(avhttp::url url) const
	try
	{
		using namespace std;
		boost::asio::io_service io;
		avhttp::http_stream h(io);
		h.open(url);

		stringstream ss;
		ss << &h;
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "mod page:\n" << ss.str();
		#endif

		stringstream json(get_script(ss.str()));
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "mod json:\n" << json.str();
		#endif
		ptree pt;
		read_json(json, pt);
		return pt;
	}
	DA_CATCH_EXCEPTION
	info::info(std::string name)
	try
	{
		pt = get_json(get_url(name)).get_child("mod.mod");
	}
	DA_CATCH_EXCEPTION
	info info::read_name(std::string name)
	try
	{
		pt = search(name);
		return *this;
	}
	DA_CATCH_EXCEPTION
	info info::read_name_fast(std::string name)
	try
	{
		pt = get_json(get_url(name)).get_child("mod.mod");
		return *this;
	}
	DA_CATCH_EXCEPTION
	info info::read_full_name(std::string name)
	try
	{
		pt = get_json("https://mods.factorio.com/mods/" + name).get_child("mod.mod");
		return *this;
	}
	DA_CATCH_EXCEPTION
	info info::read_url(std::string url)
	try
	{
		pt = get_json(url).get_child("mod.mod");
		return *this;
	}
	DA_CATCH_EXCEPTION
} /* mod */
} /* factorio */
<commit_msg>fix wrong fast and normal<commit_after>#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/regex.hpp>
#include "factorio/mod-info.hpp"
#include <DA/exception.hpp>
#include <sstream>
#define AVHTTP_ENABLE_OPENSSL
#include <avhttp.hpp>
#ifdef DEBUG
	#include <iostream>
#endif
using namespace	boost::property_tree;
using avhttp::detail::escape_string;

namespace factorio
{
namespace mod
{
	std::string get_script(std::string html)
	try
	{
		ptree pt;
		std::stringstream ss(html);
		std::string json;
		while(std::getline(ss, json))
			if(json.find("window.__INITIAL_STATE__") != std::string::npos)
				break;
		json = json.substr(json.find('{'));
		json = json.substr(0, json.rfind('}') + 1);
		return json;
	}
	DA_CATCH_EXCEPTION
	ptree search(std::string name)
	try
	{
		using namespace std;
		stringstream ss;
		{
			std::string url = "https://mods.factorio.com/?q=";
			url += escape_string(name);

			boost::asio::io_service io;
			avhttp::http_stream h(io);
			h.open(url);

			ss << &h;
		}

		stringstream json(get_script(ss.str()));
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "search json:\n" << json.str();
		#endif
		ptree pt;
		read_json(json, pt);

		auto child = pt.get_child("mods.modsPages");
		for (const auto & i : child)
		{
			for (const auto & j : i.second)
			{
				if(j.second.get<string>("name") == name)
				{
					return j.second;
				}
			}
		}
		DA_THROW_EXCEPTION_1("Can't found mod");
	}
	DA_CATCH_EXCEPTION
	avhttp::url get_url(std::string name)
	try
	{
		auto pt = search(name);
		std::string result = "https://mods.factorio.com/mods/";
		result += escape_string(pt.get<std::string>("owner"));
		result += "/";
		result += escape_string(name);
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "mod url:" << result;
		#endif
		return result;
	}
	DA_CATCH_EXCEPTION

	ptree info::get_json(avhttp::url url) const
	try
	{
		using namespace std;
		boost::asio::io_service io;
		avhttp::http_stream h(io);
		h.open(url);

		stringstream ss;
		ss << &h;
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "mod page:\n" << ss.str();
		#endif

		stringstream json(get_script(ss.str()));
		#ifdef DEBUG
			AVHTTP_LOG_DBG << "mod json:\n" << json.str();
		#endif
		ptree pt;
		read_json(json, pt);
		return pt;
	}
	DA_CATCH_EXCEPTION
	info::info(std::string name)
	try
	{
		pt = get_json(get_url(name)).get_child("mod.mod");
	}
	DA_CATCH_EXCEPTION
	info info::read_name(std::string name)
	try
	{
		pt = get_json(get_url(name)).get_child("mod.mod");
		return *this;
	}
	DA_CATCH_EXCEPTION
	info info::read_name_fast(std::string name)
	try
	{
		pt = search(name);
		return *this;
	}
	DA_CATCH_EXCEPTION
	info info::read_full_name(std::string name)
	try
	{
		pt = get_json("https://mods.factorio.com/mods/" + name).get_child("mod.mod");
		return *this;
	}
	DA_CATCH_EXCEPTION
	info info::read_url(std::string url)
	try
	{
		pt = get_json(url).get_child("mod.mod");
		return *this;
	}
	DA_CATCH_EXCEPTION
} /* mod */
} /* factorio */
<|endoftext|>


<commit_before>/*
  ==============================================================================

   Copyright (c) 2014 Jacob Sologub

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.

  ==============================================================================
*/

#include "gif2webpMain.h"
#include <node.h>
#include <node_buffer.h>
#include <v8.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

using namespace v8;
using namespace node;

// {
//     source      required. <Buffer>  Buffer with binary image data.
//     lossy:      optional. <Boolean> Encode image using lossy compression
//     mixed:      optional. <Boolean> For each frame in the image, pick lossy or lossless compression heuristically.
//     quality:    optional. <Number>  Quality factor (0:small..100:big)
//     method:     optional. <Number>  Compression method Quality (0=fast, 6=slowest)
//     kmin:       optional. <Number>  Min distance between key frames
//     kmax:       optional. <Number>  Max distance between key frames
//     filter:     optional. <Number>  Filter strength (0=off..100)
//     metadata:   optional. <String>  comma separated list of metadata to copy from the input to the output if present. Valid values: all, none, icc, xmp (default)
//     mt:         optional. <Boolean> Use multi-threading if available
//     verbose:    optional. <Boolean> Verbose output from gif2webp
// }

Handle<Value> convert (const Arguments& args) {
    HandleScope scope;

    if (args.Length() < 2) {
        return ThrowException (Exception::TypeError (String::New ("Wrong number of arguments.")));
    }

    if (!args [0]->IsObject()) {
        return ThrowException (Exception::TypeError (String::New ("First argument must be be an object.")));
    }

    if (!args [1]->IsFunction()) {
        return ThrowException (Exception::TypeError (String::New ("Second argument must be a callback function.")));
    }

    Local<Object> options = args [0]->ToObject();

    Local<Object> buffer = Local<Object>::Cast (options->Get (String::NewSymbol ("source")));
    if (buffer->IsUndefined() || !Buffer::HasInstance (buffer)) {
        return ThrowException (Exception::TypeError (String::New ("First argument should have \"source\" key with a Buffer instance")));
    }

    std::vector <std::string> optionArgs;

    if (!options->Get (String::NewSymbol ("lossy"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("lossy"))->ToBoolean();

        if (value->Value()) {
            optionArgs.push_back ("-lossy");
        }
    }

    if (!options->Get (String::NewSymbol ("mixed"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("mixed"))->ToBoolean();
        if (value->Value()) {
            optionArgs.push_back ("-mixed");
        }
    }

    if (!options->Get (String::NewSymbol ("quality"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("quality"))->ToNumber();
        optionArgs.push_back ("-q");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("method"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("method"))->ToNumber();
        optionArgs.push_back ("-m");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("kmin"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("kmin"))->ToNumber();
        optionArgs.push_back ("-kmin");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("kmax"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("kmax"))->ToNumber();
        optionArgs.push_back ("-kmax");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("filter"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("filter"))->ToNumber();
        optionArgs.push_back ("-f");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("metadata"))->IsUndefined()) {
        Local<String> value = options->Get (String::NewSymbol ("metadata"))->ToString();
        String::Utf8Value utf8Value (value);
        optionArgs.push_back ("-metadata");
        optionArgs.push_back (std::string (*utf8Value));
    }

    if (!options->Get (String::NewSymbol ("mt"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("mt"))->ToBoolean();
        if (value->Value()) {
            optionArgs.push_back ("-mt");
        }
    }

    if (!options->Get (String::NewSymbol ("verbose"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("verbose"))->ToBoolean();
        if (value->Value()) {
            optionArgs.push_back ("-v");
        }
    }

    const char* convert_argv [optionArgs.size()];
    int convert_argc = optionArgs.size();
    for (int i = 0; i < (int) optionArgs.size(); ++i) {
        convert_argv [i] = optionArgs [i].c_str();
    }

    const size_t inDataSize = Buffer::Length (buffer);
    const char* inData = Buffer::Data (buffer);

    WebPData outData;
    convert (convert_argc, convert_argv, (char*) inData, inDataSize, &outData);

    Local<Object> globalObj = v8::Context::GetCurrent()->Global();

    Buffer* slowBuffer = node::Buffer::New (outData.size);
    memcpy (node::Buffer::Data (slowBuffer), outData.bytes, outData.size);
    Local<Function> bufferConstructor = Local<Function>::Cast (globalObj->Get (String::New ("Buffer")));

    Handle<Value> constructorArgs [3] = {
      slowBuffer->handle_,
      Integer::New (outData.size),
      Integer::New (0)
    };

    Local<Object> actualBuffer = bufferConstructor->NewInstance (3, constructorArgs);
    WebPDataClear (&outData);

    const unsigned argc = 2;
    Local<Value> argv [argc] = {
        Local<Value>::New (Null()),
        Local<Value>::New (actualBuffer)
    };

    Local<Function> callback = Local<Function>::Cast (args [1]);
    callback->Call (Context::GetCurrent()->Global(), argc, argv);

    return Undefined();
}

void RegisterModule (v8::Handle<v8::Object> target) {
     target->Set (String::NewSymbol ("convert"), FunctionTemplate::New (convert)->GetFunction());
}

NODE_MODULE (gif2webp, RegisterModule);
<commit_msg>Added HandleScope#Close call in gif2webp.cpp#convert.<commit_after>/*
  ==============================================================================

   Copyright (c) 2014 Jacob Sologub

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.

  ==============================================================================
*/

#include "gif2webpMain.h"
#include <node.h>
#include <node_buffer.h>
#include <v8.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

using namespace v8;
using namespace node;

// {
//     source      required. <Buffer>  Buffer with binary image data.
//     lossy:      optional. <Boolean> Encode image using lossy compression
//     mixed:      optional. <Boolean> For each frame in the image, pick lossy or lossless compression heuristically.
//     quality:    optional. <Number>  Quality factor (0:small..100:big)
//     method:     optional. <Number>  Compression method Quality (0=fast, 6=slowest)
//     kmin:       optional. <Number>  Min distance between key frames
//     kmax:       optional. <Number>  Max distance between key frames
//     filter:     optional. <Number>  Filter strength (0=off..100)
//     metadata:   optional. <String>  comma separated list of metadata to copy from the input to the output if present. Valid values: all, none, icc, xmp (default)
//     mt:         optional. <Boolean> Use multi-threading if available
//     verbose:    optional. <Boolean> Verbose output from gif2webp
// }

Handle<Value> convert (const Arguments& args) {
    HandleScope scope;

    if (args.Length() < 2) {
        return ThrowException (Exception::TypeError (String::New ("Wrong number of arguments.")));
    }

    if (!args [0]->IsObject()) {
        return ThrowException (Exception::TypeError (String::New ("First argument must be be an object.")));
    }

    if (!args [1]->IsFunction()) {
        return ThrowException (Exception::TypeError (String::New ("Second argument must be a callback function.")));
    }

    Local<Object> options = args [0]->ToObject();

    Local<Object> buffer = Local<Object>::Cast (options->Get (String::NewSymbol ("source")));
    if (buffer->IsUndefined() || !Buffer::HasInstance (buffer)) {
        return ThrowException (Exception::TypeError (String::New ("First argument should have \"source\" key with a Buffer instance")));
    }

    std::vector <std::string> optionArgs;

    if (!options->Get (String::NewSymbol ("lossy"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("lossy"))->ToBoolean();

        if (value->Value()) {
            optionArgs.push_back ("-lossy");
        }
    }

    if (!options->Get (String::NewSymbol ("mixed"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("mixed"))->ToBoolean();
        if (value->Value()) {
            optionArgs.push_back ("-mixed");
        }
    }

    if (!options->Get (String::NewSymbol ("quality"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("quality"))->ToNumber();
        optionArgs.push_back ("-q");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("method"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("method"))->ToNumber();
        optionArgs.push_back ("-m");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("kmin"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("kmin"))->ToNumber();
        optionArgs.push_back ("-kmin");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("kmax"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("kmax"))->ToNumber();
        optionArgs.push_back ("-kmax");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("filter"))->IsUndefined()) {
        Local<Number> value = options->Get (String::NewSymbol ("filter"))->ToNumber();
        optionArgs.push_back ("-f");
        std::ostringstream s;
        s << (double) value->Value();
        optionArgs.push_back (s.str());
    }

    if (!options->Get (String::NewSymbol ("metadata"))->IsUndefined()) {
        Local<String> value = options->Get (String::NewSymbol ("metadata"))->ToString();
        String::Utf8Value utf8Value (value);
        optionArgs.push_back ("-metadata");
        optionArgs.push_back (std::string (*utf8Value));
    }

    if (!options->Get (String::NewSymbol ("mt"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("mt"))->ToBoolean();
        if (value->Value()) {
            optionArgs.push_back ("-mt");
        }
    }

    if (!options->Get (String::NewSymbol ("verbose"))->IsUndefined()) {
        Local<Boolean> value = options->Get (String::NewSymbol ("verbose"))->ToBoolean();
        if (value->Value()) {
            optionArgs.push_back ("-v");
        }
    }

    const char* convert_argv [optionArgs.size()];
    int convert_argc = optionArgs.size();
    for (int i = 0; i < (int) optionArgs.size(); ++i) {
        convert_argv [i] = optionArgs [i].c_str();
    }

    const size_t inDataSize = Buffer::Length (buffer);
    const char* inData = Buffer::Data (buffer);

    WebPData outData;
    convert (convert_argc, convert_argv, (char*) inData, inDataSize, &outData);

    Local<Object> globalObj = v8::Context::GetCurrent()->Global();

    Buffer* slowBuffer = node::Buffer::New (outData.size);
    memcpy (node::Buffer::Data (slowBuffer), outData.bytes, outData.size);
    Local<Function> bufferConstructor = Local<Function>::Cast (globalObj->Get (String::New ("Buffer")));

    Handle<Value> constructorArgs [3] = {
      slowBuffer->handle_,
      Integer::New (outData.size),
      Integer::New (0)
    };

    Local<Object> actualBuffer = bufferConstructor->NewInstance (3, constructorArgs);
    WebPDataClear (&outData);

    const unsigned argc = 2;
    Local<Value> argv [argc] = {
        Local<Value>::New (Null()),
        Local<Value>::New (actualBuffer)
    };

    Local<Function> callback = Local<Function>::Cast (args [1]);
    callback->Call (Context::GetCurrent()->Global(), argc, argv);

    return scope.Close (Undefined());
}

void RegisterModule (v8::Handle<v8::Object> target) {
     target->Set (String::NewSymbol ("convert"), FunctionTemplate::New (convert)->GetFunction());
}

NODE_MODULE (gif2webp, RegisterModule);
<|endoftext|>


<commit_before>///
/// @file  iterator.cpp
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/iterator.hpp>
#include <primesieve/IteratorHelper.hpp>
#include <primesieve/PrimeGenerator.hpp>
#include <primesieve/macros.hpp>
#include <primesieve/pod_vector.hpp>

#include <stdint.h>
#include <limits>

namespace {

void freeAllMemory(primesieve::iterator* it)
{
  if (it->memory_)
  {
    using primesieve::IteratorData;
    delete (IteratorData*) it->memory_;
    it->memory_ = nullptr;
  }
}

} // namespace

namespace primesieve {

iterator::iterator() noexcept :
  i_(0),
  size_(0),
  start_(0),
  stop_hint_(std::numeric_limits<uint64_t>::max()),
  primes_(nullptr),
  memory_(nullptr)
{ }

iterator::iterator(uint64_t start,
                   uint64_t stop_hint) noexcept :
  i_(0),
  size_(0),
  start_(start),
  stop_hint_(stop_hint),
  primes_(nullptr),
  memory_(nullptr)
{ }

/// Move constructor
iterator::iterator(iterator&& other) noexcept :
  i_(other.i_),
  size_(other.size_),
  start_(other.start_),
  stop_hint_(other.stop_hint_),
  primes_(other.primes_),
  memory_(other.memory_)
{
  other.i_ = 0;
  other.size_ = 0;
  other.start_ = 0;
  other.stop_hint_ = std::numeric_limits<uint64_t>::max();
  other.primes_ = nullptr;
  other.memory_ = nullptr;
}

/// Move assignment operator
iterator& iterator::operator=(iterator&& other) noexcept
{
  if (this != &other)
  {
    freeAllMemory(this);

    i_ = other.i_;
    size_ = other.size_;
    start_ = other.start_;
    stop_hint_ = other.stop_hint_;
    primes_ = other.primes_;
    memory_ = other.memory_;

    other.i_ = 0;
    other.size_ = 0;
    other.start_ = 0;
    other.stop_hint_ = std::numeric_limits<uint64_t>::max();
    other.primes_ = nullptr;
    other.memory_ = nullptr;
  }

  return *this;
}

void iterator::jump_to(uint64_t start,
                       uint64_t stop_hint) noexcept
{
  i_ = 0;
  size_ = 0;
  start_ = start;
  stop_hint_ = stop_hint;
  primes_ = nullptr;

  // Frees most memory, but keeps some smaller data
  // structures (e.g. the PreSieve object) that are
  // useful if the primesieve::iterator is reused.
  // The remaining memory uses at most 200 kilobytes.
  if (memory_)
  {
    auto& iterData = *(IteratorData*) memory_;
    iterData.stop = start;
    iterData.dist = 0;
    iterData.include_start_number = true;
    iterData.deletePrimeGenerator();
    iterData.deletePrimes();
  }
}

void iterator::clear() noexcept
{
  jump_to(0);
}

iterator::~iterator()
{
  freeAllMemory(this);
}

void iterator::generate_next_primes()
{
  if (!memory_)
    memory_ = new IteratorData(start_);

  auto& iterData = *(IteratorData*) memory_;
  auto& primes = iterData.primes;

  while (true)
  {
    if (!iterData.primeGenerator)
    {
      IteratorHelper::updateNext(start_, stop_hint_, iterData);
      iterData.primeGenerator = new PrimeGenerator(start_, iterData.stop, iterData.preSieve);
    }

    iterData.primeGenerator->fillNextPrimes(primes, &size_);
    primes_ = primes.data();
    i_ = 0;

    // There are 2 different cases here:
    // 1) The primes array is empty because the next prime > stop.
    //    In this case we reset the primeGenerator object, increase
    //    the start & stop numbers and sieve the next segment.
    // 2) The primes array is not empty (contains up to 1024 primes),
    //    in this case we return it to the user.
    if_unlikely(size_ == 0)
      iterData.deletePrimeGenerator();
    else
      return;
  }
}

void iterator::generate_prev_primes()
{
  if (!memory_)
    memory_ = new IteratorData(start_);

  auto& iterData = *(IteratorData*) memory_;
  auto& primes = iterData.primes;

  // Special case if generate_next_primes() has
  // been used before generate_prev_primes().
  if_unlikely(iterData.primeGenerator)
  {
    start_ = primes.front();
    iterData.deletePrimeGenerator();
    ASSERT(!iterData.include_start_number);
  }

  // When sieving backwards the sieving distance is subdivided
  // into smaller chunks. If we can prove that the total
  // sieving distance is large we enable pre-sieving.
  if (iterData.dist == 0 &&
      stop_hint_ < start_)
    iterData.preSieve.init(stop_hint_, start_);

  do
  {
    IteratorHelper::updatePrev(start_, stop_hint_, iterData);
    PrimeGenerator primeGenerator(start_, iterData.stop, iterData.preSieve);
    primeGenerator.fillPrevPrimes(primes, &size_);
    primes_ = primes.data();
    i_ = size_;
  }
  while (!size_);
}

} // namespace
<commit_msg>Use delegating constructor<commit_after>///
/// @file  iterator.cpp
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/iterator.hpp>
#include <primesieve/IteratorHelper.hpp>
#include <primesieve/PrimeGenerator.hpp>
#include <primesieve/macros.hpp>
#include <primesieve/pod_vector.hpp>

#include <stdint.h>
#include <limits>

namespace {

void freeAllMemory(primesieve::iterator* it)
{
  if (it->memory_)
  {
    using primesieve::IteratorData;
    delete (IteratorData*) it->memory_;
    it->memory_ = nullptr;
  }
}

} // namespace

namespace primesieve {

iterator::iterator() noexcept :
  iterator(0)
{ }

iterator::iterator(uint64_t start,
                   uint64_t stop_hint) noexcept :
  i_(0),
  size_(0),
  start_(start),
  stop_hint_(stop_hint),
  primes_(nullptr),
  memory_(nullptr)
{ }

/// Move constructor
iterator::iterator(iterator&& other) noexcept :
  i_(other.i_),
  size_(other.size_),
  start_(other.start_),
  stop_hint_(other.stop_hint_),
  primes_(other.primes_),
  memory_(other.memory_)
{
  other.i_ = 0;
  other.size_ = 0;
  other.start_ = 0;
  other.stop_hint_ = std::numeric_limits<uint64_t>::max();
  other.primes_ = nullptr;
  other.memory_ = nullptr;
}

/// Move assignment operator
iterator& iterator::operator=(iterator&& other) noexcept
{
  if (this != &other)
  {
    freeAllMemory(this);

    i_ = other.i_;
    size_ = other.size_;
    start_ = other.start_;
    stop_hint_ = other.stop_hint_;
    primes_ = other.primes_;
    memory_ = other.memory_;

    other.i_ = 0;
    other.size_ = 0;
    other.start_ = 0;
    other.stop_hint_ = std::numeric_limits<uint64_t>::max();
    other.primes_ = nullptr;
    other.memory_ = nullptr;
  }

  return *this;
}

void iterator::jump_to(uint64_t start,
                       uint64_t stop_hint) noexcept
{
  i_ = 0;
  size_ = 0;
  start_ = start;
  stop_hint_ = stop_hint;
  primes_ = nullptr;

  // Frees most memory, but keeps some smaller data
  // structures (e.g. the PreSieve object) that are
  // useful if the primesieve::iterator is reused.
  // The remaining memory uses at most 200 kilobytes.
  if (memory_)
  {
    auto& iterData = *(IteratorData*) memory_;
    iterData.stop = start;
    iterData.dist = 0;
    iterData.include_start_number = true;
    iterData.deletePrimeGenerator();
    iterData.deletePrimes();
  }
}

void iterator::clear() noexcept
{
  jump_to(0);
}

iterator::~iterator()
{
  freeAllMemory(this);
}

void iterator::generate_next_primes()
{
  if (!memory_)
    memory_ = new IteratorData(start_);

  auto& iterData = *(IteratorData*) memory_;
  auto& primes = iterData.primes;

  while (true)
  {
    if (!iterData.primeGenerator)
    {
      IteratorHelper::updateNext(start_, stop_hint_, iterData);
      iterData.primeGenerator = new PrimeGenerator(start_, iterData.stop, iterData.preSieve);
    }

    iterData.primeGenerator->fillNextPrimes(primes, &size_);
    primes_ = primes.data();
    i_ = 0;

    // There are 2 different cases here:
    // 1) The primes array is empty because the next prime > stop.
    //    In this case we reset the primeGenerator object, increase
    //    the start & stop numbers and sieve the next segment.
    // 2) The primes array is not empty (contains up to 1024 primes),
    //    in this case we return it to the user.
    if_unlikely(size_ == 0)
      iterData.deletePrimeGenerator();
    else
      return;
  }
}

void iterator::generate_prev_primes()
{
  if (!memory_)
    memory_ = new IteratorData(start_);

  auto& iterData = *(IteratorData*) memory_;
  auto& primes = iterData.primes;

  // Special case if generate_next_primes() has
  // been used before generate_prev_primes().
  if_unlikely(iterData.primeGenerator)
  {
    start_ = primes.front();
    iterData.deletePrimeGenerator();
    ASSERT(!iterData.include_start_number);
  }

  // When sieving backwards the sieving distance is subdivided
  // into smaller chunks. If we can prove that the total
  // sieving distance is large we enable pre-sieving.
  if (iterData.dist == 0 &&
      stop_hint_ < start_)
    iterData.preSieve.init(stop_hint_, start_);

  do
  {
    IteratorHelper::updatePrev(start_, stop_hint_, iterData);
    PrimeGenerator primeGenerator(start_, iterData.stop, iterData.preSieve);
    primeGenerator.fillPrevPrimes(primes, &size_);
    primes_ = primes.data();
    i_ = size_;
  }
  while (!size_);
}

} // namespace
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "keygen.h"
#include "crc32.h"

static char *abt_array =
    (char*)"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";

void keygen_init(
    struct keygen *keygen,
    size_t nprefix,
    struct rndinfo *prefix_len,
    struct rndinfo *prefix_dist,
    struct keygen_option *opt)
{
    keygen->nprefix = nprefix;
    keygen->prefix_len = (struct rndinfo *)malloc(sizeof(struct rndinfo) * nprefix);
    keygen->prefix_dist = (struct rndinfo *)malloc(sizeof(struct rndinfo) * nprefix);
    keygen->opt = *opt;
    keygen->abt_array_size = strlen(abt_array);

    memcpy(keygen->prefix_len, prefix_len, sizeof(struct rndinfo) * nprefix);
    memcpy(keygen->prefix_dist, prefix_dist, sizeof(struct rndinfo) * nprefix);
}

void keygen_free(struct keygen *keygen)
{
    free(keygen->prefix_len);
    free(keygen->prefix_dist);
}

void _crc2key(struct keygen *keygen, uint64_t crc, char *buf, size_t len, uint8_t abt_only)
{
    int i;
    BDR_RNG_VARS_SET(crc);
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXT;
    BDR_RNG_NEXT;

    for (i=0;i<len;i+=1){
        BDR_RNG_NEXT;
        BDR_RNG_NEXT;
        if (abt_only) {
            buf[i] = abt_array[(rngz%(keygen->abt_array_size))];
            //buf[i] = 'a' + (rngz%('z'-'a'));
        } else {
            buf[i] = rngz & 0xff;
        }
    }
}

size_t _crc2keylen(struct rndinfo *prefix_len, uint64_t crc)
{
    size_t r;
    BDR_RNG_VARS_SET(crc);
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXTPAIR;

    r = get_random(prefix_len, rngz, rngz2);
    return r;
}

uint32_t keygen_idx2crc(uint64_t idx, uint32_t seed)
{
    uint32_t crc;
    uint64_t idx64 = idx;
    crc = crc32_8(&idx64, sizeof(idx64), seed);
    crc = crc32_8(&idx64, sizeof(idx64), crc);
    return crc;
}

uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed )
{
    const uint64_t m = 0xc6a4a7935bd1e995;
    const int r = 47;

    uint64_t h = seed ^ (len * m);

    const uint64_t * data = (const uint64_t *)key;
    const uint64_t * end = data + (len/8);

    while(data != end)
    {
        uint64_t k = *data++;

        k *= m;
        k ^= k >> r;
        k *= m;

        h ^= k;
        h *= m;
    }

    const unsigned char * data2 = (const unsigned char*)data;

    switch(len & 7)
    {
        case 7: h ^= uint64_t(data2[6]) << 48;
        case 6: h ^= uint64_t(data2[5]) << 40;
        case 5: h ^= uint64_t(data2[4]) << 32;
        case 4: h ^= uint64_t(data2[3]) << 24;
        case 3: h ^= uint64_t(data2[2]) << 16;
        case 2: h ^= uint64_t(data2[1]) << 8;
        case 1: h ^= uint64_t(data2[0]);
        h *= m;
    };

    h ^= h >> r;
    h *= m;
    h ^= h >> r;

    return h;
}

size_t keygen_seed2key(struct keygen *keygen, uint64_t seed, char *buf)
{
    uint64_t i;
    size_t len, cursor;
    uint64_t seed_local, seed64, rnd_sel;

    seed64 = MurmurHash64A(&seed, sizeof(uint64_t), 0);
    BDR_RNG_VARS_SET(seed64);
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXTPAIR;

    cursor = 0;
    for (i=0;i<keygen->nprefix;++i){
        if (i+1 == keygen->nprefix) {
            len = _crc2keylen(&keygen->prefix_len[i], seed64);
            _crc2key(keygen, seed64, buf + cursor, len, keygen->opt.abt_only);
        } else {
            BDR_RNG_NEXTPAIR;
            BDR_RNG_NEXTPAIR;
            rnd_sel = get_random(&keygen->prefix_dist[i], rngz, rngz2);
            seed_local = MurmurHash64A(&rnd_sel, sizeof(rnd_sel), 0);

            len = _crc2keylen(&keygen->prefix_len[i], seed_local);
            _crc2key(keygen, seed_local, buf + cursor, len, keygen->opt.abt_only);
        }

        cursor += len;

        if (keygen->opt.delimiter && i != keygen->nprefix-1) {
            buf[cursor] = '/';
            cursor++;
        }
    }
    buf[cursor] = 0;
    return cursor;
}

<commit_msg>Fix keygen random number initialization<commit_after>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "keygen.h"
#include "crc32.h"

static char *abt_array =
    (char*)"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";

void keygen_init(
    struct keygen *keygen,
    size_t nprefix,
    struct rndinfo *prefix_len,
    struct rndinfo *prefix_dist,
    struct keygen_option *opt)
{
    keygen->nprefix = nprefix;
    keygen->prefix_len = (struct rndinfo *)malloc(sizeof(struct rndinfo) * nprefix);
    keygen->prefix_dist = (struct rndinfo *)malloc(sizeof(struct rndinfo) * nprefix);
    keygen->opt = *opt;
    keygen->abt_array_size = strlen(abt_array);

    memcpy(keygen->prefix_len, prefix_len, sizeof(struct rndinfo) * nprefix);
    memcpy(keygen->prefix_dist, prefix_dist, sizeof(struct rndinfo) * nprefix);
}

void keygen_free(struct keygen *keygen)
{
    free(keygen->prefix_len);
    free(keygen->prefix_dist);
}

void _crc2key(struct keygen *keygen, uint64_t crc, char *buf, size_t len, uint8_t abt_only)
{
    int i;
    BDR_RNG_VARS_SET(crc);
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXT;

    for (i=0;i<len;i+=1){
        BDR_RNG_NEXTPAIR;
        if (abt_only) {
            buf[i] = abt_array[(rngz%(keygen->abt_array_size))];
            //buf[i] = 'a' + (rngz%('z'-'a'));
        } else {
            buf[i] = rngz & 0xff;
        }
    }
}

size_t _crc2keylen(struct rndinfo *prefix_len, uint64_t crc)
{
    size_t r;
    BDR_RNG_VARS_SET(crc);
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXT;

    r = get_random(prefix_len, rngz, rngz2);
    return r;
}

uint32_t keygen_idx2crc(uint64_t idx, uint32_t seed)
{
    uint32_t crc;
    uint64_t idx64 = idx;
    crc = crc32_8(&idx64, sizeof(idx64), seed);
    crc = crc32_8(&idx64, sizeof(idx64), crc);
    return crc;
}

uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed )
{
    const uint64_t m = 0xc6a4a7935bd1e995;
    const int r = 47;

    uint64_t h = seed ^ (len * m);

    const uint64_t * data = (const uint64_t *)key;
    const uint64_t * end = data + (len/8);

    while(data != end)
    {
        uint64_t k = *data++;

        k *= m;
        k ^= k >> r;
        k *= m;

        h ^= k;
        h *= m;
    }

    const unsigned char * data2 = (const unsigned char*)data;

    switch(len & 7)
    {
        case 7: h ^= uint64_t(data2[6]) << 48;
        case 6: h ^= uint64_t(data2[5]) << 40;
        case 5: h ^= uint64_t(data2[4]) << 32;
        case 4: h ^= uint64_t(data2[3]) << 24;
        case 3: h ^= uint64_t(data2[2]) << 16;
        case 2: h ^= uint64_t(data2[1]) << 8;
        case 1: h ^= uint64_t(data2[0]);
        h *= m;
    };

    h ^= h >> r;
    h *= m;
    h ^= h >> r;

    return h;
}

size_t keygen_seed2key(struct keygen *keygen, uint64_t seed, char *buf)
{
    uint64_t i;
    size_t len, cursor;
    uint64_t seed_local, seed64, rnd_sel;

    seed64 = MurmurHash64A(&seed, sizeof(uint64_t), 0);
    BDR_RNG_VARS_SET(seed64);
    BDR_RNG_NEXTPAIR;
    BDR_RNG_NEXT;

    cursor = 0;
    for (i=0;i<keygen->nprefix;++i){
        if (i+1 == keygen->nprefix) {
            len = _crc2keylen(&keygen->prefix_len[i], seed64);
            _crc2key(keygen, seed64, buf + cursor, len, keygen->opt.abt_only);
        } else {
            BDR_RNG_NEXTPAIR;
            BDR_RNG_NEXT;
            rnd_sel = get_random(&keygen->prefix_dist[i], rngz, rngz2);
            seed_local = MurmurHash64A(&rnd_sel, sizeof(rnd_sel), 0);

            len = _crc2keylen(&keygen->prefix_len[i], seed_local);
            _crc2key(keygen, seed_local, buf + cursor, len, keygen->opt.abt_only);
        }

        cursor += len;

        if (keygen->opt.delimiter && i != keygen->nprefix-1) {
            buf[cursor] = '/';
            cursor++;
        }
    }
    buf[cursor] = 0;
    return cursor;
}

<|endoftext|>