<commit_before>// Onut
#include <onut/ContentManager.h>
#include <onut/Files.h>
#include <onut/Input.h>
#include <onut/Images.h>
#include <onut/Log.h>

// Private
#include "InputDeviceSDL2.h"

// STL
#include <cassert>
#include <fcntl.h>
#include <unistd.h>

namespace onut
{
    OInputDeviceRef InputDevice::create(OInput* pInput)
    {
        return std::shared_ptr<InputDeviceSDL2>(new InputDeviceSDL2(pInput));
    }

    InputDeviceSDL2::InputDeviceSDL2(OInput* pInput)
        : InputDevice(pInput)
    {
        m_mouseState[0] = 0;
        m_mouseState[1] = 1;
        m_mouseState[2] = 2;
        m_previousMouseState[0] = 0;
        m_previousMouseState[1] = 1;
        m_previousMouseState[2] = 2;

        SDL_Init(SDL_INIT_GAMECONTROLLER);

        m_pArrowCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
    }

    InputDeviceSDL2::~InputDeviceSDL2()
    {
        for (const auto& kv : m_cursors)
        {
            SDL_FreeCursor(kv.second);
        }
        SDL_FreeCursor(m_pArrowCursor);
    }

    void InputDeviceSDL2::readKeyboard()
    {
        int keyCount = (int)m_keyboardState.size();
        for (int i = 0; i < keyCount; ++i)
        {
            auto isDown = m_keyboardState[i];
            auto isPreviousDown = m_previousKeyboardState[i];
            if (!isPreviousDown && isDown)
            {
                m_pInput->setStateDown(static_cast<onut::Input::State>(i));
            }
            else if (isPreviousDown && !isDown)
            {
                m_pInput->setStateUp(static_cast<onut::Input::State>(i));
            }
        }

        memcpy(m_previousKeyboardState.data(), m_keyboardState.data(), sizeof(Uint8) * keyCount);
        bSwaped = true;
    }

    void InputDeviceSDL2::readMouse()
    {
        if (!m_previousMouseState[0] && m_mouseState[0])
        {
            m_pInput->setStateDown(OMouse1);
        }
        else if (m_previousMouseState[0] && !m_mouseState[0])
        {
            m_pInput->setStateUp(OMouse1);
        }
        if (!m_previousMouseState[1] && m_mouseState[1])
        {
            m_pInput->setStateDown(OMouse2);
        }
        else if (m_previousMouseState[1] && !m_mouseState[1])
        {
            m_pInput->setStateUp(OMouse2);
        }
        if (!m_previousMouseState[2] && m_mouseState[2])
        {
            m_pInput->setStateDown(OMouse3);
        }
        else if (m_previousMouseState[2] && !m_mouseState[2])
        {
            m_pInput->setStateUp(OMouse3);
        }

        memcpy(m_previousMouseState, m_mouseState, sizeof(Uint8) * 3);
        bSwaped = true;
    }

