<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2012 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de

#include "StandardLogSink.h"
#include "Logger.h"

#include <iostream>
#include <iomanip>

using namespace std;

namespace avg
{

StandardLogSink::StandardLogSink()
{

}

StandardLogSink::~StandardLogSink()
{

}

void StandardLogSink::logMessage(const tm* pTime, unsigned millis,
        const category_t& category, severity_t severity, const UTF8String& sMsg)
{
    char timeString[256];
    strftime(timeString, sizeof(timeString), "%y-%m-%d %H:%M:%S", pTime);
    cerr << "[" << timeString << "." <<
        setw(3) << setfill('0') << millis << setw(0) << "][";
    cerr << setw(8) << setfill('.') << Logger::severityToString(severity) << "][";
    cerr << setw(13) << setfill('.') << category << "] : " << sMsg << endl;
    cerr.flush();
}

}
<commit_msg>Shorter log messages.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2012 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de

#include "StandardLogSink.h"
#include "Logger.h"

#include <iostream>
#include <iomanip>

using namespace std;

namespace avg
{

StandardLogSink::StandardLogSink()
{

}

StandardLogSink::~StandardLogSink()
{

}

void StandardLogSink::logMessage(const tm* pTime, unsigned millis,
        const category_t& category, severity_t severity, const UTF8String& sMsg)
{
    char timeString[256];
    strftime(timeString, sizeof(timeString), "%y-%m-%d %H:%M:%S", pTime);
    cerr << "[" << timeString << "." <<
        setw(3) << setfill('0') << millis << setw(0) << "][";
    cerr << setw(4) << setfill('.') << Logger::severityToString(severity) << "][";
    cerr << setw(9) << setfill('.') << category << "] : " << sMsg << endl;
    cerr.flush();
}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <unordered_set>
#include <sstream>
#include <fstream>

#include <getopt.h>

#include "simhash.h"

void usage(int argc, char** argv)
{
    std::cout << "usage: " << argv[0]
              << " --blocks BLOCKS"
              << " --distance DISTANCE"
              << " --input INPUT"
              << " --output OUTPUT\n\n"
              << "Read simhashes from input, find all pairs within distance bits of \n"
              << "each other, writing them to output. The endianness of the output is \n"
              << "the same as that of the input.\n\n"
              << "  --blocks BLOCKS        Number of bit blocks to use\n"
              << "  --distance DISTANCE    Maximum bit distances of matches\n"
              << "  --input INPUT          Path to input ('-' for stdin)\n"
              << "  --output OUTPUT        Path to output ('-' for stdout)\n";
}

std::unordered_set<Simhash::hash_t> read_hashes(std::istream& stream)
{
    std::unordered_set<Simhash::hash_t> hashes;
    Simhash::hash_t hash(0);
    while (!stream.eof())
    {
        stream.read(reinterpret_cast<char*>(&hash), sizeof(hash));
        if (!stream.fail())
        {
            hashes.insert(hash);
        }
        else
        {
            break;
        }
    }
    return hashes;
}

void write_matches(std::ostream& stream, const Simhash::matches_t& matches)
{
    for (auto it = matches.begin(); it != matches.end() && !std::cout.fail(); ++it)
    {
        stream.write(
            reinterpret_cast<const char*>(&(it->first)), sizeof(Simhash::hash_t));
        stream.write(
            reinterpret_cast<const char*>(&(it->second)), sizeof(Simhash::hash_t));
    }
    stream.flush();
}

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

    std::string input, output;
    size_t blocks(0), distance(0);

    int getopt_return_value(0);
    while (getopt_return_value != -1)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"input",    required_argument, 0, 0 },
            {"output",   required_argument, 0, 0 },
            {"blocks",   required_argument, 0, 0 },
            {"distance", required_argument, 0, 0 },
            {"help",     no_argument,       0, 0 },
            {0,          0,                 0, 0 }
        };

        getopt_return_value = getopt_long(
            argc, argv, "i:o:b:d:h", long_options, &option_index);

        switch(getopt_return_value)
        {
            case 0:
                switch(option_index)
                {
                    case 0:
                        input = optarg;
                        break;
                    case 1:
                        output = optarg;
                        break;
                    case 2:
                        std::stringstream(std::string(optarg)) >> blocks;
                        break;
                    case 3:
                        std::stringstream(std::string(optarg)) >> distance;
                        break;
                    case 4:
                        usage(argc, argv);
                        return 0;
                }
                break;
            case 'i':
                input = optarg;
                break;
            case 'o':
                output = optarg;
                break;
            case 'b':
                std::stringstream(std::string(optarg)) >> blocks;
                break;
            case 'd':
                std::stringstream(std::string(optarg)) >> distance;
                break;
            case 'h':
                usage(argc, argv);
                return 0;
            case '?':
                return 1;
        }

    }

    if (blocks == 0)
    {
        std::cerr << "Blocks must be provided and > 0" << std::endl;
        return 2;
    }

    if (distance == 0)
    {
        std::cerr << "Distance must be provided and > 0" << std::endl;
        return 3;
    }

    if (input.empty())
    {
        std::cerr << "Input must be provided and non-empty." << std::endl;
        return 4;
    }

    if (output.empty())
    {
        std::cerr << "Output must be provided and non-empty." << std::endl;
        return 5;
    }

    if (blocks <= distance)
    {
        std::cerr << "Blocks (" << blocks << ") must be >= distance (" << distance << ")"
                  << std::endl;
        return 6;
    }

    // Read input
    std::unordered_set<Simhash::hash_t> hashes;
    if (input.compare("-") == 0)
    {
        std::cerr << "Reading hashes from stdin." << std::endl;
        hashes = read_hashes(std::cin);
    }
    else
    {
        std::cerr << "Reading hashes from " << input << std::endl;
        {
            std::ifstream fin(input, std::ifstream::in | std::ifstream::binary);
            if (!fin.good())
            {
                std::cerr << "Error reading " << input << std::endl;
                return 7;
            }
            hashes = read_hashes(fin);
        }
    }

    // Find matches
    std::cerr << "Computing matches..." << std::endl;
    Simhash::matches_t results = Simhash::find_all(hashes, blocks, distance);

    // Write output
    if (output.compare("-") == 0)
    {
        std::cerr << "Writing results to stdout." << std::endl;
        write_matches(std::cout, results);
    }
    else
    {
        std::cerr << "Writing matches to " << output << std::endl;
        {
            std::ofstream fout(output, std::ofstream::binary);
            if (!fout.good())
            {
                std::cerr << "Error writing " << output << std::endl;
                return 8;
            }
            write_matches(fout, results);
        }
    }

    return 0;
}
<commit_msg>Changed interface to simhash-find-all to be JSON in and out.<commit_after>#include <iostream>
#include <unordered_set>
#include <sstream>
#include <fstream>

#include <getopt.h>

#include "simhash.h"

void usage(int argc, char** argv)
{
    std::cout << "usage: " << argv[0]
              << " --blocks BLOCKS"
              << " --distance DISTANCE"
              << " --input INPUT"
              << " --output OUTPUT\n\n"
              << "Read simhashes from input, find all pairs within distance bits of \n"
              << "each other, writing them to output. The endianness of the output is \n"
              << "the same as that of the input.\n\n"
              << "  --blocks BLOCKS        Number of bit blocks to use\n"
              << "  --distance DISTANCE    Maximum bit distances of matches\n"
              << "  --input INPUT          Path to input ('-' for stdin)\n"
              << "  --output OUTPUT        Path to output ('-' for stdout)\n";
}

std::unordered_set<Simhash::hash_t> read_hashes(std::istream& stream)
{
    std::unordered_set<Simhash::hash_t> hashes;
    for (std::string line; std::getline(stream, line); )
    {
        hashes.insert(std::stoull(line));
    }
    return hashes;
}

void write_matches(std::ostream& stream, const Simhash::matches_t& matches)
{
    for (auto it = matches.begin(); it != matches.end() && !std::cout.fail(); ++it)
    {
        stream << "[" << it->first << ", " << it->second << "]\n";
    }
    stream.flush();
}

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

    std::string input, output;
    size_t blocks(0), distance(0);

    int getopt_return_value(0);
    while (getopt_return_value != -1)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"input",    required_argument, 0, 0 },
            {"output",   required_argument, 0, 0 },
            {"blocks",   required_argument, 0, 0 },
            {"distance", required_argument, 0, 0 },
            {"help",     no_argument,       0, 0 },
            {0,          0,                 0, 0 }
        };

        getopt_return_value = getopt_long(
            argc, argv, "i:o:b:d:h", long_options, &option_index);

        switch(getopt_return_value)
        {
            case 0:
                switch(option_index)
                {
                    case 0:
                        input = optarg;
                        break;
                    case 1:
                        output = optarg;
                        break;
                    case 2:
                        std::stringstream(std::string(optarg)) >> blocks;
                        break;
                    case 3:
                        std::stringstream(std::string(optarg)) >> distance;
                        break;
                    case 4:
                        usage(argc, argv);
                        return 0;
                }
                break;
            case 'i':
                input = optarg;
                break;
            case 'o':
                output = optarg;
                break;
            case 'b':
                std::stringstream(std::string(optarg)) >> blocks;
                break;
            case 'd':
                std::stringstream(std::string(optarg)) >> distance;
                break;
            case 'h':
                usage(argc, argv);
                return 0;
            case '?':
                return 1;
        }

    }

    if (blocks == 0)
    {
        std::cerr << "Blocks must be provided and > 0" << std::endl;
        return 2;
    }

    if (distance == 0)
    {
        std::cerr << "Distance must be provided and > 0" << std::endl;
        return 3;
    }

    if (input.empty())
    {
        std::cerr << "Input must be provided and non-empty." << std::endl;
        return 4;
    }

    if (output.empty())
    {
        std::cerr << "Output must be provided and non-empty." << std::endl;
        return 5;
    }

    if (blocks <= distance)
    {
        std::cerr << "Blocks (" << blocks << ") must be >= distance (" << distance << ")"
                  << std::endl;
        return 6;
    }

    // Read input
    std::unordered_set<Simhash::hash_t> hashes;
    if (input.compare("-") == 0)
    {
        std::cerr << "Reading hashes from stdin." << std::endl;
        hashes = read_hashes(std::cin);
    }
    else
    {
        std::cerr << "Reading hashes from " << input << std::endl;
        {
            std::ifstream fin(input, std::ifstream::in | std::ifstream::binary);
            if (!fin.good())
            {
                std::cerr << "Error reading " << input << std::endl;
                return 7;
            }
            hashes = read_hashes(fin);
        }
    }

    // Find matches
    std::cerr << "Computing matches..." << std::endl;
    Simhash::matches_t results = Simhash::find_all(hashes, blocks, distance);

    // Write output
    if (output.compare("-") == 0)
    {
        std::cerr << "Writing results to stdout." << std::endl;
        write_matches(std::cout, results);
    }
    else
    {
        std::cerr << "Writing matches to " << output << std::endl;
        {
            std::ofstream fout(output, std::ofstream::binary);
            if (!fout.good())
            {
                std::cerr << "Error writing " << output << std::endl;
                return 8;
            }
            write_matches(fout, results);
        }
    }

    return 0;
}
<|endoftext|>


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

