<commit_before>/**
 * Copyright (c) 2017 Darius Rückert
 * Licensed under the MIT License.
 * See LICENSE file for more information.
 */
#include "saiga/opengl/rendering/renderer.h"

#include "saiga/core/camera/camera.h"
#include "saiga/core/imgui/imgui_main_menu.h"
#include "saiga/core/util/ini/ini.h"
#include "saiga/opengl/glImageFormat.h"
#include "saiga/opengl/shader/basic_shaders.h"
#include "saiga/opengl/window/OpenGLWindow.h"

namespace Saiga
{
OpenGLRenderer::OpenGLRenderer(OpenGLWindow& window) : window(&window)
{
    editor_gui.enabled = true;
    main_menu.AddItem(
        "Saiga", "Log", []() { console.should_render = !console.should_render; }, 299, "F10");

    cameraBuffer.createGLBuffer(nullptr, sizeof(CameraDataGLSL), GL_DYNAMIC_DRAW);

    ResizeTarget(window.getWidth(), window.getHeight());

    window.setRenderer(this);
    default_framebuffer.MakeDefaultFramebuffer();
    // ImGUI
    imgui = window.createImGui();
    if (imgui)
    {
        timer = std::make_shared<GLTimerSystem>();
    }
}

OpenGLRenderer::~OpenGLRenderer() {}

void OpenGLRenderer::render(const RenderInfo& renderInfo)
{
    SAIGA_ASSERT(renderInfo.cameras.size() == 1);
    SAIGA_ASSERT(target_framebuffer);

    // Size and position of the 3D viewport
    // In editor mode this will be set by the imgui-window
    viewport_size        = ivec2(window->getWidth(), window->getHeight());
    viewport_offset      = ivec2(0, 0);
    bool render_viewport = true;

    // 1. Render the imgui
    //      - If we are in editor mode this will also tell us the 3DView window-size
    if (imgui)
    {
        SAIGA_ASSERT(ImGui::GetCurrentContext());

        imgui->beginFrame();
        window->renderImGui();
        dynamic_cast<RenderingInterface*>(rendering)->render(nullptr, RenderPass::GUI);
        renderImgui();
        console.render();
        timer->Imgui();
#ifdef SAIGA_USE_FFMPEG
        encoder->renderGUI();
#endif

        if (editor_gui.enabled)
        {
            ImGuiWindowFlags flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;

            use_mouse_input_in_3dview    = false;
            use_keyboard_input_in_3dview = false;

            if (ImGui::Begin("3DView", nullptr, flags))
            {
                ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 1));
                ImGui::BeginChild("viewer_child", ImVec2(0, 0), false,
                                  ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove);
                ImGui::PopStyleColor();

                use_mouse_input_in_3dview = ImGui::IsWindowHovered();
                use_keyboard_input_in_3dview =
                    use_mouse_input_in_3dview || (ImGui::IsWindowFocused() && !ImGui::captureKeyboard());

                viewport_offset.x() = ImGui::GetCursorPosX() + ImGui::GetWindowPos().x;
                viewport_offset.y() = ImGui::GetCursorPosY() + ImGui::GetWindowPos().y;

                auto w_size   = ImGui::GetWindowContentRegionMax();
                viewport_size = ivec2(w_size.x, w_size.y);

                ImGui::EndChild();
            }
            else
            {
                render_viewport = false;
            }
            ImGui::End();
        }
    }

    if (!editor_gui.enabled)
    {
        // In Fullscreen mode we check, if a gui element is used
        use_mouse_input_in_3dview    = !ImGui::captureMouse();
        use_keyboard_input_in_3dview = !ImGui::captureKeyboard();
    }

    if (render_viewport)
    {
        // 2. Render 3DView to framebuffer
        ResizeTarget(viewport_size.x(), viewport_size.y());
        Camera* camera = renderInfo.cameras.front().first;
        camera->recomputeProj(outputWidth, outputHeight);
        ViewPort viewport = ViewPort({0, 0}, {outputWidth, outputHeight});
        auto target_fb    = editor_gui.enabled ? target_framebuffer.get() : &default_framebuffer;
        target_fb->bind();
        glClear(GL_COLOR_BUFFER_BIT);

        timer->BeginFrame();
        renderGL(target_fb, viewport, camera);
        timer->EndFrame();
    }

    // 3. Add rendered 3DView to imgui (in editor mode only)
    if (imgui)
    {
        if (editor_gui.enabled && render_viewport)
        {
            ImGui::Begin("3DView");
            ImGui::BeginChild("viewer_child");
            ImGui::Texture(target_framebuffer->getTextureColor(0).get(), ImVec2(viewport_size.x(), viewport_size.y()),
                           true);
            ImGui::EndChild();
            ImGui::End();
        }
        // The imgui frame is now done
        // -> Render it to the screen (default FB)
        imgui->endFrame();
        default_framebuffer.bind();
        imgui->render();
    }

#ifdef SAIGA_USE_FFMPEG
    if (encoder && encoder->isEncoding())
    {
        // feed encoder with 3d viewport
        auto encoder_size = encoder->Size();

        TemplatedImage<ucvec4> result(encoder_size.y(), encoder_size.x());

        if (editor_gui.enabled && record_view_port_only)
        {
            TemplatedImage<ucvec4> tmp(outputHeight, outputWidth);
            auto texture = target_framebuffer->getTextureColor(0);
            texture->download(tmp.data());
            tmp.getImageView().subImageView(0, 0, encoder_size.y(), encoder_size.x()).copyTo(result.getImageView());
        }
        else
        {
            // read data from default framebuffer and restore currently bound fb.
            GLint fb;
            glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb);
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            glReadPixels(0, 0, result.width, result.height, getGlFormat(result.type), getGlType(result.type),
                         result.data());
            glBindFramebuffer(GL_FRAMEBUFFER, fb);
        }

        encoder->frame(result.getImageView().yFlippedImageView());
    }
#endif
}

void OpenGLRenderer::ResizeTarget(int windowWidth, int windowHeight)
{
    if (windowWidth == outputWidth && windowHeight == outputHeight)
    {
        // Already at correct size
        // -> Skip resize
        return;
    }

    if (windowWidth <= 0 || windowHeight <= 0)
    {
        console << "Warning: The window size must be greater than zero." << std::endl;
        windowWidth  = std::max(windowWidth, 1);
        windowHeight = std::max(windowHeight, 1);
    }

    outputWidth  = windowWidth;
    outputHeight = windowHeight;

#ifdef SAIGA_USE_FFMPEG
    // The encoder size must be divisible by 2 for most of the codecs to work
    int encoder_w = iAlignDown(outputWidth, 2);
    int encoder_h = iAlignDown(outputHeight, 2);

    if (!encoder)
    {
        encoder = std::make_shared<VideoEncoder>(encoder_w, encoder_h);
    }
    else
    {
        encoder->resize(encoder_w, encoder_h);
    }
#endif

    if (!target_framebuffer)
    {
        target_framebuffer = std::make_unique<Framebuffer>();
        target_framebuffer->create();

        std::shared_ptr<Texture> color = std::make_shared<Texture>();
        color->create(outputWidth, outputHeight, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE);

        std::shared_ptr<Texture> depth_stencil = std::make_shared<Texture>();
        depth_stencil->create(outputWidth, outputHeight, GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);

        target_framebuffer->attachTexture(color);
        target_framebuffer->attachTextureDepthStencil(depth_stencil);
        target_framebuffer->check();
    }
    else
    {
        target_framebuffer->resize(outputWidth, outputHeight);
    }

    console << "[Renderer] Target resized to " << windowWidth << "x" << windowHeight << std::endl;
}

void OpenGLRenderer::bindCamera(Camera* cam)
{
    CameraDataGLSL cd(cam);
    cameraBuffer.updateBuffer(&cd, sizeof(CameraDataGLSL), 0);
    cameraBuffer.bind(CAMERA_DATA_BINDING_POINT);
}

void RenderingParameters::fromConfigFile(const std::string& file)
{
    Saiga::SimpleIni ini;
    ini.LoadFile(file.c_str());

    //    auto section = "Rendering";

    if (ini.changed()) ini.SaveFile(file.c_str());
}

}  // namespace Saiga
<commit_msg>always create timer<commit_after>/**
 * Copyright (c) 2017 Darius Rückert
 * Licensed under the MIT License.
 * See LICENSE file for more information.
 */
#include "saiga/opengl/rendering/renderer.h"

#include "saiga/core/camera/camera.h"
#include "saiga/core/imgui/imgui_main_menu.h"
#include "saiga/core/util/ini/ini.h"
#include "saiga/opengl/glImageFormat.h"
#include "saiga/opengl/shader/basic_shaders.h"
#include "saiga/opengl/window/OpenGLWindow.h"

namespace Saiga
{
OpenGLRenderer::OpenGLRenderer(OpenGLWindow& window) : window(&window)
{
    editor_gui.enabled = true;
    main_menu.AddItem(
        "Saiga", "Log", []() { console.should_render = !console.should_render; }, 299, "F10");

    cameraBuffer.createGLBuffer(nullptr, sizeof(CameraDataGLSL), GL_DYNAMIC_DRAW);

    ResizeTarget(window.getWidth(), window.getHeight());

    window.setRenderer(this);
    default_framebuffer.MakeDefaultFramebuffer();
    // ImGUI
    imgui = window.createImGui();
    timer = std::make_shared<GLTimerSystem>();
}

OpenGLRenderer::~OpenGLRenderer() {}

void OpenGLRenderer::render(const RenderInfo& renderInfo)
{
    SAIGA_ASSERT(renderInfo.cameras.size() == 1);
    SAIGA_ASSERT(target_framebuffer);

    // Size and position of the 3D viewport
    // In editor mode this will be set by the imgui-window
    viewport_size        = ivec2(window->getWidth(), window->getHeight());
    viewport_offset      = ivec2(0, 0);
    bool render_viewport = true;

    // 1. Render the imgui
    //      - If we are in editor mode this will also tell us the 3DView window-size
    if (imgui)
    {
        SAIGA_ASSERT(ImGui::GetCurrentContext());

        imgui->beginFrame();
        window->renderImGui();
        dynamic_cast<RenderingInterface*>(rendering)->render(nullptr, RenderPass::GUI);
        renderImgui();
        console.render();
        timer->Imgui();
#ifdef SAIGA_USE_FFMPEG
        encoder->renderGUI();
#endif

        if (editor_gui.enabled)
        {
            ImGuiWindowFlags flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;

            use_mouse_input_in_3dview    = false;
            use_keyboard_input_in_3dview = false;

            if (ImGui::Begin("3DView", nullptr, flags))
            {
                ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 1));
                ImGui::BeginChild("viewer_child", ImVec2(0, 0), false,
                                  ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove);
                ImGui::PopStyleColor();

                use_mouse_input_in_3dview = ImGui::IsWindowHovered();
                use_keyboard_input_in_3dview =
                    use_mouse_input_in_3dview || (ImGui::IsWindowFocused() && !ImGui::captureKeyboard());

                viewport_offset.x() = ImGui::GetCursorPosX() + ImGui::GetWindowPos().x;
                viewport_offset.y() = ImGui::GetCursorPosY() + ImGui::GetWindowPos().y;

                auto w_size   = ImGui::GetWindowContentRegionMax();
                viewport_size = ivec2(w_size.x, w_size.y);

                ImGui::EndChild();
            }
            else
            {
                render_viewport = false;
            }
            ImGui::End();
        }
    }

    if (!editor_gui.enabled)
    {
        // In Fullscreen mode we check, if a gui element is used
        use_mouse_input_in_3dview    = !ImGui::captureMouse();
        use_keyboard_input_in_3dview = !ImGui::captureKeyboard();
    }

    if (render_viewport)
    {
        // 2. Render 3DView to framebuffer
        ResizeTarget(viewport_size.x(), viewport_size.y());
        Camera* camera = renderInfo.cameras.front().first;
        camera->recomputeProj(outputWidth, outputHeight);
        ViewPort viewport = ViewPort({0, 0}, {outputWidth, outputHeight});
        auto target_fb    = editor_gui.enabled ? target_framebuffer.get() : &default_framebuffer;
        target_fb->bind();
        glClear(GL_COLOR_BUFFER_BIT);

        SAIGA_ASSERT(timer);
        timer->BeginFrame();
        renderGL(target_fb, viewport, camera);
        timer->EndFrame();
    }

    // 3. Add rendered 3DView to imgui (in editor mode only)
    if (imgui)
    {
        if (editor_gui.enabled && render_viewport)
        {
            ImGui::Begin("3DView");
            ImGui::BeginChild("viewer_child");
            ImGui::Texture(target_framebuffer->getTextureColor(0).get(), ImVec2(viewport_size.x(), viewport_size.y()),
                           true);
            ImGui::EndChild();
            ImGui::End();
        }
        // The imgui frame is now done
        // -> Render it to the screen (default FB)
        imgui->endFrame();
        default_framebuffer.bind();
        imgui->render();
    }