    void InputDeviceSDL2::updateSDL2()
    {
        // Keyboard
        int keyCount = 0;
        auto pSDLStates = SDL_GetKeyboardState(&keyCount);

        m_previousKeyboardState.resize(keyCount, 0);
        m_keyboardState.resize(keyCount, 0);

        for (int i = 0; i < keyCount; ++i)
        {
            auto sdlState = pSDLStates[i];
            if (sdlState || bSwaped)
            {
                m_keyboardState[i] = sdlState;
            }
        }

        // Mouse
        int x, y;
        auto mouseBtnStates = SDL_GetMouseState(&x, &y);

        m_pInput->mousePos.x = x;
        m_pInput->mousePos.y = y;
        m_pInput->mousePosf.x = static_cast<float>(x);
        m_pInput->mousePosf.y = static_cast<float>(y);

        m_pInput->setStateValue(OMouseX, (float)x);
        m_pInput->setStateValue(OMouseY, (float)y);

        bool mouseL =  (mouseBtnStates & SDL_BUTTON(SDL_BUTTON_LEFT)) ? true : false;
        bool mouseM =  (mouseBtnStates & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? true : false;
        bool mouseR =  (mouseBtnStates & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? true : false;
        if (mouseL || bSwaped) m_mouseState[0] = mouseL ? 1 : 0;
        if (mouseR || bSwaped) m_mouseState[1] = mouseR ? 1 : 0;
        if (mouseM || bSwaped) m_mouseState[2] = mouseM ? 1 : 0;

        bSwaped = false;
    }

    void InputDeviceSDL2::setMouseVisible(bool isCursorVisible)
    {
        SDL_ShowCursor(isCursorVisible ? SDL_ENABLE : SDL_DISABLE);
    }

    void InputDeviceSDL2::setMouseIcon(const std::string& name, const Point& hotSpot)
    {
        auto it = m_cursors.find(name);
        if (it == m_cursors.end())
        {
            auto fullPath = oContentManager->findResourceFile(name);
            if (!fullPath.empty())
            {
                Point size;
                auto pngData = onut::loadPNG(fullPath, size);
                if (!pngData.empty())
                {
                    auto pSurface = SDL_CreateRGBSurfaceFrom(pngData.data(),
                                      size.x,
                                      size.y,
                                      32,
                                      size.x * 4,
                                      0x000000ff,
                                      0x0000ff00,
                                      0x00ff0000,
                                      0xff000000);
                    if (pSurface)
                    {
                        auto pCursor = SDL_CreateColorCursor(pSurface, hotSpot.x, hotSpot.y);
                        if (pCursor)
                        {
                            m_cursors[name] = pCursor;
                            SDL_SetCursor(pCursor);
                        }
                        SDL_FreeSurface(pSurface);
                    }
                }
            }
        }
        else
        {
            SDL_SetCursor(it->second);
        }
    }

    void InputDeviceSDL2::unsetMouseIcon()
    {
        SDL_SetCursor(m_pArrowCursor);
    }

    void InputDeviceSDL2::setMousePos(const Point& mousePos)
    {
        // ...
    }
}
<commit_msg>Fixed setMousePos on SDL2<commit_after>// Onut
#include <onut/ContentManager.h>
#include <onut/Files.h>
#include <onut/Input.h>
#include <onut/Images.h>
#include <onut/Log.h>

// Private
#include "InputDeviceSDL2.h"
#include "WindowSDL2.h"

// STL
#include <cassert>
#include <fcntl.h>
#include <unistd.h>

namespace onut
{
    OInputDeviceRef InputDevice::create(OInput* pInput)
    {
        return std::shared_ptr<InputDeviceSDL2>(new InputDeviceSDL2(pInput));
    }

    InputDeviceSDL2::InputDeviceSDL2(OInput* pInput)
        : InputDevice(pInput)
    {
        m_mouseState[0] = 0;
        m_mouseState[1] = 1;
        m_mouseState[2] = 2;
        m_previousMouseState[0] = 0;
        m_previousMouseState[1] = 1;
        m_previousMouseState[2] = 2;

        SDL_Init(SDL_INIT_GAMECONTROLLER);

        m_pArrowCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
    }

    InputDeviceSDL2::~InputDeviceSDL2()
    {
        for (const auto& kv : m_cursors)
        {
            SDL_FreeCursor(kv.second);
        }
        SDL_FreeCursor(m_pArrowCursor);
    }

    void InputDeviceSDL2::readKeyboard()
    {
        int keyCount = (int)m_keyboardState.size();
        for (int i = 0; i < keyCount; ++i)
        {
            auto isDown = m_keyboardState[i];
            auto isPreviousDown = m_previousKeyboardState[i];
            if (!isPreviousDown && isDown)
            {
                m_pInput->setStateDown(static_cast<onut::Input::State>(i));
            }
            else if (isPreviousDown && !isDown)
            {
                m_pInput->setStateUp(static_cast<onut::Input::State>(i));
            }
        }

        memcpy(m_previousKeyboardState.data(), m_keyboardState.data(), sizeof(Uint8) * keyCount);
        bSwaped = true;
    }

    void InputDeviceSDL2::readMouse()
    {
        if (!m_previousMouseState[0] && m_mouseState[0])
        {
            m_pInput->setStateDown(OMouse1);
        }
        else if (m_previousMouseState[0] && !m_mouseState[0])
        {
            m_pInput->setStateUp(OMouse1);
        }
        if (!m_previousMouseState[1] && m_mouseState[1])
        {
            m_pInput->setStateDown(OMouse2);
        }
        else if (m_previousMouseState[1] && !m_mouseState[1])
        {
            m_pInput->setStateUp(OMouse2);
        }
        if (!m_previousMouseState[2] && m_mouseState[2])
        {
            m_pInput->setStateDown(OMouse3);
        }
        else if (m_previousMouseState[2] && !m_mouseState[2])
        {
            m_pInput->setStateUp(OMouse3);
        }

        memcpy(m_previousMouseState, m_mouseState, sizeof(Uint8) * 3);
        bSwaped = true;
    }

    void InputDeviceSDL2::updateSDL2()
    {
        // Keyboard
        int keyCount = 0;
        auto pSDLStates = SDL_GetKeyboardState(&keyCount);

        m_previousKeyboardState.resize(keyCount, 0);
        m_keyboardState.resize(keyCount, 0);

        for (int i = 0; i < keyCount; ++i)
        {
            auto sdlState = pSDLStates[i];
            if (sdlState || bSwaped)
            {
                m_keyboardState[i] = sdlState;
            }
        }

        // Mouse
        int x, y;
        auto mouseBtnStates = SDL_GetMouseState(&x, &y);

        m_pInput->mousePos.x = x;
        m_pInput->mousePos.y = y;
        m_pInput->mousePosf.x = static_cast<float>(x);
        m_pInput->mousePosf.y = static_cast<float>(y);

        m_pInput->setStateValue(OMouseX, (float)x);
        m_pInput->setStateValue(OMouseY, (float)y);

        bool mouseL =  (mouseBtnStates & SDL_BUTTON(SDL_BUTTON_LEFT)) ? true : false;
        bool mouseM =  (mouseBtnStates & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? true : false;
        bool mouseR =  (mouseBtnStates & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? true : false;
        if (mouseL || bSwaped) m_mouseState[0] = mouseL ? 1 : 0;
        if (mouseR || bSwaped) m_mouseState[1] = mouseR ? 1 : 0;
        if (mouseM || bSwaped) m_mouseState[2] = mouseM ? 1 : 0;

        bSwaped = false;
    }

    void InputDeviceSDL2::setMouseVisible(bool isCursorVisible)
    {
        SDL_ShowCursor(isCursorVisible ? SDL_ENABLE : SDL_DISABLE);
    }

    void InputDeviceSDL2::setMouseIcon(const std::string& name, const Point& hotSpot)
    {
        auto it = m_cursors.find(name);
        if (it == m_cursors.end())
        {
            auto fullPath = oContentManager->findResourceFile(name);
            if (!fullPath.empty())
            {
                Point size;
                auto pngData = onut::loadPNG(fullPath, size);
                if (!pngData.empty())
                {
                    auto pSurface = SDL_CreateRGBSurfaceFrom(pngData.data(),
                                      size.x,
                                      size.y,
                                      32,
                                      size.x * 4,
                                      0x000000ff,
                                      0x0000ff00,
                                      0x00ff0000,
                                      0xff000000);
                    if (pSurface)
                    {
                        auto pCursor = SDL_CreateColorCursor(pSurface, hotSpot.x, hotSpot.y);
                        if (pCursor)
                        {
                            m_cursors[name] = pCursor;
                            SDL_SetCursor(pCursor);
                        }
                        SDL_FreeSurface(pSurface);
                    }
                }
            }
        }
        else
        {
            SDL_SetCursor(it->second);
        }
    }

    void InputDeviceSDL2::unsetMouseIcon()
    {
        SDL_SetCursor(m_pArrowCursor);
    }

    void InputDeviceSDL2::setMousePos(const Point& mousePos)
    {
        SDL_WarpMouseInWindow(((WindowSDL2*)oWindow.get())->getSDLWindow(), mousePos.x, mousePos.y);
    }
}
<|endoftext|>


<commit_before>// NanoWin32
// -----------------------------------------------------------------------
// Simple library to subset Win32(64) API functions implemenation on POSIX
// This software distributed by MIT license

// FileFind functions

#include <sys/types.h>
#include <sys/stat.h>
#include <libgen.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include "NanoWinInternal.h"
#include "NanoWinStrConvert.h"
#include "NanoWinMsSafeString.h"
#include "NanoWinFileFind.h"

#include "NanoWinError.h"

typedef struct
{
  DIR  *dirHandle;
  char *dirName;
  char *fileMask;
} NanoWinFileFindHandle;

typedef struct
{
  bool isWideVersion;

  union
  {
    WIN32_FIND_DATAA *multiByteData;
    WIN32_FIND_DATAW *wideCharData;
  };
} NanoWinFileFindData;

#define NanoWinFindFileDirSeparatorChar ('/')

NW_EXTERN_C_BEGIN

//NOTE: result string can be overwritten by consequent calls, so
//      must be copied somewhere before next call to this function
static char *FilePathGetDirectory(const char *fullName)
{
  char *clonedFullName = strdup(fullName);

  if (clonedFullName == NULL)
  {
    return NULL;
  }

  char *directory = dirname(clonedFullName);

  if (directory != NULL)
  {
    directory = strdup(directory);
  }

  free(clonedFullName);

  return directory;
}

//NOTE: result string can be overwritten by consequent calls, so
//      must be copied somewhere before next call to this function
static char *FilePathGetFileName(const char *fullName)
{
  char *clonedFullName = strdup(fullName);

  if (clonedFullName == NULL)
  {
    return NULL;
  }

  char *fileName = basename(clonedFullName);

  if (fileName != NULL)
  {
    fileName = strdup(fileName);
  }

  free(clonedFullName);

  return fileName;
}

static NanoWinFileFindHandle *NanoWinFindFileOpenHandle(char *dirName, char *fileMask)
{
  bool ok = true;
  NanoWinFileFindHandle *handle = (NanoWinFileFindHandle*)malloc(sizeof(NanoWinFileFindHandle));

  if (handle == NULL)
  {
    ok = false;

    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  }

  if (ok)
  {
    handle->dirHandle = opendir(dirName);

    if (handle->dirHandle == NULL)
    {
      ok = false;

      SetLastError(NanoWinErrorByErrnoAtFail(errno));
    }
  }

  if (ok)
  {
    handle->dirName = dirName;
    handle->fileMask = fileMask;
  }
  else
  {
    free(dirName);
    free(fileMask);

    if (handle != NULL)
    {
      if (handle->dirHandle != NULL)
      {
        closedir(handle->dirHandle);
      }

      free(handle);

      handle = NULL;
    }
  }

  return handle;
}

static void NanoWinFindFileCloseHandle(NanoWinFileFindHandle *handle)
{
  if (handle != NULL)
  {
    if (handle->dirHandle != NULL)
    {
      closedir(handle->dirHandle);
    }

    if (handle->dirName != NULL)
    {
      free(handle->dirName);
    }

    if (handle->fileMask != NULL)
    {
      free(handle->fileMask);
    }

    free(handle);
  }
}

static bool NanoWinJoinDirAndFileName(char *fullFileName, size_t fullFileNameMaxSize, const char *dirName, const char *fileName)
{
  size_t dirNameLen      = strlen(dirName);
  size_t fileNameLen     = strlen(fileName);
  size_t fullFileNameLen = dirNameLen + 1 + fileNameLen;

  if (fullFileNameLen < fullFileNameMaxSize)
  {
    memcpy(fullFileName, dirName, dirNameLen);
    fullFileName[dirNameLen] = NanoWinFindFileDirSeparatorChar;
    memcpy(&fullFileName[dirNameLen + 1], fileName, fileNameLen);
    fullFileName[fullFileNameLen] = '\0';

    return true;
  }
  else
  {
    return false;
  }
}

static void NanoWinFillFindData(NanoWinFileFindData *data, const char *dirName, struct dirent *entry)
{
  struct stat entryData;
  char        fullFileName[PATH_MAX];

  DWORD fileSizeHigh = 0;
  DWORD fileSizeLow  = 0;

  if (NanoWinJoinDirAndFileName(fullFileName, sizeof(fullFileName), dirName, entry->d_name))
  {
    if (stat(fullFileName, &entryData) == 0)
    {
      if (S_ISREG(entryData.st_mode))
      {
        if (sizeof(entryData.st_size) > sizeof(DWORD))
        {
          fileSizeHigh = entryData.st_size >> (sizeof(DWORD) * 8);
          fileSizeLow  = entryData.st_size & 0xFFFFFFFFLU;
        }
        else
        {
          fileSizeHigh = 0;
          fileSizeLow  = entryData.st_size;
        }
      }
    }
  }

  if (data->isWideVersion)
  {
    WIN32_FIND_DATAW * wideCharData = data->wideCharData;

    memset(wideCharData, 0, sizeof(*wideCharData));

    NanoWin::StrToWStrClone wideFileName(entry->d_name);

    wcsncpy_s(wideCharData->cFileName, sizeof(wideCharData->cFileName) / sizeof(wideCharData->cFileName[0]),
      wideFileName.c_str(), sizeof(wideCharData->cFileName) / sizeof(wideCharData->cFileName[0]) - 1);

    wideCharData->nFileSizeHigh = fileSizeHigh;
    wideCharData->nFileSizeLow  = fileSizeLow;
  }
  else
  {
    WIN32_FIND_DATAA * multiByteData = data->multiByteData;

    memset(multiByteData, 0, sizeof(*multiByteData));

    strncpy_s(multiByteData->cFileName, sizeof(multiByteData->cFileName), entry->d_name, sizeof(multiByteData->cFileName) - 1);

    multiByteData->nFileSizeHigh = fileSizeHigh;
    multiByteData->nFileSizeLow  = fileSizeLow;
  }
}

static bool NanoWinFindFileSeekToNextFile(NanoWinFileFindHandle *handle, NanoWinFileFindData *state)
{
  bool ok    = true;
  bool found = false;

  while (ok && !found)
  {
    errno = 0;

    struct dirent *entry = readdir(handle->dirHandle);

    if (entry != NULL)
    {
      if (NanoWinFileNameMatchMaskA(entry->d_name, handle->fileMask))
      {
        found = true;

        NanoWinFillFindData(state, handle->dirName, entry);
      }
    }
    else
    {
      ok = false;

      if (errno == 0)
      {
        SetLastError(ERROR_FILE_NOT_FOUND);
      }
      else
      {
        SetLastError(NanoWinErrorByErrnoAtFail(errno));
      }
    }
  }

  return found;
}

static HANDLE FindFirstFileUniversal(const char *Mask, NanoWinFileFindData *data)
{
  char *dirName  = FilePathGetDirectory(Mask);
  char *fileMask = FilePathGetFileName(Mask);

  if (dirName == NULL || fileMask == NULL)
  {
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);

    if (dirName != NULL)
    {
      free(dirName);
    }

    if (fileMask != NULL)
    {
      free(fileMask);
    }

    return INVALID_HANDLE_VALUE;
  }

  NanoWinFileFindHandle *handle = NanoWinFindFileOpenHandle(dirName,fileMask);

  if (handle != NULL)
  {
    if (!NanoWinFindFileSeekToNextFile(handle, data))
    {
      NanoWinFindFileCloseHandle(handle);

      handle = NULL;
    }
  }

  return handle != NULL ? handle : INVALID_HANDLE_VALUE;
}

extern HANDLE FindFirstFileA(const char *Mask, WIN32_FIND_DATAA *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = false;
  data.multiByteData = state;

  return FindFirstFileUniversal(Mask, &data);
}

extern BOOL   FindNextFileA(HANDLE handle, WIN32_FIND_DATAA *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = false;
  data.multiByteData = state;

  return NanoWinFindFileSeekToNextFile((NanoWinFileFindHandle*)handle, &data);
}

extern HANDLE FindFirstFileW(const wchar_t *Mask, WIN32_FIND_DATAW *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = true;
  data.wideCharData  = state;

  NanoWin::WStrToStrClone wideCharMask(Mask);

  return FindFirstFileUniversal(wideCharMask.c_str(), &data);
}

extern BOOL   FindNextFileW(HANDLE handle, WIN32_FIND_DATAW *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = true;
  data.wideCharData  = state;

  return NanoWinFindFileSeekToNextFile((NanoWinFileFindHandle*)handle, &data);
}

extern BOOL   FindClose(HANDLE hFindFile)
{
  NanoWinFindFileCloseHandle((NanoWinFileFindHandle*)hFindFile);

  return TRUE;
}

NW_EXTERN_C_END
<commit_msg>fixed bug in FindClose implementation<commit_after>// NanoWin32
// -----------------------------------------------------------------------
// Simple library to subset Win32(64) API functions implemenation on POSIX
// This software distributed by MIT license

// FileFind functions

#include <sys/types.h>
#include <sys/stat.h>
#include <libgen.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include "NanoWinInternal.h"
#include "NanoWinStrConvert.h"
#include "NanoWinMsSafeString.h"
#include "NanoWinFileFind.h"

#include "NanoWinError.h"

typedef struct
{
  DIR  *dirHandle;
  char *dirName;
  char *fileMask;
} NanoWinFileFindHandle;

typedef struct
{
  bool isWideVersion;

  union
  {
    WIN32_FIND_DATAA *multiByteData;
    WIN32_FIND_DATAW *wideCharData;
  };
} NanoWinFileFindData;

#define NanoWinFindFileDirSeparatorChar ('/')

NW_EXTERN_C_BEGIN

//NOTE: result string can be overwritten by consequent calls, so
//      must be copied somewhere before next call to this function
static char *FilePathGetDirectory(const char *fullName)
{
  char *clonedFullName = strdup(fullName);

  if (clonedFullName == NULL)
  {
    return NULL;
  }

  char *directory = dirname(clonedFullName);

  if (directory != NULL)
  {
    directory = strdup(directory);
  }

  free(clonedFullName);

  return directory;
}

//NOTE: result string can be overwritten by consequent calls, so
//      must be copied somewhere before next call to this function
static char *FilePathGetFileName(const char *fullName)
{
  char *clonedFullName = strdup(fullName);

  if (clonedFullName == NULL)
  {
    return NULL;
  }

  char *fileName = basename(clonedFullName);

  if (fileName != NULL)
  {
    fileName = strdup(fileName);
  }

  free(clonedFullName);

  return fileName;
}

static NanoWinFileFindHandle *NanoWinFindFileOpenHandle(char *dirName, char *fileMask)
{
  bool ok = true;
  NanoWinFileFindHandle *handle = (NanoWinFileFindHandle*)malloc(sizeof(NanoWinFileFindHandle));

  if (handle == NULL)
  {
    ok = false;

    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  }

  if (ok)
  {
    handle->dirHandle = opendir(dirName);

    if (handle->dirHandle == NULL)
    {
      ok = false;

      SetLastError(NanoWinErrorByErrnoAtFail(errno));
    }
  }

  if (ok)
  {
    handle->dirName = dirName;
    handle->fileMask = fileMask;
  }
  else
  {
    free(dirName);
    free(fileMask);

    if (handle != NULL)
    {
      if (handle->dirHandle != NULL)
      {
        closedir(handle->dirHandle);
      }

      free(handle);

      handle = NULL;
    }
  }

  return handle;
}

static void NanoWinFindFileCloseHandle(NanoWinFileFindHandle *handle)
{
  if (handle != NULL)
  {
    if (handle->dirHandle != NULL)
    {
      closedir(handle->dirHandle);
    }

    if (handle->dirName != NULL)
    {
      free(handle->dirName);
    }

    if (handle->fileMask != NULL)
    {
      free(handle->fileMask);
    }

    free(handle);
  }
}

static bool NanoWinJoinDirAndFileName(char *fullFileName, size_t fullFileNameMaxSize, const char *dirName, const char *fileName)
{
  size_t dirNameLen      = strlen(dirName);
  size_t fileNameLen     = strlen(fileName);
  size_t fullFileNameLen = dirNameLen + 1 + fileNameLen;

  if (fullFileNameLen < fullFileNameMaxSize)
  {
    memcpy(fullFileName, dirName, dirNameLen);
    fullFileName[dirNameLen] = NanoWinFindFileDirSeparatorChar;
    memcpy(&fullFileName[dirNameLen + 1], fileName, fileNameLen);
    fullFileName[fullFileNameLen] = '\0';

    return true;
  }
  else
  {
    return false;
  }
}

static void NanoWinFillFindData(NanoWinFileFindData *data, const char *dirName, struct dirent *entry)
{
  struct stat entryData;
  char        fullFileName[PATH_MAX];

  DWORD fileSizeHigh = 0;
  DWORD fileSizeLow  = 0;

  if (NanoWinJoinDirAndFileName(fullFileName, sizeof(fullFileName), dirName, entry->d_name))
  {
    if (stat(fullFileName, &entryData) == 0)
    {
      if (S_ISREG(entryData.st_mode))
      {
        if (sizeof(entryData.st_size) > sizeof(DWORD))
        {
          fileSizeHigh = entryData.st_size >> (sizeof(DWORD) * 8);
          fileSizeLow  = entryData.st_size & 0xFFFFFFFFLU;
        }
        else
        {
          fileSizeHigh = 0;
          fileSizeLow  = entryData.st_size;
        }
      }
    }
  }

  if (data->isWideVersion)
  {
    WIN32_FIND_DATAW * wideCharData = data->wideCharData;

    memset(wideCharData, 0, sizeof(*wideCharData));

    NanoWin::StrToWStrClone wideFileName(entry->d_name);

    wcsncpy_s(wideCharData->cFileName, sizeof(wideCharData->cFileName) / sizeof(wideCharData->cFileName[0]),
      wideFileName.c_str(), sizeof(wideCharData->cFileName) / sizeof(wideCharData->cFileName[0]) - 1);

    wideCharData->nFileSizeHigh = fileSizeHigh;
    wideCharData->nFileSizeLow  = fileSizeLow;
  }
  else
  {
    WIN32_FIND_DATAA * multiByteData = data->multiByteData;

    memset(multiByteData, 0, sizeof(*multiByteData));

    strncpy_s(multiByteData->cFileName, sizeof(multiByteData->cFileName), entry->d_name, sizeof(multiByteData->cFileName) - 1);

    multiByteData->nFileSizeHigh = fileSizeHigh;
    multiByteData->nFileSizeLow  = fileSizeLow;
  }
}

static bool NanoWinFindFileSeekToNextFile(NanoWinFileFindHandle *handle, NanoWinFileFindData *state)
{
  bool ok    = true;
  bool found = false;

  while (ok && !found)
  {
    errno = 0;

    struct dirent *entry = readdir(handle->dirHandle);

    if (entry != NULL)
    {
      if (NanoWinFileNameMatchMaskA(entry->d_name, handle->fileMask))
      {
        found = true;

        NanoWinFillFindData(state, handle->dirName, entry);
      }
    }
    else
    {
      ok = false;

      if (errno == 0)
      {
        SetLastError(ERROR_FILE_NOT_FOUND);
      }
      else
      {
        SetLastError(NanoWinErrorByErrnoAtFail(errno));
      }
    }
  }

  return found;
}

static HANDLE FindFirstFileUniversal(const char *Mask, NanoWinFileFindData *data)
{
  char *dirName  = FilePathGetDirectory(Mask);
  char *fileMask = FilePathGetFileName(Mask);

  if (dirName == NULL || fileMask == NULL)
  {
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);

    if (dirName != NULL)
    {
      free(dirName);
    }

    if (fileMask != NULL)
    {
      free(fileMask);
    }

    return INVALID_HANDLE_VALUE;
  }

  NanoWinFileFindHandle *handle = NanoWinFindFileOpenHandle(dirName,fileMask);

  if (handle != NULL)
  {
    if (!NanoWinFindFileSeekToNextFile(handle, data))
    {
      NanoWinFindFileCloseHandle(handle);

      handle = NULL;
    }
  }

  return handle != NULL ? handle : INVALID_HANDLE_VALUE;
}

extern HANDLE FindFirstFileA(const char *Mask, WIN32_FIND_DATAA *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = false;
  data.multiByteData = state;

  return FindFirstFileUniversal(Mask, &data);
}

extern BOOL   FindNextFileA(HANDLE handle, WIN32_FIND_DATAA *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = false;
  data.multiByteData = state;

  return NanoWinFindFileSeekToNextFile((NanoWinFileFindHandle*)handle, &data);
}

extern HANDLE FindFirstFileW(const wchar_t *Mask, WIN32_FIND_DATAW *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = true;
  data.wideCharData  = state;

  NanoWin::WStrToStrClone wideCharMask(Mask);

  return FindFirstFileUniversal(wideCharMask.c_str(), &data);
}

extern BOOL   FindNextFileW(HANDLE handle, WIN32_FIND_DATAW *state)
{
  NanoWinFileFindData data;

  data.isWideVersion = true;
  data.wideCharData  = state;

  return NanoWinFindFileSeekToNextFile((NanoWinFileFindHandle*)handle, &data);
}

extern BOOL   FindClose(HANDLE hFindFile)
{
  if (hFindFile == NULL || hFindFile == INVALID_HANDLE_VALUE)
  {
    return FALSE;
  }
  else
  {
    NanoWinFindFileCloseHandle((NanoWinFileFindHandle*)hFindFile);
  }

  return TRUE;
}

NW_EXTERN_C_END
<|endoftext|>


<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum 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 version 3 for more details.
*/

#include "Cube.h"

using namespace std;

namespace Magnum { namespace Primitives {

Cube::Cube(): MeshData(Mesh::Primitive::Triangles, new vector<unsigned int>{
    0, 1, 2,
    2, 1, 3,
    1, 5, 3,
    3, 5, 7,
    5, 4, 7,
    7, 4, 6,
    4, 0, 6,
    6, 0, 2,
    2, 3, 7,
    2, 7, 6,
    4, 5, 1,
    4, 1, 0
}, {new vector<Vector4>}, {new vector<Vector3>{
    {-1.0f, -1.0f, -1.0f},
    { 1.0f, -1.0f, -1.0f},
    {-1.0f,  1.0f, -1.0f},
    { 1.0f,  1.0f, -1.0f},
    {-1.0f, -1.0f,  1.0f},
    { 1.0f, -1.0f,  1.0f},
    {-1.0f,  1.0f,  1.0f},
    { 1.0f,  1.0f,  1.0f}
}}, {}) {
    vertices(0)->assign(normals(0)->begin(), normals(0)->end());
}

}}
<commit_msg>Flipped cube primitive face winding, so the faces are oriented outside.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum 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 version 3 for more details.
*/

#include "Cube.h"

using namespace std;

namespace Magnum { namespace Primitives {

Cube::Cube(): MeshData(Mesh::Primitive::Triangles, new vector<unsigned int>{
    0, 2, 1,
    2, 3, 1,
    1, 3, 5,
    3, 7, 5,
    5, 7, 4,
    7, 6, 4,
    4, 6, 0,
    6, 2, 0,
    2, 7, 3,
    2, 6, 7,
    4, 1, 5,
    4, 0, 1
}, {new vector<Vector4>}, {new vector<Vector3>{
    {-1.0f, -1.0f, -1.0f},
    { 1.0f, -1.0f, -1.0f},
    {-1.0f,  1.0f, -1.0f},
    { 1.0f,  1.0f, -1.0f},
    {-1.0f, -1.0f,  1.0f},
    { 1.0f, -1.0f,  1.0f},
    {-1.0f,  1.0f,  1.0f},
    { 1.0f,  1.0f,  1.0f}
}}, {}) {
    vertices(0)->assign(normals(0)->begin(), normals(0)->end());
}

}}
<|endoftext|>


<commit_before>//************************************************************/
//
//	CrossSection Implementation
//
//	Implements the SPXCrossSection class, which performs the
//	convolution and all math required to calculate the cross-
//	section from a PDF and a grid file.
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		14.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include "SPXCrossSection.h"
#include "SPXUtilities.h"
#include "SPXException.h"

//Class name for debug statements
const std::string cn = "SPXCrossSection::";

//Must define the static debug variable in the implementation
bool SPXCrossSection::debug;

//Create the CrossSection
void SPXCrossSection::Create(void) {

	//Attempt to create the Grid
	try {
		grid = new SPXGrid(pci);
	} catch(const SPXException &e) {
		throw;
	}

	//Attempt to create the PDF object and perform convolution
	try {
		pdf = new SPXPDF(psf, grid->GetGridName());
	} catch(const SPXException &e) {
		throw;
	}

	//Check if grid contains corrections
	if(pci.gridSteeringFile.GetNumberOfCorrectionFiles() != 0) {
		try {
			corrections = new SPXGridCorrections(pci);
			corrections->Parse();
			corrections->Print();
		} catch(const SPXException &e) {
			throw;
		}
	}
}

void SPXCrossSection::ApplyCorrections(void) {
	if(pci.gridSteeringFile.GetNumberOfCorrectionFiles() == 0) {
		return;
	}

	//Loop over the band bins and make sure they match, if not just do nothing

	// unsigned int nBins = pdf->h_PDFBand_results->GetN();
	// double *x = pdf->h_PDFBand_results->GetX();
	// double *y = pdf->h_PDFBand

	//@TODO Should calculate the TOTAL scale for sigma, dsig+, dsig- and have it accessible as a vector from the SPXGridCorrections class
	//		then only need to loop over bins and make sure there is a corresponding bin for each total scale, and if there is, apply it.
	//		The SPXGridCorrections class should do the check to see whether the different corrections have the same binning

	// //PDF Band
	// for(int i = 0; i < pci.gridSteeringFile.GetNumberOfCorrectionFiles(); i++) {
	// 	std::string &key = pci.gridSteeringFile.GetCorrectionFile(i);
	// 	std::vector<std::vector<double> > &matrix;
	//
	// 	matrix = corrections.GetCorrections(key);
	//
	//
	// 	//Loop over bins in band and apply corrections if the bins match up
	// 	for(int j = 0; j < nBins; j++) {
	//
	//
	// 		if(matrix[1] != )
	// 	}
	// }

	//@TODO Do the same for Alpha S and Scale uncertainty bands
}
<commit_msg>Testing Grid Corrections<commit_after>//************************************************************/
//
//	CrossSection Implementation
//
//	Implements the SPXCrossSection class, which performs the
//	convolution and all math required to calculate the cross-
//	section from a PDF and a grid file.
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		14.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include "SPXCrossSection.h"
#include "SPXUtilities.h"
#include "SPXException.h"

//Class name for debug statements
const std::string cn = "SPXCrossSection::";

//Must define the static debug variable in the implementation
bool SPXCrossSection::debug;

//Create the CrossSection
void SPXCrossSection::Create(void) {

	//Attempt to create the Grid
	try {
		grid = new SPXGrid(*pci);
	} catch(const SPXException &e) {
		throw;
	}

	//Attempt to create the PDF object and perform convolution
	try {
		pdf = new SPXPDF(psf, grid->GetGridName());
	} catch(const SPXException &e) {
		throw;
	}

	//Check if grid contains corrections
	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() != 0) {
		try {
			corrections = new SPXGridCorrections(pci);
			corrections->Parse();
			corrections->Print();
		} catch(const SPXException &e) {
			throw;
		}
	}
}

void SPXCrossSection::ApplyCorrections(void) {
	if(pci.gridSteeringFile.GetNumberOfCorrectionFiles() == 0) {
		return;
	}

	//Loop over the band bins and make sure they match, if not just do nothing

	// unsigned int nBins = pdf->h_PDFBand_results->GetN();
	// double *x = pdf->h_PDFBand_results->GetX();
	// double *y = pdf->h_PDFBand

	//@TODO Should calculate the TOTAL scale for sigma, dsig+, dsig- and have it accessible as a vector from the SPXGridCorrections class
	//		then only need to loop over bins and make sure there is a corresponding bin for each total scale, and if there is, apply it.
	//		The SPXGridCorrections class should do the check to see whether the different corrections have the same binning

	// //PDF Band
	// for(int i = 0; i < pci.gridSteeringFile.GetNumberOfCorrectionFiles(); i++) {
	// 	std::string &key = pci.gridSteeringFile.GetCorrectionFile(i);
	// 	std::vector<std::vector<double> > &matrix;
	//
	// 	matrix = corrections.GetCorrections(key);
	//
	//
	// 	//Loop over bins in band and apply corrections if the bins match up
	// 	for(int j = 0; j < nBins; j++) {
	//
	//
	// 		if(matrix[1] != )
	// 	}
	// }

	//@TODO Do the same for Alpha S and Scale uncertainty bands
}
<|endoftext|>


<commit_before>//************************************************************/
//
//	CrossSection Implementation
//
//	Implements the SPXCrossSection class, which performs the
//	convolution and all math required to calculate the cross-
//	section from a PDF and a grid file.
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		14.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include "SPXCrossSection.h"
#include "SPXUtilities.h"
#include "SPXException.h"

//Class name for debug statements
const std::string cn = "SPXCrossSection::";

//Must define the static debug variable in the implementation
bool SPXCrossSection::debug;

//Create the CrossSection
void SPXCrossSection::Create(void) {
	std::string mn = "Create: ";

	//Attempt to create the Grid
	try {
		grid = new SPXGrid(pci);
	} catch(const SPXException &e) {
		throw;
	}

	//Attempt to create the PDF object and perform convolution
	try {
		pdf = new SPXPDF(psf, grid->GetGridName());
	} catch(const SPXException &e) {
		throw;
	}

	//Set the name of the convolution graphs appropriately
	//Create name strings
	TString name;
	TString pdfName;
	TString alphaSName;
	TString scaleName;

	//Check if name exists
	if(!pci->gridSteeringFile.GetName().empty()) {
		name = TString(pci->gridSteeringFile.GetName());
		pdfName = name + "_pdf";
		alphaSName = name + "_alpha_s";
		scaleName = name + "_scale";
	}

	//Grid steering file has no [DESC]:name
	//Default to filename
	else {
		if(debug) std::cout << cn << mn << "Grid steering file has no name value: using filename instead" << std::endl;
		name = pci->gridSteeringFile.GetFilename();
		name.ReplaceAll(TString(".txt"), TString(""));
		pdfName = name + "_pdf";
		alphaSName = name + "_alpha_s";
		scaleName = name + "_scale";
	}

	//Set the graph names
	if(pdf->h_PDFBand_results) pdf->h_PDFBand_results->SetName(pdfName);
	if(pdf->h_AlphaS_results) pdf->h_AlphaS_results->SetName(alphaSName);
	if(pdf->h_Scale_results) pdf->h_Scale_results->SetName(scaleName);
}

void SPXCrossSection::ParseCorrections(void) {
	//Check if grid contains corrections
	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() != 0) {
		try {
			corrections = new SPXGridCorrections(*pci);
			corrections->Parse();
			corrections->Print();
		} catch(const SPXException &e) {
			throw;
		}
	}
}