#include "libmv/tracking/sad.h"
#include <stdlib.h>
#include <math.h>

namespace libmv {

void LaplaceFilter(ubyte* src, ubyte* dst, int width, int height, int strength) {
  for(int y=1; y<height-1; y++) for(int x=1; x<width-1; x++) {
    const ubyte* s = &src[y*width+x];
    int l = 128 +
        s[-width-1] + s[-width] + s[-width+1] +
        s[1]        - 8*s[0]    + s[1]        +
        s[ width-1] + s[ width] + s[ width+1] ;
    int d = ((256-strength)*s[0] + strength*l) / 256;
    if(d < 0) d=0;
    if(d > 255) d=255;
    dst[y*width+x] = d;
  }
}

struct vec2 {
  float x,y;
  inline vec2(float x, float y):x(x),y(y){}
};
inline vec2 operator*(mat32 m, vec2 v) {
  return vec2(v.x*m(0,0)+v.y*m(0,1)+m(0,2),v.x*m(1,0)+v.y*m(1,1)+m(1,2));
}

//! fixed point bilinear sample with precision k
template <int k> inline int sample(const ubyte* image,int stride, int x, int y, int u, int v) {
  const ubyte* s = &image[y*stride+x];
  return ((s[     0] * (k-u) + s[       1] * u) * (k-v)
        + (s[stride] * (k-u) + s[stride+1] * u) * (  v) ) / (k*k);
}

#ifdef __SSE__
#include <xmmintrin.h>
int lround(float x) { return _mm_cvtss_si32(_mm_set_ss(x)); }
#elif defined(_MSC_VER)
int lround(float x) { return x+0.5; }
#endif

//TODO(MatthiasF): SSE optimization
void SamplePattern(ubyte* image, int stride, mat32 warp, ubyte* pattern, int size) {
  const int k = 256;
  for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) {
    vec2 p = warp*vec2(j-size/2,i-size/2);
    int fx = lround(p.x*k), fy = lround(p.y*k);
    int ix = fx/k, iy = fy/k;
    int u = fx%k, v = fy%k;
    pattern[i*size+j] = sample<k>(image,stride,ix,iy,u,v);
  }
}

#ifdef __SSE2__
#include <emmintrin.h>
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  __m128i a = _mm_setzero_si128();
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size/16; j++) {
      a = _mm_adds_epu16(a, _mm_sad_epu8( _mm_loadu_si128((__m128i*)(pattern+i*size+j*16)),
                                          _mm_loadu_si128((__m128i*)(image+i*stride+j*16))));
    }
  }
  return _mm_extract_epi16(a,0) + _mm_extract_epi16(a,4);
}
#else
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  uint sad=0;
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      sad += abs((int)pattern[i*size+j] - image[i*stride+j]);
    }
  }
  return sad;
}
#endif

float sq(float x) { return x*x; }
float Track(ubyte* reference, ubyte* warped, int size, ubyte* image, int stride, int w, int h, mat32* warp, float areaPenalty, float conditionPenalty) {
  mat32 m=*warp;
  uint min=-1;

  // exhaustive search integer pixel translation
  int ix = m(0,2), iy = m(1,2);
  for(int y = size/2; y < h-size/2; y++) {
    for(int x = size/2; x < w-size/2; x++) {
      m(0,2) = x, m(1,2) = y;
      uint sad = SAD(warped,&image[(y-size/2)*stride+(x-size/2)],stride,size);
      // TODO: using chroma could help disambiguate some cases
      if(sad < min) {
        min = sad;
        ix = x, iy = y;
      }
    }
  }
  m(0,2) = ix, m(1,2) = iy;
  min=-1; //reset score since direct warped search match too well (but the wrong pattern).

  // 6D coordinate descent to find affine transform
  ubyte match = new ubyte[size*size];
  float step = 0.5;
  for(int p = 0; p < 8; p++) { //foreach precision level
    for(int i = 0; i < 2; i++) { // iterate twice per precision level
      //TODO: other sweep pattern might converge better
      for(int d=0; d < 6; d++) { // iterate dimension sequentially (cyclic descent)
        for(float x = -step; x <= step; x+=step) { //solve subproblem (evaluate only along one coordinate)
          mat32 t = m;
          t.data[d] += x;
          //TODO: better performance would also allow a more exhaustive search
          SamplePattern(image,stride,t,match,size);
          uint sad = SAD(reference,match,size,size);
          // regularization: keep constant area and good condition
          float area = t(0,0)*t(1,1)-t(0,1)*t(1,0);
          float x = sq(t(0,0))+sq(t(0,1)), y = sq(t(1,0))+sq(t(1,1));
          float condition = x>y ? x/y : y/x;
          sad += size*size*( areaPenalty*sq(area-1) + conditionPenalty*sq(condition-1) );
          if(sad < min) {
            min = sad;
            m = t;
          }
        }
      }
    }
    step /= 2;
  }
  *warp = m;

  // Compute Pearson product-moment correlation coefficient
  uint sX=0,sY=0,sXX=0,sYY=0,sXY=0;
  SamplePattern(image,stride,m,match,size);
  SAD(reference,match,size,size);
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      int x = reference[i*size+j];
      int y = match[i*size+j];
      sX += x;
      sY += y;
      sXX += x*x;
      sYY += y*y;
      sXY += x*y;
    }
  }
  delete[] match;
  const int N = size*size;
  sX /= N, sY /= N, sXX /= N, sYY /= N, sXY /= N;
  return (sXY-sX*sY)/sqrt(float((sXX-sX*sX)*(sYY-sY*sY)));
}

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

#include "libmv/tracking/sad.h"
#include <stdlib.h>
#include <math.h>

namespace libmv {

void LaplaceFilter(ubyte* src, ubyte* dst, int width, int height, int strength) {
  for(int y=1; y<height-1; y++) for(int x=1; x<width-1; x++) {
    const ubyte* s = &src[y*width+x];
    int l = 128 +
        s[-width-1] + s[-width] + s[-width+1] +
        s[1]        - 8*s[0]    + s[1]        +
        s[ width-1] + s[ width] + s[ width+1] ;
    int d = ((256-strength)*s[0] + strength*l) / 256;
    if(d < 0) d=0;
    if(d > 255) d=255;
    dst[y*width+x] = d;
  }
}

struct vec2 {
  float x,y;
  inline vec2(float x, float y):x(x),y(y){}
};
inline vec2 operator*(mat32 m, vec2 v) {
  return vec2(v.x*m(0,0)+v.y*m(0,1)+m(0,2),v.x*m(1,0)+v.y*m(1,1)+m(1,2));
}

//! fixed point bilinear sample with precision k
template <int k> inline int sample(const ubyte* image,int stride, int x, int y, int u, int v) {
  const ubyte* s = &image[y*stride+x];
  return ((s[     0] * (k-u) + s[       1] * u) * (k-v)
        + (s[stride] * (k-u) + s[stride+1] * u) * (  v) ) / (k*k);
}

#ifdef __SSE__
#include <xmmintrin.h>
int lround(float x) { return _mm_cvtss_si32(_mm_set_ss(x)); }
#elif defined(_MSC_VER)
int lround(float x) { return x+0.5; }
#endif

//TODO(MatthiasF): SSE optimization
void SamplePattern(ubyte* image, int stride, mat32 warp, ubyte* pattern, int size) {
  const int k = 256;
  for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) {
    vec2 p = warp*vec2(j-size/2,i-size/2);
    int fx = lround(p.x*k), fy = lround(p.y*k);
    int ix = fx/k, iy = fy/k;
    int u = fx%k, v = fy%k;
    pattern[i*size+j] = sample<k>(image,stride,ix,iy,u,v);
  }
}

#ifdef __SSE2__
#include <emmintrin.h>
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  __m128i a = _mm_setzero_si128();
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size/16; j++) {
      a = _mm_adds_epu16(a, _mm_sad_epu8( _mm_loadu_si128((__m128i*)(pattern+i*size+j*16)),
                                          _mm_loadu_si128((__m128i*)(image+i*stride+j*16))));
    }
  }
  return _mm_extract_epi16(a,0) + _mm_extract_epi16(a,4);
}
#else
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  uint sad=0;
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      sad += abs((int)pattern[i*size+j] - image[i*stride+j]);
    }
  }
  return sad;
}
#endif

float sq(float x) { return x*x; }
float Track(ubyte* reference, ubyte* warped, int size, ubyte* image, int stride, int w, int h, mat32* warp, float areaPenalty, float conditionPenalty) {
  mat32 m=*warp;
  uint min=-1;

  // exhaustive search integer pixel translation
  int ix = m(0,2), iy = m(1,2);
  for(int y = size/2; y < h-size/2; y++) {
    for(int x = size/2; x < w-size/2; x++) {
      m(0,2) = x, m(1,2) = y;
      uint sad = SAD(warped,&image[(y-size/2)*stride+(x-size/2)],stride,size);
      // TODO: using chroma could help disambiguate some cases
      if(sad < min) {
        min = sad;
        ix = x, iy = y;
      }
    }
  }
  m(0,2) = ix, m(1,2) = iy;
  min=-1; //reset score since direct warped search match too well (but the wrong pattern).

  // 6D coordinate descent to find affine transform
  ubyte match = new ubyte[size*size];
  float step = 0.5;
  for(int p = 0; p < 8; p++) { //foreach precision level
    for(int i = 0; i < 2; i++) { // iterate twice per precision level
      //TODO: other sweep pattern might converge better
      for(int d=0; d < 6; d++) { // iterate dimension sequentially (cyclic descent)
        for(float x = -step; x <= step; x+=step) { //solve subproblem (evaluate only along one coordinate)
          mat32 t = m;
          t.data[d] += x;
          //TODO: better performance would also allow a more exhaustive search
          SamplePattern(image,stride,t,match,size);
          uint sad = SAD(reference,match,size,size);
          // regularization: keep constant area and good condition
          float area = t(0,0)*t(1,1)-t(0,1)*t(1,0);
          float x = sq(t(0,0))+sq(t(0,1)), y = sq(t(1,0))+sq(t(1,1));
          float condition = x>y ? x/y : y/x;
          sad += size*size*( areaPenalty*sq(area-1) + conditionPenalty*sq(condition-1) );
          if(sad < min) {
            min = sad;
            m = t;
          }
        }
      }
    }
    step /= 2;
  }
  *warp = m;

  // Compute Pearson product-moment correlation coefficient
  uint sX=0,sY=0,sXX=0,sYY=0,sXY=0;
  SamplePattern(image,stride,m,match,size);
  SAD(reference,match,size,size);
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      int x = reference[i*size+j];
      int y = match[i*size+j];
      sX += x;
      sY += y;
      sXX += x*x;
      sYY += y*y;
      sXY += x*y;
    }
  }
  delete[] match;
  const int N = size*size;
  sX /= N, sY /= N, sXX /= N, sYY /= N, sXY /= N;
  return (sXY-sX*sY)/sqrt(double((sXX-sX*sX)*(sYY-sY*sY)));
}

}  // namespace libmv
<|endoftext|>