#ifdef SAIGA_USE_FFMPEG
    if (encoder && encoder->isEncoding())
    {
        // feed encoder with 3d viewport
        auto encoder_size = encoder->Size();

        TemplatedImage<ucvec4> result(encoder_size.y(), encoder_size.x());

        if (editor_gui.enabled && record_view_port_only)
        {
            TemplatedImage<ucvec4> tmp(outputHeight, outputWidth);
            auto texture = target_framebuffer->getTextureColor(0);
            texture->download(tmp.data());
            tmp.getImageView().subImageView(0, 0, encoder_size.y(), encoder_size.x()).copyTo(result.getImageView());
        }
        else
        {
            // read data from default framebuffer and restore currently bound fb.
            GLint fb;
            glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb);
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            glReadPixels(0, 0, result.width, result.height, getGlFormat(result.type), getGlType(result.type),
                         result.data());
            glBindFramebuffer(GL_FRAMEBUFFER, fb);
        }

        encoder->frame(result.getImageView().yFlippedImageView());
    }
#endif
}

void OpenGLRenderer::ResizeTarget(int windowWidth, int windowHeight)
{
    if (windowWidth == outputWidth && windowHeight == outputHeight)
    {
        // Already at correct size
        // -> Skip resize
        return;
    }

    if (windowWidth <= 0 || windowHeight <= 0)
    {
        console << "Warning: The window size must be greater than zero." << std::endl;
        windowWidth  = std::max(windowWidth, 1);
        windowHeight = std::max(windowHeight, 1);
    }

    outputWidth  = windowWidth;
    outputHeight = windowHeight;

#ifdef SAIGA_USE_FFMPEG
    // The encoder size must be divisible by 2 for most of the codecs to work
    int encoder_w = iAlignDown(outputWidth, 2);
    int encoder_h = iAlignDown(outputHeight, 2);

    if (!encoder)
    {
        encoder = std::make_shared<VideoEncoder>(encoder_w, encoder_h);
    }
    else
    {
        encoder->resize(encoder_w, encoder_h);
    }
#endif

    if (!target_framebuffer)
    {
        target_framebuffer = std::make_unique<Framebuffer>();
        target_framebuffer->create();

        std::shared_ptr<Texture> color = std::make_shared<Texture>();
        color->create(outputWidth, outputHeight, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE);

        std::shared_ptr<Texture> depth_stencil = std::make_shared<Texture>();
        depth_stencil->create(outputWidth, outputHeight, GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);

        target_framebuffer->attachTexture(color);
        target_framebuffer->attachTextureDepthStencil(depth_stencil);
        target_framebuffer->check();
    }
    else
    {
        target_framebuffer->resize(outputWidth, outputHeight);
    }

    console << "[Renderer] Target resized to " << windowWidth << "x" << windowHeight << std::endl;
}

void OpenGLRenderer::bindCamera(Camera* cam)
{
    CameraDataGLSL cd(cam);
    cameraBuffer.updateBuffer(&cd, sizeof(CameraDataGLSL), 0);
    cameraBuffer.bind(CAMERA_DATA_BINDING_POINT);
}

void RenderingParameters::fromConfigFile(const std::string& file)
{
    Saiga::SimpleIni ini;
    ini.LoadFile(file.c_str());

    //    auto section = "Rendering";

    if (ini.changed()) ini.SaveFile(file.c_str());
}

}  // namespace Saiga
<|endoftext|>


<commit_before>/*
  FN605.h - Library for Flyrontech FN605-M01
  Created by Kevin Stephens, October 6, 2015.
  Released into the public domain.
*/

#include "Arduino.h"
#include "FN605.h"

const int VOLUMES[16] = {0xFFE0,0xFFE1,0xFFE2,0xFFE3,0xFFE4,0xFFE5,0xFFE6,0xFFE7,
                         0xFFE8,0xFFE9,0xFFEA,0xFFEB,0xFFEC,0xFFED,0xFFEE,0xFFEF};

/*
  You can instaniate the object with just the Arduino pin number connected to the
  dataPin ( pin 8 ) of the FN605-M01 or you can also send the Arduino pin number
  connected to the busyPin ( pin 5 ) of the FN605-M01 to prevent playing over the
  top of already playing commands.
*/
FN605::FN605(int dataPin)
{
  pinMode(dataPin, OUTPUT);
  _dataPin = dataPin;
  _busyPin = -1;
}
// Use the busyPin
FN605::FN605(int dataPin, int busyPin)
{
  pinMode(dataPin, OUTPUT);
  if ( busyPin >= 0 )
  {
    pinMode(busyPin, INPUT);
  }
  _dataPin = dataPin;
  _busyPin = busyPin;
}

/*
  play();                 // Play the current file
  play(fileNumber);       // Play a specific file number ( 1 - 3584 )
  play(fileNumber,true);  // Play a specific file number if not already playing a file
*/
void FN605::play()
{
  play(0,false);
}
void FN605::play(int fileNumber)
{
  play(fileNumber,false);
}
void FN605::play(int fileNumber, boolean ifNotBusy)
{
  uint16_t cmd;
  if ( fileNumber >= 1 )
  {
    cmd = (uint16_t) fileNumber;
  } else {
    cmd = 0xFFF0; // Default back to just play if no file number
  }
  sndCmd(cmd,ifNotBusy);
}

/*
  playNext();     // Play next file
  playNext(true); // Play next file if not already playing a file
*/
void FN605::playNext()
{
  playNext(false);
}

void FN605::playNext(boolean ifNotBusy)
{
  sndCmd(0xFFF4,ifNotBusy);
}

/*
  playPrev();     // Play previous file
  playPrev(true); // Play previous file if not already playing a file
*/
void FN605::playPrev()
{
  playPrev(false);
}

void FN605::playPrev(boolean ifNotBusy)
{
  sndCmd(0xFFF5,ifNotBusy);
}

/*
  playRandom();     // Play random loop
  playRandom(true); // Play random loop if not already playing a file
*/
void FN605::playRandom()
{
  playRandom(false);
}

void FN605::playRandom(boolean ifNotBusy)
{
  sndCmd(0xFFF7,ifNotBusy);
}

/*
  singleLoopPlay(); // Loop playing all files one time through
  loopPlay();       // Loop playing all files endlessly
  loopPlayCancel(); // Cancel playing a loop
*/
void FN605::singleLoopPlay()
{
  sndCmd(0xFFF2);
}

void FN605::loopPlay()
{
  sndCmd(0xFFF6);
}

void FN605::loopPlayCancel()
{
  sndCmd(0xFFF3);
}

/*
  pause(); // Pause playing
  stop();  // Stop playing
*/
void FN605::pause()
{
  sndCmd(0xFFF1);
}

void FN605::stop()
{
  sndCmd(0xFFFE);
}

/*
  mute();        // Set volume to level 0
  volume(level); // Set volume to level passed in ( 0 - 15 )
*/
void FN605::mute()
{
  volume(0);
}

void FN605::volume(int level)
{
  int cmd = VOLUMES[level];
  sndCmd(cmd);
}

/*
  isBusy(); // If the busyPin was defined it will check if the FN605-M01 is busy
*/
boolean FN605::isBusy()
{
  if ( _busyPin >= 0 )
  {
    return digitalRead(_busyPin);
  } else {
    return false;
  }
}

/*
  sndCmd(cmdCode);           // Send command without checking for busy
  sndCmd(cmdCode,ifNotBusy); // Send command and check busy based on ifNotBusy parameter
*/
void FN605::sndCmd(uint16_t sndCmdCode)
{
  sndCmd(sndCmdCode,false);
}
void FN605::sndCmd(uint16_t sndCmdCode, boolean ifNotBusy)
{
  if ( ifNotBusy && isBusy() )
  {
    return;
  }
  digitalWrite(_dataPin, LOW);
  delay(5);

  for(int i=0;i<16;i++)
  {
    digitalWrite(_dataPin,HIGH);
    if( sndCmdCode &0x8000) {
      delayMicroseconds(600);
      digitalWrite(_dataPin,LOW);
      delayMicroseconds(200);
    } else {
      delayMicroseconds(200);
      digitalWrite(_dataPin,LOW);
      delayMicroseconds(600);
    }
    sndCmdCode <<=1;
  }
  digitalWrite(_dataPin,HIGH);
  delay(1000);
}<commit_msg>Shortened the delay on sndCmd()<commit_after>/*
  FN605.h - Library for Flyrontech FN605-M01
  Created by Kevin Stephens, October 6, 2015.
  Released into the public domain.
*/

#include "Arduino.h"
#include "FN605.h"

const int VOLUMES[16] = {0xFFE0,0xFFE1,0xFFE2,0xFFE3,0xFFE4,0xFFE5,0xFFE6,0xFFE7,
                         0xFFE8,0xFFE9,0xFFEA,0xFFEB,0xFFEC,0xFFED,0xFFEE,0xFFEF};

/*
  You can instaniate the object with just the Arduino pin number connected to the
  dataPin ( pin 8 ) of the FN605-M01 or you can also send the Arduino pin number
  connected to the busyPin ( pin 5 ) of the FN605-M01 to prevent playing over the
  top of already playing commands.
*/
FN605::FN605(int dataPin)
{
  pinMode(dataPin, OUTPUT);
  _dataPin = dataPin;
  _busyPin = -1;
}
// Use the busyPin
FN605::FN605(int dataPin, int busyPin)
{
  pinMode(dataPin, OUTPUT);
  if ( busyPin >= 0 )
  {
    pinMode(busyPin, INPUT);
  }
  _dataPin = dataPin;
  _busyPin = busyPin;
}

/*
  play();                 // Play the current file
  play(fileNumber);       // Play a specific file number ( 1 - 3584 )
  play(fileNumber,true);  // Play a specific file number if not already playing a file
*/
void FN605::play()
{
  play(0,false);
}
void FN605::play(int fileNumber)
{
  play(fileNumber,false);
}
void FN605::play(int fileNumber, boolean ifNotBusy)
{
  uint16_t cmd;
  if ( fileNumber >= 1 )
  {
    cmd = (uint16_t) fileNumber;
  } else {
    cmd = 0xFFF0; // Default back to just play if no file number
  }
  sndCmd(cmd,ifNotBusy);
}

/*
  playNext();     // Play next file
  playNext(true); // Play next file if not already playing a file
*/
void FN605::playNext()
{
  playNext(false);
}

void FN605::playNext(boolean ifNotBusy)
{
  sndCmd(0xFFF4,ifNotBusy);
}

/*
  playPrev();     // Play previous file
  playPrev(true); // Play previous file if not already playing a file
*/
void FN605::playPrev()
{
  playPrev(false);
}

void FN605::playPrev(boolean ifNotBusy)
{
  sndCmd(0xFFF5,ifNotBusy);
}

/*
  playRandom();     // Play random loop
  playRandom(true); // Play random loop if not already playing a file
*/
void FN605::playRandom()
{
  playRandom(false);
}

void FN605::playRandom(boolean ifNotBusy)
{
  sndCmd(0xFFF7,ifNotBusy);
}

/*
  singleLoopPlay(); // Loop playing all files one time through
  loopPlay();       // Loop playing all files endlessly
  loopPlayCancel(); // Cancel playing a loop
*/
void FN605::singleLoopPlay()
{
  sndCmd(0xFFF2);
}

void FN605::loopPlay()
{
  sndCmd(0xFFF6);
}

void FN605::loopPlayCancel()
{
  sndCmd(0xFFF3);
}

/*
  pause(); // Pause playing
  stop();  // Stop playing
*/
void FN605::pause()
{
  sndCmd(0xFFF1);
}

void FN605::stop()
{
  sndCmd(0xFFFE);
}

/*
  mute();        // Set volume to level 0
  volume(level); // Set volume to level passed in ( 0 - 15 )
*/
void FN605::mute()
{
  volume(0);
}

void FN605::volume(int level)
{
  int cmd = VOLUMES[level];
  sndCmd(cmd);
}