void SPXCrossSection::ApplyCorrections(void) {
	std::string mn = "ApplyCorrections: ";

	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() == 0) {
		return;
	}

	std::cout << cn << mn << ">>>>>>>>>>>>>>>>> APPLY CORRECTIONS <<<<<<<<<<<<<<<<<" << std::endl;

	//Loop over the band bins and make sure they match, if not just do nothing

	unsigned int nBins = pdf->h_PDFBand_results->GetN();
	double *x = pdf->h_PDFBand_results->GetX();
	double *y = pdf->h_PDFBand_results->GetY();
	double *exl = pdf->h_PDFBand_results->GetEXlow();
	double *exh = pdf->h_PDFBand_results->GetEXhigh();
	double *eyl = pdf->h_PDFBand_results->GetEYlow();
	double *eyh = pdf->h_PDFBand_results->GetEYhigh();

	unsigned int nBinsCorr = corrections->GetNumberOfBins();
	double *c_x = &(corrections->GetTotalX().at(0));
	double *c_exl = &(corrections->GetTotalEXL().at(0));
	double *c_exh = &(corrections->GetTotalEXH().at(0));
	double *c_y = &(corrections->GetTotalYCorrections().at(0));
	double *c_eyl = &(corrections->GetTotalEYLCorrections().at(0));
	double *c_eyh = &(corrections->GetTotalEYHCorrections().at(0));

	//Loop over the smallest of the two
	unsigned int n = (nBins < nBinsCorr ? nBins : nBinsCorr);

	for(int i = 0; i < nBins; i++) {
		for(int j = 0; j < nBinsCorr; j++) {

			//Check for bin match
			if(((x[i] - exl[i]) == c_exl[j]) && ((x[i] + exh[i]) == c_exh[j])) {

				if(debug) std::cout << cn << mn << "Bins Match (i, j): (" << i << ", " << j << ")" << std::endl;

				//Bins match; Scale y, eyl, and eyh
				y[i] *= c_y[j];
				eyl[i] *= c_eyl[j];
				eyh[i] *= c_eyh[j];

				break;
			}
		}
	}

	//@TODO Do the same for Alpha S and Scale uncertainty bands
}
<commit_msg>Debug<commit_after>//************************************************************/
//
//	CrossSection Implementation
//
//	Implements the SPXCrossSection class, which performs the
//	convolution and all math required to calculate the cross-
//	section from a PDF and a grid file.
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		14.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include "SPXCrossSection.h"
#include "SPXUtilities.h"
#include "SPXException.h"