<commit_before>#pragma once

#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>

#include "core/module/ThreadPool.hpp"
#include "core/utils/log.h"

class ThreadPool {
private:
    class ThreadWorker {
    private:
        unsigned int m_id;
        ThreadPool* m_pool;

    public:
        ThreadWorker(ThreadPool* pool, const unsigned int id, allpix::LogLevel log_level) : m_id(id), m_pool(pool) {
            // Set logging level
            allpix::Log::setReportingLevel(log_level);
        }
        void operator()() {
            std::function<void()> func;
            bool dequeued;
            while(!m_pool->m_shutdown) {
                {
                    std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);
                    if(m_pool->m_queue.empty()) {
                        m_pool->m_conditional_lock.wait(lock);
                    }
                    dequeued = m_pool->m_queue.pop(func);
                }
                if(dequeued) {
                    func();
                }
            }
        }
    };

    bool m_shutdown;
    allpix::ThreadPool::SafeQueue<std::function<void()>> m_queue;
    std::vector<std::thread> m_threads;
    std::mutex m_conditional_mutex;
    std::condition_variable m_conditional_lock;

public:
    ThreadPool(const unsigned int n_threads, allpix::LogLevel log_level)
        : m_shutdown(false), m_threads(std::vector<std::thread>(n_threads)) {
        for(unsigned int i = 0; i < m_threads.size(); ++i) {
            m_threads[i] = std::thread(ThreadWorker(this, i, log_level));
        }
    }

    ThreadPool(const ThreadPool&) = delete;
    ThreadPool(ThreadPool&&) = delete;

    ThreadPool& operator=(const ThreadPool&) = delete;
    ThreadPool& operator=(ThreadPool&&) = delete;

    // Waits until threads finish their current task and shutdowns the pool
    void shutdown() {
        m_shutdown = true;
        m_conditional_lock.notify_all();
        m_queue.invalidate();

        for(auto& thrd : m_threads) {
            if(thrd.joinable()) {
                thrd.join();
            }
        }
    }

    // Submit a function to be executed asynchronously by the pool
    template <typename F, typename... Args> auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
        // Create a function with bounded parameters ready to execute
        std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        // Encapsulate it into a shared ptr in order to be able to copy construct / assign
        auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);

        // Wrap packaged task into void function
        std::function<void()> wrapper_func = [task_ptr]() { (*task_ptr)(); };

        // Enqueue generic wrapper function
        m_queue.push(wrapper_func);

        // Wake up one thread if its waiting
        m_conditional_lock.notify_one();

        // Return future from promise
        return task_ptr->get_future();
    }
};
<commit_msg>fix unused variable in thread pool<commit_after>#ifndef DFISE_THREADPOOL_H
#define DFISE_THREADPOOL_H

// NOTE: class is added here temporarily as the allpix ThreadPool cannot be used and threading will be redesigned

#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <vector>

#include "core/module/ThreadPool.hpp"
#include "core/utils/log.h"

class ThreadPool {
private:
    class ThreadWorker {
    private:
        ThreadPool* m_pool;

    public:
        ThreadWorker(ThreadPool* pool, allpix::LogLevel log_level) : m_pool(pool) {
            // Set logging level
            allpix::Log::setReportingLevel(log_level);
        }
        void operator()() {
            std::function<void()> func;
            bool dequeued;
            while(!m_pool->m_shutdown) {
                {
                    std::unique_lock<std::mutex> lock(m_pool->m_conditional_mutex);
                    if(m_pool->m_queue.empty()) {
                        m_pool->m_conditional_lock.wait(lock);
                    }
                    dequeued = m_pool->m_queue.pop(func);
                }
                if(dequeued) {
                    func();
                }
            }
        }
    };

    bool m_shutdown;
    allpix::ThreadPool::SafeQueue<std::function<void()>> m_queue;
    std::vector<std::thread> m_threads;
    std::mutex m_conditional_mutex;
    std::condition_variable m_conditional_lock;

public:
    ThreadPool(const unsigned int n_threads, allpix::LogLevel log_level)
        : m_shutdown(false), m_threads(std::vector<std::thread>(n_threads)) {
        for(unsigned int i = 0; i < m_threads.size(); ++i) {
            m_threads[i] = std::thread(ThreadWorker(this, log_level));
        }
    }

    ThreadPool(const ThreadPool&) = delete;
    ThreadPool(ThreadPool&&) = delete;

    ThreadPool& operator=(const ThreadPool&) = delete;
    ThreadPool& operator=(ThreadPool&&) = delete;

    // Waits until threads finish their current task and shutdowns the pool
    void shutdown() {
        m_shutdown = true;
        m_conditional_lock.notify_all();
        m_queue.invalidate();

        for(auto& thrd : m_threads) {
            if(thrd.joinable()) {
                thrd.join();
            }
        }
    }

    // Submit a function to be executed asynchronously by the pool
    template <typename F, typename... Args> auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
        // Create a function with bounded parameters ready to execute
        std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        // Encapsulate it into a shared ptr in order to be able to copy construct / assign
        auto task_ptr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);

        // Wrap packaged task into void function
        std::function<void()> wrapper_func = [task_ptr]() { (*task_ptr)(); };

        // Enqueue generic wrapper function
        m_queue.push(wrapper_func);

        // Wake up one thread if its waiting
        m_conditional_lock.notify_one();

        // Return future from promise
        return task_ptr->get_future();
    }
};

#endif
<|endoftext|>


<commit_before>/*
 *            Copyright 2009-2017 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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.
 *
 */

// Overload of uBLAS prod function with MKL/GSL implementations
#include <votca/tools/linalg.h>
#include <votca/xtp/aomatrix.h>
#include <votca/xtp/dftcoupling.h>

#include <boost/numeric/ublas/operation.hpp>
#include <boost/numeric/ublas/banded.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <votca/tools/constants.h>
#include <boost/format.hpp>
#include <boost/progress.hpp>

namespace votca {
    namespace xtp {

        namespace ub = boost::numeric::ublas;

        using boost::format;

        double DFTcoupling::getCouplingElement(int levelA, int levelB, Orbitals* _orbitalsA,
                Orbitals* _orbitalsB, ub::matrix<double>* _JAB, double _energy_difference) {

            int _levelsA = _orbitalsA->getNumberOfLevels();

            if (_energy_difference != 0) {
                std::vector<int> list_levelsA = *_orbitalsA->getDegeneracy(levelA, _energy_difference);
                std::vector<int> list_levelsB = *_orbitalsA->getDegeneracy(levelB, _energy_difference);

                double _JAB_sq = 0;
                double _JAB_one_level;

                for (std::vector<int>::iterator iA = list_levelsA.begin()++; iA != list_levelsA.end(); iA++) {
                    for (std::vector<int>::iterator iB = list_levelsB.begin()++; iB != list_levelsB.end(); iB++) {
                        //cout << *iA << ':' << *iB << endl;
                        _JAB_one_level = _JAB->at_element(*iA - 1, *iB - 1 + _levelsA);
                        _JAB_sq += _JAB_one_level*_JAB_one_level;
                    }
                }

                return sqrt(_JAB_sq / (list_levelsA.size() * list_levelsB.size())) * tools::conv::hrt2ev;

            } else {

                return _JAB->at_element(levelA - 1, levelB - 1 + _levelsA) * tools::conv::hrt2ev;

            }
            // the  matrix should be symmetric, could also return this element
            // _JAB.at_element( _levelsA + levelB - 1  , levelA - 1 );
        }

