<commit_before>#include "../HalideRuntime.h"
#include "HexagonWrapper.h"
#include "sim_protocol.h"

#include <vector>
#include <sstream>
#include <cassert>

typedef unsigned int handle_t;

HexagonWrapper *sim = NULL;

int init_sim() {
    if (sim) return 0;

    sim = new HexagonWrapper(HEX_CPU_V60);

    HEXAPI_Status status = HEX_STAT_SUCCESS;

    // If an explicit path to the simulator is provided, use it.
    const char *sim_remote_path = getenv("HL_HEXAGON_SIM_REMOTE");
    if (!sim_remote_path || !sim_remote_path[0]) {
        // Otherwise... just assume that something with this name will be
        // available in the working directory, I guess.
        sim_remote_path = "hexagon_sim_remote";
    }
    status = sim->ConfigureExecutableBinary(sim_remote_path);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ConfigureExecutableBinary failed: %d\n", status);
        return -1;
    }

    status = sim->ConfigureNULLPointerBehavior(HEX_NULLPTR_FATAL);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ConfigureNULLPointerBehavior failed: %d\n", status);
        return -1;
    }

    // memfill defaults to 0x1f on the simulator.
    // example: HL_HEXAGON_MEMFILL=0
    const char *memfill = getenv("HL_HEXAGON_MEMFILL");
    if (memfill && memfill[0] != 0) {
        status = sim->ConfigureMemFill(atoi(memfill));
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ConfigureMemFill failed: %d\n", status);
            return -1;
        }
    }

    const char *timing = getenv("HL_HEXAGON_TIMING");
    if (timing && timing[0] != 0) {
        status = sim->ConfigureTimingMode(HEX_TIMING);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ConfigureTimingMode failed: %d\n", status);
            return -1;
        }
    }

    // Configue tracing.
    const char *T = getenv("HL_HEXAGON_SIM_MIN_TRACE");
    if (T && T[0] != 0) {
        status = sim->SetTracing(HEX_TRACE_PC_MIN, T);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::SetTracing MIN failed: %d\n", status);
            return -1;
        }
    } else {
        const char *T = getenv("HL_HEXAGON_SIM_TRACE");
        if (T && T[0] != 0) {
            status = sim->SetTracing(HEX_TRACE_PC, T);
            if (status != HEX_STAT_SUCCESS) {
                printf("HexagonWrapper::SetTracing failed: %d\n", status);
                return -1;
            }
        }
    }

    // Configure use of debugger
    int pnum = 0;
    char *s = getenv("HL_HEXAGON_SIM_DBG_PORT");
    if (s && (pnum = atoi(s))) {
        printf("Debugger port: %d\n", pnum);
        status = sim->ConfigureRemoteDebug(pnum);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ConfigureRemoteDebug failed: %d\n", status);
            return -1;
        }
    }

    status = sim->EndOfConfiguration();
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::EndOfConfiguration failed: %d\n", status);
        return -1;
    }

    status = sim->LoadExecutableBinary();
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::LoadExecutableBinary failed: %d\n", status);
        return -1;
    }
    return 0;
}

int write_memory(int dest, const void *src, int size) {
    assert(sim);

    while (size > 0) {
        // WriteMemory only works with powers of 2, so align down. It
        // also only writes up to 8 bytes, so we need to do this
        // repeatedly until we've finished copying the buffer.
        int next = 1;
        if (size >= 8) next = 8;
        else if (size >= 4) next = 4;
        else if (size >= 2) next = 2;
        HEXAPI_Status status = sim->WriteMemory(dest, next, *reinterpret_cast<const HEX_8u_t*>(src));
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::WriteMemory failed: %d\n", status);
            return -1;
        }

        size -= next;
        dest += next;
        src = reinterpret_cast<const char *>(src) + next;
    }
    return 0;
}

int read_memory(void *dest, int src, int size) {
    assert(sim);

    while (size > 0) {
        // This is the same logic as in write_memory above.
        int next = 1;
        if (size >= 8) next = 8;
        else if (size >= 4) next = 4;
        else if (size >= 2) next = 2;
        HEXAPI_Status status = sim->ReadMemory(src, next, dest);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ReadMemory failed: %d\n", status);
            return -1;
        }

        size -= next;
        src += next;
        dest = reinterpret_cast<char *>(dest) + next;
    }
    return 0;
}

int send_message(int msg, const std::vector<int> &arguments) {
    assert(sim);

    HEXAPI_Status status;

    HEX_4u_t remote_msg = 0;
    status = sim->ReadSymbolValue("rpc_call", &remote_msg);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ReadSymbolValue(rpcmsg) failed: %d\n", status);
        return -1;
    }
    if (write_memory(remote_msg, &msg, 4) != 0) { return -1; }

    // The arguments are individual numbered variables.
    for (size_t i = 0; i < arguments.size(); i++) {
        HEX_4u_t remote_arg = 0;
        std::string rpc_arg = "rpc_arg" + std::to_string(i);
        status = sim->ReadSymbolValue(rpc_arg.c_str(), &remote_arg);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ReadSymbolValue(%s) failed: %d\n", rpc_arg.c_str(), status);
            return -1;
        }
        if (write_memory(remote_arg, &arguments[i], 4) != 0) { return -1; }
    }

    HEX_4u_t remote_ret = 0;
    status = sim->ReadSymbolValue("rpc_ret", &remote_ret);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ReadSymbolValue(rpc_ret) failed: %d\n", status);
        return -1;
    }

    HEXAPI_CoreState state;
    if (msg == Message::Break) {
        // If we're trying to end the remote simulation, just run
        // until completion.
        HEX_4u_t result;
        state = sim->Run(&result);
        if (state != HEX_CORE_FINISHED) {
            printf("HexagonWrapper::Run failed: %d\n", state);
            return -1;
        }
        return 0;
    } else {
        // If we want to return and continue simulating, we execute
        // 1000 cycles at a time, until the remote indicates it has
        // completed handling the current message.
        do {
            HEX_4u_t cycles;
            state = sim->Step(1000, &cycles);
            if (read_memory(&msg, remote_msg, 4) != 0) {
                return -1;
            }
            if (msg == Message::None) {
                HEX_4u_t ret = 0;
                if (read_memory(&ret, remote_ret, 4)) {
                    return -1;
                }
                return ret;
            }
        } while (state == HEX_CORE_SUCCESS);
        printf("HexagonWrapper::StepTime failed: %d\n", state);
        return -1;
    }
}

struct host_buffer {
    unsigned char *data;
    int dataLen;
};

class remote_buffer {
public:
    int data;
    int dataLen;

    remote_buffer() : data(0), dataLen(0) {}
    remote_buffer(int dataLen) : dataLen(dataLen) {
        if (dataLen > 0) {
            data = send_message(Message::Alloc, {dataLen});
            if (data == 0) {
                printf("Failed to allocate %d bytes in the Hexagon simulation.\n", dataLen);
            }
        } else {
            data = 0;
        }
    }
    remote_buffer(const void *data, int dataLen) : remote_buffer(dataLen) {
        if (this->data != 0) {
            write_memory(this->data, data, dataLen);
        }
    }
    remote_buffer(const host_buffer &host_buf) : remote_buffer(host_buf.data, host_buf.dataLen) {}

    ~remote_buffer() {
        if (data != 0) {
            send_message(Message::Free, {data});
        }
    }

    // Enable usage with std::vector.
    remote_buffer(remote_buffer &&move) : remote_buffer() {
        std::swap(data, move.data);
        std::swap(dataLen, move.dataLen);
    }
    remote_buffer &operator = (remote_buffer &&move) {
        std::swap(data, move.data);
        std::swap(dataLen, move.dataLen);
        return *this;
    }

    remote_buffer(const remote_buffer &) = delete;
    remote_buffer &operator=(const remote_buffer &) = delete;
};

extern "C" {

int halide_hexagon_remote_initialize_kernels(const unsigned char *code, int codeLen,
                                             handle_t *module_ptr) {
    int ret = init_sim();
    if (ret != 0) return -1;

    // Copy the pointer arguments to the simulator.
    remote_buffer remote_code(code, codeLen);
    remote_buffer remote_module_ptr(module_ptr, 4);

    // Run the init kernels command.
    ret = send_message(Message::InitKernels, {remote_code.data, codeLen, remote_module_ptr.data});
    if (ret != 0) return ret;

    // Get the module ptr.
    ret = read_memory(module_ptr, remote_module_ptr.data, 4);

    return ret;
}

handle_t halide_hexagon_remote_get_symbol(handle_t module_ptr, const char* name, int nameLen) {
    assert(sim);

    // Copy the pointer arguments to the simulator.
    remote_buffer remote_name(name, nameLen);

    // Run the init kernels command.
    handle_t ret = send_message(Message::GetSymbol, {static_cast<int>(module_ptr), remote_name.data, nameLen});

    return ret;
}

int halide_hexagon_remote_run(handle_t module_ptr, handle_t function,
                              const host_buffer *input_buffersPtrs, int input_buffersLen,
                              host_buffer *output_buffersPtrs, int output_buffersLen,
                              const host_buffer *input_scalarsPtrs, int input_scalarsLen) {
    assert(sim);

    std::vector<remote_buffer> remote_input_buffers;
    std::vector<remote_buffer> remote_output_buffers;
    std::vector<remote_buffer> remote_input_scalars;

    for (int i = 0; i < input_buffersLen; i++) {
        remote_input_buffers.emplace_back(input_buffersPtrs[i]);
    }
    for (int i = 0; i < output_buffersLen; i++) {
        remote_output_buffers.emplace_back(output_buffersPtrs[i]);
    }
    for (int i = 0; i < input_scalarsLen; i++) {
        remote_input_scalars.emplace_back(input_scalarsPtrs[i]);
    }

    // Copy the pointer arguments to the simulator.
    remote_buffer remote_input_buffersPtrs(&remote_input_buffers[0], input_buffersLen * sizeof(remote_buffer));
    remote_buffer remote_output_buffersPtrs(&remote_output_buffers[0], output_buffersLen * sizeof(remote_buffer));
    remote_buffer remote_input_scalarsPtrs(&remote_input_scalars[0], input_scalarsLen * sizeof(remote_buffer));

    HEX_8u_t cycles_begin = 0;
    sim->GetSimulatedCycleCount(&cycles_begin);

    // Run the init kernels command.
    int ret = send_message(
        Message::Run,
        {static_cast<int>(module_ptr), static_cast<int>(function),
         remote_input_buffersPtrs.data, input_buffersLen,
         remote_output_buffersPtrs.data, output_buffersLen,
         remote_input_scalarsPtrs.data, input_scalarsLen});
    if (ret != 0) return ret;

    HEX_8u_t cycles_end = 0;
    sim->GetSimulatedCycleCount(&cycles_end);

    if (getenv("HL_HEXAGON_SIM_CYCLES")) {
        int cycles = static_cast<int>(cycles_end - cycles_begin);
        printf("Hexagon simulator executed function 0x%x in %d cycles\n", function, cycles);
    }

    // Copy the outputs back.
    for (int i = 0; i < output_buffersLen; i++) {
        ret = read_memory(output_buffersPtrs[i].data, remote_output_buffers[i].data, output_buffersPtrs[i].dataLen);
        if (ret != 0) return ret;
    }

    return ret;
}

int halide_hexagon_remote_release_kernels(handle_t module_ptr, int codeLen) {
    // Print out sim statistics if desired.
    if (getenv("HL_HEXAGON_SIM_STATS")) {
        char Buf[4096];
        HEXAPI_Status status = sim->EmitPerfStatistics(0, 0, 0, 0, Buf, sizeof(Buf));
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::EmitStatistics failed: %d\n", status);
        } else {
            // Print out the full stats
            printf("%s\n", Buf);
        }
    }
    return send_message(Message::ReleaseKernels, {static_cast<int>(module_ptr), codeLen});
}

}  // extern "C"
<commit_msg>Fix another operator = spacing.<commit_after>#include "../HalideRuntime.h"
#include "HexagonWrapper.h"
#include "sim_protocol.h"