//Class name for debug statements
const std::string cn = "SPXCrossSection::";

//Must define the static debug variable in the implementation
bool SPXCrossSection::debug;

//Create the CrossSection
void SPXCrossSection::Create(void) {
	std::string mn = "Create: ";

	//Attempt to create the Grid
	try {
		grid = new SPXGrid(pci);
	} catch(const SPXException &e) {
		throw;
	}

	//Attempt to create the PDF object and perform convolution
	try {
		pdf = new SPXPDF(psf, grid->GetGridName());
	} catch(const SPXException &e) {
		throw;
	}

	//Set the name of the convolution graphs appropriately
	//Create name strings
	TString name;
	TString pdfName;
	TString alphaSName;
	TString scaleName;

	//Check if name exists
	if(!pci->gridSteeringFile.GetName().empty()) {
		name = TString(pci->gridSteeringFile.GetName());
		pdfName = name + "_pdf";
		alphaSName = name + "_alpha_s";
		scaleName = name + "_scale";
	}

	//Grid steering file has no [DESC]:name
	//Default to filename
	else {
		if(debug) std::cout << cn << mn << "Grid steering file has no name value: using filename instead" << std::endl;
		name = pci->gridSteeringFile.GetFilename();
		name.ReplaceAll(TString(".txt"), TString(""));
		pdfName = name + "_pdf";
		alphaSName = name + "_alpha_s";
		scaleName = name + "_scale";
	}

	//Set the graph names
	// if(pdf->h_PDFBand_results) pdf->h_PDFBand_results->SetName(pdfName);
	// if(pdf->h_AlphaS_results) pdf->h_AlphaS_results->SetName(alphaSName);
	// if(pdf->h_Scale_results) pdf->h_Scale_results->SetName(scaleName);
}

void SPXCrossSection::ParseCorrections(void) {
	//Check if grid contains corrections
	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() != 0) {
		try {
			corrections = new SPXGridCorrections(*pci);
			corrections->Parse();
			corrections->Print();
		} catch(const SPXException &e) {
			throw;
		}
	}
}

void SPXCrossSection::ApplyCorrections(void) {
	std::string mn = "ApplyCorrections: ";

	if(pci->gridSteeringFile.GetNumberOfCorrectionFiles() == 0) {
		return;
	}

	std::cout << cn << mn << ">>>>>>>>>>>>>>>>> APPLY CORRECTIONS <<<<<<<<<<<<<<<<<" << std::endl;

	//Loop over the band bins and make sure they match, if not just do nothing

	unsigned int nBins = pdf->h_PDFBand_results->GetN();
	double *x = pdf->h_PDFBand_results->GetX();
	double *y = pdf->h_PDFBand_results->GetY();
	double *exl = pdf->h_PDFBand_results->GetEXlow();
	double *exh = pdf->h_PDFBand_results->GetEXhigh();
	double *eyl = pdf->h_PDFBand_results->GetEYlow();
	double *eyh = pdf->h_PDFBand_results->GetEYhigh();

	unsigned int nBinsCorr = corrections->GetNumberOfBins();
	double *c_x = &(corrections->GetTotalX().at(0));
	double *c_exl = &(corrections->GetTotalEXL().at(0));
	double *c_exh = &(corrections->GetTotalEXH().at(0));
	double *c_y = &(corrections->GetTotalYCorrections().at(0));
	double *c_eyl = &(corrections->GetTotalEYLCorrections().at(0));
	double *c_eyh = &(corrections->GetTotalEYHCorrections().at(0));

	//Loop over the smallest of the two
	unsigned int n = (nBins < nBinsCorr ? nBins : nBinsCorr);

	for(int i = 0; i < nBins; i++) {
		for(int j = 0; j < nBinsCorr; j++) {

			//Check for bin match
			if(((x[i] - exl[i]) == c_exl[j]) && ((x[i] + exh[i]) == c_exh[j])) {

				if(debug) std::cout << cn << mn << "Bins Match (i, j): (" << i << ", " << j << ")" << std::endl;

				//Bins match; Scale y, eyl, and eyh
				y[i] *= c_y[j];
				eyl[i] *= c_eyl[j];
				eyh[i] *= c_eyh[j];

				break;
			}
		}
	}

	//@TODO Do the same for Alpha S and Scale uncertainty bands
}
<|endoftext|>


<commit_before>#include "VehicleGLWidget.h"
#include <QKeyEvent>
#include <cmath>

// Config
const float MAXSPEED = 900;
const float REV_MAXSPEED = 400;
const int ACCELERATION = 250;
const int REV_ACCEL = 120;
const int DRAG = 0;
const int BRAKE_POWER = 1100;
const float TURN_SPEED = 1;
const float ELASTICITY = .4;		// Bounciness after collisions
// end Config

// All values are half-size.
const int VEHICLE_LENGTH = 30;
const int VEHICLE_WIDTH = 15;
const int ARENA_SIZE = 500;
const int WALL_SIZE = 10;

VehicleGLWidget::VehicleGLWidget(QWidget* const parent) :
		QGLWidget(QGLFormat(QGL::SampleBuffers), parent),
		timer(this)
{
	setFocusPolicy(Qt::ClickFocus);
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(tick(const float&)));
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(updateGL()));
	timer.startOnShow(this);
	car.maxspeed = MAXSPEED;
	car.rev_maxspeed = -REV_MAXSPEED;
}

void VehicleGLWidget::initializeGL()
{
	qglClearColor(Qt::black);
}

void VehicleGLWidget::tick(const float& elapsed)
{

	float accel = 0;
	const float dir = car.velocity > 0 ? -1 : 1;	// if car.velocity > 0 then dir = -1 else dir = 1
	const float friction = pad.brake ? dir * (BRAKE_POWER + DRAG) : dir * DRAG; // activate an opposing force
	const float antiVelocity = friction * elapsed;	// reducing speeds is easier than manipulating negative acceleration

	if (pad.accelerator) {
		accel = ACCELERATION;
	} else if (pad.reverse) {
		accel =  -REV_ACCEL;
	}

	if (pad.left && !pad.right) {
		car.angle += M_PI * elapsed * TURN_SPEED;
	}
	if (pad.right && !pad.left) {
		car.angle -= M_PI * elapsed * TURN_SPEED;
	}

	float velocity_init = car.velocity;					// for position calculation purposes
	car.velocity += accel * elapsed;					// the equations with acceleration would lead to a wrong result when moving at maxspeed
	car.velocity = abs(car.velocity) > abs(antiVelocity) ? car.velocity + antiVelocity : 0 ;

	if (car.velocity > car.maxspeed) {car.velocity = car.maxspeed; }	// no going over maxspeed
	else if (car.velocity < car.rev_maxspeed) { car.velocity = car.rev_maxspeed; }

	float x = car.pos.x() + 0.5 * (car.velocity + velocity_init) * elapsed * cos(car.angle); // S = Sinit + (1/2) * (V + Vinit) * deltaT
	float y = car.pos.y() + 0.5 * (car.velocity + velocity_init) * elapsed * sin(car.angle);

	const int range = ARENA_SIZE - VEHICLE_LENGTH;
	{
		const double diff = abs(x) - range;
		if (diff > 0) {
			car.velocity *= -ELASTICITY;
			if (x > 0) {
				// X is positive; head negative
				x = range - diff;
			} else {
				// X is negative; head positive
				x = -range + diff;
			}
		}
		car.pos.setX(x);
	}
	{
		const double diff = abs(y) - range;
		if (diff > 0) {
			car.velocity *= -ELASTICITY;
			if (y > 0) {
				// Y is positive; head negative
				y = range - diff;
			} else {
				// Y is negative; head positive
				y = -range + diff;
			}
		}
		car.pos.setY(y);
	}
}