        /**
         * \brief evaluates electronic couplings
         *
         * This is a fast version with a rather large block matrix AxB
         *
         * @param _orbitalsA molecular orbitals of molecule A
         * @param _orbitalsB molecular orbitals of molecule B
         * @param _orbitalsAB molecular orbitals of the dimer AB
         * @param _JAB matrix with electronic couplings
         * @return false if failed
         */
        bool DFTcoupling::CalculateIntegrals(Orbitals* _orbitalsA, Orbitals* _orbitalsB,
                Orbitals* _orbitalsAB, ub::matrix<double>* _JAB) {

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Calculating electronic couplings" << flush;

            const std::vector<QMAtom*> atomsA = _orbitalsA->QMAtoms();
            const std::vector<QMAtom*> atomsB = _orbitalsB->QMAtoms();
            const std::vector<QMAtom*> atomsAll = _orbitalsAB->QMAtoms();

            for (unsigned i = 0; i < atomsAll.size(); i++) {
                QMAtom* dimer = atomsAll[i];
                QMAtom* monomer = NULL;

                if (i < atomsA.size()) {
                    monomer = atomsA[i];
                    if(!monomer->getPos().isClose(dimer->getPos(), 0.001) ) {
                        CTP_LOG(ctp::logERROR, *_pLog) << "======WARNING=======\n Coordinates of monomers and dimer atoms do not agree, do you know what you are doing?\n " << flush;
                        continue;
                    }
                } else if (i < atomsB.size() + atomsA.size()) {
                    monomer = atomsB[i - atomsA.size()];
                    if(monomer->getPos().isClose(dimer->getPos(), 0.001)){
                        CTP_LOG(ctp::logERROR, *_pLog) << "======WARNING=======\n Coordinates of monomers and dimer atoms do not agree, do you know what you are doing?\n " << flush;
                        continue;
                    }
                } else {
                    // Linker
                    CTP_LOG(ctp::logERROR, *_pLog) << (format("Neither Monomer A nor Monomer B contains atom %s on line %u. Hence, this atom is part of a linker. \n") %dimer->getType() %(i+1) ).str()<<flush;
                    continue;
                }

                if (monomer->getType() != dimer->getType()) {
                    throw runtime_error("\nERROR: Atom types do not agree in dimer and monomers\n");
                }
                if (tools::abs(monomer->getPos() - dimer->getPos()) > 0.001) {
                    CTP_LOG(ctp::logERROR, *_pLog) << "======WARNING=======\n Coordinates of monomers and dimer atoms do not agree, do you know what you are doing?\n " << flush;
                    break;
                }
            }

            // constructing the direct product orbA x orbB
            int _basisA = _orbitalsA->getBasisSetSize();
            int _basisB = _orbitalsB->getBasisSetSize();

            if ((_basisA == 0) || (_basisB == 0)) {
                CTP_LOG(ctp::logERROR, *_pLog) << "Basis set size is not stored in monomers" << flush;
                return false;
            }

            int _levelsA = _orbitalsA->getNumberOfLevels();
            int _levelsB = _orbitalsB->getNumberOfLevels();

            //boost::timer t; // start timing
            //double _st = t.elapsed();

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Levels:Basis A[" << _levelsA << ":" << _basisA << "]"
                    << " B[" << _levelsB << ":" << _basisB << "]" << flush;

            if ((_levelsA == 0) || (_levelsB == 0)) {
                CTP_LOG(ctp::logERROR, *_pLog) << "No information about number of occupied/unoccupied levels is stored" << flush;
                return false;
            }

            //       | Orbitals_A          0 |      | Overlap_A |
            //       | 0          Orbitals_B |  X   | Overlap_B |  X  Transpose( Orbitals_AB )
            //ub::zero_matrix<double> zeroB(_levelsA, _basisB);
            //ub::zero_matrix<double> zeroA(_levelsB, _basisA);

            // CHANGE _basisA + _basisB to "_basisAB" of the dimer + extra
            ub::matrix<double>_psi_AxB= ub::zero_matrix<double>(_levelsA + _levelsB ,_orbitalsAB->getBasisSetSize());
            // ADD another zero matrix for "padding", OR initialize _psi_AxB as zero_matrix directly!

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Constructing direct product AxB ["
                    << _psi_AxB.size1() << "x"
                    << _psi_AxB.size2() << "]" << flush;

            // nothing needs to be done here, if _psi_AxB is initialized as zero_matrix
            //ub::project(_psi_AxB, ub::range(0, _levelsA), ub::range(_basisA, _basisA + _basisB)) = zeroB;
            //ub::project(_psi_AxB, ub::range(_levelsA, _levelsA + _levelsB), ub::range(0, _basisA)) = zeroA;
            ub::project(_psi_AxB, ub::range(0, _levelsA), ub::range(0, _basisA)) = _orbitalsA->MOCoefficients();
            ub::project(_psi_AxB, ub::range(_levelsA, _levelsA + _levelsB), ub::range(_basisA, _basisA + _basisB)) = _orbitalsB->MOCoefficients();

            // psi_AxB * S_AB * psi_AB

            // NO CHANGE NEEDED
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Projecting dimer onto monomer orbitals" << flush;
            ub::matrix<double> overlap;
            if (_orbitalsAB->hasAOOverlap()) {
                CTP_LOG(ctp::logDEBUG, *_pLog) << "Reading overlap matrix from orbitals" << flush;
                overlap = _orbitalsAB->AOOverlap();
            } else {
                CTP_LOG(ctp::logDEBUG, *_pLog) << "Calculating overlap matrix for basisset: " << _orbitalsAB->getDFTbasis() << flush;
                BasisSet _dftbasisset;
                AOBasis _dftbasis;
                _dftbasisset.LoadBasisSet(_orbitalsAB->getDFTbasis());

                _dftbasis.AOBasisFill(&_dftbasisset, _orbitalsAB->QMAtoms());
                AOOverlap _dftAOoverlap;
                _dftAOoverlap.Fill(_dftbasis);
                overlap = _dftAOoverlap.Matrix();
            }

            ub::matrix<double> _psi_AB = ub::prod(overlap, ub::trans(_orbitalsAB->MOCoefficients()));
            ub::matrix<double> _psi_AxB_dimer_basis = ub::prod(_psi_AxB, _psi_AB);
            _psi_AB.clear();

            //check to see if projection quality is sufficient
            for (unsigned i = 0; i < _psi_AxB_dimer_basis.size1(); i++) {
                double mag = 0.0;
                for (unsigned j = 0; j < _psi_AxB_dimer_basis.size2(); j++) {
                    mag += _psi_AxB_dimer_basis(i, j) * _psi_AxB_dimer_basis(i, j);

                }
                if (mag < 0.95) {
                    throw runtime_error("\nERROR: Projection of monomer orbitals on dimer is insufficient, maybe the orbital order is screwed up, otherwise increase dimer basis.\n");
                }
            }

            // J = psi_AxB_dimer_basis * HAB * psi_AxB_dimer_basis^T
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Projecting the Fock matrix onto the dimer basis" << flush;
            ub::diagonal_matrix<double> _hamiltonian_AB(_orbitalsAB->getNumberOfLevels(), _orbitalsAB->MOEnergies().data());
            ub::matrix<double> _temp = ub::prod(_hamiltonian_AB, ub::trans(_psi_AxB_dimer_basis));
            ub::matrix<double> JAB_dimer = ub::prod(_psi_AxB_dimer_basis, _temp);

            // S = psi_AxB_dimer_basis * psi_AxB_dimer_basis^T
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Constructing Overlap matrix" << flush;
            ub::matrix<double> _S_AxB = ub::prod(_psi_AxB_dimer_basis, ub::trans(_psi_AxB_dimer_basis));

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Calculating the effective overlap JAB ["
                    << JAB_dimer.size1() << "x"
                    << JAB_dimer.size2() << "]" << flush;
            double smalleig = linalg_loewdin(JAB_dimer, _S_AxB);
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Smallest eigenvalue of overlap matrix is " << smalleig << flush;
            (*_JAB) = JAB_dimer;

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Done with electronic couplings" << flush;

            return true;

        }

    }
}
<commit_msg>Removed comments<commit_after>/*
 *            Copyright 2009-2017 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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.
 *
 */

// Overload of uBLAS prod function with MKL/GSL implementations
#include <votca/tools/linalg.h>
#include <votca/xtp/aomatrix.h>
#include <votca/xtp/dftcoupling.h>

#include <boost/numeric/ublas/operation.hpp>
#include <boost/numeric/ublas/banded.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/vector_proxy.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <votca/tools/constants.h>
#include <boost/format.hpp>
#include <boost/progress.hpp>

namespace votca {
    namespace xtp {

        namespace ub = boost::numeric::ublas;

        using boost::format;

        double DFTcoupling::getCouplingElement(int levelA, int levelB, Orbitals* _orbitalsA,
                Orbitals* _orbitalsB, ub::matrix<double>* _JAB, double _energy_difference) {

            int _levelsA = _orbitalsA->getNumberOfLevels();

            if (_energy_difference != 0) {
                std::vector<int> list_levelsA = *_orbitalsA->getDegeneracy(levelA, _energy_difference);
                std::vector<int> list_levelsB = *_orbitalsA->getDegeneracy(levelB, _energy_difference);

                double _JAB_sq = 0;
                double _JAB_one_level;

                for (std::vector<int>::iterator iA = list_levelsA.begin()++; iA != list_levelsA.end(); iA++) {
                    for (std::vector<int>::iterator iB = list_levelsB.begin()++; iB != list_levelsB.end(); iB++) {
                        //cout << *iA << ':' << *iB << endl;
                        _JAB_one_level = _JAB->at_element(*iA - 1, *iB - 1 + _levelsA);
                        _JAB_sq += _JAB_one_level*_JAB_one_level;
                    }
                }

                return sqrt(_JAB_sq / (list_levelsA.size() * list_levelsB.size())) * tools::conv::hrt2ev;

            } else {

                return _JAB->at_element(levelA - 1, levelB - 1 + _levelsA) * tools::conv::hrt2ev;

            }
            // the  matrix should be symmetric, could also return this element
            // _JAB.at_element( _levelsA + levelB - 1  , levelA - 1 );
        }