/*
  isBusy(); // If the busyPin was defined it will check if the FN605-M01 is busy
*/
boolean FN605::isBusy()
{
  if ( _busyPin >= 0 )
  {
    return digitalRead(_busyPin);
  } else {
    return false;
  }
}

/*
  sndCmd(cmdCode);           // Send command without checking for busy
  sndCmd(cmdCode,ifNotBusy); // Send command and check busy based on ifNotBusy parameter
*/
void FN605::sndCmd(uint16_t sndCmdCode)
{
  sndCmd(sndCmdCode,false);
}
void FN605::sndCmd(uint16_t sndCmdCode, boolean ifNotBusy)
{
  if ( ifNotBusy && isBusy() )
  {
    return;
  }
  digitalWrite(_dataPin, LOW);
  delay(5);

  for(int i=0;i<16;i++)
  {
    digitalWrite(_dataPin,HIGH);
    if( sndCmdCode &0x8000) {
      delayMicroseconds(600);
      digitalWrite(_dataPin,LOW);
      delayMicroseconds(200);
    } else {
      delayMicroseconds(200);
      digitalWrite(_dataPin,LOW);
      delayMicroseconds(600);
    }
    sndCmdCode <<=1;
  }
  digitalWrite(_dataPin,HIGH);
  delay(40);
}
<|endoftext|>


<commit_before>/*
* @Author: Ubi de Feo | Future Tailors
* @Date:   2017-07-09 16:34:07
* @Last Modified by:   ubi
* @Last Modified time: 2017-07-09 16:41:17
*/

#include "FTDebouncer.h"
/*	CONSTRUCTORS/DESTRUCTOR						*/
FTDebouncer::FTDebouncer() : debounceDelay(40) {
	debouncedItemsCount = 0;
	firstDebounceItem = lastDebounceItem = nullptr;
}
FTDebouncer::FTDebouncer(uint16_t _debounceTime) : debounceDelay(_debounceTime) {
	debouncedItemsCount = 0;
	firstDebounceItem = lastDebounceItem = nullptr;
}
FTDebouncer::~FTDebouncer() {
}

/*	METHODS										*/
void FTDebouncer::addPin(
	uint8_t _pinNr, uint8_t _restState) {
	DebounceItem *dbItem = new DebounceItem();

	dbItem->pinNumber = _pinNr;
	dbItem->restState = _restState;

	if (firstDebounceItem == nullptr) {
		firstDebounceItem = dbItem;
	} else {
		lastDebounceItem->nextItem = dbItem;
	}
	lastDebounceItem = dbItem;

	pinMode(_pinNr, INPUT);
	debouncedItemsCount++;

}
void FTDebouncer::addPin(uint8_t _pinNr, uint8_t _restState, uint8_t _pullUpMode) {
	DebounceItem *dbItem = new DebounceItem();

	dbItem->pinNumber = _pinNr;
	dbItem->restState = _restState;

	if (firstDebounceItem == nullptr) {
		firstDebounceItem = dbItem;
	} else {
		lastDebounceItem->nextItem = dbItem;
	}

	lastDebounceItem = dbItem;

	if (_pullUpMode == 0) {
		pinMode(_pinNr, INPUT);
	} else {
		pinMode(_pinNr, _pullUpMode);
	}

	debouncedItemsCount++;

}

void FTDebouncer::init() {
	unsigned long currentMs = millis();
	DebounceItem *dbItem = firstDebounceItem;

	while (dbItem != nullptr) {
		dbItem->lastTimeChecked = currentMs;
		dbItem->currentState = dbItem->previousState = dbItem->restState;
		dbItem->currentDebouncedState = dbItem->previousDebouncedState = dbItem->restState;
		dbItem = dbItem->nextItem;
	}
}

void FTDebouncer::run() {
	DebounceItem *dbItem = firstDebounceItem;
	while (dbItem != nullptr) {
		dbItem->currentState = digitalRead(dbItem->pinNumber);
		dbItem = dbItem->nextItem;
	}

	debouncePins();
	checkStateChange();
}
void FTDebouncer::debouncePins() {
	unsigned long currentMs = millis();
	DebounceItem *dbItem = firstDebounceItem;
	while (dbItem != nullptr) {
		if (dbItem->currentState != dbItem->previousState) {
			dbItem->lastTimeChecked = currentMs;
		}
		if (currentMs - dbItem->lastTimeChecked > debounceDelay) {
			if (dbItem->previousState == dbItem->currentState) {
				dbItem->lastTimeChecked = currentMs;
				dbItem->currentDebouncedState = dbItem->currentState;
			}
		}
		dbItem->previousState = dbItem->currentState;
		dbItem = dbItem->nextItem;
	}
}

void FTDebouncer::checkStateChange() {
	DebounceItem *dbItem = firstDebounceItem;

	while (dbItem != nullptr) {
		if (dbItem->previousDebouncedState != dbItem->currentDebouncedState) {
			if (dbItem->currentDebouncedState == !dbItem->restState) {
				pinActivated(dbItem->pinNumber);
			}
			if (dbItem->currentDebouncedState == dbItem->restState) {
				pinDeactivated(dbItem->pinNumber);
			}
		}
		dbItem->previousDebouncedState = dbItem->currentDebouncedState;
		dbItem = dbItem->nextItem;
	}
}
uint8_t FTDebouncer::getPinsCount(){
	return debouncedItemsCount;
}<commit_msg>Removed duplicated code by using overloaded function<commit_after>/*
* @Author: Ubi de Feo | Future Tailors
* @Date:   2017-07-09 16:34:07
* @Last Modified by:   ubi
* @Last Modified time: 2017-07-09 16:41:17
*/

#include "FTDebouncer.h"
/*	CONSTRUCTORS/DESTRUCTOR						*/
FTDebouncer::FTDebouncer() : debounceDelay(40) {
	debouncedItemsCount = 0;
	firstDebounceItem = lastDebounceItem = nullptr;
}
FTDebouncer::FTDebouncer(uint16_t _debounceTime) : debounceDelay(_debounceTime) {
	debouncedItemsCount = 0;
	firstDebounceItem = lastDebounceItem = nullptr;
}
FTDebouncer::~FTDebouncer() {
}

/*	METHODS										*/
void FTDebouncer::addPin(uint8_t _pinNr, uint8_t _restState) {
	this->addPin(_pinNr, _restState, INPUT);
}
void FTDebouncer::addPin(uint8_t _pinNr, uint8_t _restState, uint8_t _pullUpMode) {
	DebounceItem *dbItem = new DebounceItem();

	dbItem->pinNumber = _pinNr;
	dbItem->restState = _restState;

	if (firstDebounceItem == nullptr) {
		firstDebounceItem = dbItem;
	} else {
		lastDebounceItem->nextItem = dbItem;
	}

	lastDebounceItem = dbItem;

	pinMode(_pinNr, _pullUpMode);

	debouncedItemsCount++;

}

void FTDebouncer::init() {
	unsigned long currentMs = millis();
	DebounceItem *dbItem = firstDebounceItem;

	while (dbItem != nullptr) {
		dbItem->lastTimeChecked = currentMs;
		dbItem->currentState = dbItem->previousState = dbItem->restState;
		dbItem->currentDebouncedState = dbItem->previousDebouncedState = dbItem->restState;
		dbItem = dbItem->nextItem;
	}
}

void FTDebouncer::run() {
	DebounceItem *dbItem = firstDebounceItem;
	while (dbItem != nullptr) {
		dbItem->currentState = digitalRead(dbItem->pinNumber);
		dbItem = dbItem->nextItem;
	}

	debouncePins();
	checkStateChange();
}
void FTDebouncer::debouncePins() {
	unsigned long currentMs = millis();
	DebounceItem *dbItem = firstDebounceItem;
	while (dbItem != nullptr) {
		if (dbItem->currentState != dbItem->previousState) {
			dbItem->lastTimeChecked = currentMs;
		}
		if (currentMs - dbItem->lastTimeChecked > debounceDelay) {
			if (dbItem->previousState == dbItem->currentState) {
				dbItem->lastTimeChecked = currentMs;
				dbItem->currentDebouncedState = dbItem->currentState;
			}
		}
		dbItem->previousState = dbItem->currentState;
		dbItem = dbItem->nextItem;
	}
}

void FTDebouncer::checkStateChange() {
	DebounceItem *dbItem = firstDebounceItem;

	while (dbItem != nullptr) {
		if (dbItem->previousDebouncedState != dbItem->currentDebouncedState) {
			if (dbItem->currentDebouncedState == !dbItem->restState) {
				pinActivated(dbItem->pinNumber);
			}
			if (dbItem->currentDebouncedState == dbItem->restState) {
				pinDeactivated(dbItem->pinNumber);
			}
		}
		dbItem->previousDebouncedState = dbItem->currentDebouncedState;
		dbItem = dbItem->nextItem;
	}
}
uint8_t FTDebouncer::getPinsCount(){
	return debouncedItemsCount;
}<|endoftext|>


<commit_before>#include "FastaReader.h"
#include "BasicTypes.h"
#include "glwidget.h"
#include "UiVariables.h"
#include "SkittleUtil.h"

#include <string>
#include <cctype>

