<commit_before>//------------------------------------------------------------------------------
//  imgui-emsc
//  Demonstrates basic integration with Dear Imgui (without custom
//  texture or custom font support).
//  Since emscripten is using clang exclusively, we can use designated
//  initializers even though this is C++.
//------------------------------------------------------------------------------
#include "imgui.h"
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#define SOKOL_IMPL
#define SOKOL_GLES2
#include "sokol_gfx.h"
#include "sokol_time.h"
#include "emsc.h"

const int MaxVertices = (1<<16);
const int MaxIndices = MaxVertices * 3;

uint64_t last_time = 0;
bool show_test_window = true;
bool show_another_window = false;

sg_draw_state draw_state = { };
sg_pass_action pass_action = { };
bool btn_down[3] = { };
bool btn_up[3] = { };
ImDrawVert vertices[MaxVertices];
uint16_t indices[MaxIndices];

typedef struct {
    ImVec2 disp_size;
} vs_params_t;

void draw();
void imgui_draw_cb(ImDrawData*);

int main() {
    /* setup WebGL context */
    emsc_init("#canvas", EMSC_NONE);

    /* setup sokol_gfx and sokol_time */
    stm_setup();
    sg_desc desc = { };
    sg_setup(&desc);
    assert(sg_isvalid());

    // setup the ImGui environment
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGuiIO& io = ImGui::GetIO();
    io.IniFilename = nullptr;
    io.RenderDrawListsFn = imgui_draw_cb;
    io.Fonts->AddFontDefault();
    // emscripten has no clearly defined key code constants
    io.KeyMap[ImGuiKey_Tab] = 9;
    io.KeyMap[ImGuiKey_LeftArrow] = 37;
    io.KeyMap[ImGuiKey_RightArrow] = 39;
    io.KeyMap[ImGuiKey_UpArrow] = 38;
    io.KeyMap[ImGuiKey_DownArrow] = 40;
    io.KeyMap[ImGuiKey_Home] = 36;
    io.KeyMap[ImGuiKey_End] = 35;
    io.KeyMap[ImGuiKey_Delete] = 46;
    io.KeyMap[ImGuiKey_Backspace] = 8;
    io.KeyMap[ImGuiKey_Enter] = 13;
    io.KeyMap[ImGuiKey_Escape] = 27;
    io.KeyMap[ImGuiKey_A] = 65;
    io.KeyMap[ImGuiKey_C] = 67;
    io.KeyMap[ImGuiKey_V] = 86;
    io.KeyMap[ImGuiKey_X] = 88;
    io.KeyMap[ImGuiKey_Y] = 89;
    io.KeyMap[ImGuiKey_Z] = 90;

    // emscripten to ImGui input forwarding
    emscripten_set_keydown_callback(0, nullptr, true,
        [](int, const EmscriptenKeyboardEvent* e, void*)->EM_BOOL {
            if (e->keyCode < 512) {
                ImGui::GetIO().KeysDown[e->keyCode] = true;
            }
            // only forward alpha-numeric keys to browser
            return e->keyCode < 32;
        });
    emscripten_set_keyup_callback(0, nullptr, true,
        [](int, const EmscriptenKeyboardEvent* e, void*)->EM_BOOL {
            if (e->keyCode < 512) {
                ImGui::GetIO().KeysDown[e->keyCode] = false;
            }
            // only forward alpha-numeric keys to browser
            return e->keyCode < 32;
        });
    emscripten_set_keypress_callback(0, nullptr, true,
        [](int, const EmscriptenKeyboardEvent* e, void*)->EM_BOOL {
            ImGui::GetIO().AddInputCharacter((ImWchar)e->charCode);
            return true;
        });
    emscripten_set_mousedown_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            if ((e->button >= 0) && (e->button < 3)) {
                btn_down[e->button] = true;
            }
            return true;
        });
    emscripten_set_mouseup_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            if ((e->button >= 0) && (e->button < 3)) {
                btn_up[e->button] = true;
            }
            return true;
        });
    emscripten_set_mousemove_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            ImGui::GetIO().MousePos.x = (float) e->canvasX;
            ImGui::GetIO().MousePos.y = (float) e->canvasY;
            return true;
        });
    emscripten_set_wheel_callback("#canvas", nullptr, true,
        [](int, const EmscriptenWheelEvent* e, void*)->EM_BOOL {
            ImGui::GetIO().MouseWheelH = -0.1f * (float)e->deltaX;
            ImGui::GetIO().MouseWheel = -0.1f * (float)e->deltaY;
            return true;
        });

    // dynamic vertex- and index-buffers for imgui-generated geometry
    sg_buffer_desc vbuf_desc = {
        .usage = SG_USAGE_STREAM,
        .size = sizeof(vertices)
    };
    sg_buffer_desc ibuf_desc = {
        .type = SG_BUFFERTYPE_INDEXBUFFER,
        .usage = SG_USAGE_STREAM,
        .size = sizeof(indices)
    };
    draw_state.vertex_buffers[0] = sg_make_buffer(&vbuf_desc);
    draw_state.index_buffer = sg_make_buffer(&ibuf_desc);

    // font texture for imgui's default font
    unsigned char* font_pixels;
    int font_width, font_height;
    io.Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
    sg_image_desc img_desc = {
        .width = font_width,
        .height = font_height,
        .pixel_format = SG_PIXELFORMAT_RGBA8,
        .wrap_u = SG_WRAP_CLAMP_TO_EDGE,
        .wrap_v = SG_WRAP_CLAMP_TO_EDGE,
        .content.subimage[0][0] = {
            .ptr = font_pixels,
            .size = font_width * font_height * 4
        }
    };
    draw_state.fs_images[0] = sg_make_image(&img_desc);

    // shader object for imgui rendering
    sg_shader_desc shd_desc = {
        .vs.uniform_blocks[0] = {
            .size = sizeof(vs_params_t),
            .uniforms = {
                [0] = { .name="disp_size", .type=SG_UNIFORMTYPE_FLOAT2}
            }
        },
        .vs.source =
            "uniform vec2 disp_size;\n"
            "attribute vec2 position;\n"
            "attribute vec2 texcoord0;\n"
            "attribute vec4 color0;\n"
            "varying vec2 uv;\n"
            "varying vec4 color;\n"
            "void main() {\n"
            "    gl_Position = vec4(((position/disp_size)-0.5)*vec2(2.0,-2.0), 0.5, 1.0);\n"
            "    uv = texcoord0;\n"
            "    color = color0;\n"
            "}\n",
        .fs.images[0] = { .name="tex", .type=SG_IMAGETYPE_2D },
        .fs.source =
            "precision mediump float;"
            "uniform sampler2D tex;\n"
            "varying vec2 uv;\n"
            "varying vec4 color;\n"
            "void main() {\n"
            "    gl_FragColor = texture2D(tex, uv) * color;\n"
            "}\n"
    };
    sg_shader shd = sg_make_shader(&shd_desc);

    // pipeline object for imgui rendering
    sg_pipeline_desc pip_desc = {
        .layout = {
            .buffers[0].stride = sizeof(ImDrawVert),
            .attrs = {
                [0] = { .name="position", .offset=offsetof(ImDrawVert,pos), .format=SG_VERTEXFORMAT_FLOAT2 },
                [1] = { .name="texcoord0", .offset=offsetof(ImDrawVert,uv), .format=SG_VERTEXFORMAT_FLOAT2 },
                [2] = { .name="color0", .offset=offsetof(ImDrawVert,col), .format=SG_VERTEXFORMAT_UBYTE4N }
            }
        },
        .shader = shd,
        .index_type = SG_INDEXTYPE_UINT16,
        .blend = {
            .enabled = true,
            .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
            .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
            .color_write_mask = SG_COLORMASK_RGB
        }
    };
    draw_state.pipeline = sg_make_pipeline(&pip_desc);

    // initial clear color
    pass_action = (sg_pass_action){
        .colors[0] = { .action = SG_ACTION_CLEAR, .val = { 0.0f, 0.5f, 0.7f, 1.0f } }
    };

    emscripten_set_main_loop(draw, 0, 1);
    return 0;
}

// the main draw loop, this draw the standard ImGui demo windows
void draw() {
    ImGuiIO& io = ImGui::GetIO();
    io.DisplaySize = ImVec2(float(emsc_width()), float(emsc_height()));
    io.DeltaTime = (float) stm_sec(stm_laptime(&last_time));
    // this mouse button handling fixes the problem when down- and up-events
    // happen in the same frame
    for (int i = 0; i < 3; i++) {
        if (io.MouseDown[i]) {
            if (btn_up[i]) {
                io.MouseDown[i] = false;
                btn_up[i] = false;
            }
        }
        else {
            if (btn_down[i]) {
                io.MouseDown[i] = true;
                btn_down[i] = false;
            }
        }
    }
    ImGui::NewFrame();

    // 1. Show a simple window
    // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
    static float f = 0.0f;
    ImGui::Text("Hello, world!");
    ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
    ImGui::ColorEdit3("clear color", &pass_action.colors[0].val[0]);
    if (ImGui::Button("Test Window")) show_test_window ^= 1;
    if (ImGui::Button("Another Window")) show_another_window ^= 1;
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

    // 2. Show another simple window, this time using an explicit Begin/End pair
    if (show_another_window) {
        ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
        ImGui::Begin("Another Window", &show_another_window);
        ImGui::Text("Hello");
        ImGui::End();
    }

    // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
    if (show_test_window) {
        ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiSetCond_FirstUseEver);
        ImGui::ShowTestWindow();
    }

    // the sokol_gfx draw pass
    sg_begin_default_pass(&pass_action, emsc_width(), emsc_height());
    ImGui::Render();
    sg_end_pass();
    sg_commit();
}