        /**
         * \brief evaluates electronic couplings
         *
         * This is a fast version with a rather large block matrix AxB
         *
         * @param _orbitalsA molecular orbitals of molecule A
         * @param _orbitalsB molecular orbitals of molecule B
         * @param _orbitalsAB molecular orbitals of the dimer AB
         * @param _JAB matrix with electronic couplings
         * @return false if failed
         */
        bool DFTcoupling::CalculateIntegrals(Orbitals* _orbitalsA, Orbitals* _orbitalsB,
                Orbitals* _orbitalsAB, ub::matrix<double>* _JAB) {

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Calculating electronic couplings" << flush;

            const std::vector<QMAtom*> atomsA = _orbitalsA->QMAtoms();
            const std::vector<QMAtom*> atomsB = _orbitalsB->QMAtoms();
            const std::vector<QMAtom*> atomsAll = _orbitalsAB->QMAtoms();

            for (unsigned i = 0; i < atomsAll.size(); i++) {
                QMAtom* dimer = atomsAll[i];
                QMAtom* monomer = NULL;

                if (i < atomsA.size()) {
                    monomer = atomsA[i];
                    if(!monomer->getPos().isClose(dimer->getPos(), 0.001) ) {
                        CTP_LOG(ctp::logERROR, *_pLog) << "======WARNING=======\n Coordinates of monomers and dimer atoms do not agree, do you know what you are doing?\n " << flush;
                        continue;
                    }
                } else if (i < atomsB.size() + atomsA.size()) {
                    monomer = atomsB[i - atomsA.size()];
                    if(monomer->getPos().isClose(dimer->getPos(), 0.001)){
                        CTP_LOG(ctp::logERROR, *_pLog) << "======WARNING=======\n Coordinates of monomers and dimer atoms do not agree, do you know what you are doing?\n " << flush;
                        continue;
                    }
                } else {
                    // Linker
                    CTP_LOG(ctp::logDEBUG, *_pLog) << (format("Neither Monomer A nor Monomer B contains atom %s on line %u. Hence, this atom is part of a linker. \n") %dimer->getType() %(i+1) ).str()<<flush;
                    continue;
                }

                if (monomer->getType() != dimer->getType()) {
                    throw runtime_error("\nERROR: Atom types do not agree in dimer and monomers\n");
                }
                if (tools::abs(monomer->getPos() - dimer->getPos()) > 0.001) {
                    CTP_LOG(ctp::logERROR, *_pLog) << "======WARNING=======\n Coordinates of monomers and dimer atoms do not agree, do you know what you are doing?\n " << flush;
                    break;
                }
            }

            // constructing the direct product orbA x orbB
            int _basisA = _orbitalsA->getBasisSetSize();
            int _basisB = _orbitalsB->getBasisSetSize();

            if ((_basisA == 0) || (_basisB == 0)) {
                CTP_LOG(ctp::logERROR, *_pLog) << "Basis set size is not stored in monomers" << flush;
                return false;
            }

            int _levelsA = _orbitalsA->getNumberOfLevels();
            int _levelsB = _orbitalsB->getNumberOfLevels();

            //boost::timer t; // start timing
            //double _st = t.elapsed();

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Levels:Basis A[" << _levelsA << ":" << _basisA << "]"
                    << " B[" << _levelsB << ":" << _basisB << "]" << flush;

            if ((_levelsA == 0) || (_levelsB == 0)) {
                CTP_LOG(ctp::logERROR, *_pLog) << "No information about number of occupied/unoccupied levels is stored" << flush;
                return false;
            }

            //       | Orbitals_A          0 |      | Overlap_A |
            //       | 0          Orbitals_B |  X   | Overlap_B |  X  Transpose( Orbitals_AB )

            ub::matrix<double>_psi_AxB= ub::zero_matrix<double>(_levelsA + _levelsB ,_orbitalsAB->getBasisSetSize());

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Constructing direct product AxB ["
                    << _psi_AxB.size1() << "x"
                    << _psi_AxB.size2() << "]" << flush;

            ub::project(_psi_AxB, ub::range(0, _levelsA), ub::range(0, _basisA)) = _orbitalsA->MOCoefficients();
            ub::project(_psi_AxB, ub::range(_levelsA, _levelsA + _levelsB), ub::range(_basisA, _basisA + _basisB)) = _orbitalsB->MOCoefficients();

            // psi_AxB * S_AB * psi_AB
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Projecting dimer onto monomer orbitals" << flush;
            ub::matrix<double> overlap;
            if (_orbitalsAB->hasAOOverlap()) {
                CTP_LOG(ctp::logDEBUG, *_pLog) << "Reading overlap matrix from orbitals" << flush;
                overlap = _orbitalsAB->AOOverlap();
            } else {
                CTP_LOG(ctp::logDEBUG, *_pLog) << "Calculating overlap matrix for basisset: " << _orbitalsAB->getDFTbasis() << flush;
                BasisSet _dftbasisset;
                AOBasis _dftbasis;
                _dftbasisset.LoadBasisSet(_orbitalsAB->getDFTbasis());

                _dftbasis.AOBasisFill(&_dftbasisset, _orbitalsAB->QMAtoms());
                AOOverlap _dftAOoverlap;
                _dftAOoverlap.Fill(_dftbasis);
                overlap = _dftAOoverlap.Matrix();
            }

            ub::matrix<double> _psi_AB = ub::prod(overlap, ub::trans(_orbitalsAB->MOCoefficients()));
            ub::matrix<double> _psi_AxB_dimer_basis = ub::prod(_psi_AxB, _psi_AB);
            _psi_AB.clear();

            //check to see if projection quality is sufficient
            for (unsigned i = 0; i < _psi_AxB_dimer_basis.size1(); i++) {
                double mag = 0.0;
                for (unsigned j = 0; j < _psi_AxB_dimer_basis.size2(); j++) {
                    mag += _psi_AxB_dimer_basis(i, j) * _psi_AxB_dimer_basis(i, j);

                }
                if (mag < 0.95) {
                    throw runtime_error("\nERROR: Projection of monomer orbitals on dimer is insufficient, maybe the orbital order is screwed up, otherwise increase dimer basis.\n");
                }
            }

            // J = psi_AxB_dimer_basis * HAB * psi_AxB_dimer_basis^T
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Projecting the Fock matrix onto the dimer basis" << flush;
            ub::diagonal_matrix<double> _hamiltonian_AB(_orbitalsAB->getNumberOfLevels(), _orbitalsAB->MOEnergies().data());
            ub::matrix<double> _temp = ub::prod(_hamiltonian_AB, ub::trans(_psi_AxB_dimer_basis));
            ub::matrix<double> JAB_dimer = ub::prod(_psi_AxB_dimer_basis, _temp);

            // S = psi_AxB_dimer_basis * psi_AxB_dimer_basis^T
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Constructing Overlap matrix" << flush;
            ub::matrix<double> _S_AxB = ub::prod(_psi_AxB_dimer_basis, ub::trans(_psi_AxB_dimer_basis));

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Calculating the effective overlap JAB ["
                    << JAB_dimer.size1() << "x"
                    << JAB_dimer.size2() << "]" << flush;
            double smalleig = linalg_loewdin(JAB_dimer, _S_AxB);
            CTP_LOG(ctp::logDEBUG, *_pLog) << "Smallest eigenvalue of overlap matrix is " << smalleig << flush;
            (*_JAB) = JAB_dimer;

            CTP_LOG(ctp::logDEBUG, *_pLog) << "Done with electronic couplings" << flush;

            return true;

        }

    }
}
<|endoftext|>


<commit_before>#include "locomotion_module/locomotion_module.h"

LocomotionModule::LocomotionModule()
{
}

LocomotionModule::~LocomotionModule()
{
}

void LocomotionModule::publishMessage(ros::Publisher *pub_message, int side)
{
  //std_msgs::float32 msg;

  //pub_message->publish(msg);
}

void LocomotionModule::velMessageCallback(const geometry_msgs::Twist::ConstPtr &msg)
{
  //translate twist into left and right velocities
  velLeft_.data = msg->linear.x + msg->angular.z*r_;
  velRight_.data = msg->linear.x - msg->angular.z*r_;
  //publish to left and right topics
  pub_left.publish(velLeft_);
  pub_right.publish(velRight_);
}

void LocomotionModule::odomMessageCallback(const geometry_msgs::Twist::ConstPtr &msg)
{
  current_time = ros::Time::now();

  dt = (current_time - last_time).toSec();
  delta_th = msg->angular.z*dt;
  delta_x = (msg->linear.x*cos(th) )* dt;
  delta_y = (msg->linear.y*sin(th) )* dt;

  x += delta_x;
  y += delta_y;
  th += delta_th;

  //since all odometry is 6DOF we'll need a quaternion created from yaw
    geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);

    //first, we'll publish the transform over tf
    geometry_msgs::TransformStamped odom_trans;
    odom_trans.header.stamp = current_time;
    odom_trans.header.frame_id = "odom";
    odom_trans.child_frame_id = "base_link";

    odom_trans.transform.translation.x = x;
    odom_trans.transform.translation.y = y;
    odom_trans.transform.translation.z = 0.0;
    odom_trans.transform.rotation = odom_quat;

    //send the transform
    odom_broadcaster.sendTransform(odom_trans);

    //next, we'll publish the odometry message over ROS
    nav_msgs::Odometry odom;
    odom.header.stamp = current_time;
    odom.header.frame_id = "odom";

    //set the position
    odom.pose.pose.position.x = x;
    odom.pose.pose.position.y = y;
    odom.pose.pose.position.z = 0.0;
    odom.pose.pose.orientation = odom_quat;

    //set the velocity
    odom.child_frame_id = "base_link";
    odom.twist.twist.linear.x = vx;
    odom.twist.twist.linear.y = vy;
    odom.twist.twist.angular.z = vth;

    //publish the message
    odom_pub.publish(odom);

    last_time = current_time;

}

void LocomotionModule::configCallback(locomotion_module::locomotionModuleConfig &config, uint32_t level)
{
  r_ = config.r + r_center_;
  ROS_INFO("R changed %f",r_);

}
<commit_msg>fixing new class<commit_after>#include "locomotion_module/locomotion_module.h"

LocomotionModule::LocomotionModule()
{
}

LocomotionModule::~LocomotionModule()
{
}

void LocomotionModule::publishMessage(ros::Publisher *pub_message, int side)
{
  //std_msgs::float32 msg;

  //pub_message->publish(msg);
}

void LocomotionModule::velMessageCallback(const geometry_msgs::Twist::ConstPtr &msg)
{
  //translate twist into left and right velocities
  velLeft_.data = msg->linear.x + msg->angular.z*r_;
  velRight_.data = msg->linear.x - msg->angular.z*r_;
  //publish to left and right topics
  pub_left.publish(velLeft_);
  pub_right.publish(velRight_);
}

void LocomotionModule::odomMessageCallback(const geometry_msgs::Twist::ConstPtr &msg)
{
  current_time = ros::Time::now();

  dt = (current_time - last_time).toSec();
  delta_th = msg->angular.z*dt;
  delta_x = (msg->linear.x*cos(th) )* dt;
  delta_y = (msg->linear.y*sin(th) )* dt;

  x += delta_x;
  y += delta_y;
  th += delta_th;

  //since all odometry is 6DOF we'll need a quaternion created from yaw
    geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);

    //first, we'll publish the transform over tf
    geometry_msgs::TransformStamped odom_trans;
    odom_trans.header.stamp = current_time;
    odom_trans.header.frame_id = "odom";
    odom_trans.child_frame_id = "base_link";

    odom_trans.transform.translation.x = x;
    odom_trans.transform.translation.y = y;
    odom_trans.transform.translation.z = 0.0;
    odom_trans.transform.rotation = odom_quat;

    //send the transform
    odom_broadcaster.sendTransform(odom_trans);

    //next, we'll publish the odometry message over ROS
    nav_msgs::Odometry odom;
    odom.header.stamp = current_time;
    odom.header.frame_id = "odom";

    //set the position
    odom.pose.pose.position.x = x;
    odom.pose.pose.position.y = y;
    odom.pose.pose.position.z = 0.0;
    odom.pose.pose.orientation = odom_quat;

    //set the velocity
    odom.child_frame_id = "base_link";
    odom.twist.twist.linear.x = msg->linear.x;
    odom.twist.twist.linear.y = msg->linear.y;
    odom.twist.twist.angular.z = msg->angular.z;

    //publish the message
    odom_pub.publish(odom);

    last_time = current_time;

}

void LocomotionModule::configCallback(locomotion_module::locomotionModuleConfig &config, uint32_t level)
{
  r_ = config.r + r_center_;
  ROS_INFO("R changed %f",r_);

}
<|endoftext|>


<commit_before>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// 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 "universeview.h"
#include "ui_universeview.h"
#include "streamingacn.h"
#include "sacnlistener.h"
#include "preferences.h"
#include "consts.h"
#include "flickerfinderinfoform.h"

#include <QFileDialog>
#include <QStandardPaths>
#include <QMessageBox>

QString onlineToString(bool value)
{
    if(value)
        return QString("Online");
    return QString("Offline");
}

QString protocolVerToString(int value)
{
    switch(value)
    {
    case sACNProtocolDraft:
        return QString("Draft");
    case sACNProtocolRelease:
        return QString("Release");
    }

    return QString("Unknown");
}

UniverseView::UniverseView(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UniverseView)
{
    m_selectedAddress = -1;
    m_logger = NULL;
    ui->setupUi(this);
    connect(ui->universeDisplay, SIGNAL(selectedCellChanged(int)), this, SLOT(selectedAddressChanged(int)));

    ui->btnGo->setEnabled(true);
    ui->btnPause->setEnabled(false);
    ui->sbUniverse->setEnabled(true);
    setUiForLoggingState(NOT_LOGGING);
}

UniverseView::~UniverseView()
{
    delete ui;
}

void UniverseView::startListening(int universe)
{
    ui->twSources->setRowCount(0);
    ui->btnGo->setEnabled(false);
    ui->btnPause->setEnabled(true);
    ui->sbUniverse->setEnabled(false);
    m_listener = sACNManager::getInstance()->getListener(universe);
    ui->universeDisplay->setUniverse(universe);

    // Add the existing sources
    for(int i=0; i<m_listener->sourceCount(); i++)
    {
        sourceOnline(m_listener->source(i));
    }

    connect(m_listener.data(), SIGNAL(sourceFound(sACNSource*)), this, SLOT(sourceOnline(sACNSource*)));
    connect(m_listener.data(), SIGNAL(sourceLost(sACNSource*)), this, SLOT(sourceOffline(sACNSource*)));
    connect(m_listener.data(), SIGNAL(sourceChanged(sACNSource*)), this, SLOT(sourceChanged(sACNSource*)));
    connect(m_listener.data(), SIGNAL(levelsChanged()), this, SLOT(levelsChanged()));

    if(ui->sbUniverse->value()!=universe)
        ui->sbUniverse->setValue(universe);
}

void UniverseView::on_btnGo_pressed()
{
    startListening(ui->sbUniverse->value());
}

void UniverseView::sourceChanged(sACNSource *source)
{
    if(!m_listener) return;
    if(!m_sourceToTableRow.contains(source))
    {
        return;
    }

    int row = m_sourceToTableRow[source];
    ui->twSources->item(row,COL_NAME)->setText(source->name);
    ui->twSources->item(row,COL_NAME)->setBackgroundColor(Preferences::getInstance()->colorForCID(source->src_cid));
    ui->twSources->item(row,COL_CID)->setText(source->cid_string());
    ui->twSources->item(row,COL_PRIO)->setText(QString::number(source->priority));
    ui->twSources->item(row,COL_IP)->setText(source->ip.toString());
    ui->twSources->item(row,COL_FPS)->setText(QString::number((source->fps)));
    ui->twSources->item(row,COL_SEQ_ERR)->setText(QString::number(source->seqErr));
    ui->twSources->item(row,COL_JUMPS)->setText(QString::number(source->jumps));
    ui->twSources->item(row,COL_ONLINE)->setText(onlineToString(source->src_valid));
    ui->twSources->item(row,COL_VER)->setText(protocolVerToString(source->protocol_version));
    ui->twSources->item(row,COL_DD)->setText(source->doing_per_channel ? tr("Yes") : tr("No"));
}

void UniverseView::sourceOnline(sACNSource *source)
{
    if(!m_listener) return;
    int row = ui->twSources->rowCount();
    ui->twSources->setRowCount(row+1);
    m_sourceToTableRow[source] = row;

    ui->twSources->setItem(row,COL_NAME,    new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_CID,     new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_PRIO,    new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_IP,      new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_FPS,     new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_SEQ_ERR, new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_JUMPS,   new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_ONLINE,  new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_VER,     new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_DD,      new QTableWidgetItem() );

    sourceChanged(source);

}

void UniverseView::sourceOffline(sACNSource *source)
{
    if(!m_listener) return;
    sourceChanged(source);
}

void UniverseView::levelsChanged()
{
    if(!m_listener) return;
    if(m_selectedAddress>-1)
        selectedAddressChanged(m_selectedAddress);
}

void UniverseView::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    resizeColumns();
}

void UniverseView::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);

    resizeColumns();
}