void drawQuad(float left, float right, float bottom, float top)
{
	glVertex2f(right, bottom);
	glVertex2f(right, top);
	glVertex2f(left, top);
	glVertex2f(left, bottom);
}

void drawQuad(float width, float height)
{
	drawQuad(-width, width, height, -height);
}

void VehicleGLWidget::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	// Render walls
	glBegin(GL_QUADS);
	glColor3ub(0xa3, 0xa5, 0x9f);
	drawQuad(ARENA_SIZE+WALL_SIZE, ARENA_SIZE+WALL_SIZE);
	glColor3ub(75, 54, 33);
	drawQuad(ARENA_SIZE, ARENA_SIZE);
	glEnd();
	// Render car
	glTranslatef(car.pos.x(), car.pos.y(), car.pos.z());
	glRotatef(car.angle * 180 / M_PI, 0, 0, 1);
	glBegin(GL_QUADS);
	// Body
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(VEHICLE_LENGTH, VEHICLE_WIDTH);
	// Windshields
	glColor3ub(35, 35, 35);
	drawQuad(
		-VEHICLE_LENGTH + 10,
		VEHICLE_LENGTH / 3,
		-VEHICLE_WIDTH + 2,
		VEHICLE_WIDTH - 2
		);
	// Front lights
	glColor3f(1, 1, .2);
	drawQuad(
		VEHICLE_LENGTH,
		VEHICLE_LENGTH - 3,
		-VEHICLE_WIDTH,
		VEHICLE_WIDTH
		);
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(
		VEHICLE_LENGTH,
		VEHICLE_LENGTH - 3,
		-VEHICLE_WIDTH + 5,
		VEHICLE_WIDTH - 5
		);
	// Rear lights
	if (pad.brake) {
		glColor3f(1, .2, .2);
	} else {
		glColor3f(.7, 0, 0);
	}
	drawQuad(
		-VEHICLE_LENGTH,
		-VEHICLE_LENGTH + 2,
		-VEHICLE_WIDTH,
		VEHICLE_WIDTH
		);
	// Reverse lights
	if (pad.reverse && car.velocity <= 0) {
		glColor3f(1, 1, 1);
		drawQuad(
			-VEHICLE_LENGTH,
			-VEHICLE_LENGTH + 2,
			-VEHICLE_WIDTH + 7,
			VEHICLE_WIDTH - 7
			);
	}
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(
		-VEHICLE_LENGTH,
		-VEHICLE_LENGTH + 2,
		-VEHICLE_WIDTH + 9,
		VEHICLE_WIDTH - 9
		);
	// Top
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(
		-VEHICLE_LENGTH / 2 + 2,
		0,
		-VEHICLE_WIDTH + 4,
		VEHICLE_WIDTH - 4
		);
	glEnd();
}

void VehicleGLWidget::keyPressEvent(QKeyEvent* event)
{
	switch (event->key()) {
		case Qt::Key_Space:
			car.pos = QVector3D(0, 0, 0);
			car.velocity = 0;
			car.angle = 0;
			break;
		case Qt::Key_W: pad.accelerator = true; break;
		case Qt::Key_S: pad.reverse = true; break;
		case Qt::Key_A: pad.left = true; break;
		case Qt::Key_D: pad.right = true; break;
		case Qt::Key_Shift: pad.brake = true; break;
		default:
			QGLWidget::keyPressEvent(event);
	}
}

void VehicleGLWidget::keyReleaseEvent(QKeyEvent* event)
{
	switch (event->key()) {
		case Qt::Key_W: pad.accelerator = false; break;
		case Qt::Key_S: pad.reverse = false; break;
		case Qt::Key_A: pad.left = false; break;
		case Qt::Key_D: pad.right = false; break;
		case Qt::Key_Shift: pad.brake = false; break;
		default:
			QGLWidget::keyReleaseEvent(event);
	}
}

void VehicleGLWidget::resizeGL(int width, int height)
{
	int side = qMin(width, height);
	glViewport((width - side) / 2, (height - side) / 2, side, side);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(
		-ARENA_SIZE - WALL_SIZE, ARENA_SIZE + WALL_SIZE,
		-ARENA_SIZE - WALL_SIZE, ARENA_SIZE + WALL_SIZE,
		-100, 100);
	glMatrixMode(GL_MODELVIEW);
}
<commit_msg>Slightly improved crashing in the Vehicle demo<commit_after>#include "VehicleGLWidget.h"
#include <QKeyEvent>
#include <cmath>

// Config
const float MAXSPEED = 900;
const float REV_MAXSPEED = 400;
const int ACCELERATION = 250;
const int REV_ACCEL = 160;
const int DRAG = 70;
const int BRAKE_POWER = 1100;
const float TURN_SPEED = 1;
const float ELASTICITY = .3;		// Bounciness after collisions
// end Config

// All values are half-size.
const int VEHICLE_LENGTH = 30;
const int VEHICLE_WIDTH = 15;
const int ARENA_SIZE = 500;
const int WALL_SIZE = 10;
// End
VehicleGLWidget::VehicleGLWidget(QWidget* const parent) :
		QGLWidget(QGLFormat(QGL::SampleBuffers), parent),
		timer(this)
{
	setFocusPolicy(Qt::ClickFocus);
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(tick(const float&)));
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(updateGL()));
	timer.startOnShow(this);
	car.maxspeed = MAXSPEED;
	car.rev_maxspeed = -REV_MAXSPEED;
}

void VehicleGLWidget::initializeGL()
{
	qglClearColor(Qt::black);
}

void VehicleGLWidget::tick(const float& elapsed)
{

	float accel = 0;
	const float dir = car.velocity > 0 ? -1 : 1;	// if car.velocity > 0 then dir = -1 else dir = 1
	const float friction = pad.brake ? dir * (BRAKE_POWER + DRAG) : dir * DRAG; // activate an opposing force
	const float antiVelocity = friction * elapsed;	// reducing speeds is easier than manipulating negative acceleration

	if (pad.accelerator) {
		accel = ACCELERATION;
	} else if (pad.reverse) {
		accel =  -REV_ACCEL;
	}

	if (pad.left && !pad.right) {
		car.angle += M_PI * elapsed * TURN_SPEED;
	}
	if (pad.right && !pad.left) {
		car.angle -= M_PI * elapsed * TURN_SPEED;
	}
	if ( car.angle > 2 * M_PI ) { car.angle -= 2 * M_PI; }	// keeps our angles within 1 revolution

	float velocity_init = car.velocity;					// for position calculation purposes
	car.velocity += accel * elapsed;					// the equations with acceleration would lead to a wrong result when moving at maxspeed
	car.velocity = abs(car.velocity) > abs(antiVelocity) ? car.velocity + antiVelocity : 0 ;

	if (car.velocity > car.maxspeed) {car.velocity = car.maxspeed; }	// no going over maxspeed
	else if (car.velocity < car.rev_maxspeed) { car.velocity = car.rev_maxspeed; }

	float x = car.pos.x() + 0.5 * (car.velocity + velocity_init) * elapsed * cos(car.angle); // S = Sinit + (1/2) * (V + Vinit) * deltaT
	float y = car.pos.y() + 0.5 * (car.velocity + velocity_init) * elapsed * sin(car.angle);

	const int range = ARENA_SIZE - VEHICLE_LENGTH;	// BUG: VEHICLE_LENGTH needs to be replaced with something that varies by car.angle
	{
		const double diff = abs(x) - range;
		if (diff > 0) {										// collision on the X-axis!
		car.velocity *= ELASTICITY / 2 ;					// slow the vehicle down -- 2 is arbritrary
			if (x > 0) {	// get out of the wall
				// X is positive, head negative to a good position
				x = range - diff;
			} else {
				// X is negative; head positive to a good position
				x = -range + diff;
			}

			if ( car.angle < 2 * M_PI /4 && car.angle > 1 * M_PI / 4 ) {	//
				car.angle += 2 * M_PI / 4 - car.angle;
			} else if ( car.angle > 2 * M_PI / 4 && car.angle < 3 * M_PI / 4 ) {
				car.angle -= 2 * M_PI / 4 - car.angle;
			} else if ( car.angle < 6 * M_PI / 4 && car.angle > 5 * M_PI / 4 ) {
				car.angle += 6 * M_PI / 4 - car.angle;
			} else if ( car.angle > 6 * M_PI / 4 && car.angle < 7 * M_PI / 4 ) {
				car.angle -= 6 * M_PI / 4 - car.angle;
			} else {
				car.velocity /= -2;  // bounce backwards with the correct "elasticity"
			}

		}
		car.pos.setX(x);
	}
	{
		const double diff = abs(y) - range;
		if (diff > 0) {										// collision on the Y-axis!
			car.velocity *= ELASTICITY * 2;				// slow the vehicle down -- 2 is arbritrary
			if (y > 0) {
				// Y is positive; head negative to a good position
				y = range - diff;
			} else {
				// Y is negative; head positive to a good position
				y = -range + diff;
			}
			if ( car.angle < 4 * M_PI /4 && car.angle > 3 * M_PI / 4 ) {
				car.angle += 4 * M_PI / 4 - car.angle;
			} else if ( car.angle > 4 * M_PI / 4 && car.angle < 5 * M_PI / 4 ) {
				car.angle -= 4 * M_PI / 4 - car.angle;
			} else if ( car.angle < 8 * M_PI / 4 && car.angle > 7 * M_PI / 4 ) {
				car.angle += 8 * M_PI / 4 - car.angle;
			} else if ( car.angle > 8 * M_PI / 4 && car.angle < 1 * M_PI / 4 ) {
				car.angle -= 8 * M_PI / 4 - car.angle;
			} else {
				car.velocity /= -2; // bounce backwards with the correct "elasticity"
			}
		}
		car.pos.setY(y);
	}
}

void drawQuad(float left, float right, float bottom, float top)
{
	glVertex2f(right, bottom);
	glVertex2f(right, top);
	glVertex2f(left, top);
	glVertex2f(left, bottom);
}

void drawQuad(float width, float height)
{
	drawQuad(-width, width, height, -height);
}

void VehicleGLWidget::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	// Render walls
	glBegin(GL_QUADS);
	glColor3ub(0xa3, 0xa5, 0x9f);
	drawQuad(ARENA_SIZE+WALL_SIZE, ARENA_SIZE+WALL_SIZE);
	glColor3ub(75, 54, 33);
	drawQuad(ARENA_SIZE, ARENA_SIZE);
	glEnd();
	// Render car
	glTranslatef(car.pos.x(), car.pos.y(), car.pos.z());
	glRotatef(car.angle * 180 / M_PI, 0, 0, 1);
	glBegin(GL_QUADS);
	// Body
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(VEHICLE_LENGTH, VEHICLE_WIDTH);
	// Windshields
	glColor3ub(35, 35, 35);
	drawQuad(
		-VEHICLE_LENGTH + 10,
		VEHICLE_LENGTH / 3,
		-VEHICLE_WIDTH + 2,
		VEHICLE_WIDTH - 2
		);
	// Front lights
	glColor3f(1, 1, .2);
	drawQuad(
		VEHICLE_LENGTH,
		VEHICLE_LENGTH - 3,
		-VEHICLE_WIDTH,
		VEHICLE_WIDTH
		);
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(
		VEHICLE_LENGTH,
		VEHICLE_LENGTH - 3,
		-VEHICLE_WIDTH + 5,
		VEHICLE_WIDTH - 5
		);
	// Rear lights
	if (pad.brake) {
		glColor3f(1, .2, .2);
	} else {
		glColor3f(.7, 0, 0);
	}
	drawQuad(
		-VEHICLE_LENGTH,
		-VEHICLE_LENGTH + 2,
		-VEHICLE_WIDTH,
		VEHICLE_WIDTH
		);
	// Reverse lights
	if (pad.reverse && car.velocity <= 0) {
		glColor3f(1, 1, 1);
		drawQuad(
			-VEHICLE_LENGTH,
			-VEHICLE_LENGTH + 2,
			-VEHICLE_WIDTH + 7,
			VEHICLE_WIDTH - 7
			);
	}
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(
		-VEHICLE_LENGTH,
		-VEHICLE_LENGTH + 2,
		-VEHICLE_WIDTH + 9,
		VEHICLE_WIDTH - 9
		);
	// Top
	glColor3ub(0, 0x5b, 0xa9);
	drawQuad(
		-VEHICLE_LENGTH / 2 + 2,
		0,
		-VEHICLE_WIDTH + 4,
		VEHICLE_WIDTH - 4
		);
	glEnd();
}