// imgui draw callback to render imgui-generated draw commands through sokol_gfx
void imgui_draw_cb(ImDrawData* draw_data) {
    assert(draw_data);
    if (draw_data->CmdListsCount == 0) {
        return;
    }

    // copy vertices and indices
    int num_vertices = 0;
    int num_indices = 0;
    int num_cmdlists = 0;
    for (num_cmdlists = 0; num_cmdlists < draw_data->CmdListsCount; num_cmdlists++) {
        const ImDrawList* cl = draw_data->CmdLists[num_cmdlists];
        const int cl_num_vertices = cl->VtxBuffer.size();
        const int cl_num_indices = cl->IdxBuffer.size();

        // overflow check
        if ((num_vertices + cl_num_vertices) > MaxVertices) {
            break;
        }
        if ((num_indices + cl_num_indices) > MaxIndices) {
            break;
        }

        // copy vertices
        memcpy(&vertices[num_vertices], &cl->VtxBuffer.front(), cl_num_vertices*sizeof(ImDrawVert));

        // copy indices, need to 'rebase' indices to start of global vertex buffer
        const ImDrawIdx* src_index_ptr = &cl->IdxBuffer.front();
        const uint16_t base_vertex_index = num_vertices;
        for (int i = 0; i < cl_num_indices; i++) {
            indices[num_indices++] = src_index_ptr[i] + base_vertex_index;
        }
        num_vertices += cl_num_vertices;
    }

    // update vertex and index buffers
    const int vertex_data_size = num_vertices * sizeof(ImDrawVert);
    const int index_data_size = num_indices * sizeof(uint16_t);
    sg_update_buffer(draw_state.vertex_buffers[0], vertices, vertex_data_size);
    sg_update_buffer(draw_state.index_buffer, indices, index_data_size);

    // render the command list
    vs_params_t vs_params;
    vs_params.disp_size = ImGui::GetIO().DisplaySize;
    sg_apply_draw_state(&draw_state);
    sg_apply_uniform_block(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
    int base_element = 0;
    for (int cl_index=0; cl_index<num_cmdlists; cl_index++) {
        const ImDrawList* cmd_list = draw_data->CmdLists[cl_index];
        for (const ImDrawCmd& pcmd : cmd_list->CmdBuffer) {
            if (pcmd.UserCallback) {
                pcmd.UserCallback(cmd_list, &pcmd);
            }
            else {
                const int sx = (int) pcmd.ClipRect.x;
                const int sy = (int) pcmd.ClipRect.y;
                const int sw = (int) (pcmd.ClipRect.z - pcmd.ClipRect.x);
                const int sh = (int) (pcmd.ClipRect.w - pcmd.ClipRect.y);
                sg_apply_scissor_rect(sx, sy, sw, sh, true);
                sg_draw(base_element, pcmd.ElemCount, 1);
            }
            base_element += pcmd.ElemCount;
        }
    }
}

<commit_msg>imgui-emsc sample: fix mouse button assignment, and mouse enter/leave<commit_after>//------------------------------------------------------------------------------
//  imgui-emsc
//  Demonstrates basic integration with Dear Imgui (without custom
//  texture or custom font support).
//  Since emscripten is using clang exclusively, we can use designated
//  initializers even though this is C++.
//------------------------------------------------------------------------------
#include "imgui.h"
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#define SOKOL_IMPL
#define SOKOL_GLES2
#include "sokol_gfx.h"
#include "sokol_time.h"
#include "emsc.h"

const int MaxVertices = (1<<16);
const int MaxIndices = MaxVertices * 3;

uint64_t last_time = 0;
bool show_test_window = true;
bool show_another_window = false;

sg_draw_state draw_state = { };
sg_pass_action pass_action = { };
bool btn_down[3] = { };
bool btn_up[3] = { };
ImDrawVert vertices[MaxVertices];
uint16_t indices[MaxIndices];

typedef struct {
    ImVec2 disp_size;
} vs_params_t;

void draw();
void imgui_draw_cb(ImDrawData*);

int main() {
    /* setup WebGL context */
    emsc_init("#canvas", EMSC_NONE);

    /* setup sokol_gfx and sokol_time */
    stm_setup();
    sg_desc desc = { };
    sg_setup(&desc);
    assert(sg_isvalid());

    // setup the ImGui environment
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGuiIO& io = ImGui::GetIO();
    io.IniFilename = nullptr;
    io.RenderDrawListsFn = imgui_draw_cb;
    io.Fonts->AddFontDefault();
    // emscripten has no clearly defined key code constants
    io.KeyMap[ImGuiKey_Tab] = 9;
    io.KeyMap[ImGuiKey_LeftArrow] = 37;
    io.KeyMap[ImGuiKey_RightArrow] = 39;
    io.KeyMap[ImGuiKey_UpArrow] = 38;
    io.KeyMap[ImGuiKey_DownArrow] = 40;
    io.KeyMap[ImGuiKey_Home] = 36;
    io.KeyMap[ImGuiKey_End] = 35;
    io.KeyMap[ImGuiKey_Delete] = 46;
    io.KeyMap[ImGuiKey_Backspace] = 8;
    io.KeyMap[ImGuiKey_Enter] = 13;
    io.KeyMap[ImGuiKey_Escape] = 27;
    io.KeyMap[ImGuiKey_A] = 65;
    io.KeyMap[ImGuiKey_C] = 67;
    io.KeyMap[ImGuiKey_V] = 86;
    io.KeyMap[ImGuiKey_X] = 88;
    io.KeyMap[ImGuiKey_Y] = 89;
    io.KeyMap[ImGuiKey_Z] = 90;

    // emscripten to ImGui input forwarding
    emscripten_set_keydown_callback(0, nullptr, true,
        [](int, const EmscriptenKeyboardEvent* e, void*)->EM_BOOL {
            if (e->keyCode < 512) {
                ImGui::GetIO().KeysDown[e->keyCode] = true;
            }
            // only forward alpha-numeric keys to browser
            return e->keyCode < 32;
        });
    emscripten_set_keyup_callback(0, nullptr, true,
        [](int, const EmscriptenKeyboardEvent* e, void*)->EM_BOOL {
            if (e->keyCode < 512) {
                ImGui::GetIO().KeysDown[e->keyCode] = false;
            }
            // only forward alpha-numeric keys to browser
            return e->keyCode < 32;
        });
    emscripten_set_keypress_callback(0, nullptr, true,
        [](int, const EmscriptenKeyboardEvent* e, void*)->EM_BOOL {
            ImGui::GetIO().AddInputCharacter((ImWchar)e->charCode);
            return true;
        });
    emscripten_set_mousedown_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            switch (e->button) {
                case 0: btn_down[0] = true; break;
                case 2: btn_down[1] = true; break;
            }
            return true;
        });
    emscripten_set_mouseup_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            switch (e->button) {
                case 0: btn_up[0] = true; break;
                case 2: btn_up[1] = true; break;
            }
            return true;
        });
    emscripten_set_mouseenter_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            auto& io = ImGui::GetIO();
            for (int i = 0; i < 3; i++) {
                btn_down[i] = btn_up[i] = false;
                io.MouseDown[i] = false;
            }
            return true;
        });
    emscripten_set_mouseleave_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            auto& io = ImGui::GetIO();
            for (int i = 0; i < 3; i++) {
                btn_down[i] = btn_up[i] = false;
                io.MouseDown[i] = false;
            }
            return true;
        });
    emscripten_set_mousemove_callback("#canvas", nullptr, true,
        [](int, const EmscriptenMouseEvent* e, void*)->EM_BOOL {
            ImGui::GetIO().MousePos.x = (float) e->canvasX;
            ImGui::GetIO().MousePos.y = (float) e->canvasY;
            return true;
        });
    emscripten_set_wheel_callback("#canvas", nullptr, true,
        [](int, const EmscriptenWheelEvent* e, void*)->EM_BOOL {
            ImGui::GetIO().MouseWheelH = -0.1f * (float)e->deltaX;
            ImGui::GetIO().MouseWheel = -0.1f * (float)e->deltaY;
            return true;
        });

    // dynamic vertex- and index-buffers for imgui-generated geometry
    sg_buffer_desc vbuf_desc = {
        .usage = SG_USAGE_STREAM,
        .size = sizeof(vertices)
    };
    sg_buffer_desc ibuf_desc = {
        .type = SG_BUFFERTYPE_INDEXBUFFER,
        .usage = SG_USAGE_STREAM,
        .size = sizeof(indices)
    };
    draw_state.vertex_buffers[0] = sg_make_buffer(&vbuf_desc);
    draw_state.index_buffer = sg_make_buffer(&ibuf_desc);

    // font texture for imgui's default font
    unsigned char* font_pixels;
    int font_width, font_height;
    io.Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
    sg_image_desc img_desc = {
        .width = font_width,
        .height = font_height,
        .pixel_format = SG_PIXELFORMAT_RGBA8,
        .wrap_u = SG_WRAP_CLAMP_TO_EDGE,
        .wrap_v = SG_WRAP_CLAMP_TO_EDGE,
        .content.subimage[0][0] = {
            .ptr = font_pixels,
            .size = font_width * font_height * 4
        }
    };
    draw_state.fs_images[0] = sg_make_image(&img_desc);

    // shader object for imgui rendering
    sg_shader_desc shd_desc = {
        .vs.uniform_blocks[0] = {
            .size = sizeof(vs_params_t),
            .uniforms = {
                [0] = { .name="disp_size", .type=SG_UNIFORMTYPE_FLOAT2}
            }
        },
        .vs.source =
            "uniform vec2 disp_size;\n"
            "attribute vec2 position;\n"
            "attribute vec2 texcoord0;\n"
            "attribute vec4 color0;\n"
            "varying vec2 uv;\n"
            "varying vec4 color;\n"
            "void main() {\n"
            "    gl_Position = vec4(((position/disp_size)-0.5)*vec2(2.0,-2.0), 0.5, 1.0);\n"
            "    uv = texcoord0;\n"
            "    color = color0;\n"
            "}\n",
        .fs.images[0] = { .name="tex", .type=SG_IMAGETYPE_2D },
        .fs.source =
            "precision mediump float;"
            "uniform sampler2D tex;\n"
            "varying vec2 uv;\n"
            "varying vec4 color;\n"
            "void main() {\n"
            "    gl_FragColor = texture2D(tex, uv) * color;\n"
            "}\n"
    };
    sg_shader shd = sg_make_shader(&shd_desc);

    // pipeline object for imgui rendering
    sg_pipeline_desc pip_desc = {
        .layout = {
            .buffers[0].stride = sizeof(ImDrawVert),
            .attrs = {
                [0] = { .name="position", .offset=offsetof(ImDrawVert,pos), .format=SG_VERTEXFORMAT_FLOAT2 },
                [1] = { .name="texcoord0", .offset=offsetof(ImDrawVert,uv), .format=SG_VERTEXFORMAT_FLOAT2 },
                [2] = { .name="color0", .offset=offsetof(ImDrawVert,col), .format=SG_VERTEXFORMAT_UBYTE4N }
            }
        },
        .shader = shd,
        .index_type = SG_INDEXTYPE_UINT16,
        .blend = {
            .enabled = true,
            .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
            .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
            .color_write_mask = SG_COLORMASK_RGB
        }
    };
    draw_state.pipeline = sg_make_pipeline(&pip_desc);

    // initial clear color
    pass_action = (sg_pass_action){
        .colors[0] = { .action = SG_ACTION_CLEAR, .val = { 0.0f, 0.5f, 0.7f, 1.0f } }
    };

    emscripten_set_main_loop(draw, 0, 1);
    return 0;
}

// the main draw loop, this draw the standard ImGui demo windows
void draw() {
    ImGuiIO& io = ImGui::GetIO();
    io.DisplaySize = ImVec2(float(emsc_width()), float(emsc_height()));
    io.DeltaTime = (float) stm_sec(stm_laptime(&last_time));
    // this mouse button handling fixes the problem when down- and up-events
    // happen in the same frame
    for (int i = 0; i < 3; i++) {
        if (io.MouseDown[i]) {
            if (btn_up[i]) {
                io.MouseDown[i] = false;
                btn_up[i] = false;
            }
        }
        else {
            if (btn_down[i]) {
                io.MouseDown[i] = true;
                btn_down[i] = false;
            }
        }
    }
    ImGui::NewFrame();

    // 1. Show a simple window
    // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
    static float f = 0.0f;
    ImGui::Text("Hello, world!");
    ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
    ImGui::ColorEdit3("clear color", &pass_action.colors[0].val[0]);
    if (ImGui::Button("Test Window")) show_test_window ^= 1;
    if (ImGui::Button("Another Window")) show_another_window ^= 1;
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

    // 2. Show another simple window, this time using an explicit Begin/End pair
    if (show_another_window) {
        ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
        ImGui::Begin("Another Window", &show_another_window);
        ImGui::Text("Hello");
        ImGui::End();
    }

    // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
    if (show_test_window) {
        ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiSetCond_FirstUseEver);
        ImGui::ShowTestWindow();
    }

    // the sokol_gfx draw pass
    sg_begin_default_pass(&pass_action, emsc_width(), emsc_height());
    ImGui::Render();
    sg_end_pass();
    sg_commit();
}