/** *********************
  FastaReader is the file reader for sequence files (FASTA format) usually ending in .fa.
  The first line starts with > and a name then the rest of the file is ACGT or acgt.  The
  character N is used to fill in unsequenced regions.  Capitalization is discarded by default
  since it is meant to mark "junk sequences".  All letters are capitalized for easy reading and
  so that equivalence checks A == a work in the rest of the program.

  FastaReader uses a progress bar dialog and is optimized for reading large files quickly.  It reads
  an entire file into memory, which makes reading the full 3GB human genome a big memory hog.
  FastaReader provides a string pointer (string*) to the rest of the program through the seq() method.
  The string is not ever copied, as it may be very large.  There are several unused read methods left
  over from experimentation with optimal memory management.

  FastaReader is created inside the constructor of glWidget so that there is a reader for
  every mdiChildWindow.  Each reader can only have one file open at a time.
  The actions:  openAction and addViewAction in MainWindow start a cascade that leads to the creation
  of a new FastaReader.

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

FastaReader::FastaReader()
{
    sequence = string("AATCGATCGTACGCTACGATCGCTACGCAGCTAGGACGGATT"); // random string of letters
    bytesInFile = 0;
    progressBar = NULL;
    cancelled = false;
}
FastaReader::~FastaReader()
{
    sequence.clear();
    sequence.resize(0);
}

bool FastaReader::readFile(string file)
{
    //Make sure that we were requested to open a file
    if(file.empty())
    {
        return false;
    }
    cout << file;

    //Parse the name of the chromosome from the file name and send it to glwidget to be stored
    storeChrName(file);

    //Clear out anything that may be left in the sequence string and set initial pad character
    sequence.clear();
    sequence = "";
    sequence.reserve(5);
    sequence = string(">");//extra character in front to make it 1-indexed instead of 0-indexed

    //Clear out anything that may be in the ifstream then open the new file
    wordfile.clear();
    wordfile.open(file.c_str(), ifstream::in | ifstream::binary);
    //See if we opened the file successfully
    if(wordfile.fail())
    {
        cerr << "Could not read the file. Either Skittle doesn't have file permissions or the file does not exist.";
        return false;
    }

    //Get how many characters are in the file
    wordfile.seekg(0, ios::beg);
    int begin = wordfile.tellg();
    wordfile.seekg(0, ios::end);
    int end = wordfile.tellg();
    bytesInFile = end - begin;

    //Discovered Reserve is different than malloc by creating a memory iterator
    //The iterator takes old size, then virtually allocates a new vector to new size while at the same time copying start/end memory to this new location
    //Then it destroys the old vector and walks through physical storage looking for a contiguous slot open, then dumps into the start and end location of new slot
    sequence.reserve(bytesInFile);

    //Return to the beginning of the file
    wordfile.seekg(0, ios::beg);
    //Skip the first line of the file as this is the chromosome name/info
    wordfile.ignore(500, '\n');

    //Read in the rest of the file
    char current;
    int i = 0;
    do
    {
        //Read the next character
        wordfile >> current;

        //If it is a letter, uppercase it
        current = upperCase(current);

        //if(current == 65 || current == 67 || current == 71 || current == 84 || current == 78) //A C G T N
        if(current != '\n' && current != '\r')
        {
            sequence.push_back(current);
        }

        i++;
    }
    while(!wordfile.eof() && !wordfile.fail());

    wordfile.close();

    cout << "Done loading file!";

    return true;
}

char FastaReader::upperCase(char& c)
{
    if( (int)c >= 97 && (int)c <= 122 )
        return (char)((int)c - 32);
    else
        return c;
}

void FastaReader::storeChrName(string path)
{
    string name = trimPathFromFilename(path);
}

const string* FastaReader::seq()
{
    return &sequence;
}
<commit_msg>test commit<commit_after>// comment added by salvador

#include "FastaReader.h"
#include "BasicTypes.h"
#include "glwidget.h"
#include "UiVariables.h"
#include "SkittleUtil.h"

#include <string>
#include <cctype>

/** *********************
  FastaReader is the file reader for sequence files (FASTA format) usually ending in .fa.
  The first line starts with > and a name then the rest of the file is ACGT or acgt.  The
  character N is used to fill in unsequenced regions.  Capitalization is discarded by default
  since it is meant to mark "junk sequences".  All letters are capitalized for easy reading and
  so that equivalence checks A == a work in the rest of the program.

  FastaReader uses a progress bar dialog and is optimized for reading large files quickly.  It reads
  an entire file into memory, which makes reading the full 3GB human genome a big memory hog.
  FastaReader provides a string pointer (string*) to the rest of the program through the seq() method.
  The string is not ever copied, as it may be very large.  There are several unused read methods left
  over from experimentation with optimal memory management.

  FastaReader is created inside the constructor of glWidget so that there is a reader for
  every mdiChildWindow.  Each reader can only have one file open at a time.
  The actions:  openAction and addViewAction in MainWindow start a cascade that leads to the creation
  of a new FastaReader.

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

FastaReader::FastaReader()
{
    sequence = string("AATCGATCGTACGCTACGATCGCTACGCAGCTAGGACGGATT"); // random string of letters
    bytesInFile = 0;
    progressBar = NULL;
    cancelled = false;
}
FastaReader::~FastaReader()
{
    sequence.clear();
    sequence.resize(0);
}

bool FastaReader::readFile(string file)
{
    //Make sure that we were requested to open a file
    if(file.empty())
    {
        return false;
    }
    cout << file;

    //Parse the name of the chromosome from the file name and send it to glwidget to be stored
    storeChrName(file);

    //Clear out anything that may be left in the sequence string and set initial pad character
    sequence.clear();
    sequence = "";
    sequence.reserve(5);
    sequence = string(">");//extra character in front to make it 1-indexed instead of 0-indexed

    //Clear out anything that may be in the ifstream then open the new file
    wordfile.clear();
    wordfile.open(file.c_str(), ifstream::in | ifstream::binary);
    //See if we opened the file successfully
    if(wordfile.fail())
    {
        cerr << "Could not read the file. Either Skittle doesn't have file permissions or the file does not exist.";
        return false;
    }

    //Get how many characters are in the file
    wordfile.seekg(0, ios::beg);
    int begin = wordfile.tellg();
    wordfile.seekg(0, ios::end);
    int end = wordfile.tellg();
    bytesInFile = end - begin;

    //Discovered Reserve is different than malloc by creating a memory iterator
    //The iterator takes old size, then virtually allocates a new vector to new size while at the same time copying start/end memory to this new location
    //Then it destroys the old vector and walks through physical storage looking for a contiguous slot open, then dumps into the start and end location of new slot
    sequence.reserve(bytesInFile);

    //Return to the beginning of the file
    wordfile.seekg(0, ios::beg);
    //Skip the first line of the file as this is the chromosome name/info
    wordfile.ignore(500, '\n');

    //Read in the rest of the file
    char current;
    int i = 0;
    do
    {
        //Read the next character
        wordfile >> current;

        //If it is a letter, uppercase it
        current = upperCase(current);

        //if(current == 65 || current == 67 || current == 71 || current == 84 || current == 78) //A C G T N
        if(current != '\n' && current != '\r')
        {
            sequence.push_back(current);
        }

        i++;
    }
    while(!wordfile.eof() && !wordfile.fail());

    wordfile.close();

    cout << "Done loading file!";

    return true;
}

char FastaReader::upperCase(char& c)
{
    if( (int)c >= 97 && (int)c <= 122 )
        return (char)((int)c - 32);
    else
        return c;
}

void FastaReader::storeChrName(string path)
{
    string name = trimPathFromFilename(path);
}

const string* FastaReader::seq()
{
    return &sequence;
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Sergey Lisitsyn
 * Copyright (C) 2010-2012 Jun Liu, Jieping Ye
 */

#include <shogun/lib/slep/slep_mt_lr.h>
#include <shogun/mathematics/Math.h>
#include <shogun/lib/slep/tree/altra.h>
#include <shogun/lib/slep/tree/general_altra.h>
#include <shogun/mathematics/lapack.h>

namespace shogun
{

slep_result_t slep_tree_mt_lr(
		CDotFeatures* features,
		double* y,
		double z,
		const slep_options& options)
{
	int i,j,t;
	int n_feats = features->get_dim_feature_space();
	int n_vecs = features->get_num_vectors();
	double lambda, beta;
	double funcp = 0.0, func = 0.0;

	int n_tasks = options.n_tasks;
	//SG_SPRINT("N tasks = %d \n", n_tasks);

	int iter = 1;
	bool done = false;
	bool gradient_break = false;

	int* m1 = SG_CALLOC(int, n_tasks);
	int* m2 = SG_CALLOC(int, n_tasks);
	for (t=0; t<n_tasks; t++)
	{
		int task_ind_start = options.ind[t];
		int task_ind_end = options.ind[t+1];
		for (i=task_ind_start; i<task_ind_end; i++)
		{
			if (y[i]>0)
				m1[t]++;
			else
				m2[t]++;
		}
	}

	double* ATb = SG_CALLOC(double, n_feats*n_tasks);

	if (options.regularization!=0)
	{
		if (z<0 || z>1)
			SG_SERROR("z is not in range [0,1]");

		for (t=0; t<n_tasks; t++)
		{
			int task_ind_start = options.ind[t];
			int task_ind_end = options.ind[t+1];
			double b = 0.0;
			for (i=task_ind_start; i<task_ind_end; i++)
			{
				if (y[i]>0)
					b = double(m1[t])/(m1[t]+m2[t]);
				else
					b = -double(m2[t])/(m1[t]+m2[t]);

				features->add_to_dense_vec(b,i,ATb+t*n_feats,n_feats);
			}

		}

		double lambda_max = 0.0;
		if (options.general)
			lambda_max = general_findLambdaMax_mt(ATb, n_feats, n_tasks, options.G, options.ind_t, options.n_nodes);
		else
			lambda_max = findLambdaMax_mt(ATb, n_feats, n_tasks, options.ind_t, options.n_nodes);

		lambda_max /= n_feats*n_tasks;

		lambda = z*lambda_max;
	}
	else
		lambda = z;

	SGMatrix<double> w(n_feats,n_tasks);
	w.zero();
	if (options.initial_w)
	{
		for (j=0; j<n_tasks; j++)
			for (i=0; i<n_feats; i++)
				w(i,j) = options.initial_w[j*n_feats+i];
	}
	SGVector<double> c(n_tasks);
	c.zero();

	double* s = SG_CALLOC(double, n_feats*n_tasks);
	double* sc = SG_CALLOC(double, n_tasks);
	double* g = SG_CALLOC(double, n_feats*n_tasks);
	double* v = SG_CALLOC(double, n_feats*n_tasks);

	double* Aw = SG_CALLOC(double, n_vecs);
	for (t=0; t<n_tasks; t++)
	{
		int task_ind_start = options.ind[t];
		int task_ind_end = options.ind[t+1];
		for (i=task_ind_start; i<task_ind_end; i++)
			Aw[i] = features->dense_dot(i,w.matrix+t*n_feats,n_feats);
	}

	double* Av = SG_MALLOC(double, n_vecs);
	double* As = SG_MALLOC(double, n_vecs);

	double L = 1.0/n_vecs;

	double* wp = SG_CALLOC(double, n_feats*n_tasks);
	for (i=0; i<n_feats*n_tasks; i++)
		wp[i] = w[i];
	double* Awp = SG_MALLOC(double, n_vecs);
	for (i=0; i<n_vecs; i++)
		Awp[i] = Aw[i];
	double* wwp = SG_CALLOC(double, n_feats*n_tasks);

	double* cp = SG_MALLOC(double, n_tasks);
	for (t=0; t<n_tasks; t++)
		cp[t] = c[t];
	double* ccp = SG_CALLOC(double, n_tasks);

	double* w_row = SG_MALLOC(double, n_tasks);

	double* gc = SG_MALLOC(double, n_tasks);
	double* b = SG_MALLOC(double, n_vecs);

	double alphap = 0.0;
	double alpha = 1.0;

	double fun_x = 0.0;

	while (!done && iter <= options.max_iter)
	{
		beta = (alphap-1.0)/alpha;
		//SG_SPRINT("beta = %f \n", beta);

		for (i=0; i<n_feats*n_tasks; i++)
			s[i] = w[i] + beta*wwp[i];
		for (t=0; t<n_tasks; t++)
			sc[t] = c[t] + beta*ccp[t];

		for (i=0; i<n_vecs; i++)
			As[i] = Aw[i] + beta*(Aw[i]-Awp[i]);

		//SG_SPRINT("As = %f\n",SGVector<float64_t>::dot(As,As,n_vecs));

		double fun_s = 0.0;
		for (i=0; i<n_tasks*n_feats; i++)
			g[i] = 0.0;
		for (t=0; t<n_tasks; t++)
		{
			int task_ind_start = options.ind[t];
			int task_ind_end = options.ind[t+1];

			gc[t] = 0.0;
			for (i=task_ind_start; i<task_ind_end; i++)
			{
				double aa = -y[i]*(As[i]+sc[t]);
				double bb = CMath::max(aa,0.0);

				fun_s += CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb;

				double prob = 1.0/(1.0+CMath::exp(aa));
				b[i] = -y[i]*(1.0-prob) / n_vecs;
				gc[t] += b[i];

				features->add_to_dense_vec(b[i],i,g+t*n_feats,n_feats);
			}
		}
		fun_s /= n_vecs;

		//SG_SPRINT("fun_s = %f\n", fun_s);

		//SG_SPRINT("g = %f\n", SGVector<float64_t>::dot(g,g,n_feats*n_tasks));

		for (i=0; i<n_feats*n_tasks; i++)
			wp[i] = w[i];

		for (t=0; t<n_tasks; t++)
			cp[t] = c[t];

		for (i=0; i<n_vecs; i++)
			Awp[i] = Aw[i];

		int inner_iter = 1;
		while (inner_iter < 100)
		{
			// v = s - g / L
			for (i=0; i<n_feats*n_tasks; i++)
				v[i] = s[i] - g[i]*(1.0/L);

			for (t=0; t<n_tasks; t++)
				c[t] = sc[t] - gc[t]*(1.0/L);

			if (options.general)
				general_altra_mt(w.matrix, v, n_feats, n_tasks, options.G, options.ind_t, options.n_nodes, lambda/L);
			else
				altra_mt(w.matrix, v, n_feats, n_tasks, options.ind_t, options.n_nodes, lambda/L);

			//SG_SPRINT("params [%d,%d,%f,%f]\n", n_feats, n_tasks, lambda/L, options.q);

			//w.display_matrix();
			//SG_SPRINT("w = %f \n", SGVector<float64_t>::dot(w.matrix,w.matrix,n_feats*n_tasks));

			// v = x - s
			for (i=0; i<n_feats*n_tasks; i++)
				v[i] = w[i] - s[i];

			fun_x = 0.0;
			for (t=0; t<n_tasks; t++)
			{
				int task_ind_start = options.ind[t];
				int task_ind_end = options.ind[t+1];
				for (i=task_ind_start; i<task_ind_end; i++)
				{
					Aw[i] = features->dense_dot(i,w.matrix+t*n_feats,n_feats);
					double aa = -y[i]*(Aw[i]+c[t]);
					double bb = CMath::max(aa,0.0);

					fun_x += CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb;
				}
			}
			fun_x /= n_vecs;

			//SG_SPRINT("Aw = %f\n", SGVector<float64_t>::dot(Aw,Aw,n_vecs));
			//c.display_vector();

			double r_sum = SGVector<float64_t>::dot(v,v,n_feats*n_tasks);
			double l_sum = fun_x - fun_s - SGVector<float64_t>::dot(v,g,n_feats*n_tasks);

			for (t=0; t<n_tasks; t++)
			{
				r_sum += CMath::sq(c[t] - sc[t]);
				l_sum -= (c[t] - sc[t])*gc[t];
			}
			r_sum /= 2.0;

			//SG_SPRINT("sums = [%f, %f, %f]\n", r_sum, l_sum, fun_x);

			if (r_sum <= 1e-20)
			{
				gradient_break = true;
				break;
			}

			if (l_sum <= r_sum*L)
				break;
			else
				L = CMath::max(2*L, l_sum/r_sum);
			inner_iter++;
		}

		alphap = alpha;
		alpha = 0.5*(1+CMath::sqrt(4*alpha*alpha+1));

		for (i=0; i<n_feats*n_tasks; i++)
			wwp[i] = w[i] - wp[i];

		for (t=0; t<n_tasks; t++)
			ccp[t] = c[t] - cp[t];

		double regularizer = 0.0;
		for (i=0; i<n_feats; i++)
		{
			double tree_norm = 0.0;

			for (t=0; t<n_tasks; t++)
				w_row[t] = w(i,t);

			if (options.general)
				tree_norm = general_treeNorm(w_row, n_tasks, options.G, options.ind_t, options.n_nodes);
			else
				tree_norm = treeNorm(w_row, n_tasks, options.ind_t, options.n_nodes);

			regularizer += tree_norm;
		}

		funcp = func;
		func = fun_x + lambda*regularizer;
		//SG_SPRINT("Obj = %f + %f * %f = %f \n",fun_x, lambda, regularizer, func);

		if (gradient_break)
			break;

		double norm_wp, norm_wwp;
		double step;
		switch (options.termination)
		{
			case 0:
				if (iter>=2)
				{
					step = CMath::abs(func-funcp);

					if (step <= options.tolerance)
						done = true;
				}
				break;
			case 1:
				if (iter>=2)
				{
					step = CMath::abs(func-funcp);
					if (step <= step*options.tolerance)
						done = true;
				}
				break;
			case 2:
				if (func <= options.tolerance)
					done = true;
				break;
			case 3:
				norm_wwp = CMath::sqrt(SGVector<float64_t>::dot(wwp,wwp,n_feats));
				if (norm_wwp <= options.tolerance)
					done = true;
				break;
			case 4:
				norm_wp = CMath::sqrt(SGVector<float64_t>::dot(wp,wp,n_feats));
				norm_wwp = CMath::sqrt(SGVector<float64_t>::dot(wwp,wwp,n_feats));
				if (norm_wwp <= options.tolerance*CMath::max(norm_wp,1.0))
					done = true;
				break;
			case 5:
				if (iter > options.max_iter)
					done = true;
				break;
			default:
				done = true;
		}

		iter++;
	}

	SG_FREE(wp);
	SG_FREE(wwp);
	SG_FREE(s);
	SG_FREE(sc);
	SG_FREE(cp);
	SG_FREE(ccp);
	SG_FREE(g);
	SG_FREE(v);
	SG_FREE(Aw);
	SG_FREE(Awp);
	SG_FREE(Av);
	SG_FREE(As);
	SG_FREE(w_row);
	SG_FREE(gc);
	SG_FREE(b);
	SG_FREE(m1);
	SG_FREE(m2);
	SG_FREE(ATb);

	return slep_result_t(w,c);
};
};
<commit_msg>Fixed tree guided multitask logistic regression<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Sergey Lisitsyn
 * Copyright (C) 2010-2012 Jun Liu, Jieping Ye
 */