void UniverseView::resizeColumns()
{
    // Attempt to resize so all columns fit
    int width = ui->twSources->width();

    int widthUnit = width/14;

    int used = 0;
    for(int i=COL_NAME; i<COL_END; i++)
    {
        switch(i)
        {
        case COL_NAME:
            break;
        case COL_CID:
        case COL_IP:
        case COL_DD:
            ui->twSources->setColumnWidth(i, 2*widthUnit);
            used += 2*widthUnit;
            break;
        default:
            ui->twSources->setColumnWidth(i, widthUnit);
            used += widthUnit;
            break;
        }
    }

    ui->twSources->setColumnWidth(COL_NAME, width-used-5);
}

void UniverseView::setUiForLoggingState(UniverseView::LOG_STATE state)
{
    switch(state)
    {
    case LOGGING:
        ui->btnLogToFile->setText(tr("Stop Log to File"));
        break;

    default:
    case NOT_LOGGING:
        ui->btnLogToFile->setText(tr("Start Log to File"));
        break;
    }
}

void UniverseView::selectedAddressChanged(int address)
{
    ui->teInfo->clear();
    m_selectedAddress = address;
    ui->teInfo->clear();
    if(address<0) return;

    if(!m_listener) return;
    sACNMergedSourceList list = m_listener->mergedLevels();

    QString info;

    info.append(tr("Address : %1\n")
                .arg(address+1));

    if(list[address].winningSource)
    {
            info.append(tr("Winning Source : %1 @ %2")
                        .arg(list[address].winningSource->name)
                        .arg(Preferences::getInstance()->GetFormattedValue(list[address].level)));
            if(list[address].otherSources.count()>0)
            {
                foreach(sACNSource *source, list[address].otherSources)
                {
                    int prio;
                    if(source->doing_per_channel)
                        prio = source->priority_array[address];
                    else
                        prio = source->priority;
                    info.append(tr("\nOther Source : %1 @ %2 (Priority %3)")
                                .arg(source->name)
                                .arg(Preferences::getInstance()->GetFormattedValue(source->level_array[address]))
                                .arg(prio));
                }
            }
    }
    if(!list[address].winningSource)
    {
        info.append(tr("No Sources"));
    }

    ui->teInfo->setPlainText(info);
}

void UniverseView::on_btnPause_pressed()
{
    ui->universeDisplay->pause();
    this->disconnect(m_listener.data());
    ui->btnGo->setEnabled(true);
    ui->btnPause->setEnabled(false);
    ui->sbUniverse->setEnabled(true);
}

void UniverseView::on_btnLogToFile_pressed()
{
    if(!m_logger)
    {
        //Setup dialog box
        QFileDialog dialog(this);
        dialog.setWindowTitle(APP_NAME);
        dialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
        dialog.setNameFilter("CSV Files (*.csv)");
        dialog.setDefaultSuffix("csv");
        dialog.setFileMode(QFileDialog::AnyFile);
        dialog.setViewMode(QFileDialog::Detail);
        dialog.setAcceptMode(QFileDialog::AcceptSave);
        if(dialog.exec()) {
            QString saveName = dialog.selectedFiles().at(0);
            if(saveName.isEmpty()) {
                return;
            }
            m_logger = new MergedUniverseLogger();
            m_logger->start(saveName, m_listener);
            setUiForLoggingState(LOGGING);
        }

    }
    else
    {
        m_logger->stop();
        m_logger->deleteLater();
        m_logger = nullptr;

        setUiForLoggingState(NOT_LOGGING);
    }

}

void UniverseView::on_btnStartFlickerFinder_pressed()
{
    if(ui->universeDisplay->flickerFinder())
    {
        ui->universeDisplay->setFlickerFinder(false);
        ui->btnStartFlickerFinder->setText(tr("Start Flicker Finder"));
    }
    else
    {
        if(Preferences::getInstance()->getFlickerFinderShowInfo())
        {
            FlickerFinderInfoForm form;
            int result = form.exec();
            if(!result) return;
        }
        ui->universeDisplay->setFlickerFinder(true);
        ui->btnStartFlickerFinder->setText(tr("Stop Flicker Finder"));
    }
}
<commit_msg>Show priority of winning source<commit_after>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// 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 "universeview.h"
#include "ui_universeview.h"
#include "streamingacn.h"
#include "sacnlistener.h"
#include "preferences.h"
#include "consts.h"
#include "flickerfinderinfoform.h"

#include <QFileDialog>
#include <QStandardPaths>
#include <QMessageBox>

QString onlineToString(bool value)
{
    if(value)
        return QString("Online");
    return QString("Offline");
}

QString protocolVerToString(int value)
{
    switch(value)
    {
    case sACNProtocolDraft:
        return QString("Draft");
    case sACNProtocolRelease:
        return QString("Release");
    }

    return QString("Unknown");
}

UniverseView::UniverseView(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UniverseView)
{
    m_selectedAddress = -1;
    m_logger = NULL;
    ui->setupUi(this);
    connect(ui->universeDisplay, SIGNAL(selectedCellChanged(int)), this, SLOT(selectedAddressChanged(int)));

    ui->btnGo->setEnabled(true);
    ui->btnPause->setEnabled(false);
    ui->sbUniverse->setEnabled(true);
    setUiForLoggingState(NOT_LOGGING);
}

UniverseView::~UniverseView()
{
    delete ui;
}

void UniverseView::startListening(int universe)
{
    ui->twSources->setRowCount(0);
    ui->btnGo->setEnabled(false);
    ui->btnPause->setEnabled(true);
    ui->sbUniverse->setEnabled(false);
    m_listener = sACNManager::getInstance()->getListener(universe);
    ui->universeDisplay->setUniverse(universe);

    // Add the existing sources
    for(int i=0; i<m_listener->sourceCount(); i++)
    {
        sourceOnline(m_listener->source(i));
    }

    connect(m_listener.data(), SIGNAL(sourceFound(sACNSource*)), this, SLOT(sourceOnline(sACNSource*)));
    connect(m_listener.data(), SIGNAL(sourceLost(sACNSource*)), this, SLOT(sourceOffline(sACNSource*)));
    connect(m_listener.data(), SIGNAL(sourceChanged(sACNSource*)), this, SLOT(sourceChanged(sACNSource*)));
    connect(m_listener.data(), SIGNAL(levelsChanged()), this, SLOT(levelsChanged()));

    if(ui->sbUniverse->value()!=universe)
        ui->sbUniverse->setValue(universe);
}

void UniverseView::on_btnGo_pressed()
{
    startListening(ui->sbUniverse->value());
}

void UniverseView::sourceChanged(sACNSource *source)
{
    if(!m_listener) return;
    if(!m_sourceToTableRow.contains(source))
    {
        return;
    }

    int row = m_sourceToTableRow[source];
    ui->twSources->item(row,COL_NAME)->setText(source->name);
    ui->twSources->item(row,COL_NAME)->setBackgroundColor(Preferences::getInstance()->colorForCID(source->src_cid));
    ui->twSources->item(row,COL_CID)->setText(source->cid_string());
    ui->twSources->item(row,COL_PRIO)->setText(QString::number(source->priority));
    ui->twSources->item(row,COL_IP)->setText(source->ip.toString());
    ui->twSources->item(row,COL_FPS)->setText(QString::number((source->fps)));
    ui->twSources->item(row,COL_SEQ_ERR)->setText(QString::number(source->seqErr));
    ui->twSources->item(row,COL_JUMPS)->setText(QString::number(source->jumps));
    ui->twSources->item(row,COL_ONLINE)->setText(onlineToString(source->src_valid));
    ui->twSources->item(row,COL_VER)->setText(protocolVerToString(source->protocol_version));
    ui->twSources->item(row,COL_DD)->setText(source->doing_per_channel ? tr("Yes") : tr("No"));
}

void UniverseView::sourceOnline(sACNSource *source)
{
    if(!m_listener) return;
    int row = ui->twSources->rowCount();
    ui->twSources->setRowCount(row+1);
    m_sourceToTableRow[source] = row;

    ui->twSources->setItem(row,COL_NAME,    new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_CID,     new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_PRIO,    new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_IP,      new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_FPS,     new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_SEQ_ERR, new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_JUMPS,   new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_ONLINE,  new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_VER,     new QTableWidgetItem() );
    ui->twSources->setItem(row,COL_DD,      new QTableWidgetItem() );

    sourceChanged(source);

}

void UniverseView::sourceOffline(sACNSource *source)
{
    if(!m_listener) return;
    sourceChanged(source);
}

void UniverseView::levelsChanged()
{
    if(!m_listener) return;
    if(m_selectedAddress>-1)
        selectedAddressChanged(m_selectedAddress);
}

void UniverseView::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    resizeColumns();
}

void UniverseView::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);

    resizeColumns();
}