// imgui draw callback to render imgui-generated draw commands through sokol_gfx
void imgui_draw_cb(ImDrawData* draw_data) {
    assert(draw_data);
    if (draw_data->CmdListsCount == 0) {
        return;
    }

    // copy vertices and indices
    int num_vertices = 0;
    int num_indices = 0;
    int num_cmdlists = 0;
    for (num_cmdlists = 0; num_cmdlists < draw_data->CmdListsCount; num_cmdlists++) {
        const ImDrawList* cl = draw_data->CmdLists[num_cmdlists];
        const int cl_num_vertices = cl->VtxBuffer.size();
        const int cl_num_indices = cl->IdxBuffer.size();

        // overflow check
        if ((num_vertices + cl_num_vertices) > MaxVertices) {
            break;
        }
        if ((num_indices + cl_num_indices) > MaxIndices) {
            break;
        }

        // copy vertices
        memcpy(&vertices[num_vertices], &cl->VtxBuffer.front(), cl_num_vertices*sizeof(ImDrawVert));

        // copy indices, need to 'rebase' indices to start of global vertex buffer
        const ImDrawIdx* src_index_ptr = &cl->IdxBuffer.front();
        const uint16_t base_vertex_index = num_vertices;
        for (int i = 0; i < cl_num_indices; i++) {
            indices[num_indices++] = src_index_ptr[i] + base_vertex_index;
        }
        num_vertices += cl_num_vertices;
    }

    // update vertex and index buffers
    const int vertex_data_size = num_vertices * sizeof(ImDrawVert);
    const int index_data_size = num_indices * sizeof(uint16_t);
    sg_update_buffer(draw_state.vertex_buffers[0], vertices, vertex_data_size);
    sg_update_buffer(draw_state.index_buffer, indices, index_data_size);

    // render the command list
    vs_params_t vs_params;
    vs_params.disp_size = ImGui::GetIO().DisplaySize;
    sg_apply_draw_state(&draw_state);
    sg_apply_uniform_block(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
    int base_element = 0;
    for (int cl_index=0; cl_index<num_cmdlists; cl_index++) {
        const ImDrawList* cmd_list = draw_data->CmdLists[cl_index];
        for (const ImDrawCmd& pcmd : cmd_list->CmdBuffer) {
            if (pcmd.UserCallback) {
                pcmd.UserCallback(cmd_list, &pcmd);
            }
            else {
                const int sx = (int) pcmd.ClipRect.x;
                const int sy = (int) pcmd.ClipRect.y;
                const int sw = (int) (pcmd.ClipRect.z - pcmd.ClipRect.x);
                const int sh = (int) (pcmd.ClipRect.w - pcmd.ClipRect.y);
                sg_apply_scissor_rect(sx, sy, sw, sh, true);
                sg_draw(base_element, pcmd.ElemCount, 1);
            }
            base_element += pcmd.ElemCount;
        }
    }
}

<|endoftext|>


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

    This file is part of FLINT.

    FLINT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    FLINT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with FLINT; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

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

    Copyright (C) 2013 Tom Bachmann

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

#include <iostream>

#include "arithxx.h"

#include "helpers.h"

using namespace flint;

void
test_stirling()
{
#define STIRLING(func, matfunc, n, k) \
{\
    tassert(func##_vec(n, k).size() == k); \
    fmpz_vecxx v1(func##_vec(n, k).evaluate() /* test temporary alloc */); \
    for(slong i = 0;i < v1.size();++i) \
        tassert(v1[i] == func(n, i)); \
    tassert(func##_vec_next(func##_vec(n, k), n+1).size() == k); \
    fmpz_vecxx v2(func##_vec_next(v1, n+1)); \
    for(slong i = 0;i < v2.size();++i) \
        tassert(v2[i] == func(n+1, i)); \
    fmpz_vecxx v3(func##_vec(n, n+1)); \
    fmpz_vecxx v4(func##_vec_next(v3, n+1)); \
    tassert(v4.size() == n+2 && v3.size() == n+1); \
    for(slong i = 0;i < v4.size();++i) \
        tassert(v4[i] == func(n+1, i)); \
    tassert(matfunc(n, k).rows() == n && matfunc(n, k).cols() == k); \
    fmpz_matxx M(matfunc(n, k).evaluate() /* test temporaries */); \
    for(slong i = 0;i < M.rows();++i) \
        for(slong j = 0;j < M.cols();++j) \
            tassert(M.at(i, j) == func(i, j)); \
}
STIRLING(stirling_number_1u, stirling_matrix_1u, 10, 6)
STIRLING(stirling_number_1, stirling_matrix_1, 10, 6)
STIRLING(stirling_number_2, stirling_matrix_2, 10, 6)
}

void
test_bell()
{
    tassert(bell_number_vec(10).size() == 10);
    fmpz_vecxx v(bell_number_vec(10));
    tassert(v == bell_number_vec_recursive(10));
    tassert(v == bell_number_vec_multi_mod(10));
    for(long i = 0;i < v.size();++i)
        tassert(v[i] == bell_number(static_cast<unsigned>(i)));
    tassert(bell_number(10u) == bell_number_bsplit(10u));
    tassert(bell_number(10u) == bell_number_multi_mod(10u));

    nmodxx_ctx p(1031);
    tassert(bell_number_nmod(10u, p) == nmodxx::red(bell_number(10u), p));
    nmod_vecxx v2(bell_number_nmod_vec(10u, p));
    tassert(v2.size() == 10);
    for(long i = 0;i < v2.size();++i)
        tassert(v2[i] == nmodxx::red(v[i], p));

    tassert(v2 == bell_number_nmod_vec_series(10u, p));
    tassert(v2 == bell_number_nmod_vec_recursive(10u, p));

    tassert(fmpzxx(2).pow(
                static_cast<unsigned> (bell_number_size(10u)))
            > bell_number(10u));
}

void
test_bernoulli()
{
    tassert(bernoulli_number(10u).den() == bernoulli_number_denom(10u));
    tassert(fmpqxx(2, 1u).pow(
                static_cast<slong> (bernoulli_number_size(10u)))
            > bernoulli_number(10u));
    fmpq_polyxx poly(bernoulli_polynomial(10u));
    tassert(poly.degree() == 10);
    for(long i = 0;i < poly.length();++i)
        tassert(poly.get_coeff(i)
                == fmpqxx(bin(10u, (unsigned) i)*bernoulli_number(10u - (unsigned) i)));
    tassert(bernoulli_number_vec(10u).size() == 10);
    for(unsigned i = 0;i < 10;++i)
        tassert(bernoulli_number_vec(10u)[i] == bernoulli_number(i));
}

void
test_euler()
{
    tassert(fmpzxx(2).pow(
                static_cast<unsigned> (euler_number_size(10u)))
            > euler_number(10u));
    fmpq_polyxx poly(euler_polynomial(10u));
    tassert(poly.degree() == 10);
    tassert(poly(fmpqxx(1, 2u))*fmpqxx(2, 1u).pow(10)
            == fmpqxx(euler_number(10u).evaluate(), fmpzxx(1)));
    tassert(euler_number_vec(10u).size() == 10);
    for(unsigned i = 0;i < 10;++i)
        tassert(euler_number_vec(10u)[i] == euler_number(i));
}

void
test_legendre()
{
    const unsigned short N = 10;
    fmpq_polyxx f; f = "3  -1 0 1";
    f = f.pow(N);
    for(unsigned i = 0;i < N;++i)
        f = f.derivative();
    tassert(legendre_polynomial(N)
            == f * fmpqxx(fmpzxx(1), (fmpzxx(2).pow(N)*fac(N)).evaluate()));

    fmpq_polyxx x; x = "2  0 1";
    f = chebyshev_t_polynomial(N);
    f = f(cos_series(x, N));
    f.truncate(N);
    tassert(f == cos_series(N*x, N));
    tassert(chebyshev_u_polynomial(N)*(N + 1)
            == chebyshev_t_polynomial(N+1u).derivative());
}

void
test_multiplicative()
{
    fmpzxx p(1031);
    tassert(euler_phi(p) == p-1u);
    tassert(moebius_mu(p) == -1);
    tassert(divisor_sigma(p, 4u) == 1u + p.pow(4u));
    tassert(divisors(p).to_string() == "2  1 " + p.to_string());

    fmpz_polyxx q, one;
    q = "2  0 1";
    one = "1  1";
    fmpz_polyxx res(q * (one - q).pow(24u) * (one - q*q).pow(24u));
    for(unsigned i = 3;i < 10;++i)
        res *= (one - q.pow(i)).pow(24u);
    res.truncate(10);
    tassert(res == ramanujan_tau_series(10));
    for(int i = 0;i < 10;++i)
        tassert(ramanujan_tau_series(i+1).get_coeff(i)
                == ramanujan_tau(fmpzxx(i)));
}

void
test_polys()
{
    // just very basic tests ...
    ulong N = 1234;
    tassert(cyclotomic_polynomial(N).degree() == euler_phi(fmpzxx(N)));
    tassert(cos_minpoly(N).degree() == euler_phi(fmpzxx(N))/2);

    tassert(swinnerton_dyer_polynomial(8u).degree() == fmpzxx(2).pow(8u));
}

void
test_dedekind()
{
    frandxx state;
    fmpzxx h = fmpzxx::randtest_unsigned(state, 10);
    fmpzxx k = fmpzxx::randtest_unsigned(state, 10);
    tassert(dedekind_sum_naive(h, k) == dedekind_sum(h, k));
    k /= gcd(h, k);
    tassert(dedekind_sum_coprime_large(h, k) == dedekind_sum(h, k));
    tassert(dedekind_sum_coprime(h, k) == dedekind_sum(h, k));
    // TODO dedekind_sum_coprime_d
}

void
test_number_of_partitions()
{
    unsigned short N = 15;
    nmodxx_ctx p(1031);
    fmpz_vecxx v1(number_of_partitions_vec(N));
    nmod_vecxx v2(number_of_partitions_nmod_vec(N, p));
    tassert(v1.size() == v2.size() && v1.size() == N);
    for(unsigned i = 0;i < N;++i)
    {
        tassert(v1[i] == number_of_partitions(i));
        tassert(nmodxx::red(v1[i], p) == v2[i]);
    }
}

void
test_sum_of_squares()
{
    unsigned short N = 15;
    fmpz_vecxx v(sum_of_squares_vec(7u, N));
    tassert(v.size() == N);
    for(unsigned i = 0;i < N;++i)
        tassert(v[i] == sum_of_squares(7u, fmpzxx(i)));
}

int
main()
{
    std::cout << "t-arithxx....";

    tassert(primorial(4) == 2*3);
    tassert(harmonic_number(3)
            == fmpqxx(1, 1u) + fmpqxx(1, 2u) + fmpqxx(1, 3u));

    test_stirling();
    test_bell();
    test_bernoulli();
    test_euler();
    test_legendre();
    test_multiplicative();
    test_polys();
    test_dedekind();
    test_number_of_partitions();
    test_sum_of_squares();

    tassert(landau_function_vec(9)[8] == 15);

    std::cout << "PASS\n";
    return 0;
}
<commit_msg>More constant fixes.<commit_after>/*=============================================================================

    This file is part of FLINT.

    FLINT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    FLINT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with FLINT; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

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

    Copyright (C) 2013 Tom Bachmann

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

#include <iostream>

#include "arithxx.h"

#include "helpers.h"

using namespace flint;

void
test_stirling()
{
#define STIRLING(func, matfunc, n, k) \
{\
    tassert(func##_vec(n, k).size() == k); \
    fmpz_vecxx v1(func##_vec(n, k).evaluate() /* test temporary alloc */); \
    for(slong i = 0;i < v1.size();++i) \
        tassert(v1[i] == func(n, i)); \
    tassert(func##_vec_next(func##_vec(n, k), n+1).size() == k); \
    fmpz_vecxx v2(func##_vec_next(v1, n+1)); \
    for(slong i = 0;i < v2.size();++i) \
        tassert(v2[i] == func(n+1, i)); \
    fmpz_vecxx v3(func##_vec(n, n+1)); \
    fmpz_vecxx v4(func##_vec_next(v3, n+1)); \
    tassert(v4.size() == n+2 && v3.size() == n+1); \
    for(slong i = 0;i < v4.size();++i) \
        tassert(v4[i] == func(n+1, i)); \
    tassert(matfunc(n, k).rows() == n && matfunc(n, k).cols() == k); \
    fmpz_matxx M(matfunc(n, k).evaluate() /* test temporaries */); \
    for(slong i = 0;i < M.rows();++i) \
        for(slong j = 0;j < M.cols();++j) \
            tassert(M.at(i, j) == func(i, j)); \
}
STIRLING(stirling_number_1u, stirling_matrix_1u, 10, 6)
STIRLING(stirling_number_1, stirling_matrix_1, 10, 6)
STIRLING(stirling_number_2, stirling_matrix_2, 10, 6)
}

void
test_bell()
{
    tassert(bell_number_vec(10).size() == 10);
    fmpz_vecxx v(bell_number_vec(10));
    tassert(v == bell_number_vec_recursive(10));
    tassert(v == bell_number_vec_multi_mod(10));
    for(slong i = 0;i < v.size();++i)
        tassert(v[i] == bell_number(static_cast<unsigned>(i)));
    tassert(bell_number(10u) == bell_number_bsplit(10u));
    tassert(bell_number(10u) == bell_number_multi_mod(10u));

    nmodxx_ctx p(1031);
    tassert(bell_number_nmod(10u, p) == nmodxx::red(bell_number(10u), p));
    nmod_vecxx v2(bell_number_nmod_vec(10u, p));
    tassert(v2.size() == 10);
    for(slong i = 0;i < v2.size();++i)
        tassert(v2[i] == nmodxx::red(v[i], p));

    tassert(v2 == bell_number_nmod_vec_series(10u, p));
    tassert(v2 == bell_number_nmod_vec_recursive(10u, p));

    tassert(fmpzxx(2).pow(
                static_cast<unsigned> (bell_number_size(10u)))
            > bell_number(10u));
}

void
test_bernoulli()
{
    tassert(bernoulli_number(10u).den() == bernoulli_number_denom(10u));
    tassert(fmpqxx(2, 1u).pow(
                static_cast<slong> (bernoulli_number_size(10u)))
            > bernoulli_number(10u));
    fmpq_polyxx poly(bernoulli_polynomial(10u));
    tassert(poly.degree() == 10);
    for(slong i = 0;i < poly.length();++i)
        tassert(poly.get_coeff(i)
                == fmpqxx(bin(10u, (unsigned) i)*bernoulli_number(10u - (unsigned) i)));
    tassert(bernoulli_number_vec(10u).size() == 10);
    for(unsigned i = 0;i < 10;++i)
        tassert(bernoulli_number_vec(10u)[i] == bernoulli_number(i));
}

void
test_euler()
{
    tassert(fmpzxx(2).pow(
                static_cast<unsigned> (euler_number_size(10u)))
            > euler_number(10u));
    fmpq_polyxx poly(euler_polynomial(10u));
    tassert(poly.degree() == 10);
    tassert(poly(fmpqxx(1, 2u))*fmpqxx(2, 1u).pow(10)
            == fmpqxx(euler_number(10u).evaluate(), fmpzxx(1)));
    tassert(euler_number_vec(10u).size() == 10);
    for(unsigned i = 0;i < 10;++i)
        tassert(euler_number_vec(10u)[i] == euler_number(i));
}

void
test_legendre()
{
    const unsigned short N = 10;
    fmpq_polyxx f; f = "3  -1 0 1";
    f = f.pow(N);
    for(unsigned i = 0;i < N;++i)
        f = f.derivative();
    tassert(legendre_polynomial(N)
            == f * fmpqxx(fmpzxx(1), (fmpzxx(2).pow(N)*fac(N)).evaluate()));

    fmpq_polyxx x; x = "2  0 1";
    f = chebyshev_t_polynomial(N);
    f = f(cos_series(x, N));
    f.truncate(N);
    tassert(f == cos_series(N*x, N));
    tassert(chebyshev_u_polynomial(N)*(N + 1)
            == chebyshev_t_polynomial(N+1u).derivative());
}

void
test_multiplicative()
{
    fmpzxx p(1031);
    tassert(euler_phi(p) == p-1u);
    tassert(moebius_mu(p) == -1);
    tassert(divisor_sigma(p, 4u) == 1u + p.pow(4u));
    tassert(divisors(p).to_string() == "2  1 " + p.to_string());

    fmpz_polyxx q, one;
    q = "2  0 1";
    one = "1  1";
    fmpz_polyxx res(q * (one - q).pow(24u) * (one - q*q).pow(24u));
    for(unsigned i = 3;i < 10;++i)
        res *= (one - q.pow(i)).pow(24u);
    res.truncate(10);
    tassert(res == ramanujan_tau_series(10));
    for(int i = 0;i < 10;++i)
        tassert(ramanujan_tau_series(i+1).get_coeff(i)
                == ramanujan_tau(fmpzxx(i)));
}

void
test_polys()
{
    // just very basic tests ...
    ulong N = 1234;
    tassert(cyclotomic_polynomial(N).degree() == euler_phi(fmpzxx(N)));
    tassert(cos_minpoly(N).degree() == euler_phi(fmpzxx(N))/2);

    tassert(swinnerton_dyer_polynomial(8u).degree() == fmpzxx(2).pow(8u));
}

void
test_dedekind()
{
    frandxx state;
    fmpzxx h = fmpzxx::randtest_unsigned(state, 10);
    fmpzxx k = fmpzxx::randtest_unsigned(state, 10);
    tassert(dedekind_sum_naive(h, k) == dedekind_sum(h, k));
    k /= gcd(h, k);
    tassert(dedekind_sum_coprime_large(h, k) == dedekind_sum(h, k));
    tassert(dedekind_sum_coprime(h, k) == dedekind_sum(h, k));
    // TODO dedekind_sum_coprime_d
}

void
test_number_of_partitions()
{
    unsigned short N = 15;
    nmodxx_ctx p(1031);
    fmpz_vecxx v1(number_of_partitions_vec(N));
    nmod_vecxx v2(number_of_partitions_nmod_vec(N, p));
    tassert(v1.size() == v2.size() && v1.size() == N);
    for(unsigned i = 0;i < N;++i)
    {
        tassert(v1[i] == number_of_partitions(i));
        tassert(nmodxx::red(v1[i], p) == v2[i]);
    }
}

void
test_sum_of_squares()
{
    unsigned short N = 15;
    fmpz_vecxx v(sum_of_squares_vec(7u, N));
    tassert(v.size() == N);
    for(unsigned i = 0;i < N;++i)
        tassert(v[i] == sum_of_squares(7u, fmpzxx(i)));
}

int
main()
{
    std::cout << "t-arithxx....";

    tassert(primorial(4) == 2*3);
    tassert(harmonic_number(3)
            == fmpqxx(1, 1u) + fmpqxx(1, 2u) + fmpqxx(1, 3u));

    test_stirling();
    test_bell();
    test_bernoulli();
    test_euler();
    test_legendre();
    test_multiplicative();
    test_polys();
    test_dedekind();
    test_number_of_partitions();
    test_sum_of_squares();

    tassert(landau_function_vec(9)[8] == 15);

    std::cout << "PASS\n";
    return 0;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* no header other than FlagInfo.h should be included here */

#ifdef _MSC_VER
#pragma warning( 4:4786)
#endif

/* interface header */
#include "FlagInfo.h"

/* system headers */
#include <iostream>

// implementation-specific bzflag headers
#include "BZDBCache.h"

/* private */

/* protected */

/* public */

// flags list
FlagInfo              *FlagInfo::flagList      = NULL;
std::vector<FlagType*> FlagInfo::allowedFlags;
int                    FlagInfo::numExtraFlags = 0;
int                    FlagInfo::numFlags      = 0;
int                    FlagInfo::numFlagsInAir;

FlagInfo::FlagInfo()
{
  // prep flag
  flag.type               = Flags::Null;
  flag.status             = FlagNoExist;
  flag.endurance          = FlagNormal;
  flag.owner              = NoPlayer;
  flag.position[0]        = 0.0f;
  flag.position[1]        = 0.0f;
  flag.position[2]        = 0.0f;
  flag.launchPosition[0]  = 0.0f;
  flag.launchPosition[1]  = 0.0f;
  flag.launchPosition[2]  = 0.0f;
  flag.landingPosition[0] = 0.0f;
  flag.landingPosition[1] = 0.0f;
  flag.landingPosition[2] = 0.0f;
  flag.flightTime         = 0.0f;
  flag.flightEnd          = 0.0f;
  flag.initialVelocity    = 0.0f;
  player                  = -1;
  grabs                   = 0;
}

void FlagInfo::setSize(int _numFlags)
{
  // sanity check
  if (_numFlags > 1000000) {
    std::cerr << "WARNING: FlagInfo::setSize was given an insane flag count of " << _numFlags << std::endl;
    std::cerr << "clamping to 1000000 flags just for kicks" << std::endl;
  }

  numFlags = _numFlags;
  delete[] flagList;
  flagList = NULL;
  if (numFlags)
    flagList = new FlagInfo[numFlags];
  for (int i = 0; i < numFlags; i++)
    flagList[i].flagIndex = i;
}

void FlagInfo::setAllowed(std::vector<FlagType*> allowed)
{
  allowedFlags = allowed;
}

void FlagInfo::setExtra(int extra)
{
  numExtraFlags = extra;
}

int FlagInfo::lookupFirstTeamFlag(int teamindex)
{
  for (int i = 0; i < numFlags; i++) {
    if (flagList[i].flag.type->flagTeam == teamindex)
      return i;
  }
  return -1;
}

void FlagInfo::setRequiredFlag(FlagType *desc)
{
  required = true;
  flag.type = desc;
}

void FlagInfo::addFlag()
{
  const float flagAltitude = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float gravity      = BZDBCache::gravity;
  const float maxGrabs     = BZDB.eval(StateDatabase::BZDB_MAXFLAGGRABS);

  // flag in now entering game
  numFlagsInAir++;
  flag.status          = FlagComing;

  // compute drop time
  const float flightTime = 2.0f * sqrtf(-2.0f * flagAltitude / gravity);
  flag.flightTime        = 0.0f;
  flag.flightEnd         = flightTime;
  flag.initialVelocity   = -0.5f * gravity * flightTime;
  dropDone               = TimeKeeper::getCurrent();
  dropDone              += flightTime;

  if (flag.type == Flags::Null)
    // pick a random flag
    flag.type = allowedFlags[(int)(allowedFlags.size() * (float)bzfrand())];

  // decide how sticky the flag will be
  if (flag.type->flagQuality == FlagBad)
    flag.endurance = FlagSticky;
  else
    flag.endurance = FlagUnstable;

  // how times will it stick around
  if ((flag.endurance == FlagSticky) || (flag.type == Flags::Thief))
    grabs = 1;
  else
    grabs = int(floor(maxGrabs * (float)bzfrand())) + 1;
}

void *FlagInfo::pack(void *buf)
{
  buf = nboPackUShort(buf, flagIndex);
  buf = FlagInfo::flagList[flagIndex].flag.pack(buf);
  return buf;
}

void FlagInfo::dropFlag(float pos[3], float landingPos[3], bool vanish)
{
  numFlagsInAir++;
  flag.status             = vanish ? FlagGoing : FlagInAir;

  flag.landingPosition[0] = landingPos[0];
  flag.landingPosition[1] = landingPos[1];
  flag.landingPosition[2] = landingPos[2];

  flag.position[0]       = landingPos[0];
  flag.position[1]       = landingPos[1];
  flag.position[2]       = landingPos[2];
  flag.launchPosition[0] = pos[0];
  flag.launchPosition[1] = pos[1];
  flag.launchPosition[2] = pos[2] + BZDBCache::tankHeight;

  // compute flight info -- flight time depends depends on start and end
  // altitudes and desired height above start altitude
  const float gravity        = BZDBCache::gravity;
  const float flagAltitude   = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float thrownAltitude = (flag.type == Flags::Shield) ?
    BZDB.eval(StateDatabase::BZDB_SHIELDFLIGHT) * flagAltitude : flagAltitude;
  const float maxAltitude    = pos[2] + thrownAltitude;
  const float upTime         = sqrtf(-2.0f * thrownAltitude / gravity);
  const float downTime       = sqrtf(-2.0f * (maxAltitude - pos[2]) / gravity);
  const float flightTime     = upTime + downTime;

  dropDone             = TimeKeeper::getCurrent();
  dropDone            += flightTime;
  flag.flightTime      = 0.0f;
  flag.flightEnd       = flightTime;
  flag.initialVelocity = -gravity * upTime;
}

void FlagInfo::resetFlag(float position[3], bool teamIsEmpty)
{
  // reset a flag's info
  player      = -1;
  // if it's a random flag, reset flag id
  if (flagIndex >= numFlags - numExtraFlags)
    flag.type = Flags::Null;

  flag.position[0] = position[0];
  flag.position[1] = position[1];
  flag.position[2] = position[2];

  // required flags mustn't just disappear
  if (required) {
    if (flag.type->flagTeam == ::NoTeam)
      // flag in now entering game
      addFlag();
    else if (teamIsEmpty)
      flag.status = FlagNoExist;
    else
      flag.status = FlagOnGround;
  } else {
    flag.status = FlagNoExist;
  }
}

void FlagInfo::grab(int playerIndex)
{
  flag.status = FlagOnTank;
  flag.owner  = playerIndex;
  player      = playerIndex;
  numShots    = 0;
}

int FlagInfo::teamIndex()
{
  return flag.type->flagTeam;
}

int FlagInfo::getIndex()
{
  return flagIndex;
}

float FlagInfo::getNextDrop(TimeKeeper &tm)
{
  // find timeout when next flag would hit ground
  float waitTime = 3.0f;
  if (numFlagsInAir > 0) {
    for (int i = 0; i < numFlags; i++) {
      FlagInfo &flag = flagList[i];
      if (flag.flag.status != FlagNoExist &&
	  flag.flag.status != FlagOnTank &&
	  flag.flag.status != FlagOnGround &&
	  flag.dropDone - tm < waitTime)
	waitTime = flag.dropDone - tm;
    }
  }
  return waitTime;
}

bool FlagInfo::landing(const TimeKeeper &tm)
{
  if (numFlagsInAir <= 0)
    return false;

  bool land = false;
  if (flag.status == FlagInAir || flag.status == FlagComing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagOnGround;
      numFlagsInAir--;
      land        = true;
    }
  } else if (flag.status == FlagGoing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagNoExist;
      numFlagsInAir--;
      land        = true;
    }
  }
  return land;
}

void FlagInfo::setNoFlagInAir()
{
  numFlagsInAir = 0;
}

void FlagInfo::getTextualInfo(char *message)
{
  sprintf(message, "%d p:%d r:%d g:%d i:%s s:%d p:%3.1fx%3.1fx%3.1f",
	  flagIndex, player, required, grabs, flag.type->flagAbbv, flag.status,
	  flag.position[0], flag.position[1], flag.position[2]);
}

bool FlagInfo::exist()
{
  return flag.status != FlagNoExist;
}

FlagInfo *FlagInfo::get(int index)
{
  if (index < 0)
    return NULL;
  if (index >= numFlags)
    return NULL;
  return &flagList[index];
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>er, do what was written too<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* no header other than FlagInfo.h should be included here */

#ifdef _MSC_VER
#pragma warning( 4:4786)
#endif

/* interface header */
#include "FlagInfo.h"

/* system headers */
#include <iostream>

// implementation-specific bzflag headers
#include "BZDBCache.h"

/* private */

/* protected */

/* public */

// flags list
FlagInfo              *FlagInfo::flagList      = NULL;
std::vector<FlagType*> FlagInfo::allowedFlags;
int                    FlagInfo::numExtraFlags = 0;
int                    FlagInfo::numFlags      = 0;
int                    FlagInfo::numFlagsInAir;

FlagInfo::FlagInfo()
{
  // prep flag
  flag.type               = Flags::Null;
  flag.status             = FlagNoExist;
  flag.endurance          = FlagNormal;
  flag.owner              = NoPlayer;
  flag.position[0]        = 0.0f;
  flag.position[1]        = 0.0f;
  flag.position[2]        = 0.0f;
  flag.launchPosition[0]  = 0.0f;
  flag.launchPosition[1]  = 0.0f;
  flag.launchPosition[2]  = 0.0f;
  flag.landingPosition[0] = 0.0f;
  flag.landingPosition[1] = 0.0f;
  flag.landingPosition[2] = 0.0f;
  flag.flightTime         = 0.0f;
  flag.flightEnd          = 0.0f;
  flag.initialVelocity    = 0.0f;
  player                  = -1;
  grabs                   = 0;
}

void FlagInfo::setSize(int _numFlags)
{
  // sanity check
  if (_numFlags > 1000000) {
    std::cerr << "WARNING: FlagInfo::setSize was given an insane flag count of " << _numFlags << std::endl;
    std::cerr << "clamping to 1000000 flags just for kicks" << std::endl;
    _numFlags = 100000;
  }

  numFlags = _numFlags;
  delete[] flagList;
  flagList = NULL;
  if (numFlags)
    flagList = new FlagInfo[numFlags];
  for (int i = 0; i < numFlags; i++)
    flagList[i].flagIndex = i;
}

void FlagInfo::setAllowed(std::vector<FlagType*> allowed)
{
  allowedFlags = allowed;
}

void FlagInfo::setExtra(int extra)
{
  numExtraFlags = extra;
}

int FlagInfo::lookupFirstTeamFlag(int teamindex)
{
  for (int i = 0; i < numFlags; i++) {
    if (flagList[i].flag.type->flagTeam == teamindex)
      return i;
  }
  return -1;
}

void FlagInfo::setRequiredFlag(FlagType *desc)
{
  required = true;
  flag.type = desc;
}

void FlagInfo::addFlag()
{
  const float flagAltitude = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float gravity      = BZDBCache::gravity;
  const float maxGrabs     = BZDB.eval(StateDatabase::BZDB_MAXFLAGGRABS);

  // flag in now entering game
  numFlagsInAir++;
  flag.status          = FlagComing;

  // compute drop time
  const float flightTime = 2.0f * sqrtf(-2.0f * flagAltitude / gravity);
  flag.flightTime        = 0.0f;
  flag.flightEnd         = flightTime;
  flag.initialVelocity   = -0.5f * gravity * flightTime;
  dropDone               = TimeKeeper::getCurrent();
  dropDone              += flightTime;

  if (flag.type == Flags::Null)
    // pick a random flag
    flag.type = allowedFlags[(int)(allowedFlags.size() * (float)bzfrand())];

  // decide how sticky the flag will be
  if (flag.type->flagQuality == FlagBad)
    flag.endurance = FlagSticky;
  else
    flag.endurance = FlagUnstable;

  // how times will it stick around
  if ((flag.endurance == FlagSticky) || (flag.type == Flags::Thief))
    grabs = 1;
  else
    grabs = int(floor(maxGrabs * (float)bzfrand())) + 1;
}

void *FlagInfo::pack(void *buf)
{
  buf = nboPackUShort(buf, flagIndex);
  buf = FlagInfo::flagList[flagIndex].flag.pack(buf);
  return buf;
}

void FlagInfo::dropFlag(float pos[3], float landingPos[3], bool vanish)
{
  numFlagsInAir++;
  flag.status             = vanish ? FlagGoing : FlagInAir;

  flag.landingPosition[0] = landingPos[0];
  flag.landingPosition[1] = landingPos[1];
  flag.landingPosition[2] = landingPos[2];

  flag.position[0]       = landingPos[0];
  flag.position[1]       = landingPos[1];
  flag.position[2]       = landingPos[2];
  flag.launchPosition[0] = pos[0];
  flag.launchPosition[1] = pos[1];
  flag.launchPosition[2] = pos[2] + BZDBCache::tankHeight;

  // compute flight info -- flight time depends depends on start and end
  // altitudes and desired height above start altitude
  const float gravity        = BZDBCache::gravity;
  const float flagAltitude   = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float thrownAltitude = (flag.type == Flags::Shield) ?
    BZDB.eval(StateDatabase::BZDB_SHIELDFLIGHT) * flagAltitude : flagAltitude;
  const float maxAltitude    = pos[2] + thrownAltitude;
  const float upTime         = sqrtf(-2.0f * thrownAltitude / gravity);
  const float downTime       = sqrtf(-2.0f * (maxAltitude - pos[2]) / gravity);
  const float flightTime     = upTime + downTime;

  dropDone             = TimeKeeper::getCurrent();
  dropDone            += flightTime;
  flag.flightTime      = 0.0f;
  flag.flightEnd       = flightTime;
  flag.initialVelocity = -gravity * upTime;
}

void FlagInfo::resetFlag(float position[3], bool teamIsEmpty)
{
  // reset a flag's info
  player      = -1;
  // if it's a random flag, reset flag id
  if (flagIndex >= numFlags - numExtraFlags)
    flag.type = Flags::Null;

  flag.position[0] = position[0];
  flag.position[1] = position[1];
  flag.position[2] = position[2];

  // required flags mustn't just disappear
  if (required) {
    if (flag.type->flagTeam == ::NoTeam)
      // flag in now entering game
      addFlag();
    else if (teamIsEmpty)
      flag.status = FlagNoExist;
    else
      flag.status = FlagOnGround;
  } else {
    flag.status = FlagNoExist;
  }
}

void FlagInfo::grab(int playerIndex)
{
  flag.status = FlagOnTank;
  flag.owner  = playerIndex;
  player      = playerIndex;
  numShots    = 0;
}

int FlagInfo::teamIndex()
{
  return flag.type->flagTeam;
}

int FlagInfo::getIndex()
{
  return flagIndex;
}

float FlagInfo::getNextDrop(TimeKeeper &tm)
{
  // find timeout when next flag would hit ground
  float waitTime = 3.0f;
  if (numFlagsInAir > 0) {
    for (int i = 0; i < numFlags; i++) {
      FlagInfo &flag = flagList[i];
      if (flag.flag.status != FlagNoExist &&
	  flag.flag.status != FlagOnTank &&
	  flag.flag.status != FlagOnGround &&
	  flag.dropDone - tm < waitTime)
	waitTime = flag.dropDone - tm;
    }
  }
  return waitTime;
}

bool FlagInfo::landing(const TimeKeeper &tm)
{
  if (numFlagsInAir <= 0)
    return false;

  bool land = false;
  if (flag.status == FlagInAir || flag.status == FlagComing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagOnGround;
      numFlagsInAir--;
      land        = true;
    }
  } else if (flag.status == FlagGoing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagNoExist;
      numFlagsInAir--;
      land        = true;
    }
  }
  return land;
}

void FlagInfo::setNoFlagInAir()
{
  numFlagsInAir = 0;
}

void FlagInfo::getTextualInfo(char *message)
{
  sprintf(message, "%d p:%d r:%d g:%d i:%s s:%d p:%3.1fx%3.1fx%3.1f",
	  flagIndex, player, required, grabs, flag.type->flagAbbv, flag.status,
	  flag.position[0], flag.position[1], flag.position[2]);
}

bool FlagInfo::exist()
{
  return flag.status != FlagNoExist;
}

FlagInfo *FlagInfo::get(int index)
{
  if (index < 0)
    return NULL;
  if (index >= numFlags)
    return NULL;
  return &flagList[index];
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>
/*The MIT License (MIT)
 *
 * Copyright (c) 2017, Scanse, LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "ros/ros.h"
#include <iostream>
#include <pcl/point_types.h>
#include "sensor_msgs/PointCloud2.h"
#include <pcl/point_cloud.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/io/pcd_io.h>
#include <neo/neo.hpp>

#include <dynamic_reconfigure/server.h>
#include <neo_ros_pc2/FilterConfig.h>
#include <neo_ros_pc2/neo_filter.h>
#include <neo_ros_pc2/datatypes.h>

typedef dynamic_reconfigure::Server<neo_ros_pc2::FilterConfig> FilterConfigServer;

neo_filter::Config filter_config;

void callback(neo_ros_pc2::FilterConfig &config, uint32_t level) {
    // filter config
    filter_config.MedianFilter = config.median_filter_;
    filter_config.MedianFilterWindowsSize = config.median_filter_half_windows_size_ * 2 + 1;
    filter_config.ClosedPointFilter = config.close_point_filter_;
    filter_config.ClosePointDistance = config.close_point_distance_;
    filter_config.MaxDistance = config.max_distance_;

    ROS_DEBUG("Reconfigure Request:");
    ROS_DEBUG("  median_filter: %s", config.median_filter_ ? "True" : "False");
    ROS_DEBUG("  median_filter_windows_size_: %d", config.median_filter_half_windows_size_);
    ROS_DEBUG("  close_point_filter: %s", config.close_point_filter_ ? "True" : "False");
    ROS_DEBUG("  close_point_distance: %d", config.close_point_distance_);

}

float median_value(PointCloudXY::Ptr pointcloud) {
    float value;
    int large, equal, less;

    for (unsigned int i = 0; i < pointcloud->points.size(); i++) {
        large = 0; equal = 0; less = 0;
        value = pointcloud->points[i].y;
        for (unsigned int j = 0; j < pointcloud->points.size(); j++) {
            if (i == j) continue;
            if (pointcloud->points[j].y == value) equal++;
            else if (pointcloud->points[j].y > value) large++;
            else less++;
        }
        if (large > less + equal || less > large + equal)
            continue;
        else
            break;
    }
    return value;
}

void median_filter(PointCloudXY::Ptr pointcloud) {
    int half_windows_size;
    //pcl::PointCloud<pcl::PointXYZ> temp_pc;
    PointCloudXY::Ptr temp_pc(new PointCloudXY);

    half_windows_size = std::floor(filter_config.MedianFilterWindowsSize / 2);
    pcl::copyPointCloud(*pointcloud, *temp_pc);

    for (int i = 0; i < (int)temp_pc->points.size(); i++) {
        // construct the fix filter window
        PointCloudXY::Ptr fixed_windows_size_pc(new PointCloudXY);
        for (int j = i - half_windows_size; j <= i + half_windows_size; j++) {
            if (j < 0)
                fixed_windows_size_pc->push_back(temp_pc->points[j+temp_pc->points.size()]);
            else if (j >= (int)temp_pc->points.size())
                fixed_windows_size_pc->push_back(temp_pc->points[j-temp_pc->points.size()]);
            else
                fixed_windows_size_pc->push_back(temp_pc->points[j]);
        }

        pointcloud->points[i].x = temp_pc->points[i].x;
        pointcloud->points[i].y = median_value(fixed_windows_size_pc);
        // std::cout << i << ": " << pointcloud->points[i].x << " "
        //     << pointcloud->points[i].y << " "
        //     << "origin point: "
        //     << temp_pc->points[i].x << " "
        //     << temp_pc->points[i].y << std::endl;
    }

}

void publish_scan(ros::Publisher *pub,
                  const neo::scan *scan, std::string frame_id)
{
    PointCloudXYZ::Ptr pub_cloud(new PointCloudXYZ);

    PointCloudXY::Ptr polar_cloud(new PointCloudXY);
    PointCloudXY::Ptr cartesian_cloud(new PointCloudXY);

    sensor_msgs::PointCloud2 cloud_msg;
    // ros::Time ros_time_now = ros::Time::now();

    float angle;
    int32_t range;
    float x;
    float y;
    int i = 0;

    polar_cloud->height = 1;
    polar_cloud->width = scan->samples.size();
    polar_cloud->resize(polar_cloud->width * polar_cloud->height);

    for (const neo::sample& sample : scan->samples)
    {
        range = sample.distance;
        angle = ((float)sample.angle / 1000); //millidegrees to degrees
        if (filter_config.ClosedPointFilter) {
            if (range < filter_config.ClosePointDistance || range > filter_config.MaxDistance)
                continue;
        }

        polar_cloud->points[i].y = float(range);
        polar_cloud->points[i].x = angle;

        if (i >= 1) {
            if (angle == polar_cloud->points[i-1].x) continue;
        }
        i++;
    }

    if (i <= 1) return;
    polar_cloud->width = i;
    polar_cloud->points.resize(i * polar_cloud->height);

    if (filter_config.MedianFilter)
        median_filter(polar_cloud);

    cartesian_cloud->height = 1;
    cartesian_cloud->width = i;
    cartesian_cloud->points.resize(cartesian_cloud->width * cartesian_cloud->height);

    for (size_t index = 0; index < polar_cloud->points.size(); index++) {
        angle = polar_cloud->points[index].x;
        range = polar_cloud->points[index].y;

        // Polar to Cartesian Conversion
        x = ((float)range * cos(DEG2RAD(angle)));
        y = ((float)range * sin(DEG2RAD(angle)));
        cartesian_cloud->points[index].x = x;
        cartesian_cloud->points[index].y = y;
    }

		for (size_t ii = 0; ii < cartesian_cloud->points.size(); ii++) {
			cartesian_cloud->points[ii].x /= 100;
			cartesian_cloud->points[ii].y /= 100;
		}
		pcl::copyPointCloud(*cartesian_cloud, *pub_cloud);
	//Convert pcl PC to ROS PC2
	pcl::toROSMsg(*pub_cloud, cloud_msg);
	cloud_msg.header.frame_id = frame_id;
	cloud_msg.header.stamp = ros::Time::now();

	ROS_DEBUG("Publishing a full scan");
	pub->publish(cloud_msg);
}

int main(int argc, char *argv[]) try
{
    //Initialize Node and handles
    ros::init(argc, argv, "neo_node");
    ros::NodeHandle nh;
    ros::NodeHandle nh_private("~");

    //Get Serial Parameters
    std::string serial_port;
    nh_private.param<std::string>("serial_port", serial_port, "/dev/ttyUSB0");
    int serial_baudrate;
    nh_private.param<int>("serial_baudrate", serial_baudrate, 115200);

    //Get Scanner Parameters
    int rotation_speed;
    nh_private.param<int>("rotation_speed", rotation_speed, 5);

    //Get frame id Parameters
    std::string frame_id;
    nh_private.param<std::string>("frame_id", frame_id, "laser_frame");

    //Setup Publisher
    ros::Publisher scan_pub = nh.advertise<sensor_msgs::PointCloud2>("pc2", 1000);
    //ros::Publisher interpolation_pub = nh.advertise<sensor_msgs::PointCloud2>("interpolation", 1000);

    //Create Neo Driver Object
    neo::neo device{serial_port.c_str(), serial_baudrate};
    ROS_INFO("Device connect successful!");

    //Send Rotation Speed
    device.set_motor_speed(rotation_speed);

    ROS_INFO("expected rotation frequency: %d (Hz)", rotation_speed);

    //Start Scan
    device.start_scanning();

    // dynamic_reconfigure server
    FilterConfigServer server;
    FilterConfigServer::CallbackType f;
    f = boost::bind(&callback, _1, _2);
    server.setCallback(f);

    while (ros::ok())
    {
        const neo::scan scan = device.get_scan();
        //Grab Full Scan

        publish_scan(&scan_pub, &scan, frame_id);

        ros::spinOnce();
    }

    //Stop Scanning & Destroy Driver
    device.stop_scanning();
    device.set_motor_speed(0);
} catch (const neo::device_error& e) {
      ROS_ERROR_STREAM("Error: " << e.what() << std::endl);
}
<commit_msg>style(code style): change the style of code<commit_after>
/*The MIT License (MIT)
 *
 * Copyright (c) 2017, Scanse, LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "ros/ros.h"
#include <iostream>
#include <pcl/point_types.h>
#include "sensor_msgs/PointCloud2.h"
#include <pcl/point_cloud.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/io/pcd_io.h>
#include <neo/neo.hpp>

#include <dynamic_reconfigure/server.h>
#include <neo_ros_pc2/FilterConfig.h>
#include <neo_ros_pc2/neo_filter.h>
#include <neo_ros_pc2/datatypes.h>

typedef dynamic_reconfigure::Server<neo_ros_pc2::FilterConfig> FilterConfigServer;

neo_filter::Config filter_config;

void callback(neo_ros_pc2::FilterConfig &config, uint32_t level) {
  // filter config
  filter_config.MedianFilter = config.median_filter_;
  filter_config.MedianFilterWindowsSize =
    config.median_filter_half_windows_size_ * 2 + 1;
  filter_config.ClosedPointFilter = config.close_point_filter_;
  filter_config.ClosePointDistance = config.close_point_distance_;
  filter_config.MaxDistance = config.max_distance_;

  ROS_DEBUG("Reconfigure Request:");
  ROS_DEBUG("  median_filter: %s", config.median_filter_ ? "True" : "False");
  ROS_DEBUG("  median_filter_windows_size_: %d",
      config.median_filter_half_windows_size_);
  ROS_DEBUG("  close_point_filter: %s",
      config.close_point_filter_ ? "True" : "False");
  ROS_DEBUG("  close_point_distance: %d", config.close_point_distance_);

}

float median_value(PointCloudXY::Ptr pointcloud) {
    float value;
    int large, equal, less;

    for (unsigned int i = 0; i < pointcloud->points.size(); i++) {
        large = 0; equal = 0; less = 0;
        value = pointcloud->points[i].y;
        for (unsigned int j = 0; j < pointcloud->points.size(); j++) {
            if (i == j) continue;
            if (pointcloud->points[j].y == value) equal++;
            else if (pointcloud->points[j].y > value) large++;
            else less++;
        }
        if (large > less + equal || less > large + equal)
            continue;
        else
            break;
    }
    return value;
}

void median_filter(PointCloudXY::Ptr pointcloud) {
    int half_windows_size;
    //pcl::PointCloud<pcl::PointXYZ> temp_pc;
    PointCloudXY::Ptr temp_pc(new PointCloudXY);

    half_windows_size = std::floor(filter_config.MedianFilterWindowsSize / 2);
    pcl::copyPointCloud(*pointcloud, *temp_pc);

    for (int i = 0; i < (int)temp_pc->points.size(); i++) {
        // construct the fix filter window
        PointCloudXY::Ptr fixed_windows_size_pc(new PointCloudXY);
        for (int j = i - half_windows_size; j <= i + half_windows_size; j++) {
            if (j < 0)
                fixed_windows_size_pc->push_back(
                    temp_pc->points[j+temp_pc->points.size()]);
            else if (j >= (int)temp_pc->points.size())
                fixed_windows_size_pc->push_back(
                    temp_pc->points[j-temp_pc->points.size()]);
            else
                fixed_windows_size_pc->push_back(temp_pc->points[j]);
        }

        pointcloud->points[i].x = temp_pc->points[i].x;
        pointcloud->points[i].y = median_value(fixed_windows_size_pc);
        // std::cout << i << ": " << pointcloud->points[i].x << " "
        //     << pointcloud->points[i].y << " "
        //     << "origin point: "
        //     << temp_pc->points[i].x << " "
        //     << temp_pc->points[i].y << std::endl;
    }

}

void publish_scan(ros::Publisher *pub,
                  const neo::scan *scan, std::string frame_id)
{
    PointCloudXYZ::Ptr pub_cloud(new PointCloudXYZ);

    PointCloudXY::Ptr polar_cloud(new PointCloudXY);
    PointCloudXY::Ptr cartesian_cloud(new PointCloudXY);

    sensor_msgs::PointCloud2 cloud_msg;
    // ros::Time ros_time_now = ros::Time::now();

    float angle;
    int32_t range;
    float x;
    float y;
    int i = 0;

    polar_cloud->height = 1;
    polar_cloud->width = scan->samples.size();
    polar_cloud->resize(polar_cloud->width * polar_cloud->height);

    for (const neo::sample& sample : scan->samples)
    {
        range = sample.distance;
        angle = ((float)sample.angle / 1000); //millidegrees to degrees
        if (filter_config.ClosedPointFilter) {
            if (range < filter_config.ClosePointDistance ||
                range > filter_config.MaxDistance)
                continue;
        }

        polar_cloud->points[i].y = float(range);
        polar_cloud->points[i].x = angle;

        if (i >= 1) {
            if (angle == polar_cloud->points[i-1].x) continue;
        }
        i++;
    }

    if (i <= 1) return;
    polar_cloud->width = i;
    polar_cloud->points.resize(i * polar_cloud->height);

    if (filter_config.MedianFilter)
        median_filter(polar_cloud);

    cartesian_cloud->height = 1;
    cartesian_cloud->width = i;
    cartesian_cloud->points.resize(
        cartesian_cloud->width * cartesian_cloud->height);

    for (size_t index = 0; index < polar_cloud->points.size(); index++) {
        angle = polar_cloud->points[index].x;
        range = polar_cloud->points[index].y;

        // Polar to Cartesian Conversion
        x = ((float)range * cos(DEG2RAD(angle)));
        y = ((float)range * sin(DEG2RAD(angle)));
        cartesian_cloud->points[index].x = x;
        cartesian_cloud->points[index].y = y;
    }

    for (size_t ii = 0; ii < cartesian_cloud->points.size(); ii++) {
      cartesian_cloud->points[ii].x /= 100;
      cartesian_cloud->points[ii].y /= 100;
    }
    pcl::copyPointCloud(*cartesian_cloud, *pub_cloud);
  //Convert pcl PC to ROS PC2
  pcl::toROSMsg(*pub_cloud, cloud_msg);
  cloud_msg.header.frame_id = frame_id;
  cloud_msg.header.stamp = ros::Time::now();

  ROS_DEBUG("Publishing a full scan");
  pub->publish(cloud_msg);
}

int main(int argc, char *argv[]) try
{
    //Initialize Node and handles
    ros::init(argc, argv, "neo_node");
    ros::NodeHandle nh;
    ros::NodeHandle nh_private("~");

    //Get Serial Parameters
    std::string serial_port;
    nh_private.param<std::string>("serial_port", serial_port, "/dev/ttyUSB0");
    int serial_baudrate;
    nh_private.param<int>("serial_baudrate", serial_baudrate, 115200);

    //Get Scanner Parameters
    int rotation_speed;
    nh_private.param<int>("rotation_speed", rotation_speed, 5);

    //Get frame id Parameters
    std::string frame_id;
    nh_private.param<std::string>("frame_id", frame_id, "laser_frame");

    //Setup Publisher
    ros::Publisher scan_pub =
      nh.advertise<sensor_msgs::PointCloud2>("pc2", 1000);
    //ros::Publisher interpolation_pub =
    //  nh.advertise<sensor_msgs::PointCloud2>("interpolation", 1000);

    //Create Neo Driver Object
    neo::neo device{serial_port.c_str(), serial_baudrate};
    ROS_INFO("Device connect successful!");

    //Send Rotation Speed
    device.set_motor_speed(rotation_speed);

    ROS_INFO("expected rotation frequency: %d (Hz)", rotation_speed);

    //Start Scan
    device.start_scanning();

    // dynamic_reconfigure server
    FilterConfigServer server;
    FilterConfigServer::CallbackType f;
    f = boost::bind(&callback, _1, _2);
    server.setCallback(f);

    while (ros::ok())
    {
        const neo::scan scan = device.get_scan();
        //Grab Full Scan

        publish_scan(&scan_pub, &scan, frame_id);

        ros::spinOnce();
    }

    //Stop Scanning & Destroy Driver
    device.stop_scanning();
    device.set_motor_speed(0);
} catch (const neo::device_error& e) {
      ROS_ERROR_STREAM("Error: " << e.what() << std::endl);
}
<|endoftext|>


<commit_before>int main() {

    int x = 5;
    for(int rok=2014; rok<2114; rok++, x--)
    {
        if(rok%4==0 && rok!=2100) x--;

        if(x <= 0) x+= 7;
        printf("%d %d\n", x, x+1);
    }

    return 0;
}<commit_msg>MWPZ 2013: Task D<commit_after>int main() {

    int x = 5;
    for(int year=2014; year<2114; year++, x--)
    {
        if(year%4==0 && year!=2100) x--;

        if(x <= 0) x+= 7;
        printf("%d %d\n", x, x+1);
    }

    return 0;
}<|endoftext|>


<commit_before>//#define USE_REGULAR_QUEUE //comment our if you use priority-queue
/*
  This provides an implementation of Gauss sieving, including using
  tuples of vectors in fplll framework. The Gauss Sieve code is
  based on Panagiotis Voulgaris's implementation of the Gauss sieve.
*/
#include "sieve_main.h"
#include "fplll.h"
#include "LatticePoint.h"
#include "PointList.h"
#include <thread>
#include <chrono>
#include "SieveGauss.h"
#include "LatticePoint2.h"
#include "TermCondNew.h"
#include "FilteredPoint.h"

using namespace fplll;
//using namespace LatticeApproximations;

/**
 * help function
 */
//static void main_usage(char *myself)
//{
//  cout << "Usage: " << myself << " [options]\n"
//       << "List of options:\n"
//       << "  -a [2|3|4]\n"
//       << "     2- or 3- or 4-sieve;\n"
//       << "  -f filename\n"
//       << "     Input filename\n"
//       << "  -r nnn\n"
//       << "     Generate a random instance of dimension nnn\n"
//       << "  -t nnn\n"
//       << "     Targeted norm^2=nnn\n"
//       << "  -s nnn\n"
//       << "     Using seed=nnn\n"
//       << "  -b nnn\n"
//       << "     BKZ preprocessing of blocksize=nnn\n"
//       << "  -v\n"
//       << "     Verbose mode\n";
//  exit(0);
//}

/**
 * run sieve
 */

#if 0
template <class ZT> int main_run_sieve(ZZ_mat<ZT> B, Z_NR<ZT> goal_norm, int alg, int ver, int seed)
{
  /*
   GaussSieve<ZT, FP_NR<double>> gsieve(B, alg, ver, seed);
  gsieve.set_goal_norm2(goal_norm);
  if (gsieve.alg == 3)
    gsieve.run_3sieve();
  else if (gsieve.alg == 4)
    gsieve.run_4sieve();
  else
    gsieve.run_2sieve();
   */
  return 0;
}
#endif

/**
 * main function
 */

/*
template<class DT>
void ListTester(ListMultiThreaded<DT> * const Z, GarbageBin<DT> * const gb, int id,int verbose)
{
for (int i=0; i <25; ++i)
{
    int count =0;
    int insertions=0;
    int deletions =0;
    for(MTListIterator<DT> it = Z->begin(); !it.is_end(); ++it)
    {
        ++count;
        DT tmp = *it;
        if(( tmp * tmp + i + 33*id) % 39 == 11)
        {
        Z->unlink(it,*gb);
        if (verbose>=2) cout << "Deleted";
        ++deletions;
        }
        if(( tmp * tmp + i + 18*id) %57 ==13  )
        {
        Z->insert(it, 1000000*id + 100* i + ((tmp * tmp )%93) );
        if (verbose>=2) cout << "Inserted";
        ++insertions;
        }
    }
    if (verbose>=1)
    {
    cout << "Thread " << id <<", iteration " << i << "count: " <<count <<" deletes: "<<deletions << "inserts: "<< insertions<<endl;
    }
    MTListIterator<DT> it = Z->end();
    Z->insert(it, 1000000*id + 100*i + 1);
}
return;
}

*/

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

    char *target_norm_string = NULL;
    int opt, dim = 10;
    Z_NR<mpz_t> target_norm;
    target_norm = 0;
    int k=2;

    if (argc == 1)
    {
        cout << "Please provide the dimension." << endl;
        return -1;
    }

    while ((opt = getopt(argc, argv, "d:t:k:")) != -1) {
        switch (opt) {
            case 'd':
                dim = atoi(optarg);
                break;
            case 't':
                target_norm_string = optarg;
                break;
            case 'k':
                k=atoi(optarg);
        }
    }

    if (target_norm_string!=NULL)
    {
        target_norm.set_str(target_norm_string);
    }
    if(target_norm > 0)
    {
        cout << "target norm set: " << target_norm << endl;
    }

    // ZZ_mat is an integer row-oriented matrix. See /nr/matrix.h
    ZZ_mat<mpz_t> B;

    B.resize(dim, dim);

    //generates a lower-triangular matrix B; the argument determines (in a complicated way) the bit-size of entries
    //B.gen_trg(1.1);

    srand (1);
    //generates GM lattice
    B.gen_qary_prime(1, 10*dim);

    //KleinSampler<ZT, F> is templated by two classes; returns NumVect<Z_NR<ZT> of dim = B.NumCols()
    //    KleinSampler<mpz_t, FP_NR<double>> *Sampler = new KleinSampler<mpz_t, FP_NR<double>>(B, 0, 234234);
    //    NumVect<Z_NR<mpz_t> > sample(dim);
    //    sample = Sampler->sample();
    //    cout << sample << endl;

    lll_reduction(B, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER);

    /* preprocessing of basis */
    clock_t stime = clock();
    //lll_reduction(B, 0.75, 0.51, LM_WRAPPER);
    //bkzReduction(B, 20, BKZ_DEFAULT, FT_DEFAULT, 0);

    clock_t etime = clock();
    double secs = (etime - stime) / (double) CLOCKS_PER_SEC;
    cout << "# [info] LLL took time " << secs << " s" << endl;

    //ApproxLatticePoint<Z_NR<mpz_t>,false,-1> X ( conv_matrixrow_to_lattice_point(B[0]) );

    //ApproxLatticePoint<Z_NR<mpz_t>,false,-1> p ( conv_matrixrow_to_lattice_point(B[1]) );
    //int32_t inner_prod = LatticeApproximations::compute_sc_prod(X.get_approx(), p.get_approx(), dim);

    //cout << inner_prod << endl;

    //cout << "A point from a filtered list: " << l.getApproxVector() << " sc_prod: " << l.get_sc_prod() << endl;

    //cout << X;
    bool constexpr multithreaded = false;

    #ifndef USE_REGULAR_QUEUE
        cout << "Use Priority Queue" << endl;
    #else
        cout << "Use Standard Queue" << endl;
    #endif
    //cout << "run sieve on B[0] = " << B[0] << endl;
    //cout << "B[1] = " << B[1] << endl;
    auto start = std::chrono::high_resolution_clock::now();

	Sieve<Z_NR< mpz_t > , multithreaded> Test_2Sieve (B);
	TerminationCondition<Z_NR<mpz_t>,multithreaded> * termcond = new MinkowskiTerminationCondition<Z_NR<mpz_t>, multithreaded>;
	Test_2Sieve.set_termination_condition(termcond);
	if(target_norm!=0)
    {
        delete termcond;
        termcond = new LengthTerminationCondition<Z_NR<mpz_t>,multithreaded>(target_norm);
        Test_2Sieve.set_termination_condition(termcond);
        cout << "Setting target norm2 to" << target_norm << endl << flush;
    }

    //Test_2Sieve.run();
	//cout << "sv is " << endl;
    //Test_2Sieve.get_shortest_vector_found().printLatticePoint();
    //Test_2Sieve.print_status();

    Sieve<Z_NR<mpz_t>, false> Test_3Sieve(B, k);
    TerminationCondition<Z_NR<mpz_t>,false> * termcond2 = new MinkowskiTerminationCondition<Z_NR<mpz_t>, false>;
    Test_3Sieve.set_termination_condition(termcond2); //if this is commented out, the next line segfaults
    Test_3Sieve.run();

    auto finish = std::chrono::high_resolution_clock::now();
    auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(finish-start);
    cout << " Time taken: " << microseconds.count()/1000000.0 << "sec" << endl;
    delete termcond;
#if 0
#if 0
  dot_time = 0;
  dot_num = 0;
  count_bad = 0;
#endif

  alg = 2;

  /* parse */
  if (argc == 1)
  {
    main_usage(argv[0]);
    return -1;
  }
  while ((option = getopt(argc, argv, "a:f:r:t:s:b:v")) != -1)
  {
    switch (option)
    {
    case 'a':
      alg = atoi(optarg);
      if (alg != 2 && alg != 3 && alg != 4)
      {
        cout << " Error, only support 2-, 3- and 4-sieve" << endl;
        exit(1);
      }
    case 'f':
      input_file_name = optarg;
      flag_file       = true;
      break;
    case 'r':
      dim       = atoi(optarg);
      flag_file = false;
      break;
    case 's':
      seed = atoi(optarg);
      break;
    case 'b':
      bs = atoi(optarg);
      break;
    case 'v':
      flag_verbose = true;
      break;
    case 't':
      // ngoal_norm = atol(optarg);
      cout << optarg << endl;
      goal_norm_s = optarg;
      break;
    case 'h':
      main_usage(argv[0]);
      return -1;
    case '?':
      main_usage(argv[0]);
      return -1;
    case ':':
      main_usage(argv[0]);
      return -1;
    }
  }

  /* set lattice */
  ZZ_mat<mpz_t> B;
  if (flag_file)
  {
    ifstream input_file(input_file_name);
    if (input_file.is_open())
    {
      input_file >> B;
      input_file.close();
    }
    else
    {
      cin >> B;
    }
    if (flag_verbose)
    {
      cout << "# [info] reading lattice of dimension " << B.get_rows() << "x" << B.get_cols()
           << endl;
    }
  }
  else
  {
    if (flag_verbose)
    {
      cout << "# [info] generating random lattice of dimension " << dim << endl;
    }
    srand(time(NULL));
    B.resize(dim, dim);
    //B.gen_trg(1.1);
    BTest.gen_qary_prime(1, 10*dim);
  }

  /* set targeted norm */
  Z_NR<mpz_t> goal_norm, max;
  if (goal_norm_s != NULL)
  {
    goal_norm.set_str(goal_norm_s);
  }
  if (goal_norm < 0)
    goal_norm = 0;
  if (flag_verbose)
    cout << "# [info] goal norm^2 is " << goal_norm << endl;

  /* preprocessing of basis */
  clock_t stime = clock();
  if (bs > 0)
    bkz_reduction(B, bs, BKZ_DEFAULT, FT_DEFAULT, 0);
  else
    lll_reduction(B, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER);

  clock_t etime = clock();
  double secs   = (etime - stime) / (double)CLOCKS_PER_SEC;
  if (flag_verbose)
  {
    if (bs > 0)
      cout << "# [info] BKZ took time " << secs << " s" << endl;
    else
      cout << "# [info] LLL took time " << secs << " s" << endl;
  }
  // cout << B << endl;

  /* decide integer type */
  stime = clock();
  max   = B.get_max();

#if 1
  if (max < std::numeric_limits<int>::max())
  {
    long goal_norm_l = abs(goal_norm.get_si());
    Z_NR<long> goal_norm_lt;
    goal_norm_lt = goal_norm_l;
    ZZ_mat<long> B2(B.get_rows(), B.get_cols());
    for (int i = 0; i < B.get_rows(); i++)
      for (int j = 0; j < B.get_cols(); j++)
        B2(i, j) = B(i, j).get_si();
    main_run_sieve<long>(B2, goal_norm_lt, alg, flag_verbose, seed);
  }
  else
#endif
 //   main_run_sieve<mpz_t>(B, goal_norm, alg, flag_verbose, seed); //commented out for test

  etime = clock();
  secs  = (etime - stime) / (double)CLOCKS_PER_SEC;
  if (flag_verbose)
  {
    cout << "# [info] sieve took time " << secs << " s" << endl;
/* dot product time */
#if 0
    cout << "# [info] dot_time " << dot_time << endl;
    cout << "# [info] dot_num " << dot_num << endl;
    cout << "# [info] dot_time/dot_number " << (double) dot_time/dot_num << endl;
#endif
  }
#endif
  return 1;
}
<commit_msg>Added possibility to bkz reduce the input. New option -b<commit_after>//#define USE_REGULAR_QUEUE //comment our if you use priority-queue
/*
  This provides an implementation of Gauss sieving, including using
  tuples of vectors in fplll framework. The Gauss Sieve code is
  based on Panagiotis Voulgaris's implementation of the Gauss sieve.
*/
#include "sieve_main.h"
#include "fplll.h"
#include "LatticePoint.h"
#include "PointList.h"
#include <thread>
#include <chrono>
#include "SieveGauss.h"
#include "LatticePoint2.h"
#include "TermCondNew.h"
#include "FilteredPoint.h"

using namespace fplll;
//using namespace LatticeApproximations;

/**
 * help function
 */
//static void main_usage(char *myself)
//{
//  cout << "Usage: " << myself << " [options]\n"
//       << "List of options:\n"
//       << "  -a [2|3|4]\n"
//       << "     2- or 3- or 4-sieve;\n"
//       << "  -f filename\n"
//       << "     Input filename\n"
//       << "  -r nnn\n"
//       << "     Generate a random instance of dimension nnn\n"
//       << "  -t nnn\n"
//       << "     Targeted norm^2=nnn\n"
//       << "  -s nnn\n"
//       << "     Using seed=nnn\n"
//       << "  -b nnn\n"
//       << "     BKZ preprocessing of blocksize=nnn\n"
//       << "  -v\n"
//       << "     Verbose mode\n";
//  exit(0);
//}

/**
 * run sieve
 */

#if 0
template <class ZT> int main_run_sieve(ZZ_mat<ZT> B, Z_NR<ZT> goal_norm, int alg, int ver, int seed)
{
  /*
   GaussSieve<ZT, FP_NR<double>> gsieve(B, alg, ver, seed);
  gsieve.set_goal_norm2(goal_norm);
  if (gsieve.alg == 3)
    gsieve.run_3sieve();
  else if (gsieve.alg == 4)
    gsieve.run_4sieve();
  else
    gsieve.run_2sieve();
   */
  return 0;
}
#endif

/**
 * main function
 */

/*
template<class DT>
void ListTester(ListMultiThreaded<DT> * const Z, GarbageBin<DT> * const gb, int id,int verbose)
{
for (int i=0; i <25; ++i)
{
    int count =0;
    int insertions=0;
    int deletions =0;
    for(MTListIterator<DT> it = Z->begin(); !it.is_end(); ++it)
    {
        ++count;
        DT tmp = *it;
        if(( tmp * tmp + i + 33*id) % 39 == 11)
        {
        Z->unlink(it,*gb);
        if (verbose>=2) cout << "Deleted";
        ++deletions;
        }
        if(( tmp * tmp + i + 18*id) %57 ==13  )
        {
        Z->insert(it, 1000000*id + 100* i + ((tmp * tmp )%93) );
        if (verbose>=2) cout << "Inserted";
        ++insertions;
        }
    }
    if (verbose>=1)
    {
    cout << "Thread " << id <<", iteration " << i << "count: " <<count <<" deletes: "<<deletions << "inserts: "<< insertions<<endl;
    }
    MTListIterator<DT> it = Z->end();
    Z->insert(it, 1000000*id + 100*i + 1);
}
return;
}

*/

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

    char *target_norm_string = NULL;
    int opt, dim = 10;
    Z_NR<mpz_t> target_norm;
    target_norm = 0;
    int k=2;
    int bs=2;

    if (argc == 1)
    {
        cout << "Please provide the dimension." << endl;
        return -1;
    }

    while ((opt = getopt(argc, argv, "d:t:k:")) != -1) {
        switch (opt) {
            case 'd':
                dim = atoi(optarg);
                break;
            case 't':
                target_norm_string = optarg;
                break;
            case 'k':
                k=atoi(optarg);
            case 'b':
                bs = atoi(optarg);
            break;
        }
    }

    if (target_norm_string!=NULL)
    {
        target_norm.set_str(target_norm_string);
    }
    if(target_norm > 0)
    {
        cout << "target norm set: " << target_norm << endl;
    }

    // ZZ_mat is an integer row-oriented matrix. See /nr/matrix.h
    ZZ_mat<mpz_t> B;

    B.resize(dim, dim);

    //generates a lower-triangular matrix B; the argument determines (in a complicated way) the bit-size of entries
    //B.gen_trg(1.1);

    srand (1);
    //generates GM lattice
    B.gen_qary_prime(1, 10*dim);

    //KleinSampler<ZT, F> is templated by two classes; returns NumVect<Z_NR<ZT> of dim = B.NumCols()
    //    KleinSampler<mpz_t, FP_NR<double>> *Sampler = new KleinSampler<mpz_t, FP_NR<double>>(B, 0, 234234);
    //    NumVect<Z_NR<mpz_t> > sample(dim);
    //    sample = Sampler->sample();
    //    cout << sample << endl;

    /* preprocessing of basis */
    clock_t stime = clock();
    if (bs > 0)
        bkz_reduction(B, bs, BKZ_DEFAULT, FT_DEFAULT, 0);
    else
        lll_reduction(B, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER);

    clock_t etime = clock();
    double secs   = (etime - stime) / (double)CLOCKS_PER_SEC;

    if (bs > 0)
        cout << "# [info] BKZ took time " << secs << " s" << endl;
    else
        cout << "# [info] LLL took time " << secs << " s" << endl;

    //ApproxLatticePoint<Z_NR<mpz_t>,false,-1> X ( conv_matrixrow_to_lattice_point(B[0]) );

    //ApproxLatticePoint<Z_NR<mpz_t>,false,-1> p ( conv_matrixrow_to_lattice_point(B[1]) );
    //int32_t inner_prod = LatticeApproximations::compute_sc_prod(X.get_approx(), p.get_approx(), dim);

    //cout << inner_prod << endl;

    //cout << "A point from a filtered list: " << l.getApproxVector() << " sc_prod: " << l.get_sc_prod() << endl;

    //cout << X;
    bool constexpr multithreaded = false;

    #ifndef USE_REGULAR_QUEUE
        cout << "Use Priority Queue" << endl;
    #else
        cout << "Use Standard Queue" << endl;
    #endif
    //cout << "run sieve on B[0] = " << B[0] << endl;
    //cout << "B[1] = " << B[1] << endl;
    auto start = std::chrono::high_resolution_clock::now();

	Sieve<Z_NR< mpz_t > , multithreaded> Test_2Sieve (B);
	TerminationCondition<Z_NR<mpz_t>,multithreaded> * termcond = new MinkowskiTerminationCondition<Z_NR<mpz_t>, multithreaded>;
	Test_2Sieve.set_termination_condition(termcond);
	if(target_norm!=0)
    {
        delete termcond;
        termcond = new LengthTerminationCondition<Z_NR<mpz_t>,multithreaded>(target_norm);
        Test_2Sieve.set_termination_condition(termcond);
        cout << "Setting target norm2 to" << target_norm << endl << flush;
    }

    //Test_2Sieve.run();
	//cout << "sv is " << endl;
    //Test_2Sieve.get_shortest_vector_found().printLatticePoint();
    //Test_2Sieve.print_status();

    Sieve<Z_NR<mpz_t>, false> Test_3Sieve(B, k);
    TerminationCondition<Z_NR<mpz_t>,false> * termcond2 = new MinkowskiTerminationCondition<Z_NR<mpz_t>, false>;
    Test_3Sieve.set_termination_condition(termcond2); //if this is commented out, the next line segfaults
    Test_3Sieve.run();

    auto finish = std::chrono::high_resolution_clock::now();
    auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(finish-start);
    cout << " Time taken: " << microseconds.count()/1000000.0 << "sec" << endl;
    delete termcond;
#if 0
#if 0
  dot_time = 0;
  dot_num = 0;
  count_bad = 0;
#endif

  alg = 2;

  /* parse */
  if (argc == 1)
  {
    main_usage(argv[0]);
    return -1;
  }
  while ((option = getopt(argc, argv, "a:f:r:t:s:b:v")) != -1)
  {
    switch (option)
    {
    case 'a':
      alg = atoi(optarg);
      if (alg != 2 && alg != 3 && alg != 4)
      {
        cout << " Error, only support 2-, 3- and 4-sieve" << endl;
        exit(1);
      }
    case 'f':
      input_file_name = optarg;
      flag_file       = true;
      break;
    case 'r':
      dim       = atoi(optarg);
      flag_file = false;
      break;
    case 's':
      seed = atoi(optarg);
      break;
    case 'b':
      bs = atoi(optarg);
      break;
    case 'v':
      flag_verbose = true;
      break;
    case 't':
      // ngoal_norm = atol(optarg);
      cout << optarg << endl;
      goal_norm_s = optarg;
      break;
    case 'h':
      main_usage(argv[0]);
      return -1;
    case '?':
      main_usage(argv[0]);
      return -1;
    case ':':
      main_usage(argv[0]);
      return -1;
    }
  }

  /* set lattice */
  ZZ_mat<mpz_t> B;
  if (flag_file)
  {
    ifstream input_file(input_file_name);
    if (input_file.is_open())
    {
      input_file >> B;
      input_file.close();
    }
    else
    {
      cin >> B;
    }
    if (flag_verbose)
    {
      cout << "# [info] reading lattice of dimension " << B.get_rows() << "x" << B.get_cols()
           << endl;
    }
  }
  else
  {
    if (flag_verbose)
    {
      cout << "# [info] generating random lattice of dimension " << dim << endl;
    }
    srand(time(NULL));
    B.resize(dim, dim);
    //B.gen_trg(1.1);
    BTest.gen_qary_prime(1, 10*dim);
  }

  /* set targeted norm */
  Z_NR<mpz_t> goal_norm, max;
  if (goal_norm_s != NULL)
  {
    goal_norm.set_str(goal_norm_s);
  }
  if (goal_norm < 0)
    goal_norm = 0;
  if (flag_verbose)
    cout << "# [info] goal norm^2 is " << goal_norm << endl;

  /* preprocessing of basis */
  clock_t stime = clock();
  if (bs > 0)
    bkz_reduction(B, bs, BKZ_DEFAULT, FT_DEFAULT, 0);
  else
      lll_reduction(B, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER);

  clock_t etime = clock();
  double secs   = (etime - stime) / (double)CLOCKS_PER_SEC;
  if (flag_verbose)
  {
    if (bs > 0)
      cout << "# [info] BKZ took time " << secs << " s" << endl;
    else
      cout << "# [info] LLL took time " << secs << " s" << endl;
  }
  // cout << B << endl;

  /* decide integer type */
  stime = clock();
  max   = B.get_max();

#if 1
  if (max < std::numeric_limits<int>::max())
  {
    long goal_norm_l = abs(goal_norm.get_si());
    Z_NR<long> goal_norm_lt;
    goal_norm_lt = goal_norm_l;
    ZZ_mat<long> B2(B.get_rows(), B.get_cols());
    for (int i = 0; i < B.get_rows(); i++)
      for (int j = 0; j < B.get_cols(); j++)
        B2(i, j) = B(i, j).get_si();
    main_run_sieve<long>(B2, goal_norm_lt, alg, flag_verbose, seed);
  }
  else
#endif
 //   main_run_sieve<mpz_t>(B, goal_norm, alg, flag_verbose, seed); //commented out for test

  etime = clock();
  secs  = (etime - stime) / (double)CLOCKS_PER_SEC;
  if (flag_verbose)
  {
    cout << "# [info] sieve took time " << secs << " s" << endl;
/* dot product time */
#if 0
    cout << "# [info] dot_time " << dot_time << endl;
    cout << "# [info] dot_num " << dot_num << endl;
    cout << "# [info] dot_time/dot_number " << (double) dot_time/dot_num << endl;
#endif
  }
#endif
  return 1;
}
<|endoftext|>