void VehicleGLWidget::keyPressEvent(QKeyEvent* event)
{
	switch (event->key()) {
		case Qt::Key_Space:
			car.pos = QVector3D(0, 0, 0);
			car.velocity = 0;
			car.angle = 0;
			break;
		case Qt::Key_W: pad.accelerator = true; break;
		case Qt::Key_S: pad.reverse = true; break;
		case Qt::Key_A: pad.left = true; break;
		case Qt::Key_D: pad.right = true; break;
		case Qt::Key_Shift: pad.brake = true; break;
		default:
			QGLWidget::keyPressEvent(event);
	}
}

void VehicleGLWidget::keyReleaseEvent(QKeyEvent* event)
{
	switch (event->key()) {
		case Qt::Key_W: pad.accelerator = false; break;
		case Qt::Key_S: pad.reverse = false; break;
		case Qt::Key_A: pad.left = false; break;
		case Qt::Key_D: pad.right = false; break;
		case Qt::Key_Shift: pad.brake = false; break;
		default:
			QGLWidget::keyReleaseEvent(event);
	}
}

void VehicleGLWidget::resizeGL(int width, int height)
{
	int side = qMin(width, height);
	glViewport((width - side) / 2, (height - side) / 2, side, side);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(
		-ARENA_SIZE - WALL_SIZE, ARENA_SIZE + WALL_SIZE,
		-ARENA_SIZE - WALL_SIZE, ARENA_SIZE + WALL_SIZE,
		-100, 100);
	glMatrixMode(GL_MODELVIEW);
}
<|endoftext|>


<commit_before>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// 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 "VkMemory.hpp"

#include "VkConfig.hpp"
#include "System/Memory.hpp"

namespace vk {

void *allocateDeviceMemory(size_t bytes, size_t alignment)
{
	// TODO(b/140991626): Use allocateZeroOrPoison() instead of allocateZero() to detect MemorySanitizer errors.
	// TODO(b/140991626): Use allocateUninitialized() instead of allocateZeroOrPoison() to improve startup peformance.
	return sw::allocateZero(bytes, alignment);
}

void freeDeviceMemory(void *ptr)
{
	sw::freeMemory(ptr);
}

void *allocateHostMemory(size_t bytes, size_t alignment, const VkAllocationCallbacks *pAllocator, VkSystemAllocationScope allocationScope)
{
	// TODO(b/140991626): Use allocateUninitialized() instead of allocateZeroOrPoison() to improve startup peformance.
	return pAllocator ? pAllocator->pfnAllocation(pAllocator->pUserData, bytes, alignment, allocationScope)
	                  : sw::allocateZeroOrPoison(bytes, alignment);
}

void freeHostMemory(void *ptr, const VkAllocationCallbacks *pAllocator)
{
	pAllocator ? pAllocator->pfnFree(pAllocator->pUserData, ptr) : sw::freeMemory(ptr);
}

}  // namespace vk
<commit_msg>Don't initialize device memory allocations in MSan builds<commit_after>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// 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 "VkMemory.hpp"

#include "VkConfig.hpp"
#include "System/Memory.hpp"

namespace vk {

void *allocateDeviceMemory(size_t bytes, size_t alignment)
{
	// TODO(b/140991626): Use allocateUninitialized() instead of allocateZeroOrPoison() to improve startup peformance.
	return sw::allocateZeroOrPoison(bytes, alignment);
}

void freeDeviceMemory(void *ptr)
{
	sw::freeMemory(ptr);
}

void *allocateHostMemory(size_t bytes, size_t alignment, const VkAllocationCallbacks *pAllocator, VkSystemAllocationScope allocationScope)
{
	// TODO(b/140991626): Use allocateUninitialized() instead of allocateZeroOrPoison() to improve startup peformance.
	return pAllocator ? pAllocator->pfnAllocation(pAllocator->pUserData, bytes, alignment, allocationScope)
	                  : sw::allocateZeroOrPoison(bytes, alignment);
}

void freeHostMemory(void *ptr, const VkAllocationCallbacks *pAllocator)
{
	pAllocator ? pAllocator->pfnFree(pAllocator->pUserData, ptr) : sw::freeMemory(ptr);
}

}  // namespace vk
<|endoftext|>


<commit_before>nifndef _H_DOCUMENT_NODE
#define _H_DOCUMENT_NODE

#include "XmlNode.hpp"

namespace Xml
{

    /**
     * Defines the abstract class of a document node for interface purpose
     */
    class DocumentNode : public Node
    {
    public:

        /**
         * Constructor
         *
         * @param parent Parent of the node
         */
        DocumentNode(Node * parent = nullptr);

        /**
         * Destructor
         */
        virtual
        ~DocumentNode();
    };
}

#endif //_H_DOCUMENT_NODE
<commit_msg>Fixed typo in XmlDocumentNode.hpp<commit_after>#ifndef _H_DOCUMENT_NODE
#define _H_DOCUMENT_NODE

#include "XmlNode.hpp"

namespace Xml
{

    /**
     * Defines the abstract class of a document node for interface purpose
     */
    class DocumentNode : public Node
    {
    public:

        /**
         * Constructor
         *
         * @param parent Parent of the node
         */
        DocumentNode(Node * parent = nullptr);

        /**
         * Destructor
         */
        virtual
        ~DocumentNode();
    };
}

#endif //_H_DOCUMENT_NODE
<|endoftext|>


<commit_before>#include <octree/octree_nn.h>
#include <octree/points.h>
#include <octree/points_parser.h>

#include "ocnn.h"

namespace {

PointsInfo::PropType get_ptype(const string property) {
  PointsInfo::PropType ptype = PointsInfo::kPoint;
  if (property == "xyz" || property == "xyzi") {
    ptype = PointsInfo::kPoint;
  } else if (property == "label") {
    ptype = PointsInfo::kLabel;
  } else if (property == "normal") {
    ptype = PointsInfo::kNormal;
  } else if (property == "feature") {
    ptype = PointsInfo::kFeature;
  } else {
    LOG(FATAL) << "Unsupported Property: " << property;
  }
  return ptype;
}

vector<float> tensor2vector(const Tensor& data_in) {
  vector<float> vec;
  Tensor data = data_in.contiguous();  // !!! make sure the Tensor is contiguous
  const int64_t num = data.numel();
  if (num > 0) {
    const float* ptr = data.data_ptr<float>();
    vec.assign(ptr, ptr + num);
  }
  return vec;
}

}  // anonymous namespace

Tensor points_new(Tensor pts, Tensor normals, Tensor features, Tensor labels) {
  // input
  vector<float> pts_in = tensor2vector(pts);
  vector<float> normals_in = tensor2vector(normals);
  vector<float> features_in = tensor2vector(features);
  vector<float> labels_in = tensor2vector(labels);

  // create the point cloud
  Points point_cloud;
  bool succ = point_cloud.set_points(pts_in, normals_in, features_in, labels_in);
  CHECK(succ) << "Error occurs when setting points";
  const vector<char>& points_buf = point_cloud.get_buffer();

  // output
  size_t sz = points_buf.size();
  Tensor output = torch::zeros({(int64_t)sz}, torch::dtype(torch::kUInt8));
  memcpy(output.data_ptr<uint8_t>(), points_buf.data(), sz);
  return output;
}

Tensor points_set_property(Tensor points_in, Tensor data, string property) {
  CHECK_EQ(data.dim(), 2);
  int num = data.size(0);
  int channel = data.size(1);
  data = data.contiguous();  // !!! make sure the Tensor is contiguous

  // init the points
  Points pts;
  auto points_ptr = points_in.data_ptr<uint8_t>();
  vector<char> points_buf(points_ptr, points_ptr + points_in.numel());
  pts.set(points_buf.data());

  // check the points
  string msg;
  bool succ = pts.info().check_format(msg);
  CHECK(succ) << msg;

  // get prop
  PointsInfo::PropType ptype = get_ptype(property);

  // set the property
  float* ptr = pts.mutable_ptr(ptype);
  CHECK(ptr != nullptr) << "The property does not exist.";
  CHECK_EQ(channel, pts.info().channel(ptype)) << "The channel is wrong.";
  CHECK_EQ(num, pts.info().pt_num()) << "The point number is wrong.";
  memcpy_cpu(num * channel, data.data_ptr<float>(), ptr);

  // output
  size_t sz = points_buf.size();
  Tensor output = torch::zeros({(int64_t)sz}, torch::dtype(torch::kUInt8));
  memcpy(output.data_ptr<uint8_t>(), points_buf.data(), sz);
  return output;
}

Tensor points_property(Tensor points, string property) {
  PointsParser points_in;
  points_in.set(points.data_ptr<uint8_t>());
  PointsInfo::PropType ptype = get_ptype(property);

  int npt = points_in.info().pt_num();
  int channel = points_in.info().channel(ptype);
  const float* ptr = points_in.ptr(ptype);
  CHECK_NE(ptr, nullptr) << "The specified property does not exist.";

  Tensor data_out = torch::zeros({npt, channel}, torch::dtype(torch::kFloat32));
  float* out_ptr = data_out.data_ptr<float>();
  memcpy_cpu(channel * npt, ptr, out_ptr);
  return data_out;
}

Tensor points_batch_property(vector<Tensor> tensors, string property) {
  int batch_size = tensors.size();
  vector<PointsParser> points_in(batch_size);
  for (int i = 0; i < batch_size; ++i) {
    points_in[i].set(tensors[i].data_ptr<uint8_t>());
  }

  // pt number
  int total_num = 0;
  vector<int> npts(batch_size);
  for (int i = 0; i < batch_size; ++i) {
    npts[i] = points_in[i].info().pt_num();
    total_num += npts[i];
  }

  // check
  PointsInfo::PropType ptype = get_ptype(property);
  int channel = points_in[0].info().channel(ptype);
  for (int i = 0; i < batch_size; ++i) {
    int ch = points_in[i].info().channel(ptype);
    CHECK_EQ(ch, channel) << "The specified channel_out is wrong.";
    const float* ptr = points_in[i].ptr(ptype);
    CHECK_NE(ptr, nullptr) << "The specified property does not exist.";
  }
  int channel_out = channel;
  if (property == "xyzi") { channel_out = 4; }

  // init output
  Tensor output = torch::zeros({total_num, channel_out}, torch::dtype(torch::kFloat32));
  float* out_ptr = output.data_ptr<float>();

  // copy output
  for (int i = 0; i < batch_size; ++i) {
    const float* in_ptr = points_in[i].ptr(ptype);
    for (int j = 0; j < npts[i]; ++j) {
      int jxc_in = j * channel, jxc_out = j * channel_out;
      for (int c = 0; c < channel; ++c) {
        out_ptr[jxc_out + c] = in_ptr[jxc_in + c];
      }
    }
    out_ptr += npts[i] * channel_out;
  }

  // output point index if channel == 4
  if (property == "xyzi") {
    out_ptr = output.data_ptr<float>();
    for (int i = 0; i < batch_size; ++i) {
      for (int j = 0; j < npts[i]; ++j) {
        out_ptr[j * channel_out + 3] = static_cast<float>(i);  // id
      }
      out_ptr += npts[i] * channel_out;
    }
  }

  return output;
}
<commit_msg>Update cpp of pytorch<commit_after>#include <octree/octree_nn.h>
#include <octree/points.h>
#include <octree/points_parser.h>

#include "ocnn.h"