#include <vector>
#include <sstream>
#include <cassert>

typedef unsigned int handle_t;

HexagonWrapper *sim = NULL;

int init_sim() {
    if (sim) return 0;

    sim = new HexagonWrapper(HEX_CPU_V60);

    HEXAPI_Status status = HEX_STAT_SUCCESS;

    // If an explicit path to the simulator is provided, use it.
    const char *sim_remote_path = getenv("HL_HEXAGON_SIM_REMOTE");
    if (!sim_remote_path || !sim_remote_path[0]) {
        // Otherwise... just assume that something with this name will be
        // available in the working directory, I guess.
        sim_remote_path = "hexagon_sim_remote";
    }
    status = sim->ConfigureExecutableBinary(sim_remote_path);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ConfigureExecutableBinary failed: %d\n", status);
        return -1;
    }

    status = sim->ConfigureNULLPointerBehavior(HEX_NULLPTR_FATAL);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ConfigureNULLPointerBehavior failed: %d\n", status);
        return -1;
    }

    // memfill defaults to 0x1f on the simulator.
    // example: HL_HEXAGON_MEMFILL=0
    const char *memfill = getenv("HL_HEXAGON_MEMFILL");
    if (memfill && memfill[0] != 0) {
        status = sim->ConfigureMemFill(atoi(memfill));
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ConfigureMemFill failed: %d\n", status);
            return -1;
        }
    }

    const char *timing = getenv("HL_HEXAGON_TIMING");
    if (timing && timing[0] != 0) {
        status = sim->ConfigureTimingMode(HEX_TIMING);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ConfigureTimingMode failed: %d\n", status);
            return -1;
        }
    }

    // Configue tracing.
    const char *T = getenv("HL_HEXAGON_SIM_MIN_TRACE");
    if (T && T[0] != 0) {
        status = sim->SetTracing(HEX_TRACE_PC_MIN, T);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::SetTracing MIN failed: %d\n", status);
            return -1;
        }
    } else {
        const char *T = getenv("HL_HEXAGON_SIM_TRACE");
        if (T && T[0] != 0) {
            status = sim->SetTracing(HEX_TRACE_PC, T);
            if (status != HEX_STAT_SUCCESS) {
                printf("HexagonWrapper::SetTracing failed: %d\n", status);
                return -1;
            }
        }
    }

    // Configure use of debugger
    int pnum = 0;
    char *s = getenv("HL_HEXAGON_SIM_DBG_PORT");
    if (s && (pnum = atoi(s))) {
        printf("Debugger port: %d\n", pnum);
        status = sim->ConfigureRemoteDebug(pnum);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ConfigureRemoteDebug failed: %d\n", status);
            return -1;
        }
    }

    status = sim->EndOfConfiguration();
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::EndOfConfiguration failed: %d\n", status);
        return -1;
    }

    status = sim->LoadExecutableBinary();
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::LoadExecutableBinary failed: %d\n", status);
        return -1;
    }
    return 0;
}

int write_memory(int dest, const void *src, int size) {
    assert(sim);

    while (size > 0) {
        // WriteMemory only works with powers of 2, so align down. It
        // also only writes up to 8 bytes, so we need to do this
        // repeatedly until we've finished copying the buffer.
        int next = 1;
        if (size >= 8) next = 8;
        else if (size >= 4) next = 4;
        else if (size >= 2) next = 2;
        HEXAPI_Status status = sim->WriteMemory(dest, next, *reinterpret_cast<const HEX_8u_t*>(src));
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::WriteMemory failed: %d\n", status);
            return -1;
        }

        size -= next;
        dest += next;
        src = reinterpret_cast<const char *>(src) + next;
    }
    return 0;
}

int read_memory(void *dest, int src, int size) {
    assert(sim);

    while (size > 0) {
        // This is the same logic as in write_memory above.
        int next = 1;
        if (size >= 8) next = 8;
        else if (size >= 4) next = 4;
        else if (size >= 2) next = 2;
        HEXAPI_Status status = sim->ReadMemory(src, next, dest);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ReadMemory failed: %d\n", status);
            return -1;
        }

        size -= next;
        src += next;
        dest = reinterpret_cast<char *>(dest) + next;
    }
    return 0;
}

int send_message(int msg, const std::vector<int> &arguments) {
    assert(sim);

    HEXAPI_Status status;

    HEX_4u_t remote_msg = 0;
    status = sim->ReadSymbolValue("rpc_call", &remote_msg);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ReadSymbolValue(rpcmsg) failed: %d\n", status);
        return -1;
    }
    if (write_memory(remote_msg, &msg, 4) != 0) { return -1; }

    // The arguments are individual numbered variables.
    for (size_t i = 0; i < arguments.size(); i++) {
        HEX_4u_t remote_arg = 0;
        std::string rpc_arg = "rpc_arg" + std::to_string(i);
        status = sim->ReadSymbolValue(rpc_arg.c_str(), &remote_arg);
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::ReadSymbolValue(%s) failed: %d\n", rpc_arg.c_str(), status);
            return -1;
        }
        if (write_memory(remote_arg, &arguments[i], 4) != 0) { return -1; }
    }

    HEX_4u_t remote_ret = 0;
    status = sim->ReadSymbolValue("rpc_ret", &remote_ret);
    if (status != HEX_STAT_SUCCESS) {
        printf("HexagonWrapper::ReadSymbolValue(rpc_ret) failed: %d\n", status);
        return -1;
    }

    HEXAPI_CoreState state;
    if (msg == Message::Break) {
        // If we're trying to end the remote simulation, just run
        // until completion.
        HEX_4u_t result;
        state = sim->Run(&result);
        if (state != HEX_CORE_FINISHED) {
            printf("HexagonWrapper::Run failed: %d\n", state);
            return -1;
        }
        return 0;
    } else {
        // If we want to return and continue simulating, we execute
        // 1000 cycles at a time, until the remote indicates it has
        // completed handling the current message.
        do {
            HEX_4u_t cycles;
            state = sim->Step(1000, &cycles);
            if (read_memory(&msg, remote_msg, 4) != 0) {
                return -1;
            }
            if (msg == Message::None) {
                HEX_4u_t ret = 0;
                if (read_memory(&ret, remote_ret, 4)) {
                    return -1;
                }
                return ret;
            }
        } while (state == HEX_CORE_SUCCESS);
        printf("HexagonWrapper::StepTime failed: %d\n", state);
        return -1;
    }
}

struct host_buffer {
    unsigned char *data;
    int dataLen;
};

class remote_buffer {
public:
    int data;
    int dataLen;

    remote_buffer() : data(0), dataLen(0) {}
    remote_buffer(int dataLen) : dataLen(dataLen) {
        if (dataLen > 0) {
            data = send_message(Message::Alloc, {dataLen});
            if (data == 0) {
                printf("Failed to allocate %d bytes in the Hexagon simulation.\n", dataLen);
            }
        } else {
            data = 0;
        }
    }
    remote_buffer(const void *data, int dataLen) : remote_buffer(dataLen) {
        if (this->data != 0) {
            write_memory(this->data, data, dataLen);
        }
    }
    remote_buffer(const host_buffer &host_buf) : remote_buffer(host_buf.data, host_buf.dataLen) {}

    ~remote_buffer() {
        if (data != 0) {
            send_message(Message::Free, {data});
        }
    }

    // Enable usage with std::vector.
    remote_buffer(remote_buffer &&move) : remote_buffer() {
        std::swap(data, move.data);
        std::swap(dataLen, move.dataLen);
    }
    remote_buffer &operator=(remote_buffer &&move) {
        std::swap(data, move.data);
        std::swap(dataLen, move.dataLen);
        return *this;
    }

    remote_buffer(const remote_buffer &) = delete;
    remote_buffer &operator=(const remote_buffer &) = delete;
};