void UniverseView::resizeColumns()
{
    // Attempt to resize so all columns fit
    int width = ui->twSources->width();

    int widthUnit = width/14;

    int used = 0;
    for(int i=COL_NAME; i<COL_END; i++)
    {
        switch(i)
        {
        case COL_NAME:
            break;
        case COL_CID:
        case COL_IP:
        case COL_DD:
            ui->twSources->setColumnWidth(i, 2*widthUnit);
            used += 2*widthUnit;
            break;
        default:
            ui->twSources->setColumnWidth(i, widthUnit);
            used += widthUnit;
            break;
        }
    }

    ui->twSources->setColumnWidth(COL_NAME, width-used-5);
}

void UniverseView::setUiForLoggingState(UniverseView::LOG_STATE state)
{
    switch(state)
    {
    case LOGGING:
        ui->btnLogToFile->setText(tr("Stop Log to File"));
        break;

    default:
    case NOT_LOGGING:
        ui->btnLogToFile->setText(tr("Start Log to File"));
        break;
    }
}

void UniverseView::selectedAddressChanged(int address)
{
    ui->teInfo->clear();
    m_selectedAddress = address;
    ui->teInfo->clear();
    if(address<0) return;

    if(!m_listener) return;
    sACNMergedSourceList list = m_listener->mergedLevels();

    QString info;

    info.append(tr("Address : %1\n")
                .arg(address+1));

    if(list[address].winningSource)
    {
        int prio;
        if(list[address].winningSource->doing_per_channel)
            prio = list[address].winningSource->priority_array[address];
        else
            prio = list[address].winningSource->priority;

            info.append(tr("Winning Source : %1 @ %2 (Priority %3)")
                        .arg(list[address].winningSource->name)
                        .arg(Preferences::getInstance()->GetFormattedValue(list[address].level))
                        .arg(prio));
            if(list[address].otherSources.count()>0)
            {
                foreach(sACNSource *source, list[address].otherSources)
                {
                    if(source->doing_per_channel)
                        prio = source->priority_array[address];
                    else
                        prio = source->priority;
                    info.append(tr("\nOther Source : %1 @ %2 (Priority %3)")
                                .arg(source->name)
                                .arg(Preferences::getInstance()->GetFormattedValue(source->level_array[address]))
                                .arg(prio));
                }
            }
    }
    if(!list[address].winningSource)
    {
        info.append(tr("No Sources"));
    }

    ui->teInfo->setPlainText(info);
}

void UniverseView::on_btnPause_pressed()
{
    ui->universeDisplay->pause();
    this->disconnect(m_listener.data());
    ui->btnGo->setEnabled(true);
    ui->btnPause->setEnabled(false);
    ui->sbUniverse->setEnabled(true);
}

void UniverseView::on_btnLogToFile_pressed()
{
    if(!m_logger)
    {
        //Setup dialog box
        QFileDialog dialog(this);
        dialog.setWindowTitle(APP_NAME);
        dialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
        dialog.setNameFilter("CSV Files (*.csv)");
        dialog.setDefaultSuffix("csv");
        dialog.setFileMode(QFileDialog::AnyFile);
        dialog.setViewMode(QFileDialog::Detail);
        dialog.setAcceptMode(QFileDialog::AcceptSave);
        if(dialog.exec()) {
            QString saveName = dialog.selectedFiles().at(0);
            if(saveName.isEmpty()) {
                return;
            }
            m_logger = new MergedUniverseLogger();
            m_logger->start(saveName, m_listener);
            setUiForLoggingState(LOGGING);
        }

    }
    else
    {
        m_logger->stop();
        m_logger->deleteLater();
        m_logger = nullptr;

        setUiForLoggingState(NOT_LOGGING);
    }

}

void UniverseView::on_btnStartFlickerFinder_pressed()
{
    if(ui->universeDisplay->flickerFinder())
    {
        ui->universeDisplay->setFlickerFinder(false);
        ui->btnStartFlickerFinder->setText(tr("Start Flicker Finder"));
    }
    else
    {
        if(Preferences::getInstance()->getFlickerFinderShowInfo())
        {
            FlickerFinderInfoForm form;
            int result = form.exec();
            if(!result) return;
        }
        ui->universeDisplay->setFlickerFinder(true);
        ui->btnStartFlickerFinder->setText(tr("Stop Flicker Finder"));
    }
}
<|endoftext|>


<commit_before>/*
 * kinetic-cpp-client
 * Copyright (C) 2014 Seagate Technology.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include "kinetic/reader_writer.h"

#include <errno.h>
#include <unistd.h>

#include "glog/logging.h"

const uint32_t SOCKET_TIMEOUT = 10000;  //10 seconds

namespace kinetic {

ReaderWriter::ReaderWriter(int fd) : fd_(fd) {}

bool ReaderWriter::Read(void *buf, size_t n, int* err) {
    size_t bytes_read = 0;
    uint32_t socket_timeout = 0;
    while (bytes_read < n && socket_timeout < SOCKET_TIMEOUT) {
        int status = read(fd_, reinterpret_cast<char *>(buf) + bytes_read, n - bytes_read);
        if (status == -1 && errno == EINTR) {
            continue;
        } else if (status == -1 && (errno == EAGAIN || errno == EWOULDBLOCK )) {
	    LOG(INFO) << "Peer is slow to transmit";
	    //Wait for 500us;
	    usleep(500);
            socket_timeout++;
            continue;
        } else if (status < 0) {
            *err = errno;
            PLOG(WARNING) << "Failed to read from socket";
            return false;
        }
        if (status == 0) {
            LOG(WARNING) << "Unexpected EOF. Socket (TX) may be closed by Peer";
            return false;
        }
        bytes_read += status;
    }

    return true;
}

bool ReaderWriter::Write(const void *buf, size_t n) {
    size_t bytes_written = 0;
    uint32_t socket_timeout = 0;
    while (bytes_written < n && socket_timeout < SOCKET_TIMEOUT) {
        int status = write(fd_, reinterpret_cast<const char *>(buf) + bytes_written,
            n - bytes_written);
        if (status == -1 && errno == EINTR) {
            continue;
        } else if (status == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
	    LOG(INFO) << " Peer is slow to receive";
	    usleep(500);
	    socket_timeout++;
            continue;
        } else if (status < 0) {
            PLOG(WARNING) << "Failed to write to socket";
            return false;
        }
        if (status == 0) {
            LOG(WARNING) << "Unexpected EOF, Socket(RX) may be closed by Peer";
            return false;
        }
        bytes_written += status;
    }

    return true;
}

} // namespace kinetic
<commit_msg>Change timeout to 20K<commit_after>/*
 * kinetic-cpp-client
 * Copyright (C) 2014 Seagate Technology.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include "kinetic/reader_writer.h"

#include <errno.h>
#include <unistd.h>

#include "glog/logging.h"

const uint32_t SOCKET_TIMEOUT = 20000;  //10 seconds

namespace kinetic {

ReaderWriter::ReaderWriter(int fd) : fd_(fd) {}

bool ReaderWriter::Read(void *buf, size_t n, int* err) {
    size_t bytes_read = 0;
    uint32_t socket_timeout = 0;
    while (bytes_read < n && socket_timeout < SOCKET_TIMEOUT) {
        int status = read(fd_, reinterpret_cast<char *>(buf) + bytes_read, n - bytes_read);
        if (status == -1 && errno == EINTR) {
            continue;
        } else if (status == -1 && (errno == EAGAIN || errno == EWOULDBLOCK )) {
	    LOG(INFO) << "Peer is slow to transmit";
	    //Wait for 500us;
	    usleep(500);
            socket_timeout++;
            continue;
        } else if (status < 0) {
            *err = errno;
            PLOG(WARNING) << "Failed to read from socket";
            return false;
        }
        if (status == 0) {
            LOG(WARNING) << "Unexpected EOF. Socket (TX) may be closed by Peer";
            return false;
        }
        bytes_read += status;
    }

    return true;
}

bool ReaderWriter::Write(const void *buf, size_t n) {
    size_t bytes_written = 0;
    uint32_t socket_timeout = 0;
    while (bytes_written < n && socket_timeout < SOCKET_TIMEOUT) {
        int status = write(fd_, reinterpret_cast<const char *>(buf) + bytes_written,
            n - bytes_written);
        if (status == -1 && errno == EINTR) {
            continue;
        } else if (status == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
	    LOG(INFO) << " Peer is slow to receive";
	    usleep(500);
	    socket_timeout++;
            continue;
        } else if (status < 0) {
            PLOG(WARNING) << "Failed to write to socket";
            return false;
        }
        if (status == 0) {
            LOG(WARNING) << "Unexpected EOF, Socket(RX) may be closed by Peer";
            return false;
        }
        bytes_written += status;
    }

    return true;
}

} // namespace kinetic
<|endoftext|>


<commit_before>#include <QtGui>
#include "hled.h"

struct HLed::Private
{
public:
    Private()
        : darkerFactor(300), color(Qt::green), isOn(true)
    { }

    int darkerFactor;
    QColor color;
    bool isOn;
};

HLed::HLed(QWidget *parent)
    :QWidget(parent), m_d(new Private)
{
}

HLed::~HLed()
{
    delete m_d;
}

QColor HLed::color() const
{
    return m_d->color;
}

void HLed::setColor(const QColor &color)
{
    if (m_d->color == color)
        return;
    update();
}

QSize HLed::sizeHint() const
{
    return QSize(20, 20);
}

QSize HLed::minimumSizeHint() const
{
    return QSize(16, 16);
}

void HLed::toggle()
{
    m_d->isOn = !m_d->isOn;
    update();
}

void HLed::turnOn(bool on)
{
    m_d->isOn = on;
    update();
}

void HLed::turnOff(bool off)
{
    turnOn(!off);
}

void HLed::paintEvent(QPaintEvent* /* event*/)
{
    int width = ledWidth();

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QColor color = m_d->isOn ? m_d->color
                             : m_d->color.darker(m_d->darkerFactor);

    QBrush brush;
    brush.setStyle(Qt::SolidPattern);
    brush.setColor(color);
    painter.setBrush(brush);
    // draw plain
    painter.drawEllipse(1, 1, width-1, width-1);

    QPen pen;
    pen.setWidth(2);

    int pos = width / 5 + 1;
    int lightWidth = width * 2 / 3;
    int lightQuote = 130 * 2 / (lightWidth ? lightWidth : 1) + 100;

    // draw bright spot
    while (lightWidth) {
        color = color.lighter(lightQuote);
        pen.setColor(color);
        painter.setPen(pen);
        painter.drawEllipse(pos, pos, lightWidth, lightWidth);
        lightWidth--;

        if (!lightWidth)
            break;

        painter.drawEllipse(pos, pos, lightWidth, lightWidth);
        lightWidth--;

        if (!lightWidth)
            break;

        painter.drawEllipse(pos, pos, lightWidth, lightWidth);
        pos++;
        lightWidth--;
    }

    //draw border
    painter.setBrush(Qt::NoBrush);

    int angle = -720;
    color = palette().color(QPalette::Light);

    for (int arc=120; arc<2880; arc+=240) {
        pen.setColor(color);
        painter.setPen(pen);
        int w = width - pen.width()/2;
        painter.drawArc(pen.width()/2, pen.width()/2, w, w, angle+arc, 240);
        painter.drawArc(pen.width()/2, pen.width()/2, w, w, angle-arc, 240);
        color = color.darker(110);
    }
}