namespace {

PointsInfo::PropType get_ptype(const string property) {
  PointsInfo::PropType ptype = PointsInfo::kPoint;
  if (property == "xyz" || property == "xyzi") {
    ptype = PointsInfo::kPoint;
  } else if (property == "label") {
    ptype = PointsInfo::kLabel;
  } else if (property == "normal") {
    ptype = PointsInfo::kNormal;
  } else if (property == "feature") {
    ptype = PointsInfo::kFeature;
  } else {
    LOG(FATAL) << "Unsupported Property: " << property;
  }
  return ptype;
}

vector<float> tensor2vector(const Tensor& data_in) {
  vector<float> vec;
  Tensor data = data_in.contiguous();  // !!! make sure the Tensor is contiguous
  const int64_t num = data.numel();
  if (num > 0) {
    const float* ptr = data.data_ptr<float>();
    vec.assign(ptr, ptr + num);
  }
  return vec;
}

}  // anonymous namespace

Tensor points_new(Tensor pts, Tensor normals, Tensor features, Tensor labels) {
  // input
  vector<float> pts_in = tensor2vector(pts);
  vector<float> normals_in = tensor2vector(normals);
  vector<float> features_in = tensor2vector(features);
  vector<float> labels_in = tensor2vector(labels);

  // create the point cloud
  Points point_cloud;
  bool succ = point_cloud.set_points(pts_in, normals_in, features_in, labels_in);
  CHECK(succ) << "Error occurs when setting points";
  const vector<char>& points_buf = point_cloud.get_buffer();

  // output
  size_t sz = points_buf.size();
  Tensor output = torch::zeros({(int64_t)sz}, torch::dtype(torch::kUInt8));
  memcpy(output.data_ptr<uint8_t>(), points_buf.data(), sz);
  return output;
}

Tensor points_set_property(Tensor points_in, Tensor data, string property) {
  CHECK_EQ(data.dim(), 2);
  int num = data.size(0);
  int channel = data.size(1);
  data = data.contiguous();  // !!! make sure the Tensor is contiguous

  // init the points
  Points pts;
  auto points_ptr = points_in.data_ptr<uint8_t>();
  vector<char> points_buf(points_ptr, points_ptr + points_in.numel());
  pts.set(points_buf.data());

  // check the points
  string msg;
  bool succ = pts.info().check_format(msg);
  CHECK(succ) << msg;

  // get prop
  PointsInfo::PropType ptype = get_ptype(property);

  // set the property
  float* ptr = pts.mutable_ptr(ptype);
  CHECK(ptr != nullptr) << "The property does not exist.";
  CHECK_EQ(channel, pts.info().channel(ptype)) << "The channel is wrong.";
  CHECK_EQ(num, pts.info().pt_num()) << "The point number is wrong.";
  memcpy_cpu(num * channel, data.data_ptr<float>(), ptr);

  // output
  size_t sz = points_buf.size();
  Tensor output = torch::zeros({(int64_t)sz}, torch::dtype(torch::kUInt8));
  memcpy(output.data_ptr<uint8_t>(), points_buf.data(), sz);
  return output;
}

Tensor points_property(Tensor points, string property) {
  PointsParser points_in;
  points_in.set(points.data_ptr<uint8_t>());
  PointsInfo::PropType ptype = get_ptype(property);

  int npt = points_in.info().pt_num();
  int channel = points_in.info().channel(ptype);
  const float* ptr = points_in.ptr(ptype);
  // CHECK_NE(ptr, nullptr) << "The specified property does not exist.";
  if (ptr == nullptr) {
    return Tensor();
  }

  Tensor data_out = torch::zeros({npt, channel}, torch::dtype(torch::kFloat32));
  float* out_ptr = data_out.data_ptr<float>();
  memcpy_cpu(channel * npt, ptr, out_ptr);
  return data_out;
}

Tensor points_batch_property(vector<Tensor> tensors, string property) {
  int batch_size = tensors.size();
  vector<PointsParser> points_in(batch_size);
  for (int i = 0; i < batch_size; ++i) {
    points_in[i].set(tensors[i].data_ptr<uint8_t>());
  }

  // pt number
  int total_num = 0;
  vector<int> npts(batch_size);
  for (int i = 0; i < batch_size; ++i) {
    npts[i] = points_in[i].info().pt_num();
    total_num += npts[i];
  }

  // check
  PointsInfo::PropType ptype = get_ptype(property);
  int channel = points_in[0].info().channel(ptype);
  for (int i = 0; i < batch_size; ++i) {
    int ch = points_in[i].info().channel(ptype);
    CHECK_EQ(ch, channel) << "The specified channel_out is wrong.";
    const float* ptr = points_in[i].ptr(ptype);
    CHECK_NE(ptr, nullptr) << "The specified property does not exist.";
  }
  int channel_out = channel;
  if (property == "xyzi") { channel_out = 4; }

  // init output
  Tensor output = torch::zeros({total_num, channel_out}, torch::dtype(torch::kFloat32));
  float* out_ptr = output.data_ptr<float>();

  // copy output
  for (int i = 0; i < batch_size; ++i) {
    const float* in_ptr = points_in[i].ptr(ptype);
    for (int j = 0; j < npts[i]; ++j) {
      int jxc_in = j * channel, jxc_out = j * channel_out;
      for (int c = 0; c < channel; ++c) {
        out_ptr[jxc_out + c] = in_ptr[jxc_in + c];
      }
    }
    out_ptr += npts[i] * channel_out;
  }

  // output point index if channel == 4
  if (property == "xyzi") {
    out_ptr = output.data_ptr<float>();
    for (int i = 0; i < batch_size; ++i) {
      for (int j = 0; j < npts[i]; ++j) {
        out_ptr[j * channel_out + 3] = static_cast<float>(i);  // id
      }
      out_ptr += npts[i] * channel_out;
    }
  }

  return output;
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC 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.

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

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_CORE_HXX
   #error Please #include <abc/core.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::dmstr

namespace abc {

#ifdef ABC_CXX_VARIADIC_TEMPLATES

template <typename ... Ts>
inline dmstr str_base::format(Ts const & ... ts) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), ts ...);
   return os.release_content();
}

#else //ifdef ABC_CXX_VARIADIC_TEMPLATES

inline dmstr str::format() const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this));
   return os.release_content();
}
template <typename T0>
inline dmstr str_base::format(T0 const & t0) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0);
   return os.release_content();
}

template <typename T0, typename T1>
inline dmstr str_base::format(T0 const & t0, T1 const & t1) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1);
   return os.release_content();
}
template <typename T0, typename T1, typename T2>
inline dmstr str_base::format(T0 const & t0, T1 const & t1, T2 const & t2) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2);
   return os.release_content();
}
template <typename T0, typename T1, typename T2, typename T3>
inline dmstr str_base::format(T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3);
   return os.release_content();
}
template <typename T0, typename T1, typename T2, typename T3, typename T4>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4);
   return os.release_content();
}
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
   typename T7
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6, T7 const & t7
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6, t7);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
   typename T7, typename T8
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6, T7 const & t7, T8 const & t8
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6, t7, t8);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
   typename T7, typename T8, typename T9
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6, T7 const & t7, T8 const & t8, T9 const & t9
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
   return os.release_content();
}

#endif //ifdef ABC_CXX_VARIADIC_TEMPLATES … else

} //namespace abc

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

<commit_msg>Fix typo<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC 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.

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

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_CORE_HXX
   #error Please #include <abc/core.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::dmstr

namespace abc {

#ifdef ABC_CXX_VARIADIC_TEMPLATES

template <typename ... Ts>
inline dmstr str_base::format(Ts const & ... ts) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), ts ...);
   return os.release_content();
}

#else //ifdef ABC_CXX_VARIADIC_TEMPLATES

inline dmstr str_base::format() const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this));
   return os.release_content();
}
template <typename T0>
inline dmstr str_base::format(T0 const & t0) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0);
   return os.release_content();
}

template <typename T0, typename T1>
inline dmstr str_base::format(T0 const & t0, T1 const & t1) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1);
   return os.release_content();
}
template <typename T0, typename T1, typename T2>
inline dmstr str_base::format(T0 const & t0, T1 const & t1, T2 const & t2) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2);
   return os.release_content();
}
template <typename T0, typename T1, typename T2, typename T3>
inline dmstr str_base::format(T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3);
   return os.release_content();
}
template <typename T0, typename T1, typename T2, typename T3, typename T4>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4);
   return os.release_content();
}
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
   typename T7
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6, T7 const & t7
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6, t7);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
   typename T7, typename T8
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6, T7 const & t7, T8 const & t8
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6, t7, t8);
   return os.release_content();
}
template <
   typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
   typename T7, typename T8, typename T9
>
inline dmstr str_base::format(
   T0 const & t0, T1 const & t1, T2 const & t2, T3 const & t3, T4 const & t4, T5 const & t5,
   T6 const & t6, T7 const & t7, T8 const & t8, T9 const & t9
) const {
   io::str_ostream os;
   os.print(*static_cast<istr const *>(this), t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
   return os.release_content();
}

#endif //ifdef ABC_CXX_VARIADIC_TEMPLATES … else

} //namespace abc

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

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <algorithm>

#include "etl/traits_lite.hpp"

namespace etl {

namespace impl {

namespace standard {

template<typename A, typename B, typename C>
void strassen_mm_mul_r(const A& a, const B& b, C& c){
    using type = typename A::value_type;

    auto n = dim<0>(a);

    //1x1 matrix mul
    if (n == 1) {
        c(0,0) = a(0,0) * b(0,0);
    } else if(n == 2){
        auto a11 = a(0,0);
        auto a12 = a(0,1);
        auto a21 = a(1,0);
        auto a22 = a(1,1);

        auto b11 = b(0,0);
        auto b12 = b(0,1);
        auto b21 = b(1,0);
        auto b22 = b(1,1);

        auto p1 = (a11 + a22) * (b11 + b22);
        auto p2 = (a12 - a22) * (b21 + b22);
        auto p3 = a11 * (b12 - b22);
        auto p4 = a22 * (b21 - b11);
        auto p5 = (a11 + a12) * b22;
        auto p6 = (a21 + a22) * b11;
        auto p7 = (a21 - a11) * (b11 + b12);

        c(0,0) = p1 + p4 + p2 - p5;
        c(0,1) = p3 + p5;
        c(1,0) = p6 + p4;
        c(1,1) = p1 + p3 + p7 - p6;
    } else if(n == 4){
        //This is entirely done on stack

        auto new_n = n / 2;

        etl::fast_matrix<type, 2, 2> a11;
        etl::fast_matrix<type, 2, 2> a12;
        etl::fast_matrix<type, 2, 2> a21;
        etl::fast_matrix<type, 2, 2> a22;

        etl::fast_matrix<type, 2, 2> b11;
        etl::fast_matrix<type, 2, 2> b12;
        etl::fast_matrix<type, 2, 2> b21;
        etl::fast_matrix<type, 2, 2> b22;

        etl::fast_matrix<type, 2, 2> p1;
        etl::fast_matrix<type, 2, 2> p2;
        etl::fast_matrix<type, 2, 2> p3;
        etl::fast_matrix<type, 2, 2> p4;
        etl::fast_matrix<type, 2, 2> p5;

        for (std::size_t i = 0; i < new_n; i++) {
            for (std::size_t j = 0; j < new_n; j++) {
                a11(i,j) = a(i,j);
                a12(i,j) = a(i,j + new_n);
                a21(i,j) = a(i + new_n,j);
                a22(i,j) = a(i + new_n,j + new_n);

                b11(i,j) = b(i,j);
                b12(i,j) = b(i,j + new_n);
                b21(i,j) = b(i + new_n,j);
                b22(i,j) = b(i + new_n,j + new_n);
            }
        }

        strassen_mm_mul_r(a11 + a22, b11 + b22, p1);
        strassen_mm_mul_r(a12 - a22, b21 + b22, p2);
        strassen_mm_mul_r(a22, b21 - b11, p4);
        strassen_mm_mul_r(a11 + a12, b22, p5);

        auto c11 = p1 + p4 + p2 - p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j) = c11(i,j);
            }
        }

        strassen_mm_mul_r(a11, b12 - b22, p3);