extern "C" {

int halide_hexagon_remote_initialize_kernels(const unsigned char *code, int codeLen,
                                             handle_t *module_ptr) {
    int ret = init_sim();
    if (ret != 0) return -1;

    // Copy the pointer arguments to the simulator.
    remote_buffer remote_code(code, codeLen);
    remote_buffer remote_module_ptr(module_ptr, 4);

    // Run the init kernels command.
    ret = send_message(Message::InitKernels, {remote_code.data, codeLen, remote_module_ptr.data});
    if (ret != 0) return ret;

    // Get the module ptr.
    ret = read_memory(module_ptr, remote_module_ptr.data, 4);

    return ret;
}

handle_t halide_hexagon_remote_get_symbol(handle_t module_ptr, const char* name, int nameLen) {
    assert(sim);

    // Copy the pointer arguments to the simulator.
    remote_buffer remote_name(name, nameLen);

    // Run the init kernels command.
    handle_t ret = send_message(Message::GetSymbol, {static_cast<int>(module_ptr), remote_name.data, nameLen});

    return ret;
}

int halide_hexagon_remote_run(handle_t module_ptr, handle_t function,
                              const host_buffer *input_buffersPtrs, int input_buffersLen,
                              host_buffer *output_buffersPtrs, int output_buffersLen,
                              const host_buffer *input_scalarsPtrs, int input_scalarsLen) {
    assert(sim);

    std::vector<remote_buffer> remote_input_buffers;
    std::vector<remote_buffer> remote_output_buffers;
    std::vector<remote_buffer> remote_input_scalars;

    for (int i = 0; i < input_buffersLen; i++) {
        remote_input_buffers.emplace_back(input_buffersPtrs[i]);
    }
    for (int i = 0; i < output_buffersLen; i++) {
        remote_output_buffers.emplace_back(output_buffersPtrs[i]);
    }
    for (int i = 0; i < input_scalarsLen; i++) {
        remote_input_scalars.emplace_back(input_scalarsPtrs[i]);
    }

    // Copy the pointer arguments to the simulator.
    remote_buffer remote_input_buffersPtrs(&remote_input_buffers[0], input_buffersLen * sizeof(remote_buffer));
    remote_buffer remote_output_buffersPtrs(&remote_output_buffers[0], output_buffersLen * sizeof(remote_buffer));
    remote_buffer remote_input_scalarsPtrs(&remote_input_scalars[0], input_scalarsLen * sizeof(remote_buffer));

    HEX_8u_t cycles_begin = 0;
    sim->GetSimulatedCycleCount(&cycles_begin);

    // Run the init kernels command.
    int ret = send_message(
        Message::Run,
        {static_cast<int>(module_ptr), static_cast<int>(function),
         remote_input_buffersPtrs.data, input_buffersLen,
         remote_output_buffersPtrs.data, output_buffersLen,
         remote_input_scalarsPtrs.data, input_scalarsLen});
    if (ret != 0) return ret;

    HEX_8u_t cycles_end = 0;
    sim->GetSimulatedCycleCount(&cycles_end);

    if (getenv("HL_HEXAGON_SIM_CYCLES")) {
        int cycles = static_cast<int>(cycles_end - cycles_begin);
        printf("Hexagon simulator executed function 0x%x in %d cycles\n", function, cycles);
    }

    // Copy the outputs back.
    for (int i = 0; i < output_buffersLen; i++) {
        ret = read_memory(output_buffersPtrs[i].data, remote_output_buffers[i].data, output_buffersPtrs[i].dataLen);
        if (ret != 0) return ret;
    }

    return ret;
}

int halide_hexagon_remote_release_kernels(handle_t module_ptr, int codeLen) {
    // Print out sim statistics if desired.
    if (getenv("HL_HEXAGON_SIM_STATS")) {
        char Buf[4096];
        HEXAPI_Status status = sim->EmitPerfStatistics(0, 0, 0, 0, Buf, sizeof(Buf));
        if (status != HEX_STAT_SUCCESS) {
            printf("HexagonWrapper::EmitStatistics failed: %d\n", status);
        } else {
            // Print out the full stats
            printf("%s\n", Buf);
        }
    }
    return send_message(Message::ReleaseKernels, {static_cast<int>(module_ptr), codeLen});
}

}  // extern "C"
<|endoftext|>


<commit_before>///
/// @file  pi_deleglise_rivat_parallel2.cpp
/// @brief Parallel implementation of the Deleglise-Rivat prime
///        counting algorithm. Compared to
///        pi_deleglise_rivat_parallel1.cpp this version uses
///        compression (FactorTable & PiTable) to reduce the memory
///        usage.
///
///        This implementation is based on the paper:
///        Tomás Oliveira e Silva, Computing pi(x): the combinatorial
///        method, Revista do DETUA, vol. 4, no. 6, March 2006,
///        pp. 759-768.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <FactorTable.hpp>
#include <primecount-internal.hpp>
#include <generate.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>
#include "S2.hpp"

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

/// Calculate the contribution of the trivial leaves.
///
int64_t S2_trivial(int64_t x,
                   int64_t y,
                   int64_t z,
                   int64_t c,
                   PiTable& pi,
                   vector<int32_t>& primes,
                   int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== S2_trivial(x, y) ===" << endl;
    cout << "Computation of the trivial special leaves" << endl;
  }

  int64_t pi_y = pi[y];
  int64_t pi_sqrtz = pi[min(isqrt(z), y)];
  int64_t S2_total = 0;
  double time = get_wtime();

  // Find all trivial leaves: n = primes[b] * primes[l]
  // which satisfy phi(x / n), b - 1) = 1
  #pragma omp parallel for num_threads(threads) reduction(+: S2_total)
  for (int64_t b = max(c, pi_sqrtz + 1); b < pi_y; b++)
  {
    int64_t prime = primes[b];
    S2_total += pi_y - pi[max(x / (prime * prime), prime)];
  }

  if (print_status())
    print_result("S2_trivial", S2_total, time);

  return S2_total;
}

/// Calculate the contribution of the special leaves.
/// @pre y > 0 && c > 1
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t z,
           int64_t c,
           vector<int32_t>& primes,
           FactorTable<uint16_t>& factors,
           int threads)
{
  int64_t S2_total = 0;
  int64_t limit = z + 1;
  threads = validate_threads(threads, limit);
  PiTable pi(y);

  S2_total += S2_trivial(x, y, z, c, pi, primes, threads);
  S2_total += S2_easy(x, y, z, c, pi, primes, threads);
  S2_total += S2_sieve(x, y, z, c, pi, primes, factors, threads);

  return S2_total;
}