int HLed::ledWidth() const
{
    int width = qMin(this->width(), this->height());
    width -= 2;
    return width > 0 ? width : 0;
}

<commit_msg>HLed setColor forgot to set<commit_after>#include <QtGui>
#include "hled.h"

struct HLed::Private
{
public:
    Private()
        : darkerFactor(300), color(Qt::green), isOn(true)
    { }

    int darkerFactor;
    QColor color;
    bool isOn;
};

HLed::HLed(QWidget *parent)
    :QWidget(parent), m_d(new Private)
{
}

HLed::~HLed()
{
    delete m_d;
}

QColor HLed::color() const
{
    return m_d->color;
}

void HLed::setColor(const QColor &color)
{
    if (m_d->color == color)
        return;
    m_d->color = color;
    update();
}

QSize HLed::sizeHint() const
{
    return QSize(20, 20);
}

QSize HLed::minimumSizeHint() const
{
    return QSize(16, 16);
}

void HLed::toggle()
{
    m_d->isOn = !m_d->isOn;
    update();
}

void HLed::turnOn(bool on)
{
    m_d->isOn = on;
    update();
}

void HLed::turnOff(bool off)
{
    turnOn(!off);
}

void HLed::paintEvent(QPaintEvent* /* event*/)
{
    int width = ledWidth();

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QColor color = m_d->isOn ? m_d->color
                             : m_d->color.darker(m_d->darkerFactor);

    QBrush brush;
    brush.setStyle(Qt::SolidPattern);
    brush.setColor(color);
    painter.setBrush(brush);
    // draw plain
    painter.drawEllipse(1, 1, width-1, width-1);

    QPen pen;
    pen.setWidth(2);

    int pos = width / 5 + 1;
    int lightWidth = width * 2 / 3;
    int lightQuote = 130 * 2 / (lightWidth ? lightWidth : 1) + 100;

    // draw bright spot
    while (lightWidth) {
        color = color.lighter(lightQuote);
        pen.setColor(color);
        painter.setPen(pen);
        painter.drawEllipse(pos, pos, lightWidth, lightWidth);
        lightWidth--;

        if (!lightWidth)
            break;

        painter.drawEllipse(pos, pos, lightWidth, lightWidth);
        lightWidth--;

        if (!lightWidth)
            break;

        painter.drawEllipse(pos, pos, lightWidth, lightWidth);
        pos++;
        lightWidth--;
    }

    //draw border
    painter.setBrush(Qt::NoBrush);

    int angle = -720;
    color = palette().color(QPalette::Light);

    for (int arc=120; arc<2880; arc+=240) {
        pen.setColor(color);
        painter.setPen(pen);
        int w = width - pen.width()/2;
        painter.drawArc(pen.width()/2, pen.width()/2, w, w, angle+arc, 240);
        painter.drawArc(pen.width()/2, pen.width()/2, w, w, angle-arc, 240);
        color = color.darker(110);
    }
}

int HLed::ledWidth() const
{
    int width = qMin(this->width(), this->height());
    width -= 2;
    return width > 0 ? width : 0;
}

<|endoftext|>


<commit_before>#if defined(DEBUGGER_BRIDGE)

#include "dbg_delayload.h"
#include <windows.h>
#define DELAYIMP_INSECURE_WRITABLE_HOOKS
#include <DelayImp.h>
#include "dbg_luacompatibility.h"

namespace delayload
{
	static std::wstring luadll_path;
	static HMODULE luadll_handle = 0;
	static GetLuaApi get_lua_api = ::GetProcAddress;

	void set_luadll(const std::wstring& path)
	{
		luadll_path = path;
		get_lua_api = ::GetProcAddress;
	}

	void set_luadll(HMODULE handle, GetLuaApi fn)
	{
		luadll_handle = handle;
		get_lua_api = fn ? fn : ::GetProcAddress;
	}

	static FARPROC WINAPI hook(unsigned dliNotify, PDelayLoadInfo pdli)
	{
		switch (dliNotify) {
		case dliStartProcessing:
			break;
		case dliNotePreLoadLibrary:
			if (strcmp("lua53.dll", pdli->szDll) == 0) {
				if (!luadll_path.empty()) {
					HMODULE m = LoadLibraryW(luadll_path.c_str());
					lua::check_version(m);
					return (FARPROC)m;
				}
				else if (luadll_handle) {
					lua::check_version(luadll_handle);
					return (FARPROC)luadll_handle;
				}
			}
			break;
		case dliNotePreGetProcAddress: {
			FARPROC ret = get_lua_api(pdli->hmodCur, pdli->dlp.szProcName);
			if (ret) {
				return ret;
			}
			if (strcmp(pdli->dlp.szProcName, "lua_getuservalue") == 0) {
				lua::lua54::lua_getiuservalue = (int(__cdecl*)(lua_State*, int, int))get_lua_api(pdli->hmodCur, "lua_getiuservalue");
				if (lua::lua54::lua_getiuservalue) {
					return (FARPROC)lua::lua54::lua_getuservalue;
				}
			}
			char str[256];
			sprintf(str, "Can't find lua c function: `%s`.", pdli->dlp.szProcName);
			MessageBoxA(0, "Fatal Error.", str, 0);
			return NULL;
		}
			break;
		case dliFailLoadLib:
			break;
		case dliFailGetProc:
			break;
		case dliNoteEndProcessing:
			break;
		default:
			return NULL;
		}
		return NULL;
	}
}

PfnDliHook __pfnDliNotifyHook2 = delayload::hook;

#endif
<commit_msg>setluadll只能用一次<commit_after>#if defined(DEBUGGER_BRIDGE)

#include "dbg_delayload.h"
#include <windows.h>
#define DELAYIMP_INSECURE_WRITABLE_HOOKS
#include <DelayImp.h>
#include "dbg_luacompatibility.h"

namespace delayload
{
	static std::wstring luadll_path;
	static HMODULE luadll_handle = 0;
	static GetLuaApi get_lua_api = ::GetProcAddress;

	bool has_luadll()
	{
		return !luadll_path.empty() || luadll_handle != 0;
	}

	void set_luadll(const std::wstring& path)
	{
		if (has_luadll()) return;
		luadll_path = path;
		get_lua_api = ::GetProcAddress;
	}

	void set_luadll(HMODULE handle, GetLuaApi fn)
	{
		if (has_luadll()) return;
		luadll_handle = handle;
		get_lua_api = fn ? fn : ::GetProcAddress;
	}

	static FARPROC WINAPI hook(unsigned dliNotify, PDelayLoadInfo pdli)
	{
		switch (dliNotify) {
		case dliStartProcessing:
			break;
		case dliNotePreLoadLibrary:
			if (strcmp("lua53.dll", pdli->szDll) == 0) {
				if (!luadll_path.empty()) {
					HMODULE m = LoadLibraryW(luadll_path.c_str());
					lua::check_version(m);
					return (FARPROC)m;
				}
				else if (luadll_handle) {
					lua::check_version(luadll_handle);
					return (FARPROC)luadll_handle;
				}
			}
			break;
		case dliNotePreGetProcAddress: {
			FARPROC ret = get_lua_api(pdli->hmodCur, pdli->dlp.szProcName);
			if (ret) {
				return ret;
			}
			if (strcmp(pdli->dlp.szProcName, "lua_getuservalue") == 0) {
				lua::lua54::lua_getiuservalue = (int(__cdecl*)(lua_State*, int, int))get_lua_api(pdli->hmodCur, "lua_getiuservalue");
				if (lua::lua54::lua_getiuservalue) {
					return (FARPROC)lua::lua54::lua_getuservalue;
				}
			}
			char str[256];
			sprintf(str, "Can't find lua c function: `%s`.", pdli->dlp.szProcName);
			MessageBoxA(0, "Fatal Error.", str, 0);
			return NULL;
		}
			break;
		case dliFailLoadLib:
			break;
		case dliFailGetProc:
			break;
		case dliNoteEndProcessing:
			break;
		default:
			return NULL;
		}
		return NULL;
	}
}

PfnDliHook __pfnDliNotifyHook2 = delayload::hook;

#endif
<|endoftext|>


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

#include <QStringList>

#include "version.h"

Version::Version(const QString &versionString)
    : mMajor(0),
      mMinor(0),
      mPatch(0)
{
    // Split into components and assign them to the correct member
    QStringList components = versionString.split('.');

    mMajor = components.at(0).toInt();
    if(components.count() > 1) {
        mMinor = components.at(1).toInt();
    }
    if(components.count() > 2) {
        mPatch = components.at(2).toInt();
    }
}

Version::Version(int major, int minor, int patch)
    : mMajor(major),
      mMinor(minor),
      mPatch(patch)
{
}

bool Version::operator==(const Version &other) const
{
    return mMajor == other.mMajor &&
           mMinor == other.mMinor &&
           mPatch == other.mPatch;
}

bool Version::operator!=(const Version &other) const
{
    return !(*this == other);
}

bool Version::operator<(const Version &other) const
{
    return mMajor < other.mMajor ||
           (mMajor == other.mMajor && mMinor < other.mMinor) ||
           (mMajor == other.mMajor && mMinor == other.mMinor && mPatch < other.mPatch);
}

bool Version::operator>(const Version &other) const
{
    return !(*this < other || *this == other);
}

bool Version::operator>=(const Version &other) const
{
    return !(*this < other);
}

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

#include <QRegExp>

#include "version.h"

// Match any version in the format "xx.yy.zz"
const QRegExp VersionPattern("^(\\d+).(\\d+).(\\d+)$");

Version::Version(const QString &versionString)
    : mMajor(0),
      mMinor(0),
      mPatch(0)
{
    if(!VersionPattern.indexIn(versionString)) {
        mMajor = VersionPattern.cap(1).toInt();
        mMinor = VersionPattern.cap(2).toInt();
        mPatch = VersionPattern.cap(3).toInt();
    }
}

Version::Version(int major, int minor, int patch)
    : mMajor(major),
      mMinor(minor),
      mPatch(patch)
{
}

bool Version::operator==(const Version &other) const
{
    return mMajor == other.mMajor &&
           mMinor == other.mMinor &&
           mPatch == other.mPatch;
}

bool Version::operator!=(const Version &other) const
{
    return !(*this == other);
}

bool Version::operator<(const Version &other) const
{
    return mMajor < other.mMajor ||
           (mMajor == other.mMajor && mMinor < other.mMinor) ||
           (mMajor == other.mMajor && mMinor == other.mMinor && mPatch < other.mPatch);
}

bool Version::operator>(const Version &other) const
{
    return !(*this < other || *this == other);
}

bool Version::operator>=(const Version &other) const
{
    return !(*this < other);
}

bool Version::operator<=(const Version &other) const
{
    return !(*this > other);
}
<|endoftext|>