        auto c12 = p3 + p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j + new_n) = c12(i,j);
            }
        }

        strassen_mm_mul_r(a21 + a22, b11, p2);
        strassen_mm_mul_r(a21 - a11, b11 + b12, p5);

        auto c21 = p2 + p4;
        auto c22 = p1 + p3 + p5 - p2;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i + new_n,j) = c21(i,j);
                c(i + new_n,j + new_n) = c22(i,j);
            }
        }
    } else {
        auto new_n = n / 2;

        etl::dyn_matrix<type> a11(new_n, new_n);
        etl::dyn_matrix<type> a12(new_n, new_n);
        etl::dyn_matrix<type> a21(new_n, new_n);
        etl::dyn_matrix<type> a22(new_n, new_n);

        etl::dyn_matrix<type> b11(new_n, new_n);
        etl::dyn_matrix<type> b12(new_n, new_n);
        etl::dyn_matrix<type> b21(new_n, new_n);
        etl::dyn_matrix<type> b22(new_n, new_n);

        etl::dyn_matrix<type> p1(new_n, new_n);
        etl::dyn_matrix<type> p2(new_n, new_n);
        etl::dyn_matrix<type> p3(new_n, new_n);
        etl::dyn_matrix<type> p4(new_n, new_n);
        etl::dyn_matrix<type> p5(new_n, new_n);

        for (std::size_t i = 0; i < new_n; i++) {
            for (std::size_t j = 0; j < new_n; j++) {
                a11(i,j) = a(i,j);
                a12(i,j) = a(i,j + new_n);
                a21(i,j) = a(i + new_n,j);
                a22(i,j) = a(i + new_n,j + new_n);

                b11(i,j) = b(i,j);
                b12(i,j) = b(i,j + new_n);
                b21(i,j) = b(i + new_n,j);
                b22(i,j) = b(i + new_n,j + new_n);
            }
        }

        strassen_mm_mul_r(a11 + a22, b11 + b22, p1);
        strassen_mm_mul_r(a12 - a22, b21 + b22, p2);
        strassen_mm_mul_r(a22, b21 - b11, p4);
        strassen_mm_mul_r(a11 + a12, b22, p5);

        auto c11 = p1 + p4 + p2 - p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j) = c11(i,j);
            }
        }

        strassen_mm_mul_r(a11, b12 - b22, p3);

        auto c12 = p3 + p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j + new_n) = c12(i,j);
            }
        }

        strassen_mm_mul_r(a21 + a22, b11, p2);
        strassen_mm_mul_r(a21 - a11, b11 + b12, p5);

        auto c21 = p2 + p4;
        auto c22 = p1 + p3 + p5 - p2;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i + new_n,j) = c21(i,j);
                c(i + new_n,j + new_n) = c22(i,j);
            }
        }
    }
}

inline std::size_t nextPowerOfTwo(std::size_t n) {
    return std::pow(2, static_cast<std::size_t>(std::ceil(std::log2(n))));
}

template<typename A, typename B, typename C>
void strassen_mm_mul(const A& a, const B& b, C& c){
    c = 0;

    //For now, assume matrices are of size 2^nx2^n

    auto n = std::max(dim<0>(a), std::max(dim<1>(a), dim<1>(b)));
    auto m = nextPowerOfTwo(n);

    if(dim<0>(a) == m && dim<0>(b) == m && dim<1>(a) == m && dim<1>(b) == m){
        strassen_mm_mul_r(a, b, c);
    } else {
        using type = typename A::value_type;

        etl::dyn_matrix<type> a_prep(m, m, static_cast<type>(0));
        etl::dyn_matrix<type> b_prep(m, m, static_cast<type>(0));
        etl::dyn_matrix<type> c_prep(m, m, static_cast<type>(0));

        for(std::size_t i=0; i< dim<0>(a); i++) {
            for (std::size_t j=0; j<dim<1>(a); j++) {
                a_prep(i,j) = a(i,j);
            }
        }

        for(std::size_t i=0; i< dim<0>(b); i++) {
            for (std::size_t j=0; j<dim<1>(b); j++) {
                b_prep(i,j) = b(i,j);
            }
        }

        strassen_mm_mul_r(a_prep, b_prep, c_prep);

        for(std::size_t i=0; i< dim<0>(c); i++) {
            for (std::size_t j=0; j<dim<1>(c); j++) {
                c(i,j) = c_prep(i,j);
            }
        }
    }
}

} //end of namespace standard

} //end of namespace impl

} //end of namespace etl
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <algorithm>

#include "etl/traits_lite.hpp"

namespace etl {

namespace impl {

namespace standard {

template<typename A, typename B, typename C>
void strassen_mm_mul_r(const A& a, const B& b, C& c){
    using value_type = value_t<A>;

    std::size_t n = dim<0>(a);

    //1x1 matrix mul
    if (n == 1) {
        c(0,0) = a(0,0) * b(0,0);
    } else if(n == 2){
        value_type a11 = a(0,0);
        value_type a12 = a(0,1);
        value_type a21 = a(1,0);
        value_type a22 = a(1,1);

        value_type b11 = b(0,0);
        value_type b12 = b(0,1);
        value_type b21 = b(1,0);
        value_type b22 = b(1,1);

        value_type p1 = (a11 + a22) * (b11 + b22);
        value_type p2 = (a12 - a22) * (b21 + b22);
        value_type p3 = a11 * (b12 - b22);
        value_type p4 = a22 * (b21 - b11);
        value_type p5 = (a11 + a12) * b22;
        value_type p6 = (a21 + a22) * b11;
        value_type p7 = (a21 - a11) * (b11 + b12);

        c(0,0) = p1 + p4 + p2 - p5;
        c(0,1) = p3 + p5;
        c(1,0) = p6 + p4;
        c(1,1) = p1 + p3 + p7 - p6;
    } else if(n == 4){
        //This is entirely done on stack

        std::size_t new_n = n / 2;

        etl::fast_matrix<value_type, 2, 2> a11;
        etl::fast_matrix<value_type, 2, 2> a12;
        etl::fast_matrix<value_type, 2, 2> a21;
        etl::fast_matrix<value_type, 2, 2> a22;

        etl::fast_matrix<value_type, 2, 2> b11;
        etl::fast_matrix<value_type, 2, 2> b12;
        etl::fast_matrix<value_type, 2, 2> b21;
        etl::fast_matrix<value_type, 2, 2> b22;

        etl::fast_matrix<value_type, 2, 2> p1;
        etl::fast_matrix<value_type, 2, 2> p2;
        etl::fast_matrix<value_type, 2, 2> p3;
        etl::fast_matrix<value_type, 2, 2> p4;
        etl::fast_matrix<value_type, 2, 2> p5;

        for (std::size_t i = 0; i < new_n; i++) {
            for (std::size_t j = 0; j < new_n; j++) {
                a11(i,j) = a(i,j);
                a12(i,j) = a(i,j + new_n);
                a21(i,j) = a(i + new_n,j);
                a22(i,j) = a(i + new_n,j + new_n);

                b11(i,j) = b(i,j);
                b12(i,j) = b(i,j + new_n);
                b21(i,j) = b(i + new_n,j);
                b22(i,j) = b(i + new_n,j + new_n);
            }
        }

        strassen_mm_mul_r(a11 + a22, b11 + b22, p1);
        strassen_mm_mul_r(a12 - a22, b21 + b22, p2);
        strassen_mm_mul_r(a22, b21 - b11, p4);
        strassen_mm_mul_r(a11 + a12, b22, p5);

        auto c11 = p1 + p4 + p2 - p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j) = c11(i,j);
            }
        }

        strassen_mm_mul_r(a11, b12 - b22, p3);

        auto c12 = p3 + p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j + new_n) = c12(i,j);
            }
        }

        strassen_mm_mul_r(a21 + a22, b11, p2);
        strassen_mm_mul_r(a21 - a11, b11 + b12, p5);

        auto c21 = p2 + p4;
        auto c22 = p1 + p3 + p5 - p2;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i + new_n,j) = c21(i,j);
                c(i + new_n,j + new_n) = c22(i,j);
            }
        }
    } else {
        std::size_t new_n = n / 2;

        etl::dyn_matrix<value_type> a11(new_n, new_n);
        etl::dyn_matrix<value_type> a12(new_n, new_n);
        etl::dyn_matrix<value_type> a21(new_n, new_n);
        etl::dyn_matrix<value_type> a22(new_n, new_n);

        etl::dyn_matrix<value_type> b11(new_n, new_n);
        etl::dyn_matrix<value_type> b12(new_n, new_n);
        etl::dyn_matrix<value_type> b21(new_n, new_n);
        etl::dyn_matrix<value_type> b22(new_n, new_n);

        etl::dyn_matrix<value_type> p1(new_n, new_n);
        etl::dyn_matrix<value_type> p2(new_n, new_n);
        etl::dyn_matrix<value_type> p3(new_n, new_n);
        etl::dyn_matrix<value_type> p4(new_n, new_n);
        etl::dyn_matrix<value_type> p5(new_n, new_n);

        for (std::size_t i = 0; i < new_n; i++) {
            for (std::size_t j = 0; j < new_n; j++) {
                a11(i,j) = a(i,j);
                a12(i,j) = a(i,j + new_n);
                a21(i,j) = a(i + new_n,j);
                a22(i,j) = a(i + new_n,j + new_n);

                b11(i,j) = b(i,j);
                b12(i,j) = b(i,j + new_n);
                b21(i,j) = b(i + new_n,j);
                b22(i,j) = b(i + new_n,j + new_n);
            }
        }

        strassen_mm_mul_r(a11 + a22, b11 + b22, p1);
        strassen_mm_mul_r(a12 - a22, b21 + b22, p2);
        strassen_mm_mul_r(a22, b21 - b11, p4);
        strassen_mm_mul_r(a11 + a12, b22, p5);

        auto c11 = p1 + p4 + p2 - p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j) = c11(i,j);
            }
        }

        strassen_mm_mul_r(a11, b12 - b22, p3);

        auto c12 = p3 + p5;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i,j + new_n) = c12(i,j);
            }
        }

        strassen_mm_mul_r(a21 + a22, b11, p2);
        strassen_mm_mul_r(a21 - a11, b11 + b12, p5);

        auto c21 = p2 + p4;
        auto c22 = p1 + p3 + p5 - p2;

        for (std::size_t i = 0; i < new_n ; i++) {
            for (std::size_t j = 0 ; j < new_n ; j++) {
                c(i + new_n,j) = c21(i,j);
                c(i + new_n,j + new_n) = c22(i,j);
            }
        }
    }
}

inline std::size_t nextPowerOfTwo(std::size_t n) {
    return std::pow(2, static_cast<std::size_t>(std::ceil(std::log2(n))));
}

template<typename A, typename B, typename C>
void strassen_mm_mul(const A& a, const B& b, C& c){
    c = 0;

    //For now, assume matrices are of size 2^nx2^n

    std::size_t n = std::max(dim<0>(a), std::max(dim<1>(a), dim<1>(b)));
    std::size_t m = nextPowerOfTwo(n);

    if(dim<0>(a) == m && dim<0>(b) == m && dim<1>(a) == m && dim<1>(b) == m){
        strassen_mm_mul_r(a, b, c);
    } else {
        using value_type = typename A::value_type;

        etl::dyn_matrix<value_type> a_prep(m, m, value_type(0));
        etl::dyn_matrix<value_type> b_prep(m, m, value_type(0));
        etl::dyn_matrix<value_type> c_prep(m, m, value_type(0));

        for(std::size_t i=0; i< dim<0>(a); i++) {
            for (std::size_t j=0; j<dim<1>(a); j++) {
                a_prep(i,j) = a(i,j);
            }
        }

        for(std::size_t i=0; i< dim<0>(b); i++) {
            for (std::size_t j=0; j<dim<1>(b); j++) {
                b_prep(i,j) = b(i,j);
            }
        }

        strassen_mm_mul_r(a_prep, b_prep, c_prep);

        for(std::size_t i=0; i< dim<0>(c); i++) {
            for (std::size_t j=0; j<dim<1>(c); j++) {
                c(i,j) = c_prep(i,j);
            }
        }
    }
}

} //end of namespace standard

} //end of namespace impl

} //end of namespace etl
<|endoftext|>