/// alpha is a tuning factor which should grow like (log(x))^3
/// for the Deleglise-Rivat prime counting algorithm.
///
double compute_alpha(int64_t x)
{
  double d = (double) x;
  double alpha = log(d) * log(d) * log(d) / 1200;
  return in_between(1, alpha, iroot<6>(x));
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat_parallel2(int64_t x, int threads)
{
  if (x < 2)
    return 0;

  double alpha = compute_alpha(x);
  int64_t y = (int64_t) (alpha * iroot<3>(x));
  int64_t z = x / y;

  if (print_status())
  {
    cout << endl;
    cout << "=== pi_deleglise_rivat_parallel2(x) ===" << endl;
    cout << "pi(x) = S1 + S2 + pi(y) - 1 - P2" << endl;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "c = " << PhiTiny::max_a() << endl;
    cout << "threads = " << validate_threads(threads) << endl;
  }

  int64_t p2 = P2(x, y, threads);
  vector<int32_t> primes = generate_primes(y);
  FactorTable<uint16_t> factors(y);

  int64_t pi_y = pi_bsearch(primes, y);
  int64_t c = min(pi_y, PhiTiny::max_a());
  int64_t s1 = S1(x, y, c, primes[c], factors, threads);
  int64_t s2 = S2(x, y, z, c, primes, factors, threads);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace primecount
<commit_msg>Moved S2_trivial(x, y) to S2_trivial.cpp<commit_after>///
/// @file  pi_deleglise_rivat_parallel2.cpp
/// @brief Parallel implementation of the Deleglise-Rivat prime
///        counting algorithm. Compared to
///        pi_deleglise_rivat_parallel1.cpp this version uses
///        compression (FactorTable & PiTable) to reduce the memory
///        usage.
///
///        This implementation is based on the paper:
///        Tomás Oliveira e Silva, Computing pi(x): the combinatorial
///        method, Revista do DETUA, vol. 4, no. 6, March 2006,
///        pp. 759-768.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <FactorTable.hpp>
#include <primecount-internal.hpp>
#include <generate.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>
#include "S2.hpp"

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

/// Calculate the contribution of the special leaves.
/// @pre y > 0 && c > 1
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t z,
           int64_t c,
           vector<int32_t>& primes,
           FactorTable<uint16_t>& factors,
           int threads)
{
  int64_t S2_total = 0;
  int64_t limit = z + 1;
  threads = validate_threads(threads, limit);
  PiTable pi(y);

  S2_total += S2_trivial(x, y, z, c, pi, primes, threads);
  S2_total += S2_easy(x, y, z, c, pi, primes, threads);
  S2_total += S2_sieve(x, y, z, c, pi, primes, factors, threads);

  return S2_total;
}

/// alpha is a tuning factor which should grow like (log(x))^3
/// for the Deleglise-Rivat prime counting algorithm.
///
double compute_alpha(int64_t x)
{
  double d = (double) x;
  double alpha = log(d) * log(d) * log(d) / 1200;
  return in_between(1, alpha, iroot<6>(x));
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat_parallel2(int64_t x, int threads)
{
  if (x < 2)
    return 0;

  double alpha = compute_alpha(x);
  int64_t y = (int64_t) (alpha * iroot<3>(x));
  int64_t z = x / y;

  if (print_status())
  {
    cout << endl;
    cout << "=== pi_deleglise_rivat_parallel2(x) ===" << endl;
    cout << "pi(x) = S1 + S2 + pi(y) - 1 - P2" << endl;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
    cout << "c = " << PhiTiny::max_a() << endl;
    cout << "threads = " << validate_threads(threads) << endl;
  }

  int64_t p2 = P2(x, y, threads);
  vector<int32_t> primes = generate_primes(y);
  FactorTable<uint16_t> factors(y);

  int64_t pi_y = pi_bsearch(primes, y);
  int64_t c = min(pi_y, PhiTiny::max_a());
  int64_t s1 = S1(x, y, c, primes[c], factors, threads);
  int64_t s2 = S2(x, y, z, c, primes, factors, threads);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace primecount
<|endoftext|>


<commit_before>/*
 * This software is distributed under BSD 3-clause license (see LICENSE file).
 *
 * Authors: Soeren Sonnenburg, Giovanni De Toni, Viktor Gal, Heiko Strathmann,
 *          Thoralf Klein, Evangelos Anagnostopoulos, Weijie Lin, Bjoern Esser,
 *          Saurabh Goyal
 */

#define SPDLOG_NO_NAME
#define SPDLOG_NO_THREAD_ID
#define SPDLOG_DISABLE_DEFAULT_LOGGER
#define SPDLOG_CLOCK_COARSE

#include <shogun/io/SGIO.h>
#include <shogun/lib/common.h>
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
#include <spdlog/async_logger.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/sinks/null_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>

using namespace shogun;
using namespace shogun::io;

class Formatter : public spdlog::formatter
{
public:
	Formatter(bool syntax_highlight)
	{
		if (syntax_highlight)
			formatter_ = std::make_unique<spdlog::pattern_formatter>(
			    "[%D %T %^%l%$] ", spdlog::pattern_time_type::local, "");
		else
			formatter_ = std::make_unique<spdlog::pattern_formatter>(
			    "[%D %T %l] ", spdlog::pattern_time_type::local, "");
	}

	Formatter(const Formatter& orig) : formatter_(orig.formatter_->clone())
	{
	}

	void format(
	    const spdlog::details::log_msg& msg, fmt::memory_buffer& dest) override
	{
		using namespace spdlog::details::fmt_helper;
		if (static_cast<EMessageType>(msg.level) == MSG_MESSAGEONLY)
		{
			append_string_view(msg.payload, dest);
		}
		else
		{
			formatter_->format(msg, dest);
			if (!msg.source.empty())
			{
				dest.push_back('[');
				// show filename and line only in debug build
#ifdef DEBUG_BUILD
				append_string_view(msg.source.filename, dest);
				dest.push_back(':');
				append_int(msg.source.line, dest);
				dest.push_back(' ');
#endif
				append_string_view(msg.source.funcname, dest);
				dest.push_back(']');
				dest.push_back(' ');
			}
			append_string_view(msg.payload, dest);
			dest.push_back('\n');
		}
	}

	std::unique_ptr<spdlog::formatter> clone() const override
	{
		return std::make_unique<Formatter>(*this);
	}

private:
	std::unique_ptr<spdlog::formatter> formatter_;
};

class SGIO::RedirectSink : public spdlog::sinks::base_sink<std::mutex>
{
public:
	RedirectSink()
	{
		stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
		stderr_sink = stdout_sink;
	}

	void redirect_stdout(std::shared_ptr<spdlog::sinks::sink> sink_)
	{
		set_sink_(stdout_sink, sink_);
	}

	void redirect_stderr(std::shared_ptr<spdlog::sinks::sink> sink_)
	{
		set_sink_(stderr_sink, sink_);
	}

protected:
	void sink_it_(const spdlog::details::log_msg& msg) override
	{
		if (msg.level == spdlog::level::err)
			stderr_sink->log(msg);
		else
			stdout_sink->log(msg);
	}

	void flush_() override
	{
		stdout_sink->flush();
		if (stdout_sink != stderr_sink)
			stderr_sink->flush();
	}

	void
	set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override
	{
		if (stdout_sink != stderr_sink)
			stderr_sink->set_formatter(sink_formatter->clone());
		stdout_sink->set_formatter(std::move(sink_formatter));
	}

private:
	void set_sink_(
	    std::shared_ptr<spdlog::sinks::sink>& old_sink,
	    const std::shared_ptr<spdlog::sinks::sink>& new_sink)
	{
		std::lock_guard<std::mutex> lock(mutex_);
		flush_();
		if (new_sink)
			old_sink = new_sink;
		else
			old_sink = std::make_shared<spdlog::sinks::null_sink_mt>();
	}

	std::shared_ptr<spdlog::sinks::sink> stdout_sink;
	std::shared_ptr<spdlog::sinks::sink> stderr_sink;
};

SGIO::SGIO() : show_progress(false)
{
	init_default_sink();
	init_default_logger();
}

void SGIO::init_default_logger(uint64_t queue_size, uint64_t n_threads)
{
	thread_pool =
	    std::make_shared<spdlog::details::thread_pool>(queue_size, n_threads);
	io_logger = std::make_shared<spdlog::async_logger>(
	    "sg_global", io_sink, thread_pool,
	    spdlog::async_overflow_policy::block);
}

void SGIO::init_default_sink()
{
	io_sink = std::make_shared<RedirectSink>();
	if (io_logger)
	{
		io_logger->sinks().clear();
		io_logger->sinks().push_back(io_sink);
	}
	io_sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

void SGIO::message_(
    EMessageType prio, const SourceLocation& loc,
    const fmt::string_view& msg) const
{
	io_logger->log(
	    {loc.file, loc.line, loc.function},
	    static_cast<spdlog::level::level_enum>(prio), msg);
}

EMessageType SGIO::get_loglevel() const
{
	return static_cast<EMessageType>(io_logger->level());
}

void SGIO::set_loglevel(EMessageType level)
{
	io_logger->set_level(static_cast<spdlog::level::level_enum>(level));
}

char* SGIO::c_string_of_substring(substring s)
{
	uint32_t len = s.end - s.start + 1;
	char* ret = SG_CALLOC(char, len);
	sg_memcpy(ret, s.start, len - 1);
	return ret;
}

float32_t SGIO::float_of_substring(substring s)
{
	char* endptr = s.end;
	float32_t f = strtof(s.start, &endptr);
	if (endptr == s.start && s.start != s.end)
		error("{} is not a float!", c_string_of_substring(s));

	return f;
}

float64_t SGIO::double_of_substring(substring s)
{
	char* endptr = s.end;
	float64_t f = strtod(s.start, &endptr);
	if (endptr == s.start && s.start != s.end)
		error("{} is not a double!", c_string_of_substring(s));

	return f;
}

int32_t SGIO::int_of_substring(substring s)
{
	char* c_string = c_string_of_substring(s);
	int32_t int_val = atoi(c_string);
	SG_FREE(c_string);

	return int_val;
}

uint32_t SGIO::ulong_of_substring(substring s)
{
	return strtoul(s.start, NULL, 10);
}

uint32_t SGIO::ss_length(substring s)
{
	return (s.end - s.start);
}

SGIO::~SGIO()
{
	io_logger->flush();
}

void SGIO::redirect_stdout(std::shared_ptr<spdlog::sinks::sink> sink)
{
	io_sink->redirect_stdout(sink);
	sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

void SGIO::redirect_stderr(std::shared_ptr<spdlog::sinks::sink> sink)
{
	io_sink->redirect_stderr(sink);
	sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

bool SGIO::should_log(EMessageType prio) const
{
	return io_logger->should_log(static_cast<spdlog::level::level_enum>(prio));
}

void SGIO::enable_syntax_highlighting()
{
	syntax_highlight = true;
	io_sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

void SGIO::disable_syntax_highlighting()
{
	syntax_highlight = false;
	io_sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}
<commit_msg>fix SGIO Formatter for spdlog 1.4.x or later<commit_after>/*
 * This software is distributed under BSD 3-clause license (see LICENSE file).
 *
 * Authors: Soeren Sonnenburg, Giovanni De Toni, Viktor Gal, Heiko Strathmann,
 *          Thoralf Klein, Evangelos Anagnostopoulos, Weijie Lin, Bjoern Esser,
 *          Saurabh Goyal
 */

#define SPDLOG_NO_NAME
#define SPDLOG_NO_THREAD_ID
#define SPDLOG_DISABLE_DEFAULT_LOGGER
#define SPDLOG_CLOCK_COARSE

#include <shogun/io/SGIO.h>
#include <shogun/lib/common.h>
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
#include <spdlog/async_logger.h>
#include <spdlog/sinks/base_sink.h>
#include <spdlog/sinks/null_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/version.h>

using namespace shogun;
using namespace shogun::io;

class Formatter : public spdlog::formatter
{
public:
#if ((SPDLOG_VER_MAJOR == 1) && (SPDLOG_VER_MINOR < 4))
	using mem_buffer = fmt::memory_buffer;
#else
	using mem_buffer = spdlog::memory_buf_t;
#endif

	Formatter(bool syntax_highlight)
	{
		if (syntax_highlight)
			formatter_ = std::make_unique<spdlog::pattern_formatter>(
			    "[%D %T %^%l%$] ", spdlog::pattern_time_type::local, "");
		else
			formatter_ = std::make_unique<spdlog::pattern_formatter>(
			    "[%D %T %l] ", spdlog::pattern_time_type::local, "");
	}

	Formatter(const Formatter& orig) : formatter_(orig.formatter_->clone())
	{
	}

	void format(
	    const spdlog::details::log_msg& msg, mem_buffer& dest) override
	{
		using namespace spdlog::details::fmt_helper;
		if (static_cast<EMessageType>(msg.level) == MSG_MESSAGEONLY)
		{
			append_string_view(msg.payload, dest);
		}
		else
		{
			formatter_->format(msg, dest);
			if (!msg.source.empty())
			{
				dest.push_back('[');
				// show filename and line only in debug build
#ifdef DEBUG_BUILD
				append_string_view(msg.source.filename, dest);
				dest.push_back(':');
				append_int(msg.source.line, dest);
				dest.push_back(' ');
#endif
				append_string_view(msg.source.funcname, dest);
				dest.push_back(']');
				dest.push_back(' ');
			}
			append_string_view(msg.payload, dest);
			dest.push_back('\n');
		}
	}

	std::unique_ptr<spdlog::formatter> clone() const override
	{
		return std::make_unique<Formatter>(*this);
	}

private:
	std::unique_ptr<spdlog::formatter> formatter_;
};

class SGIO::RedirectSink : public spdlog::sinks::base_sink<std::mutex>
{
public:
	RedirectSink()
	{
		stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
		stderr_sink = stdout_sink;
	}

	void redirect_stdout(std::shared_ptr<spdlog::sinks::sink> sink_)
	{
		set_sink_(stdout_sink, sink_);
	}

	void redirect_stderr(std::shared_ptr<spdlog::sinks::sink> sink_)
	{
		set_sink_(stderr_sink, sink_);
	}

protected:
	void sink_it_(const spdlog::details::log_msg& msg) override
	{
		if (msg.level == spdlog::level::err)
			stderr_sink->log(msg);
		else
			stdout_sink->log(msg);
	}

	void flush_() override
	{
		stdout_sink->flush();
		if (stdout_sink != stderr_sink)
			stderr_sink->flush();
	}

	void
	set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override
	{
		if (stdout_sink != stderr_sink)
			stderr_sink->set_formatter(sink_formatter->clone());
		stdout_sink->set_formatter(std::move(sink_formatter));
	}

private:
	void set_sink_(
	    std::shared_ptr<spdlog::sinks::sink>& old_sink,
	    const std::shared_ptr<spdlog::sinks::sink>& new_sink)
	{
		std::lock_guard<std::mutex> lock(mutex_);
		flush_();
		if (new_sink)
			old_sink = new_sink;
		else
			old_sink = std::make_shared<spdlog::sinks::null_sink_mt>();
	}

	std::shared_ptr<spdlog::sinks::sink> stdout_sink;
	std::shared_ptr<spdlog::sinks::sink> stderr_sink;
};

SGIO::SGIO() : show_progress(false)
{
	init_default_sink();
	init_default_logger();
}

void SGIO::init_default_logger(uint64_t queue_size, uint64_t n_threads)
{
	thread_pool =
	    std::make_shared<spdlog::details::thread_pool>(queue_size, n_threads);
	io_logger = std::make_shared<spdlog::async_logger>(
	    "sg_global", io_sink, thread_pool,
	    spdlog::async_overflow_policy::block);
}

void SGIO::init_default_sink()
{
	io_sink = std::make_shared<RedirectSink>();
	if (io_logger)
	{
		io_logger->sinks().clear();
		io_logger->sinks().push_back(io_sink);
	}
	io_sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

void SGIO::message_(
    EMessageType prio, const SourceLocation& loc,
    const fmt::string_view& msg) const
{
	io_logger->log(
	    {loc.file, loc.line, loc.function},
	    static_cast<spdlog::level::level_enum>(prio), msg);
}

EMessageType SGIO::get_loglevel() const
{
	return static_cast<EMessageType>(io_logger->level());
}

void SGIO::set_loglevel(EMessageType level)
{
	io_logger->set_level(static_cast<spdlog::level::level_enum>(level));
}

char* SGIO::c_string_of_substring(substring s)
{
	uint32_t len = s.end - s.start + 1;
	char* ret = SG_CALLOC(char, len);
	sg_memcpy(ret, s.start, len - 1);
	return ret;
}

float32_t SGIO::float_of_substring(substring s)
{
	char* endptr = s.end;
	float32_t f = strtof(s.start, &endptr);
	if (endptr == s.start && s.start != s.end)
		error("{} is not a float!", c_string_of_substring(s));

	return f;
}

float64_t SGIO::double_of_substring(substring s)
{
	char* endptr = s.end;
	float64_t f = strtod(s.start, &endptr);
	if (endptr == s.start && s.start != s.end)
		error("{} is not a double!", c_string_of_substring(s));

	return f;
}

int32_t SGIO::int_of_substring(substring s)
{
	char* c_string = c_string_of_substring(s);
	int32_t int_val = atoi(c_string);
	SG_FREE(c_string);

	return int_val;
}

uint32_t SGIO::ulong_of_substring(substring s)
{
	return strtoul(s.start, NULL, 10);
}

uint32_t SGIO::ss_length(substring s)
{
	return (s.end - s.start);
}

SGIO::~SGIO()
{
	io_logger->flush();
}

void SGIO::redirect_stdout(std::shared_ptr<spdlog::sinks::sink> sink)
{
	io_sink->redirect_stdout(sink);
	sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

void SGIO::redirect_stderr(std::shared_ptr<spdlog::sinks::sink> sink)
{
	io_sink->redirect_stderr(sink);
	sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

bool SGIO::should_log(EMessageType prio) const
{
	return io_logger->should_log(static_cast<spdlog::level::level_enum>(prio));
}

void SGIO::enable_syntax_highlighting()
{
	syntax_highlight = true;
	io_sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}

void SGIO::disable_syntax_highlighting()
{
	syntax_highlight = false;
	io_sink->set_formatter(std::make_unique<Formatter>(syntax_highlight));
}
<|endoftext|>


<commit_before>#include "functions.h"

axis_type set_axis_type(string &keyvalue){
  string saxis(toLower(keyvalue));
  int axOption(static_cast<int>(keyvalue));

  if(saxis == "colorf1f3")
    axOption = 0;
  else if(saxis == "colorf2f3")
    axOption = 1;
  else if(saxis == "colorf1f2")
    axOption = 2;
  else if(saxis == "flux1")
    axOption = 3;
  else if(saxis == "flux2")
    axOption = 4;
  else if(saxis == "flux3")
    axOption = 5;

  switch(axOption){
  case 0:
    return ColorF1F3;
  case 1:
    return ColorF2F3;
  case 2:
    return ColorF1F2;
  case 3:
    return Flux1;
  case 4:
    return Flux2;
  case 5:
    return Flux3;
  default:
    printf("set_axis_type: keyvalue \"%s\" invalid\n",keyvalue.c_str());
    throw(-1);
  }
}

double metric_value(const double& f1,const double &f2,const double &f3,const axis_type &opt){

  switch(opt){
  case ColorF1F3:
    return log10(f3/f1);
  case ColorF2F3:
    return log10(f3/f2);
  case ColorF1F2:
    return log10(f2/f1);
  case Flux1:
    return log10(f1);
  case Flux2:
    return log10(f2);
  case Flux3:
    return log10(f3);
  default:
    printf("Simulator::metric_value Error: Unknown option\n");
    return -99.0;
  }

}

string toLower(const string &oldstr){
  string newstr(oldstr);
  for(string::iterator it = newstr.begin(); it != newstr.end(); it++)
    *it = tolower(*it);
  return newstr;
}

Configuration::Configuration(int argc, char *argv[]){
  if(argc < 4){
    printf("ERROR: Invalid number of arguments.\n");
    printf("Calling sequence should be \"%s obsfile modfile sedfile [output]\"\n",argv[0]);
    exit(1);
  }

  char * ffile = getenv("FILTERFILE");
  if(ffile != NULL)
    filterfile = static_cast<string>(ffile);
  else
    filterfile = "/usr/local/surveysim/filters/filterlib.txt";

  //File names passed in by Widget
  obsfile = argv[1];
  modfile = argv[2];
  sedfile = argv[3];
  //If outfile specified as argument, change from default
  if(argc > 4)
    outfile = argv[4];
  else
    outfile = "output.fits";

  load();
}

void Configuration::print(){

  printf("\n>> Printing Configuration <<\n\n");
  //output found settings
  if(oprint)
    printf("Using Verbose Output\n\n");
  else
    printf("Using Concise Output\n\n");

  printf("File Settings:\n");
  printf("  Main Settings:  %s\n",modfile.c_str());
  printf("  SED library:    %s\n",sedfile.c_str());
  printf("  Observations:   %s\n",obsfile.c_str());
  printf("  Filter library: %s\n",filterfile.c_str());

  printf("\nMCMC Settings:\n");
  printf("  Chain Number         : %lu\n", nchain);
  printf("  Starting Temp        : %5.2f\n",tmax);
  printf("  Ideal Accept Pct     : %4.2f\n",idealpct);
  printf("  Burn-in Step         : %lu\n",burn_step);
  printf("  Convergence Step     : %lu\n",conv_step);
  printf("  Run:Burn-In          : %lu\n",burn_ratio);
  printf("  Convergence Criterion: %4.2f\n",rmax);
  printf("  Confidence Interval  : %4.2f\n",a_ci);

  printf("\nSimulation Settings:\n");
  printf("  Run Number Max       : %lu\n",runs);
  printf("  Number Redshift Bins : %i\n",nz);
  printf("  Redshift Bin Width   : %f\n",dz);
  printf("  Area [square deg]    : %f\n",area);

  string pnames[] = {"PHI0","L0","ALPHA","BETA","P","Q","ZCUT"};
  printf("\nLuminosity Function Parameter Settings:\n");
  printf("Parameter\tStart\t Min \t Max \tStep \tFit\n");
  for(int i=0;i<LUMPARS;i++){
    printf("%9s\t%5.2f\t%5.2f\t%5.2f\t%s\n",
	   pnames[i].c_str(),
	   LFParameters[i][value],
	   LFParameters[i][min],
	   LFParameters[i][max],
	   LFParameters[i][fixed] == 0.0 ? "True" : "False"
	   );
  }
  printf("%9s\t%5.2f\t%5.2f\t%5.2f\t%s\n\n",
	 "CEXP",
	 colorEvolution[value],
	 colorEvolution[min],
	 colorEvolution[max],
	 colorEvolution[fixed] == 0.0 ? "True" : "False"
	 );

  printf("\nNumber Unfixed Parameters: %lu\n",nparams);

}

double Configuration::areaSteradian(){
  return area*pow((M_PI/180.0),2.0);
}

void Configuration::LFparameters(double lpars[], short type){
  for(int i=0;i<LUMPARS;i++)
    lpars[i] = LFParameters[i][type];
}

void Configuration::load(){

  //IO variables
  string pnames[] = {"PHI0","L0","ALPHA","BETA","P","Q","ZCUT"};
  string suffix[] = {"","_FIX","_MIN","_MAX"};
  string tag;

  axes[0] = ColorF1F3;
  axes[1] = ColorF2F3;

  std::unique_ptr<CCfits::FITS> pInfile;
  try{
    pInfile.reset(new CCfits::FITS(modfile,CCfits::Read));
  }
  catch(...){
    printf("Error reading FITS file %s\n",modfile.c_str());
    exit(1);
  }

  string stemp;
  try{
    tab.readKey("AXIS1",stemp);
    axes[0] = set_axis_type(stemp);
  }
  catch(CCfits::HDU::NoSuchKeyword){
    printf("Keyword \"Axis1\" not specified, defaulting to ColorF1F3");
  }
  catch(-1){
    printf("Value of \"Axis1\" invalid, defaulting to ColorF1F3");
  }

  try{
    tab.readKey("AXIS2",stemp);
    axes[1] = set_axis_type(stemp);
  }
  catch(CCfits::HDU::NoSuchKeyword){
    printf("Keyword \"Axis2\" not specified, defaulting to ColorF2F3")
  }
  catch(-1){
    printf("Value of \"Axis2\" invalid, defaulting to ColorF2F3");
  }

  //reading primary header from fits file
  CCfits::HDU& tab = pInfile->pHDU();

  double rtemp;
  //Read in simulation settings
  tab.readKey("RUNS",rtemp);
  runs = static_cast<unsigned long>(rtemp);
  tab.readKey("ZMIN",zmin);
  tab.readKey("ZMAX",zmax);
  tab.readKey("DZ",dz);
  tab.readKey("AREA",area);

  tab.readKey("NCHAIN",rtemp);
  nchain = static_cast<unsigned long>(rtemp);
  tab.readKey("TMAX",tmax);
  tab.readKey("TSCALE",tscale);
  tab.readKey("ANN_PCT",idealpct);
  tab.readKey("ANN_RNG",annrng);
  tab.readKey("BURN_STE",rtemp);
  burn_step = static_cast<unsigned long>(rtemp);
  tab.readKey("CONV_STE",rtemp);
  conv_step = static_cast<unsigned long>(rtemp);
  tab.readKey("BURNVRUN",rtemp);
  burn_ratio = static_cast<unsigned long>(rtemp);
  tab.readKey("CONV_RMA",rmax);
  tab.readKey("CONV_CON",a_ci);
  tab.readKey("PRINT",rtemp);
  oprint = rtemp == 0.0 ? true : false;

  //compute redshift bin number from FITS values
  nz = (zmax-zmin)/dz;

  //=================================================================
  //Read-in Luminosity Function Parameters
  //-----------------------------------------------------------------

  for(int i=0;i<LUMPARS;i++){
    for(int j=0;j<4;j++){
      tag = pnames[i]+suffix[j];
      tag = tag.substr(0,8);
      tab.readKey(tag,LFParameters[i][j]);
    }
    if(LFParameters[i][fixed] == 0)
      param_inds.push_back(i);
  }

  //color evolution parameters
  for(int j=0;j<4;j++){
    tag = "CEXP"+suffix[j];
    tag = tag.substr(0,8);
    tab.readKey(tag,colorEvolution[j]);
  }

  nparams = param_inds.size();
  cind = nparams;
  if(colorEvolution[fixed] == 0){
    nparams++;
    vary_cexp = true;
  }
  else
    vary_cexp = false;

  burn_num = runs/burn_ratio;

}

RandomNumberGenerator::RandomNumberGenerator(){
  gsl_rng_default_seed=time(NULL);
  T=gsl_rng_default;
  r=gsl_rng_alloc(T);
}

RandomNumberGenerator::~RandomNumberGenerator(){
  gsl_rng_free (r);
}

double RandomNumberGenerator::gaussian(double mean, double sigma, double min, double max){
  static double temp;
  do{
    temp = mean+gsl_ran_gaussian(r,sigma);
  }while((temp < min) or (temp > max));

  return temp;
}

double RandomNumberGenerator::flat(double min, double max){
  return gsl_ran_flat(r,min,max);
}
<commit_msg>Fixed compilation error in functions<commit_after>#include "functions.h"

axis_type set_axis_type(string &keyvalue){
  string saxis(toLower(keyvalue));
  char axOption(saxis[0]);

  if(saxis == "colorf1f3")
    axOption = '0';
  else if(saxis == "colorf2f3")
    axOption = '1';
  else if(saxis == "colorf1f2")
    axOption = '2';
  else if(saxis == "flux1")
    axOption = '3';
  else if(saxis == "flux2")
    axOption = '4';
  else if(saxis == "flux3")
    axOption = '5';

  switch(axOption){
  case '0':
    return ColorF1F3;
  case '1':
    return ColorF2F3;
  case '2':
    return ColorF1F2;
  case '3':
    return Flux1;
  case '4':
    return Flux2;
  case '5':
    return Flux3;
  default:
    printf("set_axis_type: keyvalue \"%s\" invalid\n",keyvalue.c_str());
    throw(-1);
  }
}

double metric_value(const double& f1,const double &f2,const double &f3,const axis_type &opt){

  switch(opt){
  case ColorF1F3:
    return log10(f3/f1);
  case ColorF2F3:
    return log10(f3/f2);
  case ColorF1F2:
    return log10(f2/f1);
  case Flux1:
    return log10(f1);
  case Flux2:
    return log10(f2);
  case Flux3:
    return log10(f3);
  default:
    printf("Simulator::metric_value Error: Unknown option\n");
    return -99.0;
  }

}

string toLower(const string &oldstr){
  string newstr(oldstr);
  for(string::iterator it = newstr.begin(); it != newstr.end(); it++)
    *it = tolower(*it);
  return newstr;
}

Configuration::Configuration(int argc, char *argv[]){
  if(argc < 4){
    printf("ERROR: Invalid number of arguments.\n");
    printf("Calling sequence should be \"%s obsfile modfile sedfile [output]\"\n",argv[0]);
    exit(1);
  }

  char * ffile = getenv("FILTERFILE");
  if(ffile != NULL)
    filterfile = static_cast<string>(ffile);
  else
    filterfile = "/usr/local/surveysim/filters/filterlib.txt";

  //File names passed in by Widget
  obsfile = argv[1];
  modfile = argv[2];
  sedfile = argv[3];
  //If outfile specified as argument, change from default
  if(argc > 4)
    outfile = argv[4];
  else
    outfile = "output.fits";

  load();
}

void Configuration::print(){

  printf("\n>> Printing Configuration <<\n\n");
  //output found settings
  if(oprint)
    printf("Using Verbose Output\n\n");
  else
    printf("Using Concise Output\n\n");

  printf("File Settings:\n");
  printf("  Main Settings:  %s\n",modfile.c_str());
  printf("  SED library:    %s\n",sedfile.c_str());
  printf("  Observations:   %s\n",obsfile.c_str());
  printf("  Filter library: %s\n",filterfile.c_str());

  printf("\nMCMC Settings:\n");
  printf("  Chain Number         : %lu\n", nchain);
  printf("  Starting Temp        : %5.2f\n",tmax);
  printf("  Ideal Accept Pct     : %4.2f\n",idealpct);
  printf("  Burn-in Step         : %lu\n",burn_step);
  printf("  Convergence Step     : %lu\n",conv_step);
  printf("  Run:Burn-In          : %lu\n",burn_ratio);
  printf("  Convergence Criterion: %4.2f\n",rmax);
  printf("  Confidence Interval  : %4.2f\n",a_ci);

  printf("\nSimulation Settings:\n");
  printf("  Run Number Max       : %lu\n",runs);
  printf("  Number Redshift Bins : %i\n",nz);
  printf("  Redshift Bin Width   : %f\n",dz);
  printf("  Area [square deg]    : %f\n",area);

  string pnames[] = {"PHI0","L0","ALPHA","BETA","P","Q","ZCUT"};
  printf("\nLuminosity Function Parameter Settings:\n");
  printf("Parameter\tStart\t Min \t Max \tStep \tFit\n");
  for(int i=0;i<LUMPARS;i++){
    printf("%9s\t%5.2f\t%5.2f\t%5.2f\t%s\n",
	   pnames[i].c_str(),
	   LFParameters[i][value],
	   LFParameters[i][min],
	   LFParameters[i][max],
	   LFParameters[i][fixed] == 0.0 ? "True" : "False"
	   );
  }
  printf("%9s\t%5.2f\t%5.2f\t%5.2f\t%s\n\n",
	 "CEXP",
	 colorEvolution[value],
	 colorEvolution[min],
	 colorEvolution[max],
	 colorEvolution[fixed] == 0.0 ? "True" : "False"
	 );

  printf("\nNumber Unfixed Parameters: %lu\n",nparams);

}

double Configuration::areaSteradian(){
  return area*pow((M_PI/180.0),2.0);
}

void Configuration::LFparameters(double lpars[], short type){
  for(int i=0;i<LUMPARS;i++)
    lpars[i] = LFParameters[i][type];
}

void Configuration::load(){

  //IO variables
  string pnames[] = {"PHI0","L0","ALPHA","BETA","P","Q","ZCUT"};
  string suffix[] = {"","_FIX","_MIN","_MAX"};
  string tag;

  axes[0] = ColorF1F3;
  axes[1] = ColorF2F3;

  std::unique_ptr<CCfits::FITS> pInfile;
  try{
    pInfile.reset(new CCfits::FITS(modfile,CCfits::Read));
  }
  catch(...){
    printf("Error reading FITS file %s\n",modfile.c_str());
    exit(1);
  }

  //reading primary header from fits file
  CCfits::HDU& tab = pInfile->pHDU();

  string stemp;
  try{
    tab.readKey("AXIS1",stemp);
    axes[0] = set_axis_type(stemp);
  }
  catch(CCfits::HDU::NoSuchKeyword){
    printf("Keyword \"Axis1\" not specified, defaulting to ColorF1F3");
  }
  catch(...){
    printf("Value of \"Axis1\" invalid, defaulting to ColorF1F3");
  }

  try{
    tab.readKey("AXIS2",stemp);
    axes[1] = set_axis_type(stemp);
  }
  catch(CCfits::HDU::NoSuchKeyword){
    printf("Keyword \"Axis2\" not specified, defaulting to ColorF2F3");
  }
  catch(...){
    printf("Value of \"Axis2\" invalid, defaulting to ColorF2F3");
  }

  double rtemp;
  //Read in simulation settings
  tab.readKey("RUNS",rtemp);
  runs = static_cast<unsigned long>(rtemp);
  tab.readKey("ZMIN",zmin);
  tab.readKey("ZMAX",zmax);
  tab.readKey("DZ",dz);
  tab.readKey("AREA",area);

  tab.readKey("NCHAIN",rtemp);
  nchain = static_cast<unsigned long>(rtemp);
  tab.readKey("TMAX",tmax);
  tab.readKey("TSCALE",tscale);
  tab.readKey("ANN_PCT",idealpct);
  tab.readKey("ANN_RNG",annrng);
  tab.readKey("BURN_STE",rtemp);
  burn_step = static_cast<unsigned long>(rtemp);
  tab.readKey("CONV_STE",rtemp);
  conv_step = static_cast<unsigned long>(rtemp);
  tab.readKey("BURNVRUN",rtemp);
  burn_ratio = static_cast<unsigned long>(rtemp);
  tab.readKey("CONV_RMA",rmax);
  tab.readKey("CONV_CON",a_ci);
  tab.readKey("PRINT",rtemp);
  oprint = rtemp == 0.0 ? true : false;

  //compute redshift bin number from FITS values
  nz = (zmax-zmin)/dz;

  //=================================================================
  //Read-in Luminosity Function Parameters
  //-----------------------------------------------------------------

  for(int i=0;i<LUMPARS;i++){
    for(int j=0;j<4;j++){
      tag = pnames[i]+suffix[j];
      tag = tag.substr(0,8);
      tab.readKey(tag,LFParameters[i][j]);
    }
    if(LFParameters[i][fixed] == 0)
      param_inds.push_back(i);
  }

  //color evolution parameters
  for(int j=0;j<4;j++){
    tag = "CEXP"+suffix[j];
    tag = tag.substr(0,8);
    tab.readKey(tag,colorEvolution[j]);
  }

  nparams = param_inds.size();
  cind = nparams;
  if(colorEvolution[fixed] == 0){
    nparams++;
    vary_cexp = true;
  }
  else
    vary_cexp = false;

  burn_num = runs/burn_ratio;

}

RandomNumberGenerator::RandomNumberGenerator(){
  gsl_rng_default_seed=time(NULL);
  T=gsl_rng_default;
  r=gsl_rng_alloc(T);
}

RandomNumberGenerator::~RandomNumberGenerator(){
  gsl_rng_free (r);
}

double RandomNumberGenerator::gaussian(double mean, double sigma, double min, double max){
  static double temp;
  do{
    temp = mean+gsl_ran_gaussian(r,sigma);
  }while((temp < min) or (temp > max));

  return temp;
}

double RandomNumberGenerator::flat(double min, double max){
  return gsl_ran_flat(r,min,max);
}
<|endoftext|>


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

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "scene.h"

#include "geometryvisitor.h"

#include <Eigen/Geometry>

namespace Avogadro {
namespace Rendering {

Scene::Scene() : m_center(Vector3f::Zero()), m_radius(4.0f)
{
}

Scene::~Scene()
{
}

Vector3f Scene::center()
{
  GeometryVisitor visitor;
  m_rootNode.accept(visitor);

  // For an empty scene ensure that a minimum radius of 4.0 (gives space).
  m_center = visitor.center();
  m_radius = std::max(4.0f, visitor.radius());

  return m_center;
}

float Scene::radius()
{
  // We need to know where the center is to get the radius
  center();
  return m_radius;
}

void Scene::clear()
{
  m_rootNode.clear();
}

} // End Rendering namespace
} // End Avogadro namespace
<commit_msg>Add a little padding to the radius<commit_after>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "scene.h"

#include "geometryvisitor.h"

#include <Eigen/Geometry>

namespace Avogadro {
namespace Rendering {

Scene::Scene() : m_center(Vector3f::Zero()), m_radius(4.0f)
{
}

Scene::~Scene()
{
}

Vector3f Scene::center()
{
  GeometryVisitor visitor;
  m_rootNode.accept(visitor);

  // For an empty scene ensure that a minimum radius of 4.0 (gives space).
  m_center = visitor.center();
  m_radius = std::max(4.0f, visitor.radius()) + 2.0f;

  return m_center;
}

float Scene::radius()
{
  // We need to know where the center is to get the radius
  center();
  return m_radius;
}

void Scene::clear()
{
  m_rootNode.clear();
}

} // End Rendering namespace
} // End Avogadro namespace
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char * argv[]) {
  bool localMem = false;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  AstroData::Observation observation;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    localMem = args.getSwitch("-local");
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-local] -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);
  std::vector< int > * shifts = PulsarSearch::getShifts(observation);

  observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + (*shifts)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]);

	// Allocate memory
  cl::Buffer shifts_d;
  std::vector< dataType > dispersedData = std::vector< dataType >(observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel());
  cl::Buffer dispersedData_d;
  std::vector< dataType > dedispersedData = std::vector< dataType >(observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  cl::Buffer dedispersedData_d;
  try {
    shifts_d = cl::Buffer(*clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(int), 0, 0);
    dispersedData_d = cl::Buffer(*clContext, CL_MEM_READ_ONLY, dispersedData.size() * sizeof(dataType), 0, 0);
    dedispersedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, dedispersedData.size() * sizeof(dataType), 0, 0);
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
	for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerDispersedChannel(); sample++ ) {
      dispersedData[(channel * observation.getNrSamplesPerDispersedChannel()) + sample] = static_cast< dataType >(rand() % 10);
		}
	}

  // Copy data structures to device
  try {
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(shifts_d, CL_FALSE, 0, shifts->size() * sizeof(int), reinterpret_cast< void * >(shifts->data()));
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(dispersedData_d, CL_FALSE, 0, dispersedData.size() * sizeof(dataType), reinterpret_cast< void * >(dispersedData.data()));
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples local samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread unroll GFLOP/s GB/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
			if ( ((*samples) * (*DMs)) > maxThreads ) {
				break;
			} else if ( ((*samples) * (*DMs)) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
				if ( (observation.getNrSamplesPerPaddedSecond() % ((*samples) * samplesPerThread)) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
					if ( (observation.getNrDMs() % ((*DMs) * DMsPerThread)) != 0 ) {
						continue;
					} else if ( (samplesPerThread * DMsPerThread) > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            if ( observation.getNrChannels() % unroll != 0 ) {
              continue;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            double gbs = isa::utils::giga(((static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrSamplesPerSecond() * (observation.getNrChannels() + 1)) * sizeof(dataType)) + ((observation.getNrDMs() * observation.getNrChannels()) * sizeof(unsigned int)));
            isa::utils::Timer timer;
            cl::Event event;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(localMem, *samples, *DMs, samplesPerThread, DMsPerThread, unroll, typeName, observation, *shifts);

            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              continue;
            }

            cl::NDRange global(observation.getNrSamplesPerPaddedSecond() / samplesPerThread, observation.getNrDMs() / DMsPerThread);
            cl::NDRange local(*samples, *DMs);

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            // Warm-up run
            try {
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
              continue;
            }
            // Tuning runs
            try {
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
              continue;
            }

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " " << localMem << " " << *samples << " " << *DMs << " " << samplesPerThread << " " << DMsPerThread << " " << unroll << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << gbs / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

<commit_msg>If there are too many variables and unrolling takes place, some GPU crash.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char * argv[]) {
  bool localMem = false;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    localMem = args.getSwitch("-local");
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-local] -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);
  std::vector< int > * shifts = PulsarSearch::getShifts(observation);

  observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + (*shifts)[((observation.getNrDMs() - 1) * observation.getNrPaddedChannels())]);

	// Allocate memory
  cl::Buffer shifts_d;
  std::vector< dataType > dispersedData = std::vector< dataType >(observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel());
  cl::Buffer dispersedData_d;
  std::vector< dataType > dedispersedData = std::vector< dataType >(observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  cl::Buffer dedispersedData_d;
  try {
    shifts_d = cl::Buffer(*clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(int), 0, 0);
    dispersedData_d = cl::Buffer(*clContext, CL_MEM_READ_ONLY, dispersedData.size() * sizeof(dataType), 0, 0);
    dedispersedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, dedispersedData.size() * sizeof(dataType), 0, 0);
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
	for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ ) {
		for ( unsigned int sample = 0; sample < observation.getNrSamplesPerDispersedChannel(); sample++ ) {
      dispersedData[(channel * observation.getNrSamplesPerDispersedChannel()) + sample] = static_cast< dataType >(rand() % 10);
		}
	}

  // Copy data structures to device
  try {
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(shifts_d, CL_FALSE, 0, shifts->size() * sizeof(int), reinterpret_cast< void * >(shifts->data()));
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(dispersedData_d, CL_FALSE, 0, dispersedData.size() * sizeof(dataType), reinterpret_cast< void * >(dispersedData.data()));
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString(err.err()) << "." << std::endl;
    return 1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples local samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread unroll GFLOP/s GB/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
			if ( ((*samples) * (*DMs)) > maxThreads ) {
				break;
			} else if ( ((*samples) * (*DMs)) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
				if ( (observation.getNrSamplesPerPaddedSecond() % ((*samples) * samplesPerThread)) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
					if ( (observation.getNrDMs() % ((*DMs) * DMsPerThread)) != 0 ) {
						continue;
					} else if ( (samplesPerThread * DMsPerThread) > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            if ( observation.getNrChannels() % unroll != 0 ) {
              continue;
            } else if ( (samplesPerThread * DMsPerThread * unroll) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            double gbs = isa::utils::giga(((static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrSamplesPerSecond() * (observation.getNrChannels() + 1)) * sizeof(dataType)) + ((observation.getNrDMs() * observation.getNrChannels()) * sizeof(unsigned int)));
            isa::utils::Timer timer;
            cl::Event event;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(localMem, *samples, *DMs, samplesPerThread, DMsPerThread, unroll, typeName, observation, *shifts);

            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              continue;
            }

            cl::NDRange global(observation.getNrSamplesPerPaddedSecond() / samplesPerThread, observation.getNrDMs() / DMsPerThread);
            cl::NDRange local(*samples, *DMs);

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            // Warm-up run
            try {
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
              continue;
            }
            // Tuning runs
            try {
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution: " << isa::utils::toString(err.err()) << "." << std::endl;
              continue;
            }

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " " << localMem << " " << *samples << " " << *DMs << " " << samplesPerThread << " " << DMsPerThread << " " << unroll << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << gbs / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

<|endoftext|>


<commit_before>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "EratMedium.h"
#include "SieveOfEratosthenes.h"
#include "SieveOfEratosthenes-inline.h"
#include "EratBase.h"
#include "WheelFactorization.h"
#include "config.h"

#include <stdint.h>
#include <stdexcept>
#include <algorithm>
#include <list>

namespace soe {

EratMedium::EratMedium(const SieveOfEratosthenes& soe) :
  EratBase<Modulo210Wheel_t>(soe)
{
  // Conditions that assert multipleIndex < 2^23 in sieve()
  static_assert(config::FACTOR_ERATMEDIUM <= 6, "config::FACTOR_ERATMEDIUM must not be > 6");
  if (soe.getSieveSize() > (1U << 22))
    throw std::overflow_error("EratMedium: sieveSize must be <= 2^22, 4096 kilobytes.");
  uint_t sqrtStop = soe.getSquareRoot();
  uint_t max      = soe.getSieveSize() * config::FACTOR_ERATMEDIUM;
  uint_t limit    = std::min(sqrtStop, max);
  this->setLimit(limit);
}

/// Implementation of the segmented sieve of Eratosthenes with wheel
/// factorization optimized for medium sieving primes that have a
/// few multiples per segment. This implementation uses a sieve array
/// with 30 numbers per byte and a modulo 210 wheel that skips
/// multiples of 2, 3, 5 and 7.
/// @see SieveOfEratosthenes::crossOffMultiples()
///
void EratMedium::sieve(uint8_t* sieve, uint_t sieveSize)
{
  for (BucketList_t::iterator bucket = buckets_.begin(); bucket != buckets_.end(); ++bucket) {
    WheelPrime* wPrime    = bucket->begin();
    WheelPrime* const end = bucket->end();
    // 2 sieving primes are processed per loop iteration to break the
    // dependency chain and reduce pipeline stalls
    for (; wPrime + 2 <= end; wPrime += 2) {
      uint_t multipleIndex0 = wPrime[0].getMultipleIndex();
      uint_t wheelIndex0    = wPrime[0].getWheelIndex();
      uint_t sievingPrime0  = wPrime[0].getSievingPrime();
      uint_t multipleIndex1 = wPrime[1].getMultipleIndex();
      uint_t wheelIndex1    = wPrime[1].getWheelIndex();
      uint_t sievingPrime1  = wPrime[1].getSievingPrime();
      while (multipleIndex0 < sieveSize) {
        // cross-off the current multiple (unset bit) of sievingPrime0
        // and sievingPrime1 and calculate their next multiple
        sieve[multipleIndex0] &= wheel(wheelIndex0).unsetBit;
        multipleIndex0        += wheel(wheelIndex0).nextMultipleFactor * sievingPrime0;
        multipleIndex0        += wheel(wheelIndex0).correct;
        wheelIndex0           += wheel(wheelIndex0).next;
        if (multipleIndex1 >= sieveSize) break;
        sieve[multipleIndex1] &= wheel(wheelIndex1).unsetBit;
        multipleIndex1        += wheel(wheelIndex1).nextMultipleFactor * sievingPrime1;
        multipleIndex1        += wheel(wheelIndex1).correct;
        wheelIndex1           += wheel(wheelIndex1).next;
      }
      while (multipleIndex0 < sieveSize) {
        sieve[multipleIndex0] &= wheel(wheelIndex0).unsetBit;
        multipleIndex0        += wheel(wheelIndex0).nextMultipleFactor * sievingPrime0;
        multipleIndex0        += wheel(wheelIndex0).correct;
        wheelIndex0           += wheel(wheelIndex0).next;
      }
      while (multipleIndex1 < sieveSize) {
        sieve[multipleIndex1] &= wheel(wheelIndex1).unsetBit;
        multipleIndex1        += wheel(wheelIndex1).nextMultipleFactor * sievingPrime1;
        multipleIndex1        += wheel(wheelIndex1).correct;
        wheelIndex1           += wheel(wheelIndex1).next;
      }
      multipleIndex0 -= sieveSize;
      multipleIndex1 -= sieveSize;
      // set the multipleIndex and wheelIndex for the next segment
      wPrime[0].set(multipleIndex0, wheelIndex0);
      wPrime[1].set(multipleIndex1, wheelIndex1);
    }
    if (wPrime != end) {
      uint_t multipleIndex = wPrime->getMultipleIndex();
      uint_t wheelIndex    = wPrime->getWheelIndex();
      uint_t sievingPrime  = wPrime->getSievingPrime();
      while (multipleIndex < sieveSize) {
        sieve[multipleIndex] &= wheel(wheelIndex).unsetBit;
        multipleIndex        += wheel(wheelIndex).nextMultipleFactor * sievingPrime;
        multipleIndex        += wheel(wheelIndex).correct;
        wheelIndex           += wheel(wheelIndex).next;
      }
      multipleIndex -= sieveSize;
      wPrime->set(multipleIndex, wheelIndex);
    }
  }
}

} // namespace soe
<commit_msg>improved code readability<commit_after>//
// Copyright (c) 2012 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "EratMedium.h"
#include "SieveOfEratosthenes.h"
#include "SieveOfEratosthenes-inline.h"
#include "EratBase.h"
#include "WheelFactorization.h"
#include "config.h"

#include <stdint.h>
#include <stdexcept>
#include <algorithm>
#include <list>

namespace soe {

EratMedium::EratMedium(const SieveOfEratosthenes& soe) :
  EratBase<Modulo210Wheel_t>(soe)
{
  // Conditions that assert multipleIndex < 2^23 in sieve()
  static_assert(config::FACTOR_ERATMEDIUM <= 6, "config::FACTOR_ERATMEDIUM must not be > 6");
  if (soe.getSieveSize() > (1u << 22))
    throw std::overflow_error("EratMedium: sieveSize must be <= 2^22, 4096 kilobytes.");
  uint_t sqrtStop = soe.getSquareRoot();
  uint_t max      = soe.getSieveSize() * config::FACTOR_ERATMEDIUM;
  uint_t limit    = std::min(sqrtStop, max);
  this->setLimit(limit);
}

/// Implementation of the segmented sieve of Eratosthenes with wheel
/// factorization optimized for medium sieving primes that have a
/// few multiples per segment. This implementation uses a sieve array
/// with 30 numbers per byte and a modulo 210 wheel that skips
/// multiples of 2, 3, 5 and 7.
/// @see SieveOfEratosthenes::crossOffMultiples()
///
void EratMedium::sieve(uint8_t* sieve, uint_t sieveSize)
{
  for (BucketList_t::iterator bucket = buckets_.begin(); bucket != buckets_.end(); ++bucket) {
    WheelPrime* wPrime    = bucket->begin();
    WheelPrime* const end = bucket->end();
    // 2 sieving primes are processed per loop iteration to break the
    // dependency chain and reduce pipeline stalls
    for (; wPrime + 2 <= end; wPrime += 2) {
      uint_t multipleIndex0 = wPrime[0].getMultipleIndex();
      uint_t wheelIndex0    = wPrime[0].getWheelIndex();
      uint_t sievingPrime0  = wPrime[0].getSievingPrime();
      uint_t multipleIndex1 = wPrime[1].getMultipleIndex();
      uint_t wheelIndex1    = wPrime[1].getWheelIndex();
      uint_t sievingPrime1  = wPrime[1].getSievingPrime();
      while (multipleIndex0 < sieveSize) {
        // cross-off the current multiple (unset bit) of sievingPrime0
        // and sievingPrime1 and calculate their next multiple
        sieve[multipleIndex0] &= wheel(wheelIndex0).unsetBit;
        multipleIndex0        += wheel(wheelIndex0).nextMultipleFactor * sievingPrime0;
        multipleIndex0        += wheel(wheelIndex0).correct;
        wheelIndex0           += wheel(wheelIndex0).next;
        if (multipleIndex1 >= sieveSize) break;
        sieve[multipleIndex1] &= wheel(wheelIndex1).unsetBit;
        multipleIndex1        += wheel(wheelIndex1).nextMultipleFactor * sievingPrime1;
        multipleIndex1        += wheel(wheelIndex1).correct;
        wheelIndex1           += wheel(wheelIndex1).next;
      }
      while (multipleIndex0 < sieveSize) {
        sieve[multipleIndex0] &= wheel(wheelIndex0).unsetBit;
        multipleIndex0        += wheel(wheelIndex0).nextMultipleFactor * sievingPrime0;
        multipleIndex0        += wheel(wheelIndex0).correct;
        wheelIndex0           += wheel(wheelIndex0).next;
      }
      while (multipleIndex1 < sieveSize) {
        sieve[multipleIndex1] &= wheel(wheelIndex1).unsetBit;
        multipleIndex1        += wheel(wheelIndex1).nextMultipleFactor * sievingPrime1;
        multipleIndex1        += wheel(wheelIndex1).correct;
        wheelIndex1           += wheel(wheelIndex1).next;
      }
      multipleIndex0 -= sieveSize;
      multipleIndex1 -= sieveSize;
      // set the multipleIndex and wheelIndex for the next segment
      wPrime[0].set(multipleIndex0, wheelIndex0);
      wPrime[1].set(multipleIndex1, wheelIndex1);
    }
    if (wPrime != end) {
      uint_t multipleIndex = wPrime->getMultipleIndex();
      uint_t wheelIndex    = wPrime->getWheelIndex();
      uint_t sievingPrime  = wPrime->getSievingPrime();
      while (multipleIndex < sieveSize) {
        sieve[multipleIndex] &= wheel(wheelIndex).unsetBit;
        multipleIndex        += wheel(wheelIndex).nextMultipleFactor * sievingPrime;
        multipleIndex        += wheel(wheelIndex).correct;
        wheelIndex           += wheel(wheelIndex).next;
      }
      multipleIndex -= sieveSize;
      wPrime->set(multipleIndex, wheelIndex);
    }
  }
}

} // namespace soe
<|endoftext|>