#include <shogun/lib/slep/slep_mt_lr.h>
#include <shogun/mathematics/Math.h>
#include <shogun/lib/slep/tree/altra.h>
#include <shogun/lib/slep/tree/general_altra.h>
#include <shogun/mathematics/lapack.h>

namespace shogun
{

slep_result_t slep_tree_mt_lr(
		CDotFeatures* features,
		double* y,
		double z,
		const slep_options& options)
{
	int i,j,t;
	int n_feats = features->get_dim_feature_space();
	int n_vecs = features->get_num_vectors();
	double lambda, beta;
	double funcp = 0.0, func = 0.0;

	int n_tasks = options.n_tasks;

	int iter = 1;
	bool done = false;
	bool gradient_break = false;

	int* m1 = SG_CALLOC(int, n_tasks);
	int* m2 = SG_CALLOC(int, n_tasks);
	for (t=0; t<n_tasks; t++)
	{
		int task_ind_start = options.ind[t];
		int task_ind_end = options.ind[t+1];
		for (i=task_ind_start; i<task_ind_end; i++)
		{
			if (y[i]>0)
				m1[t]++;
			else
				m2[t]++;
		}
	}

	double* ATb = SG_CALLOC(double, n_feats*n_tasks);

	if (options.regularization!=0)
	{
		if (z<0 || z>1)
			SG_SERROR("z is not in range [0,1]");

		for (t=0; t<n_tasks; t++)
		{
			int task_ind_start = options.ind[t];
			int task_ind_end = options.ind[t+1];
			double b = 0.0;
			for (i=task_ind_start; i<task_ind_end; i++)
			{
				if (y[i]>0)
					b = double(m1[t])/(m1[t]+m2[t]);
				else
					b = -double(m2[t])/(m1[t]+m2[t]);

				features->add_to_dense_vec(b,i,ATb+t*n_feats,n_feats);
			}

		}

		double lambda_max = 0.0;
		if (options.general)
			lambda_max = general_findLambdaMax_mt(ATb, n_feats, n_tasks, options.G, options.ind_t, options.n_nodes);
		else
			lambda_max = findLambdaMax_mt(ATb, n_feats, n_tasks, options.ind_t, options.n_nodes);

		lambda_max /= n_vecs*n_tasks;

		lambda = z*lambda_max;
	}
	else
		lambda = z;

	SGMatrix<double> w(n_feats,n_tasks);
	w.zero();
	if (options.initial_w)
	{
		for (j=0; j<n_tasks; j++)
			for (i=0; i<n_feats; i++)
				w(i,j) = options.initial_w[j*n_feats+i];
	}
	SGVector<double> c(n_tasks);
	c.zero();

	double* s = SG_CALLOC(double, n_feats*n_tasks);
	double* sc = SG_CALLOC(double, n_tasks);
	double* g = SG_CALLOC(double, n_feats*n_tasks);
	double* v = SG_CALLOC(double, n_feats*n_tasks);

	double* Aw = SG_CALLOC(double, n_vecs);
	for (t=0; t<n_tasks; t++)
	{
		int task_ind_start = options.ind[t];
		int task_ind_end = options.ind[t+1];
		for (i=task_ind_start; i<task_ind_end; i++)
			Aw[i] = features->dense_dot(i,w.matrix+t*n_feats,n_feats);
	}

	double* Av = SG_MALLOC(double, n_vecs);
	double* As = SG_MALLOC(double, n_vecs);

	double L = 1.0/n_vecs;

	double* wp = SG_CALLOC(double, n_feats*n_tasks);
	for (i=0; i<n_feats*n_tasks; i++)
		wp[i] = w[i];
	double* Awp = SG_MALLOC(double, n_vecs);
	for (i=0; i<n_vecs; i++)
		Awp[i] = Aw[i];
	double* wwp = SG_CALLOC(double, n_feats*n_tasks);

	double* cp = SG_MALLOC(double, n_tasks);
	for (t=0; t<n_tasks; t++)
		cp[t] = c[t];
	double* ccp = SG_CALLOC(double, n_tasks);

	double* w_row = SG_MALLOC(double, n_tasks);

	double* gc = SG_MALLOC(double, n_tasks);
	double* b = SG_MALLOC(double, n_vecs);

	double alphap = 0.0;
	double alpha = 1.0;

	double fun_x = 0.0;

	while (!done && iter <= options.max_iter)
	{
		beta = (alphap-1.0)/alpha;

		for (i=0; i<n_feats*n_tasks; i++)
			s[i] = w[i] + beta*wwp[i];
		for (t=0; t<n_tasks; t++)
			sc[t] = c[t] + beta*ccp[t];

		for (i=0; i<n_vecs; i++)
			As[i] = Aw[i] + beta*(Aw[i]-Awp[i]);

		double fun_s = 0.0;
		for (i=0; i<n_tasks*n_feats; i++)
			g[i] = 0.0;
		for (t=0; t<n_tasks; t++)
		{
			int task_ind_start = options.ind[t];
			int task_ind_end = options.ind[t+1];

			gc[t] = 0.0;
			for (i=task_ind_start; i<task_ind_end; i++)
			{
				double aa = -y[i]*(As[i]+sc[t]);
				double bb = CMath::max(aa,0.0);

				fun_s += CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb;

				double prob = 1.0/(1.0+CMath::exp(aa));
				b[i] = -y[i]*(1.0-prob) / n_vecs;
				gc[t] += b[i];

				features->add_to_dense_vec(b[i],i,g+t*n_feats,n_feats);
			}
		}
		fun_s /= n_vecs;

		for (i=0; i<n_feats*n_tasks; i++)
			wp[i] = w[i];

		for (t=0; t<n_tasks; t++)
			cp[t] = c[t];

		for (i=0; i<n_vecs; i++)
			Awp[i] = Aw[i];

		int inner_iter = 1;
		while (inner_iter < 1000)
		{
			// v = s - g / L
			for (i=0; i<n_feats*n_tasks; i++)
				v[i] = s[i] - g[i]*(1.0/L);

			for (t=0; t<n_tasks; t++)
				c[t] = sc[t] - gc[t]*(1.0/L);

			if (options.general)
				general_altra_mt(w.matrix, v, n_feats, n_tasks, options.G, options.ind_t, options.n_nodes, lambda/L);
			else
				altra_mt(w.matrix, v, n_feats, n_tasks, options.ind_t, options.n_nodes, lambda/L);

			for (i=0; i<n_feats*n_tasks; i++)
				v[i] = w[i] - s[i];

			fun_x = 0.0;
			for (t=0; t<n_tasks; t++)
			{
				int task_ind_start = options.ind[t];
				int task_ind_end = options.ind[t+1];
				for (i=task_ind_start; i<task_ind_end; i++)
				{
					Aw[i] = features->dense_dot(i,w.matrix+t*n_feats,n_feats);
					double aa = -y[i]*(Aw[i]+c[t]);
					double bb = CMath::max(aa,0.0);

					fun_x += CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb;
				}
			}
			fun_x /= n_vecs;

			double r_sum = SGVector<float64_t>::dot(v,v,n_feats*n_tasks);
			double l_sum = fun_x - fun_s - SGVector<float64_t>::dot(v,g,n_feats*n_tasks);

			for (t=0; t<n_tasks; t++)
			{
				r_sum += CMath::sq(c[t] - sc[t]);
				l_sum -= (c[t] - sc[t])*gc[t];
			}
			r_sum /= 2.0;

			if (r_sum <= 1e-20)
			{
				gradient_break = true;
				break;
			}

			if (l_sum <= r_sum*L)
				break;
			else
				L = CMath::max(2*L, l_sum/r_sum);
			inner_iter++;
		}

		alphap = alpha;
		alpha = 0.5*(1+CMath::sqrt(4*alpha*alpha+1));

		for (i=0; i<n_feats*n_tasks; i++)
			wwp[i] = w[i] - wp[i];

		for (t=0; t<n_tasks; t++)
			ccp[t] = c[t] - cp[t];

		double regularizer = 0.0;
		for (i=0; i<n_feats; i++)
		{
			double tree_norm = 0.0;

			for (t=0; t<n_tasks; t++)
				w_row[t] = w(i,t);

			if (options.general)
				tree_norm = general_treeNorm(w_row, n_tasks, options.G, options.ind_t, options.n_nodes);
			else
				tree_norm = treeNorm(w_row, n_tasks, options.ind_t, options.n_nodes);

			regularizer += tree_norm;
		}

		funcp = func;
		func = fun_x + lambda*regularizer;

		if (gradient_break)
			break;

		double norm_wp, norm_wwp;
		double step;
		switch (options.termination)
		{
			case 0:
				if (iter>=2)
				{
					step = CMath::abs(func-funcp);

					if (step <= options.tolerance)
						done = true;
				}
				break;
			case 1:
				if (iter>=2)
				{
					step = CMath::abs(func-funcp);
					if (step <= step*options.tolerance)
						done = true;
				}
				break;
			case 2:
				if (func <= options.tolerance)
					done = true;
				break;
			case 3:
				norm_wwp = CMath::sqrt(SGVector<float64_t>::dot(wwp,wwp,n_feats));
				if (norm_wwp <= options.tolerance)
					done = true;
				break;
			case 4:
				norm_wp = CMath::sqrt(SGVector<float64_t>::dot(wp,wp,n_feats));
				norm_wwp = CMath::sqrt(SGVector<float64_t>::dot(wwp,wwp,n_feats));
				if (norm_wwp <= options.tolerance*CMath::max(norm_wp,1.0))
					done = true;
				break;
			case 5:
				if (iter > options.max_iter)
					done = true;
				break;
			default:
				done = true;
		}

		iter++;
	}

	SG_FREE(wp);
	SG_FREE(wwp);
	SG_FREE(s);
	SG_FREE(sc);
	SG_FREE(cp);
	SG_FREE(ccp);
	SG_FREE(g);
	SG_FREE(v);
	SG_FREE(Aw);
	SG_FREE(Awp);
	SG_FREE(Av);
	SG_FREE(As);
	SG_FREE(w_row);
	SG_FREE(gc);
	SG_FREE(b);
	SG_FREE(m1);
	SG_FREE(m2);
	SG_FREE(ATb);

	return slep_result_t(w,c);
};
};
<|endoftext|>


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

#include "stdafx.h"

#include <cerrno>
#include <cstdlib>

#include "util/ascii_util.h"
#include "util/cxx_util.h"
#include "util/string_util.h"

#include "integer.h"
#include "decimal.h"
#include "floatimpl.h"
#include "numconversions.h"

using namespace std;

#ifdef WIN32
namespace std {
  inline long long strtoll( char const *s, char **end, int base ) {
    return ::_strtoi64( s, end, base );
  }

  inline long long strtoull( char const *s, char **end, int base ) {
    return ::_strtoui64( s, end, base );
  }
}
#endif /* WIN32 */

namespace zorba {

///////////////////////////////////////////////////////////////////////////////

void Integer::parse( char const *s ) {
#ifdef ZORBA_WITH_BIG_INTEGER
  Decimal::parse( s, &value_, Decimal::parse_integer );
#else
  value_ = ztd::atoll( s );
#endif /* ZORBA_WITH_BIG_INTEGER */
}

////////// constructors ///////////////////////////////////////////////////////

#ifdef ZORBA_WITH_BIG_INTEGER
Integer::Integer( long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
}

Integer::Integer( unsigned long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
}

Integer::Integer( unsigned long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
}
#endif /* ZORBA_WITH_BIG_INTEGER */

Integer::Integer( Decimal const &d ) {
  value_ = ftoi( d.value_ );
}

Integer::Integer( Double const &d ) {
  if ( !d.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( d.theFloating );
}

Integer::Integer( Float const &f ) {
  if ( !f.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( f.theFloating );
}

////////// assignment operators ///////////////////////////////////////////////

#ifdef ZORBA_WITH_BIG_INTEGER
Integer& Integer::operator=( long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
  return *this;
}

Integer& Integer::operator=( unsigned long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
  return *this;
}

Integer& Integer::operator=( unsigned long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
  return *this;
}
#endif /* ZORBA_WITH_BIG_INTEGER */

Integer& Integer::operator=( Decimal const &d ) {
  value_ = ftoi( d.value_ );
  return *this;
}

Integer& Integer::operator=( Double const &d ) {
  if ( !d.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( d.theFloating );
  return *this;
}

Integer& Integer::operator=( Float const &f ) {
  if ( !f.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( f.theFloating );
  return *this;
}

////////// arithmetic operators ///////////////////////////////////////////////

Decimal operator+( Integer const &i, Decimal const &d ) {
  return i.itod() + d.value_;
}

Decimal operator-( Integer const &i, Decimal const &d ) {
  return i.itod() - d.value_;
}

Decimal operator*( Integer const &i, Decimal const &d ) {
  return i.itod() * d.value_;
}

Decimal operator/( Integer const &i, Decimal const &d ) {
  return i.itod() / d.value_;
}

Decimal operator%( Integer const &i, Decimal const &d ) {
  return i.itod() % d.value_;
}

////////// relational operators ///////////////////////////////////////////////

bool operator==( Integer const &i, Decimal const &d ) {
  return d.is_integer() && i.itod() == d.value_;
}

bool operator!=( Integer const &i, Decimal const &d ) {
  return i.itod() != d.value_;
}

bool operator<( Integer const &i, Decimal const &d ) {
  return i.itod() < d.value_;
}

bool operator<=( Integer const &i, Decimal const &d ) {
  return i.itod() <= d.value_;
}

bool operator>( Integer const &i, Decimal const &d ) {
  return i.itod() > d.value_;
}

bool operator>=( Integer const &i, Decimal const &d ) {
  return i.itod() >= d.value_;
}

////////// math functions /////////////////////////////////////////////////////

Double Integer::pow( Integer const &power ) const {
#ifdef ZORBA_WITH_BIG_INTEGER
  value_type const result( value_.pow( power.value_, 15 ) );
  char buf[300];
  result.toFixPtString( buf, 15 );
  xs_double double_result;
  xs_double::parseString( buf, double_result );
  return double_result;
#else
  return Double(
    // The casts are needed for disambiguation with MSVC++.
    ::pow( static_cast<double>( value_ ), static_cast<double>( power.value_ ) )
  );
#endif /* ZORBA_WITH_BIG_INTEGER */
}

Integer Integer::round( Integer const &precision ) const {
  return Integer( Decimal::round( itod(), precision.itod() ) );
}

Integer Integer::roundHalfToEven( Integer const &precision ) const {
  return Integer( Decimal::roundHalfToEven( itod(), precision.itod() ) );
}

////////// miscellaneous //////////////////////////////////////////////////////

#ifndef ZORBA_WITH_BIG_INTEGER
Integer::value_type Integer::ftoi( MAPM const &d ) {
  MAPM const temp( d.sign() >= 0 ? d.floor() : d.ceil() );
  char *const buf = new char[ temp.exponent() + 3 ];
  temp.toIntegerString( buf );
  value_type const result( std::strtoll( buf, nullptr, 10 ) );
  delete[] buf;
  return result;
}

MAPM Integer::itod() const {
  if ( is_long() )
    return static_cast<long>( value_ );
  ztd::itoa_buf_type buf;
  return ztd::itoa( value_, buf );
}
#endif /* ZORBA_WITH_BIG_INTEGER */

#ifdef ZORBA_WITH_BIG_INTEGER
uint32_t Integer::hash() const {
  return Decimal::hash( value_ );
}
#endif /* ZORBA_WITH_BIG_INTEGER */

Integer const& Integer::one() {
  static Integer const i(1);
  return i;
}

zstring Integer::toString() const {
#ifdef ZORBA_WITH_BIG_INTEGER
  char *const buf = new char[ value_.exponent() + 3 ];
  value_.toIntegerString( buf );
  zstring const result( buf );
  delete[] buf;
  return result;
#else
  ztd::itoa_buf_type buf;
  return ztd::itoa( value_, buf );
#endif /* ZORBA_WITH_BIG_INTEGER */
}

Integer const& Integer::zero() {
  static Integer const i(0);
  return i;
}

///////////////////////////////////////////////////////////////////////////////

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>Removed unused include.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "stdafx.h"

#include <cerrno>
#include <cstdlib>

#include "util/cxx_util.h"
#include "util/string_util.h"

#include "integer.h"
#include "decimal.h"
#include "floatimpl.h"
#include "numconversions.h"

using namespace std;

#ifdef WIN32
namespace std {
  inline long long strtoll( char const *s, char **end, int base ) {
    return ::_strtoi64( s, end, base );
  }

  inline long long strtoull( char const *s, char **end, int base ) {
    return ::_strtoui64( s, end, base );
  }
}
#endif /* WIN32 */

namespace zorba {

///////////////////////////////////////////////////////////////////////////////

void Integer::parse( char const *s ) {
#ifdef ZORBA_WITH_BIG_INTEGER
  Decimal::parse( s, &value_, Decimal::parse_integer );
#else
  value_ = ztd::atoll( s );
#endif /* ZORBA_WITH_BIG_INTEGER */
}

////////// constructors ///////////////////////////////////////////////////////

#ifdef ZORBA_WITH_BIG_INTEGER
Integer::Integer( long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
}

Integer::Integer( unsigned long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
}

Integer::Integer( unsigned long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
}
#endif /* ZORBA_WITH_BIG_INTEGER */

Integer::Integer( Decimal const &d ) {
  value_ = ftoi( d.value_ );
}

Integer::Integer( Double const &d ) {
  if ( !d.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( d.theFloating );
}

Integer::Integer( Float const &f ) {
  if ( !f.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( f.theFloating );
}

////////// assignment operators ///////////////////////////////////////////////

#ifdef ZORBA_WITH_BIG_INTEGER
Integer& Integer::operator=( long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
  return *this;
}

Integer& Integer::operator=( unsigned long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
  return *this;
}

Integer& Integer::operator=( unsigned long long n ) {
  ztd::itoa_buf_type buf;
  value_ = ztd::itoa( n, buf );
  return *this;
}
#endif /* ZORBA_WITH_BIG_INTEGER */

Integer& Integer::operator=( Decimal const &d ) {
  value_ = ftoi( d.value_ );
  return *this;
}

Integer& Integer::operator=( Double const &d ) {
  if ( !d.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( d.theFloating );
  return *this;
}

Integer& Integer::operator=( Float const &f ) {
  if ( !f.isFinite() )
    throw std::invalid_argument( "not finite" );
  value_ = ftoi( f.theFloating );
  return *this;
}

////////// arithmetic operators ///////////////////////////////////////////////

Decimal operator+( Integer const &i, Decimal const &d ) {
  return i.itod() + d.value_;
}

Decimal operator-( Integer const &i, Decimal const &d ) {
  return i.itod() - d.value_;
}

Decimal operator*( Integer const &i, Decimal const &d ) {
  return i.itod() * d.value_;
}

Decimal operator/( Integer const &i, Decimal const &d ) {
  return i.itod() / d.value_;
}

Decimal operator%( Integer const &i, Decimal const &d ) {
  return i.itod() % d.value_;
}

////////// relational operators ///////////////////////////////////////////////

bool operator==( Integer const &i, Decimal const &d ) {
  return d.is_integer() && i.itod() == d.value_;
}

bool operator!=( Integer const &i, Decimal const &d ) {
  return i.itod() != d.value_;
}

bool operator<( Integer const &i, Decimal const &d ) {
  return i.itod() < d.value_;
}

bool operator<=( Integer const &i, Decimal const &d ) {
  return i.itod() <= d.value_;
}

bool operator>( Integer const &i, Decimal const &d ) {
  return i.itod() > d.value_;
}

bool operator>=( Integer const &i, Decimal const &d ) {
  return i.itod() >= d.value_;
}

////////// math functions /////////////////////////////////////////////////////

Double Integer::pow( Integer const &power ) const {
#ifdef ZORBA_WITH_BIG_INTEGER
  value_type const result( value_.pow( power.value_, 15 ) );
  char buf[300];
  result.toFixPtString( buf, 15 );
  xs_double double_result;
  xs_double::parseString( buf, double_result );
  return double_result;
#else
  return Double(
    // The casts are needed for disambiguation with MSVC++.
    ::pow( static_cast<double>( value_ ), static_cast<double>( power.value_ ) )
  );
#endif /* ZORBA_WITH_BIG_INTEGER */
}

Integer Integer::round( Integer const &precision ) const {
  return Integer( Decimal::round( itod(), precision.itod() ) );
}

Integer Integer::roundHalfToEven( Integer const &precision ) const {
  return Integer( Decimal::roundHalfToEven( itod(), precision.itod() ) );
}

////////// miscellaneous //////////////////////////////////////////////////////

#ifndef ZORBA_WITH_BIG_INTEGER
Integer::value_type Integer::ftoi( MAPM const &d ) {
  MAPM const temp( d.sign() >= 0 ? d.floor() : d.ceil() );
  char *const buf = new char[ temp.exponent() + 3 ];
  temp.toIntegerString( buf );
  value_type const result( std::strtoll( buf, nullptr, 10 ) );
  delete[] buf;
  return result;
}

MAPM Integer::itod() const {
  if ( is_long() )
    return static_cast<long>( value_ );
  ztd::itoa_buf_type buf;
  return ztd::itoa( value_, buf );
}
#endif /* ZORBA_WITH_BIG_INTEGER */

#ifdef ZORBA_WITH_BIG_INTEGER
uint32_t Integer::hash() const {
  return Decimal::hash( value_ );
}
#endif /* ZORBA_WITH_BIG_INTEGER */

Integer const& Integer::one() {
  static Integer const i(1);
  return i;
}

zstring Integer::toString() const {
#ifdef ZORBA_WITH_BIG_INTEGER
  char *const buf = new char[ value_.exponent() + 3 ];
  value_.toIntegerString( buf );
  zstring const result( buf );
  delete[] buf;
  return result;
#else
  ztd::itoa_buf_type buf;
  return ztd::itoa( value_, buf );
#endif /* ZORBA_WITH_BIG_INTEGER */
}

Integer const& Integer::zero() {
  static Integer const i(0);
  return i;
}

///////////////////////////////////////////////////////////////////////////////

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011-2013 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "load_pipe.h"
#include "load_pipe_exception.h"

#if defined(_WIN32) || defined(_WIN64)
#include <sprokit/pipeline_util/include-paths.h>
#endif
#include "path.h"
#include "pipe_grammar.h"

#include <sprokit/pipeline/pipeline.h>
#include <sprokit/pipeline/utils.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/foreach.hpp>

#include <istream>
#include <sstream>
#include <string>

/**
 * \file load_pipe.cxx
 *
 * \brief Implementation of the pipeline declaration loading.
 */

namespace sprokit
{

static std::string const default_include_dirs = std::string(DEFAULT_PIPE_INCLUDE_PATHS);
static envvar_name_t const sprokit_include_envvar = envvar_name_t("SPROKIT_PIPE_INCLUDE_PATH");
static std::string const include_directive = "!include ";
static char const comment_marker = '#';

static void flatten_pipe_declaration(std::stringstream& sstr, std::istream& istr, path_t const& inc_root);
static bool is_separator(char ch);

pipe_blocks
load_pipe_blocks_from_file(path_t const& fname)
{
  std::stringstream sstr;
  std::string const str = fname.string<std::string>();

  sstr << include_directive << str;

  pipe_blocks const blocks = load_pipe_blocks(sstr, fname.parent_path());

  return blocks;
}

pipe_blocks
load_pipe_blocks(std::istream& istr, path_t const& inc_root)
{
  std::stringstream sstr;

  sstr.exceptions(std::stringstream::failbit | std::stringstream::badbit);

  try
  {
    flatten_pipe_declaration(sstr, istr, inc_root);
  }
  catch (std::ios_base::failure const& e)
  {
    throw stream_failure_exception(e.what());
  }

  return parse_pipe_blocks_from_string(sstr.str());
}

cluster_blocks
load_cluster_blocks_from_file(path_t const& fname)
{
  std::stringstream sstr;
  path_t::string_type const& fstr = fname.native();
  std::string const str(fstr.begin(), fstr.end());

  sstr << include_directive << str;

  cluster_blocks const blocks = load_cluster_blocks(sstr, fname.parent_path());

  return blocks;
}

cluster_blocks
load_cluster_blocks(std::istream& istr, path_t const& inc_root)
{
  std::stringstream sstr;

  sstr.exceptions(std::stringstream::failbit | std::stringstream::badbit);

  try
  {
    flatten_pipe_declaration(sstr, istr, inc_root);
  }
  catch (std::ios_base::failure const& e)
  {
    throw stream_failure_exception(e.what());
  }

  return parse_cluster_blocks_from_string(sstr.str());
}

void
flatten_pipe_declaration(std::stringstream& sstr, std::istream& istr, path_t const& inc_root)
{
  typedef path_t include_path_t;
  typedef std::vector<include_path_t> include_paths_t;

  include_paths_t include_dirs;

  // Build include directories.
  {
    include_dirs.push_back(inc_root);

    include_paths_t include_dirs_tmp;

    envvar_value_t const extra_include_dirs = get_envvar(sprokit_include_envvar);

    if (extra_include_dirs)
    {
      boost::split(include_dirs_tmp, *extra_include_dirs, is_separator, boost::token_compress_on);

      include_dirs.insert(include_dirs.end(), include_dirs_tmp.begin(), include_dirs_tmp.end());
    }

    boost::split(include_dirs_tmp, default_include_dirs, is_separator, boost::token_compress_on);

    include_dirs.insert(include_dirs.end(), include_dirs_tmp.begin(), include_dirs_tmp.end());
  }

  while (istr.good())
  {
    std::string line;

    std::getline(istr, line);

    boost::trim_left(line);

    if (line.empty())
    {
      continue;
    }

    if (boost::starts_with(line, include_directive))
    {
      path_t file_path(line.substr(include_directive.size()));

      boost::system::error_code ec;

      if (file_path.is_relative())
      {
        BOOST_FOREACH (include_path_t const& include_dir, include_dirs)
        {
          path_t const inc_file_path = include_dir / file_path;

          if (boost::filesystem::exists(inc_file_path, ec))
          {
            file_path = inc_file_path;
            break;
          }
        }
      }

      if (!boost::filesystem::exists(file_path, ec))
      {
        throw file_no_exist_exception(file_path);
      }

      /// \todo Check ec.

      if (!boost::filesystem::is_regular_file(file_path, ec))
      {
        throw not_a_file_exception(file_path);
      }

      /// \todo Check ec.

      boost::filesystem::ifstream fin;

      fin.open(file_path);

      if (!fin.good())
      {
        throw file_open_exception(file_path);
      }

      flatten_pipe_declaration(sstr, fin, file_path.parent_path());

      fin.close();
    }
    /// \todo: Support comments not starting in column 1?
    else if (line[0] == comment_marker)
    {
      continue;
    }
    else
    {
      sstr << line << std::endl;
    }
  }
}

bool
is_separator(char ch)
{
  char const separator =
#if defined(_WIN32) || defined(_WIN64)
    ';';
#else
    ':';
#endif

  return (ch == separator);
}

}
<commit_msg>Iterate on the status of the stream after reading<commit_after>/*ckwg +5
 * Copyright 2011-2013 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "load_pipe.h"
#include "load_pipe_exception.h"

#if defined(_WIN32) || defined(_WIN64)
#include <sprokit/pipeline_util/include-paths.h>
#endif
#include "path.h"
#include "pipe_grammar.h"

#include <sprokit/pipeline/pipeline.h>
#include <sprokit/pipeline/utils.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/foreach.hpp>

#include <istream>
#include <sstream>
#include <string>

/**
 * \file load_pipe.cxx
 *
 * \brief Implementation of the pipeline declaration loading.
 */

namespace sprokit
{

static std::string const default_include_dirs = std::string(DEFAULT_PIPE_INCLUDE_PATHS);
static envvar_name_t const sprokit_include_envvar = envvar_name_t("SPROKIT_PIPE_INCLUDE_PATH");
static std::string const include_directive = "!include ";
static char const comment_marker = '#';

static void flatten_pipe_declaration(std::stringstream& sstr, std::istream& istr, path_t const& inc_root);
static bool is_separator(char ch);

pipe_blocks
load_pipe_blocks_from_file(path_t const& fname)
{
  std::stringstream sstr;
  std::string const str = fname.string<std::string>();

  sstr << include_directive << str;

  pipe_blocks const blocks = load_pipe_blocks(sstr, fname.parent_path());

  return blocks;
}

pipe_blocks
load_pipe_blocks(std::istream& istr, path_t const& inc_root)
{
  std::stringstream sstr;

  sstr.exceptions(std::stringstream::failbit | std::stringstream::badbit);

  try
  {
    flatten_pipe_declaration(sstr, istr, inc_root);
  }
  catch (std::ios_base::failure const& e)
  {
    throw stream_failure_exception(e.what());
  }

  return parse_pipe_blocks_from_string(sstr.str());
}

cluster_blocks
load_cluster_blocks_from_file(path_t const& fname)
{
  std::stringstream sstr;
  path_t::string_type const& fstr = fname.native();
  std::string const str(fstr.begin(), fstr.end());

  sstr << include_directive << str;

  cluster_blocks const blocks = load_cluster_blocks(sstr, fname.parent_path());

  return blocks;
}

cluster_blocks
load_cluster_blocks(std::istream& istr, path_t const& inc_root)
{
  std::stringstream sstr;

  sstr.exceptions(std::stringstream::failbit | std::stringstream::badbit);

  try
  {
    flatten_pipe_declaration(sstr, istr, inc_root);
  }
  catch (std::ios_base::failure const& e)
  {
    throw stream_failure_exception(e.what());
  }

  return parse_cluster_blocks_from_string(sstr.str());
}

void
flatten_pipe_declaration(std::stringstream& sstr, std::istream& istr, path_t const& inc_root)
{
  typedef path_t include_path_t;
  typedef std::vector<include_path_t> include_paths_t;

  include_paths_t include_dirs;

  // Build include directories.
  {
    include_dirs.push_back(inc_root);

    include_paths_t include_dirs_tmp;

    envvar_value_t const extra_include_dirs = get_envvar(sprokit_include_envvar);

    if (extra_include_dirs)
    {
      boost::split(include_dirs_tmp, *extra_include_dirs, is_separator, boost::token_compress_on);

      include_dirs.insert(include_dirs.end(), include_dirs_tmp.begin(), include_dirs_tmp.end());
    }

    boost::split(include_dirs_tmp, default_include_dirs, is_separator, boost::token_compress_on);

    include_dirs.insert(include_dirs.end(), include_dirs_tmp.begin(), include_dirs_tmp.end());
  }

  std::string line;

  while (std::getline(istr, line))
  {
    boost::trim_left(line);

    if (line.empty())
    {
      continue;
    }

    if (boost::starts_with(line, include_directive))
    {
      path_t file_path(line.substr(include_directive.size()));

      boost::system::error_code ec;

      if (file_path.is_relative())
      {
        BOOST_FOREACH (include_path_t const& include_dir, include_dirs)
        {
          path_t const inc_file_path = include_dir / file_path;

          if (boost::filesystem::exists(inc_file_path, ec))
          {
            file_path = inc_file_path;
            break;
          }
        }
      }

      if (!boost::filesystem::exists(file_path, ec))
      {
        throw file_no_exist_exception(file_path);
      }

      /// \todo Check ec.

      if (!boost::filesystem::is_regular_file(file_path, ec))
      {
        throw not_a_file_exception(file_path);
      }

      /// \todo Check ec.

      boost::filesystem::ifstream fin;

      fin.open(file_path);

      if (!fin.good())
      {
        throw file_open_exception(file_path);
      }

      flatten_pipe_declaration(sstr, fin, file_path.parent_path());

      fin.close();
    }
    /// \todo: Support comments not starting in column 1?
    else if (line[0] == comment_marker)
    {
      continue;
    }
    else
    {
      sstr << line << std::endl;
    }
  }
}

bool
is_separator(char ch)
{
  char const separator =
#if defined(_WIN32) || defined(_WIN64)
    ';';
#else
    ':';
#endif

  return (ch == separator);
}

}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_POW_HPP
#define STAN_MATH_PRIM_FUN_POW_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <cmath>
#include <complex>

namespace stan {
namespace math {

/**
 * Return the first argument raised to the power of the second
 * argument.
 *
 * @tparam T1 type of base
 * @tparam T2 type of exponent
 * @param x base
 * @param y exponent
 * @return base raised to the power of the exponent
 */
template<typename T1, typename T2,
         typename = require_arithmetic_t<T1>,
         typename = require_arithmetic_t<T2>>
inline double pow(T1 x, T2 y) {
  return std::pow(x, y);
}

namespace internal {

/**
 * Return the first argument raised to the power of the second
 * argument.  At least one of the arguments must be a complex number.
 *
 * @tparam U type of base
 * @tparam V type of exponent
 * @param[in] x base
 * @param[in] y exponent
 * @return base raised to the power of the exponent
 */
template <typename U, typename V>
inline complex_return_t<U, V> complex_pow(const U& x, const V& y) {
  return exp(y * log(x));
}
}  // namespace internal
}  // namespace math
}  // namespace stan
#endif
<commit_msg>Added std::pow to stan::math namespace to handle arithmetic types (Issue #1809)<commit_after>#ifndef STAN_MATH_PRIM_FUN_POW_HPP
#define STAN_MATH_PRIM_FUN_POW_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <cmath>
#include <complex>

namespace stan {
namespace math {

using std::pow;

namespace internal {

/**
 * Return the first argument raised to the power of the second
 * argument.  At least one of the arguments must be a complex number.
 *
 * @tparam U type of base
 * @tparam V type of exponent
 * @param[in] x base
 * @param[in] y exponent
 * @return base raised to the power of the exponent
 */
template <typename U, typename V>
inline complex_return_t<U, V> complex_pow(const U& x, const V& y) {
  return exp(y * log(x));
}
}  // namespace internal
}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "nonlinear_implicit_system.h"
#include "diff_solver.h"
#include "equation_systems.h"
#include "libmesh_logging.h"
#include "nonlinear_solver.h"
#include "sparse_matrix.h"

namespace libMesh
{

// ------------------------------------------------------------
// NonlinearImplicitSystem implementation
NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems& es,
						  const std::string& name,
						  const unsigned int number) :

  Parent                    (es, name, number),
  nonlinear_solver          (NonlinearSolver<Number>::build(*this)),
  diff_solver               (NULL),
  _n_nonlinear_iterations   (0),
  _final_nonlinear_residual (1.e20)
{
  // Set default parameters
  // These were chosen to match the Petsc defaults
  es.parameters.set<Real>        ("linear solver tolerance") = 1e-5;
  es.parameters.set<Real>        ("linear solver minimum tolerance") = 1e-5;
  es.parameters.set<unsigned int>("linear solver maximum iterations") = 10000;

  es.parameters.set<unsigned int>("nonlinear solver maximum iterations") = 50;
  es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") = 10000;

  es.parameters.set<Real>("nonlinear solver absolute residual tolerance") = 1e-50;
  es.parameters.set<Real>("nonlinear solver relative residual tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver absolute step tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;
}

NonlinearImplicitSystem::~NonlinearImplicitSystem ()
{
  // Clear data
  this->clear();
}

void NonlinearImplicitSystem::clear ()
{
  // clear the nonlinear solver
  nonlinear_solver->clear();

  // clear the parent data
  Parent::clear();
}

void NonlinearImplicitSystem::reinit ()
{
  // re-initialize the nonlinear solver interface
  nonlinear_solver->clear();

  if (diff_solver.get())
    diff_solver->reinit();

  // initialize parent data
  Parent::reinit();
}

void NonlinearImplicitSystem::set_solver_parameters ()
{
  // Get a reference to the EquationSystems
  const EquationSystems& es =
    this->get_equation_systems();

  // Get the user-specifiied nonlinear solver tolerances
  const unsigned int maxits =
    es.parameters.get<unsigned int>("nonlinear solver maximum iterations");

  const unsigned int maxfuncs =
    es.parameters.get<unsigned int>("nonlinear solver maximum function evaluations");

  const Real abs_resid_tol =
    es.parameters.get<Real>("nonlinear solver absolute residual tolerance");

  const Real rel_resid_tol =
    es.parameters.get<Real>("nonlinear solver relative residual tolerance");

  const Real abs_step_tol =
    es.parameters.get<Real>("nonlinear solver absolute step tolerance");

  const Real rel_step_tol =
    es.parameters.get<Real>("nonlinear solver relative step tolerance");

  // Get the user-specified linear solver toleranaces
  const unsigned int maxlinearits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const Real linear_tol =
    es.parameters.get<Real>("linear solver tolerance");

  const Real linear_min_tol =
    es.parameters.get<Real>("linear solver minimum tolerance");

  // Set all the parameters on the NonlinearSolver
  nonlinear_solver->max_nonlinear_iterations = maxits;
  nonlinear_solver->max_function_evaluations = maxfuncs;
  nonlinear_solver->absolute_residual_tolerance = abs_resid_tol;
  nonlinear_solver->relative_residual_tolerance = rel_resid_tol;
  nonlinear_solver->absolute_step_tolerance = abs_step_tol;
  nonlinear_solver->relative_step_tolerance = rel_step_tol;
  nonlinear_solver->max_linear_iterations = maxlinearits;
  nonlinear_solver->initial_linear_tolerance = linear_tol;
  nonlinear_solver->minimum_linear_tolerance = linear_min_tol;

  if (diff_solver.get())
    {
      diff_solver->max_nonlinear_iterations = maxits;
      diff_solver->absolute_residual_tolerance = abs_resid_tol;
      diff_solver->relative_residual_tolerance = rel_resid_tol;
      diff_solver->absolute_step_tolerance = abs_step_tol;
      diff_solver->relative_step_tolerance = rel_step_tol;
      diff_solver->max_linear_iterations = maxlinearits;
      diff_solver->initial_linear_tolerance = linear_tol;
      diff_solver->minimum_linear_tolerance = linear_min_tol;
    }
}

void NonlinearImplicitSystem::solve ()
{
  // Log how long the nonlinear solve takes.
  START_LOG("solve()", "System");

  this->set_solver_parameters();

  if (diff_solver.get())
    {
      diff_solver->solve();

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = diff_solver->total_outer_iterations();
      _final_nonlinear_residual = 0.; // FIXME - support this!
    }
  else
    {
      // Solve the nonlinear system.
      const std::pair<unsigned int, Real> rval =
        nonlinear_solver->solve (*matrix, *solution, *rhs,
			         nonlinear_solver->relative_residual_tolerance,
                                 nonlinear_solver->max_linear_iterations);

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = rval.first;
      _final_nonlinear_residual = rval.second;
    }

  // Stop logging the nonlinear solve
  STOP_LOG("solve()", "System");

  // Update the system after the solve
  this->update();
}

std::pair<unsigned int, Real> NonlinearImplicitSystem::get_linear_solve_parameters() const
{
  if (diff_solver.get())
    return std::make_pair(this->diff_solver->max_linear_iterations,
                        this->diff_solver->relative_residual_tolerance);
  return std::make_pair(this->nonlinear_solver->max_linear_iterations,
                        this->nonlinear_solver->relative_residual_tolerance);
}

void NonlinearImplicitSystem::assembly(bool get_residual,
				       bool get_jacobian)
{
  // Get current_local_solution in sync
  this->update();

  if (get_jacobian)
    {
      if (nonlinear_solver->jacobian != NULL)
        nonlinear_solver->jacobian (*current_local_solution.get(), *matrix, *this);
      else if (nonlinear_solver->matvec != NULL)
        nonlinear_solver->matvec (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);
      else libmesh_error();
    }

  if (get_residual)
    {
      if (nonlinear_solver->residual != NULL)
        nonlinear_solver->residual (*current_local_solution.get(), *rhs, *this);
      else if (nonlinear_solver->matvec != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->matvec (*current_local_solution.get(), rhs, NULL, *this);
        }
      else
        libmesh_error();
    }
  else if (!get_jacobian)
    libmesh_assert(false);  // I can't believe you really wanted to assemble *nothing*
}

} // namespace libMesh
<commit_msg>Better fix for overzealous assert<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "nonlinear_implicit_system.h"
#include "diff_solver.h"
#include "equation_systems.h"
#include "libmesh_logging.h"
#include "nonlinear_solver.h"
#include "sparse_matrix.h"

namespace libMesh
{

// ------------------------------------------------------------
// NonlinearImplicitSystem implementation
NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems& es,
						  const std::string& name,
						  const unsigned int number) :

  Parent                    (es, name, number),
  nonlinear_solver          (NonlinearSolver<Number>::build(*this)),
  diff_solver               (NULL),
  _n_nonlinear_iterations   (0),
  _final_nonlinear_residual (1.e20)
{
  // Set default parameters
  // These were chosen to match the Petsc defaults
  es.parameters.set<Real>        ("linear solver tolerance") = 1e-5;
  es.parameters.set<Real>        ("linear solver minimum tolerance") = 1e-5;
  es.parameters.set<unsigned int>("linear solver maximum iterations") = 10000;

  es.parameters.set<unsigned int>("nonlinear solver maximum iterations") = 50;
  es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") = 10000;

  es.parameters.set<Real>("nonlinear solver absolute residual tolerance") = 1e-50;
  es.parameters.set<Real>("nonlinear solver relative residual tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver absolute step tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;
}

NonlinearImplicitSystem::~NonlinearImplicitSystem ()
{
  // Clear data
  this->clear();
}

void NonlinearImplicitSystem::clear ()
{
  // clear the nonlinear solver
  nonlinear_solver->clear();

  // clear the parent data
  Parent::clear();
}

void NonlinearImplicitSystem::reinit ()
{
  // re-initialize the nonlinear solver interface
  nonlinear_solver->clear();

  if (diff_solver.get())
    diff_solver->reinit();

  // initialize parent data
  Parent::reinit();
}

void NonlinearImplicitSystem::set_solver_parameters ()
{
  // Get a reference to the EquationSystems
  const EquationSystems& es =
    this->get_equation_systems();

  // Get the user-specifiied nonlinear solver tolerances
  const unsigned int maxits =
    es.parameters.get<unsigned int>("nonlinear solver maximum iterations");

  const unsigned int maxfuncs =
    es.parameters.get<unsigned int>("nonlinear solver maximum function evaluations");

  const Real abs_resid_tol =
    es.parameters.get<Real>("nonlinear solver absolute residual tolerance");

  const Real rel_resid_tol =
    es.parameters.get<Real>("nonlinear solver relative residual tolerance");

  const Real abs_step_tol =
    es.parameters.get<Real>("nonlinear solver absolute step tolerance");

  const Real rel_step_tol =
    es.parameters.get<Real>("nonlinear solver relative step tolerance");

  // Get the user-specified linear solver toleranaces
  const unsigned int maxlinearits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const Real linear_tol =
    es.parameters.get<Real>("linear solver tolerance");

  const Real linear_min_tol =
    es.parameters.get<Real>("linear solver minimum tolerance");

  // Set all the parameters on the NonlinearSolver
  nonlinear_solver->max_nonlinear_iterations = maxits;
  nonlinear_solver->max_function_evaluations = maxfuncs;
  nonlinear_solver->absolute_residual_tolerance = abs_resid_tol;
  nonlinear_solver->relative_residual_tolerance = rel_resid_tol;
  nonlinear_solver->absolute_step_tolerance = abs_step_tol;
  nonlinear_solver->relative_step_tolerance = rel_step_tol;
  nonlinear_solver->max_linear_iterations = maxlinearits;
  nonlinear_solver->initial_linear_tolerance = linear_tol;
  nonlinear_solver->minimum_linear_tolerance = linear_min_tol;

  if (diff_solver.get())
    {
      diff_solver->max_nonlinear_iterations = maxits;
      diff_solver->absolute_residual_tolerance = abs_resid_tol;
      diff_solver->relative_residual_tolerance = rel_resid_tol;
      diff_solver->absolute_step_tolerance = abs_step_tol;
      diff_solver->relative_step_tolerance = rel_step_tol;
      diff_solver->max_linear_iterations = maxlinearits;
      diff_solver->initial_linear_tolerance = linear_tol;
      diff_solver->minimum_linear_tolerance = linear_min_tol;
    }
}

void NonlinearImplicitSystem::solve ()
{
  // Log how long the nonlinear solve takes.
  START_LOG("solve()", "System");

  this->set_solver_parameters();

  if (diff_solver.get())
    {
      diff_solver->solve();

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = diff_solver->total_outer_iterations();
      _final_nonlinear_residual = 0.; // FIXME - support this!
    }
  else
    {
      // Solve the nonlinear system.
      const std::pair<unsigned int, Real> rval =
        nonlinear_solver->solve (*matrix, *solution, *rhs,
			         nonlinear_solver->relative_residual_tolerance,
                                 nonlinear_solver->max_linear_iterations);

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = rval.first;
      _final_nonlinear_residual = rval.second;
    }

  // Stop logging the nonlinear solve
  STOP_LOG("solve()", "System");

  // Update the system after the solve
  this->update();
}

std::pair<unsigned int, Real> NonlinearImplicitSystem::get_linear_solve_parameters() const
{
  if (diff_solver.get())
    return std::make_pair(this->diff_solver->max_linear_iterations,
                        this->diff_solver->relative_residual_tolerance);
  return std::make_pair(this->nonlinear_solver->max_linear_iterations,
                        this->nonlinear_solver->relative_residual_tolerance);
}

void NonlinearImplicitSystem::assembly(bool get_residual,
				       bool get_jacobian)
{
  // Get current_local_solution in sync
  this->update();

  if (get_jacobian)
    {
      if (nonlinear_solver->jacobian != NULL)
        nonlinear_solver->jacobian (*current_local_solution.get(), *matrix, *this);
      else if (nonlinear_solver->matvec != NULL)
        nonlinear_solver->matvec (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);
      else libmesh_error();
    }

  if (get_residual)
    {
      if (nonlinear_solver->residual != NULL)
        nonlinear_solver->residual (*current_local_solution.get(), *rhs, *this);
      else if (nonlinear_solver->matvec != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->matvec (*current_local_solution.get(), rhs, NULL, *this);
        }
      else
        libmesh_error();
    }
  else
    libmesh_assert(get_jacobian);  // I can't believe you really wanted to assemble *nothing*
}

} // namespace libMesh
<|endoftext|>