<commit_before>#include "NodeSpotify.h"
#include "../../Application.h"
#include "../../exceptions.h"
#include "../../common_macros.h"
#include "../../callbacks/SessionCallbacks.h"
#include "../spotify/SpotifyOptions.h"
#include "NodePlaylist.h"
#include "NodePlaylistFolder.h"
#include "NodePlaylistContainer.h"
#include "NodePlayer.h"
#include "NodeArtist.h"
#include "NodeAlbum.h"
#include "NodeTrack.h"
#include "NodeUser.h"
#include "../../utils/V8Utils.h"

extern Application* application;

NodeSpotify::NodeSpotify(Handle<Object> options) {
  /*
   * Important note: The session callbacks must be initialized before
   * the sp_session is started. The uv timer and async handle must be set up
   * as they will be used as soon as the sp_session is created, which happens in the
   * NodeSpotify ctor.
   */
  //initiate uv_timer and uv_async
  SessionCallbacks::init();

  SpotifyOptions _options;
  HandleScope scope;
  Handle<String> settingsFolderKey = String::New("settingsFolder");
  Handle<String> cacheFolderKey = String::New("cacheFolder");
  Handle<String> traceFileKey = String::New("traceFile");
  Handle<String> appkeyFileKey = String::New("appkeyFile");
  if(options->Has(settingsFolderKey)) {
    String::Utf8Value settingsFolderValue(options->Get(settingsFolderKey)->ToString());
    _options.settingsFolder = *settingsFolderValue;
  } else {
    _options.settingsFolder = "settings";
  }
  if(options->Has(cacheFolderKey)) {
    String::Utf8Value cacheFolderValue(options->Get(cacheFolderKey)->ToString());
    _options.cacheFolder = *cacheFolderValue;
  } else {
    _options.cacheFolder = "cache";
  }
  if(options->Has(traceFileKey)) {
    String::Utf8Value traceFileValue(options->Get(traceFileKey)->ToString());
    _options.traceFile = *traceFileValue;
  }
  if(options->Has(appkeyFileKey)) {
    String::Utf8Value appkeyFileValue(options->Get(appkeyFileKey)->ToString());
    _options.appkeyFile = *appkeyFileValue;
  }
  spotify = std::unique_ptr<Spotify>(new Spotify(_options));
  scope.Close(Undefined());
}

NodeSpotify::~NodeSpotify() {

}

Handle<Value> NodeSpotify::createFromLink(const Arguments& args) {
  HandleScope scope;
  Handle<Value> out;
  String::Utf8Value linkToParse(args[0]->ToString());
  sp_link* parsedLink = sp_link_create_from_string(*linkToParse);
  if(parsedLink != nullptr) {
    sp_linktype linkType = sp_link_type(parsedLink);
    switch(linkType) {
      case SP_LINKTYPE_TRACK:
      {
        sp_track* track = sp_link_as_track(parsedLink);
        NodeTrack* nodeTrack = new NodeTrack(std::make_shared<Track>(track));
        out = nodeTrack->getV8Object();
        break;
      }
      case SP_LINKTYPE_ALBUM:
      {
        sp_album* album = sp_link_as_album(parsedLink);
        NodeAlbum* nodeAlbum = new NodeAlbum(std::make_shared<Album>(album));
        out = nodeAlbum->getV8Object();
        break;
      }
      case SP_LINKTYPE_ARTIST:
      {
        sp_artist* artist = sp_link_as_artist(parsedLink);
        NodeArtist* nodeArtist = new NodeArtist(std::make_shared<Artist>(artist));
        out = nodeArtist->getV8Object();
        break;
      }
      case SP_LINKTYPE_PROFILE:
      {
        sp_user* user = sp_link_as_user(parsedLink);
        NodeUser* nodeUser = new NodeUser(std::make_shared<User>(user));
        out = nodeUser->getV8Object();
        break;
      }
      case SP_LINKTYPE_PLAYLIST:
      {
        sp_playlist* spPlaylist = sp_playlist_create(application->session, parsedLink);
        auto playlist = Playlist::fromCache(spPlaylist);
        NodePlaylist* nodePlaylist = new NodePlaylist(playlist);
        out = nodePlaylist->getV8Object();
        break;
      }
      default:
        out = Undefined();
    }
    sp_link_release(parsedLink);
  } else {
    out = Undefined();
  }
  return scope.Close(out);
}

Handle<Value> NodeSpotify::login(const Arguments& args) {
  HandleScope scope;
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(args.This());
  String::Utf8Value v8User(args[0]->ToString());
  String::Utf8Value v8Password(args[1]->ToString());
  bool rememberMe = args[2]->ToBoolean()->Value();
  bool withRemembered = args[3]->ToBoolean()->Value();
  std::string user(*v8User);
  std::string password(*v8Password);
  nodeSpotify->spotify->login(user, password, rememberMe, withRemembered);
  return scope.Close(Undefined());
}

Handle<Value> NodeSpotify::logout(const Arguments& args) {
  HandleScope scope;
  if(args.Length() > 0) {
    Handle<Function> fun = Handle<Function>::Cast(args[0]);
    Persistent<Function> p = Persistent<Function>::New(fun);
    SessionCallbacks::logoutCallback = p;
  }
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(args.This());
  nodeSpotify->spotify->logout();
  return scope.Close(Undefined());
}

Handle<Value> NodeSpotify::getPlaylistContainer(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodePlaylistContainer* nodePlaylistContainer = new NodePlaylistContainer(application->playlistContainer);
  return scope.Close(nodePlaylistContainer->getV8Object());
}

Handle<Value> NodeSpotify::getRememberedUser(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(info.Holder());
  return scope.Close(String::New(nodeSpotify->spotify->rememberedUser().c_str()));
}

Handle<Value> NodeSpotify::getSessionUser(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(info.Holder());
  NodeUser* nodeUser = new NodeUser(nodeSpotify->spotify->sessionUser());
  return scope.Close(nodeUser->getV8Object());
}

Handle<Value> NodeSpotify::getConstants(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> constants = Object::New();
  constants->Set(String::NewSymbol("ARTISTBROWSE_FULL"), Number::New(SP_ARTISTBROWSE_FULL));
  constants->Set(String::NewSymbol("ARTISTBROWSE_NO_TRACKS"), Number::New(SP_ARTISTBROWSE_NO_TRACKS));
  constants->Set(String::NewSymbol("ARTISTBROWSE_NO_ALBUMS"), Number::New(SP_ARTISTBROWSE_NO_ALBUMS));

  constants->Set(String::NewSymbol("PLAYLIST_TYPE_PLAYLIST"), Number::New(SP_PLAYLIST_TYPE_PLAYLIST));
  constants->Set(String::NewSymbol("PLAYLIST_TYPE_START_FOLDER"), Number::New(SP_PLAYLIST_TYPE_START_FOLDER));
  constants->Set(String::NewSymbol("PLAYLIST_TYPE_END_FOLDER"), Number::New(SP_PLAYLIST_TYPE_END_FOLDER));
  return scope.Close(constants);
}

Handle<Value> NodeSpotify::on(const Arguments& args) {
  HandleScope scope;
  if(args.Length() < 1 || !args[0]->IsObject()) {
    return scope.Close(V8_EXCEPTION("on needs an object as its first argument."));
  }
  Handle<Object> callbacks = args[0]->ToObject();
  Handle<String> metadataUpdatedKey = String::New("metadataUpdated");
  Handle<String> readyKey = String::New("ready");
  Handle<String> logoutKey = String::New("logout");
  SessionCallbacks::metadataUpdatedCallback = V8Utils::getFunctionFromObject(callbacks, metadataUpdatedKey);
  SessionCallbacks::loginCallback = V8Utils::getFunctionFromObject(callbacks, readyKey);
  SessionCallbacks::logoutCallback = V8Utils::getFunctionFromObject(callbacks, logoutKey);
  return scope.Close(Undefined());
}

void NodeSpotify::init() {
  HandleScope scope;
  Handle<FunctionTemplate> constructorTemplate = NodeWrapped::init("Spotify");
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "login", login);
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "logout", logout);
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "createFromLink", createFromLink);
  //Because of the special metadataUpdated callback with convenience functions we provide _on here, will provide "on" in spotify.js
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "_on", on);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("rememberedUser"), getRememberedUser);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("sessionUser"), getSessionUser);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("playlistContainer"), getPlaylistContainer);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("constants"), getConstants);

  constructor = Persistent<Function>::New(constructorTemplate->GetFunction());
  scope.Close(Undefined());
}
<commit_msg>PLAYLIST_TYPE_PLACEHOLDER constant<commit_after>#include "NodeSpotify.h"
#include "../../Application.h"
#include "../../exceptions.h"
#include "../../common_macros.h"
#include "../../callbacks/SessionCallbacks.h"
#include "../spotify/SpotifyOptions.h"
#include "NodePlaylist.h"
#include "NodePlaylistFolder.h"
#include "NodePlaylistContainer.h"
#include "NodePlayer.h"
#include "NodeArtist.h"
#include "NodeAlbum.h"
#include "NodeTrack.h"
#include "NodeUser.h"
#include "../../utils/V8Utils.h"

extern Application* application;

NodeSpotify::NodeSpotify(Handle<Object> options) {
  /*
   * Important note: The session callbacks must be initialized before
   * the sp_session is started. The uv timer and async handle must be set up
   * as they will be used as soon as the sp_session is created, which happens in the
   * NodeSpotify ctor.
   */
  //initiate uv_timer and uv_async
  SessionCallbacks::init();

  SpotifyOptions _options;
  HandleScope scope;
  Handle<String> settingsFolderKey = String::New("settingsFolder");
  Handle<String> cacheFolderKey = String::New("cacheFolder");
  Handle<String> traceFileKey = String::New("traceFile");
  Handle<String> appkeyFileKey = String::New("appkeyFile");
  if(options->Has(settingsFolderKey)) {
    String::Utf8Value settingsFolderValue(options->Get(settingsFolderKey)->ToString());
    _options.settingsFolder = *settingsFolderValue;
  } else {
    _options.settingsFolder = "settings";
  }
  if(options->Has(cacheFolderKey)) {
    String::Utf8Value cacheFolderValue(options->Get(cacheFolderKey)->ToString());
    _options.cacheFolder = *cacheFolderValue;
  } else {
    _options.cacheFolder = "cache";
  }
  if(options->Has(traceFileKey)) {
    String::Utf8Value traceFileValue(options->Get(traceFileKey)->ToString());
    _options.traceFile = *traceFileValue;
  }
  if(options->Has(appkeyFileKey)) {
    String::Utf8Value appkeyFileValue(options->Get(appkeyFileKey)->ToString());
    _options.appkeyFile = *appkeyFileValue;
  }
  spotify = std::unique_ptr<Spotify>(new Spotify(_options));
  scope.Close(Undefined());
}

NodeSpotify::~NodeSpotify() {

}

Handle<Value> NodeSpotify::createFromLink(const Arguments& args) {
  HandleScope scope;
  Handle<Value> out;
  String::Utf8Value linkToParse(args[0]->ToString());
  sp_link* parsedLink = sp_link_create_from_string(*linkToParse);
  if(parsedLink != nullptr) {
    sp_linktype linkType = sp_link_type(parsedLink);
    switch(linkType) {
      case SP_LINKTYPE_TRACK:
      {
        sp_track* track = sp_link_as_track(parsedLink);
        NodeTrack* nodeTrack = new NodeTrack(std::make_shared<Track>(track));
        out = nodeTrack->getV8Object();
        break;
      }
      case SP_LINKTYPE_ALBUM:
      {
        sp_album* album = sp_link_as_album(parsedLink);
        NodeAlbum* nodeAlbum = new NodeAlbum(std::make_shared<Album>(album));
        out = nodeAlbum->getV8Object();
        break;
      }
      case SP_LINKTYPE_ARTIST:
      {
        sp_artist* artist = sp_link_as_artist(parsedLink);
        NodeArtist* nodeArtist = new NodeArtist(std::make_shared<Artist>(artist));
        out = nodeArtist->getV8Object();
        break;
      }
      case SP_LINKTYPE_PROFILE:
      {
        sp_user* user = sp_link_as_user(parsedLink);
        NodeUser* nodeUser = new NodeUser(std::make_shared<User>(user));
        out = nodeUser->getV8Object();
        break;
      }
      case SP_LINKTYPE_PLAYLIST:
      {
        sp_playlist* spPlaylist = sp_playlist_create(application->session, parsedLink);
        auto playlist = Playlist::fromCache(spPlaylist);
        NodePlaylist* nodePlaylist = new NodePlaylist(playlist);
        out = nodePlaylist->getV8Object();
        break;
      }
      default:
        out = Undefined();
    }
    sp_link_release(parsedLink);
  } else {
    out = Undefined();
  }
  return scope.Close(out);
}

Handle<Value> NodeSpotify::login(const Arguments& args) {
  HandleScope scope;
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(args.This());
  String::Utf8Value v8User(args[0]->ToString());
  String::Utf8Value v8Password(args[1]->ToString());
  bool rememberMe = args[2]->ToBoolean()->Value();
  bool withRemembered = args[3]->ToBoolean()->Value();
  std::string user(*v8User);
  std::string password(*v8Password);
  nodeSpotify->spotify->login(user, password, rememberMe, withRemembered);
  return scope.Close(Undefined());
}

Handle<Value> NodeSpotify::logout(const Arguments& args) {
  HandleScope scope;
  if(args.Length() > 0) {
    Handle<Function> fun = Handle<Function>::Cast(args[0]);
    Persistent<Function> p = Persistent<Function>::New(fun);
    SessionCallbacks::logoutCallback = p;
  }
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(args.This());
  nodeSpotify->spotify->logout();
  return scope.Close(Undefined());
}

Handle<Value> NodeSpotify::getPlaylistContainer(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodePlaylistContainer* nodePlaylistContainer = new NodePlaylistContainer(application->playlistContainer);
  return scope.Close(nodePlaylistContainer->getV8Object());
}

Handle<Value> NodeSpotify::getRememberedUser(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(info.Holder());
  return scope.Close(String::New(nodeSpotify->spotify->rememberedUser().c_str()));
}

Handle<Value> NodeSpotify::getSessionUser(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  NodeSpotify* nodeSpotify = node::ObjectWrap::Unwrap<NodeSpotify>(info.Holder());
  NodeUser* nodeUser = new NodeUser(nodeSpotify->spotify->sessionUser());
  return scope.Close(nodeUser->getV8Object());
}

Handle<Value> NodeSpotify::getConstants(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> constants = Object::New();
  constants->Set(String::NewSymbol("ARTISTBROWSE_FULL"), Number::New(SP_ARTISTBROWSE_FULL));
  constants->Set(String::NewSymbol("ARTISTBROWSE_NO_TRACKS"), Number::New(SP_ARTISTBROWSE_NO_TRACKS));
  constants->Set(String::NewSymbol("ARTISTBROWSE_NO_ALBUMS"), Number::New(SP_ARTISTBROWSE_NO_ALBUMS));

  constants->Set(String::NewSymbol("PLAYLIST_TYPE_PLAYLIST"), Number::New(SP_PLAYLIST_TYPE_PLAYLIST));
  constants->Set(String::NewSymbol("PLAYLIST_TYPE_START_FOLDER"), Number::New(SP_PLAYLIST_TYPE_START_FOLDER));
  constants->Set(String::NewSymbol("PLAYLIST_TYPE_END_FOLDER"), Number::New(SP_PLAYLIST_TYPE_END_FOLDER));
  constants->Set(String::NewSymbol("PLAYLIST_TYPE_PLACEHOLDER"), Number::New(SP_PLAYLIST_TYPE_PLACEHOLDER));
  return scope.Close(constants);
}

Handle<Value> NodeSpotify::on(const Arguments& args) {
  HandleScope scope;
  if(args.Length() < 1 || !args[0]->IsObject()) {
    return scope.Close(V8_EXCEPTION("on needs an object as its first argument."));
  }
  Handle<Object> callbacks = args[0]->ToObject();
  Handle<String> metadataUpdatedKey = String::New("metadataUpdated");
  Handle<String> readyKey = String::New("ready");
  Handle<String> logoutKey = String::New("logout");
  SessionCallbacks::metadataUpdatedCallback = V8Utils::getFunctionFromObject(callbacks, metadataUpdatedKey);
  SessionCallbacks::loginCallback = V8Utils::getFunctionFromObject(callbacks, readyKey);
  SessionCallbacks::logoutCallback = V8Utils::getFunctionFromObject(callbacks, logoutKey);
  return scope.Close(Undefined());
}

void NodeSpotify::init() {
  HandleScope scope;
  Handle<FunctionTemplate> constructorTemplate = NodeWrapped::init("Spotify");
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "login", login);
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "logout", logout);
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "createFromLink", createFromLink);
  //Because of the special metadataUpdated callback with convenience functions we provide _on here, will provide "on" in spotify.js
  NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "_on", on);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("rememberedUser"), getRememberedUser);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("sessionUser"), getSessionUser);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("playlistContainer"), getPlaylistContainer);
  constructorTemplate->InstanceTemplate()->SetAccessor(String::NewSymbol("constants"), getConstants);

  constructor = Persistent<Function>::New(constructorTemplate->GetFunction());
  scope.Close(Undefined());
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 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 Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include "chordsdetection.h"
#include "essentiamath.h"

using namespace std;

namespace essentia {
namespace standard {

const char* ChordsDetection::name = "ChordsDetection";
const char* ChordsDetection::category = "Tonal";
const char* ChordsDetection::description = DOC("This algorithm estimates chords using pitch profile classes. It finds the best matching major or minor triad and outputs the result as a string (e.g. A#, Bm, G#m, C). This algorithm uses the Sharp versions of each Flatted note (i.e. Bb -> A#).\n"
"\n"
"Note:\n"
"  - This algorithm assumes that input pcps have been computed with framesize = 2*hopsize\n"
"\n"
"Quality: experimental (prone to errors, algorithm needs improvement)\n"
"\n"
"References:\n"
"  [1] E. Gómez, \"Tonal Description of Polyphonic Audio for Music Content\n"
"  Processing,\" INFORMS Journal on Computing, vol. 18, no. 3, pp. 294–304,\n"
"  2006.\n\n"
"  [2] D. Temperley, \"What's key for key? The Krumhansl-Schmuckler\n"
"  key-finding algorithm reconsidered\", Music Perception vol. 17, no. 1,\n"
"  pp. 65-100, 1999.");

void ChordsDetection::configure() {
  Real wsize = parameter("windowSize").toReal();
  Real sampleRate = parameter("sampleRate").toReal();
  int hopSize = parameter("hopSize").toInt();

  // NB: this assumes that frameSize = hopSize * 2, so that we don't have to
  //     require frameSize as well as parameter.
  _numFramesWindow = int((wsize * sampleRate) / hopSize) - 1;
}

void ChordsDetection::compute() {
  const vector<vector<Real> >& hpcp = _pcp.get();
  vector<string>& chords= _chords.get();
  vector<Real>& strength= _strength.get();

  string key;
  string scale;
  Real firstToSecondRelativeStrength;
  Real str; // strength

  chords.reserve(int(hpcp.size()/_numFramesWindow));
  strength.reserve(int(hpcp.size()/_numFramesWindow));

  for (int i=0; i<int(hpcp.size()); ++i) {

    int indexStart = max(0, i - _numFramesWindow/2);
    int indexEnd = min(i + _numFramesWindow/2, (int)hpcp.size());

    vector<Real> hpcpAverage = meanFrames(hpcp, indexStart, indexEnd);
    normalize(hpcpAverage);

    _chordsAlgo->input("pcp").set(hpcpAverage);
    _chordsAlgo->output("key").set(key);
    _chordsAlgo->output("scale").set(scale);
    _chordsAlgo->output("strength").set(str);
    _chordsAlgo->output("firstToSecondRelativeStrength").set(firstToSecondRelativeStrength);
    _chordsAlgo->compute();

    if (scale == "minor") {
      chords.push_back(key + 'm');
    }
    else {
      chords.push_back(key);
    }

    strength.push_back(str);

  }
}

} // namespace standard
} // namespace essentia

#include "poolstorage.h"

namespace essentia {
namespace streaming {

const char* ChordsDetection::name = standard::ChordsDetection::name;
const char* ChordsDetection::description = standard::ChordsDetection::description;

ChordsDetection::ChordsDetection() : AlgorithmComposite() {

  declareInput(_pcp, "pcp", "the pitch class profile from which to detect the chord");
  declareOutput(_chords, 1, "chords", "the resulting chords, from A to G");
  declareOutput(_strength, 1, "strength", "the strength of the chord");

  _chordsAlgo = standard::AlgorithmFactory::create("Key");
  _chordsAlgo->configure("profileType", "tonictriad", "usePolyphony", false);
  _poolStorage = new PoolStorage<vector<Real> >(&_pool, "internal.hpcp");

  // FIXME: this is just a temporary hack...
  //        the correct way to do this is to have the algorithm output the chords
  //        continuously while processing, which requires a FrameCutter for vectors
  // Need to set the buffer type to multiple frames as all the chords
  // are output all at once
  _chords.setBufferType(BufferUsage::forMultipleFrames);
  _strength.setBufferType(BufferUsage::forMultipleFrames);

  attach(_pcp, _poolStorage->input("data"));
}

ChordsDetection::~ChordsDetection() {
  delete _chordsAlgo;
  delete _poolStorage;
}

void ChordsDetection::configure() {
  Real wsize = parameter("windowSize").toReal();
  Real sampleRate = parameter("sampleRate").toReal();
  int hopSize = parameter("hopSize").toInt();

  // NB: this assumes that frameSize = hopSize * 2, so that we don't have to
  //     require frameSize as well as parameter.
  _numFramesWindow = int((wsize * sampleRate) / hopSize) - 1;
}

AlgorithmStatus ChordsDetection::process() {
  if (!shouldStop()) return PASS;

  const vector<vector<Real> >& hpcp = _pool.value<vector<vector<Real> > >("internal.hpcp");
  string key;
  string scale;
  Real strength;
  Real firstToSecondRelativeStrength;

  // This is very strange, because we jump by a single frame each time, not by
  // the defined windowSize. Is that the expected behavior or is it a bug?
  // eaylon: windowSize is not intended for advancing, but for searching
  // nwack: maybe it could be a smart idea to jump from 1 beat to another instead
  //        of a fixed amount a time (arbitrary frame size)

  for (int i=0; i<(int)hpcp.size(); i++) {

    int indexStart = max(0, i - _numFramesWindow/2);
    int indexEnd = min(i + _numFramesWindow/2, (int)hpcp.size());

    vector<Real> hpcpAverage = meanFrames(hpcp, indexStart, indexEnd);
    normalize(hpcpAverage);

    _chordsAlgo->input("pcp").set(hpcpAverage);
    _chordsAlgo->output("key").set(key);
    _chordsAlgo->output("scale").set(scale);
    _chordsAlgo->output("strength").set(strength);
    _chordsAlgo->output("firstToSecondRelativeStrength").set(firstToSecondRelativeStrength);
    _chordsAlgo->compute();

    if (scale == "minor") {
      _chords.push(key + 'm');
    }
    else {
      _chords.push(key);
    }

    _strength.push(strength);
  }

  return FINISHED;
}

void ChordsDetection::reset() {
  AlgorithmComposite::reset();
  _chordsAlgo->reset();
}

} // namespace streaming
} // namespace essentia
<commit_msg>Improve documentation for the ChordsDetection algo<commit_after>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 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 Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include "chordsdetection.h"
#include "essentiamath.h"

using namespace std;

namespace essentia {
namespace standard {

const char* ChordsDetection::name = "ChordsDetection";
const char* ChordsDetection::category = "Tonal";
const char* ChordsDetection::description = DOC("This algorithm estimates chords given an input sequence of harmonic pitch class profiles (HPCPs). It finds the best matching major or minor triad and outputs the result as a string (e.g. A#, Bm, G#m, C). This algorithm uses the Sharp versions of each Flatted note (i.e. Bb -> A#).\n"
"\n"
"Note:\n"
"  - The algorithm assumes that the sequence of the input HPCP frames has been computed with framesize = 2*hopsize\n"
"  - The algorithm estimates a sequence of chord values corresponding to the input HPCP frames (one chord value for each frame, estimated using a temporal window of HPCPs centered at that frame).\n"
"\n"
"Quality: experimental (prone to errors, algorithm needs improvement)\n"
"\n"
"References:\n"
"  [1] E. Gómez, \"Tonal Description of Polyphonic Audio for Music Content\n"
"  Processing,\" INFORMS Journal on Computing, vol. 18, no. 3, pp. 294–304,\n"
"  2006.\n\n"
"  [2] D. Temperley, \"What's key for key? The Krumhansl-Schmuckler\n"
"  key-finding algorithm reconsidered\", Music Perception vol. 17, no. 1,\n"
"  pp. 65-100, 1999.");

void ChordsDetection::configure() {
  Real wsize = parameter("windowSize").toReal();
  Real sampleRate = parameter("sampleRate").toReal();
  int hopSize = parameter("hopSize").toInt();

  // NB: this assumes that frameSize = hopSize * 2, so that we don't have to
  //     require frameSize as well as parameter.
  _numFramesWindow = int((wsize * sampleRate) / hopSize) - 1;
}

void ChordsDetection::compute() {
  const vector<vector<Real> >& hpcp = _pcp.get();
  vector<string>& chords= _chords.get();
  vector<Real>& strength= _strength.get();

  string key;
  string scale;
  Real firstToSecondRelativeStrength;
  Real str; // strength

  chords.reserve(int(hpcp.size()/_numFramesWindow));
  strength.reserve(int(hpcp.size()/_numFramesWindow));

  for (int i=0; i<int(hpcp.size()); ++i) {

    int indexStart = max(0, i - _numFramesWindow/2);
    int indexEnd = min(i + _numFramesWindow/2, (int)hpcp.size());

    vector<Real> hpcpAverage = meanFrames(hpcp, indexStart, indexEnd);
    normalize(hpcpAverage);

    _chordsAlgo->input("pcp").set(hpcpAverage);
    _chordsAlgo->output("key").set(key);
    _chordsAlgo->output("scale").set(scale);
    _chordsAlgo->output("strength").set(str);
    _chordsAlgo->output("firstToSecondRelativeStrength").set(firstToSecondRelativeStrength);
    _chordsAlgo->compute();

    if (scale == "minor") {
      chords.push_back(key + 'm');
    }
    else {
      chords.push_back(key);
    }

    strength.push_back(str);

  }
}

} // namespace standard
} // namespace essentia

#include "poolstorage.h"

namespace essentia {
namespace streaming {

const char* ChordsDetection::name = standard::ChordsDetection::name;
const char* ChordsDetection::description = standard::ChordsDetection::description;

ChordsDetection::ChordsDetection() : AlgorithmComposite() {

  declareInput(_pcp, "pcp", "the pitch class profile from which to detect the chord");
  declareOutput(_chords, 1, "chords", "the resulting chords, from A to G");
  declareOutput(_strength, 1, "strength", "the strength of the chord");

  _chordsAlgo = standard::AlgorithmFactory::create("Key");
  _chordsAlgo->configure("profileType", "tonictriad", "usePolyphony", false);
  _poolStorage = new PoolStorage<vector<Real> >(&_pool, "internal.hpcp");

  // FIXME: this is just a temporary hack...
  //        the correct way to do this is to have the algorithm output the chords
  //        continuously while processing, which requires a FrameCutter for vectors
  // Need to set the buffer type to multiple frames as all the chords
  // are output all at once
  _chords.setBufferType(BufferUsage::forMultipleFrames);
  _strength.setBufferType(BufferUsage::forMultipleFrames);

  attach(_pcp, _poolStorage->input("data"));
}

ChordsDetection::~ChordsDetection() {
  delete _chordsAlgo;
  delete _poolStorage;
}

void ChordsDetection::configure() {
  Real wsize = parameter("windowSize").toReal();
  Real sampleRate = parameter("sampleRate").toReal();
  int hopSize = parameter("hopSize").toInt();

  // NB: this assumes that frameSize = hopSize * 2, so that we don't have to
  //     require frameSize as well as parameter.
  _numFramesWindow = int((wsize * sampleRate) / hopSize) - 1;
}

AlgorithmStatus ChordsDetection::process() {
  if (!shouldStop()) return PASS;

  const vector<vector<Real> >& hpcp = _pool.value<vector<vector<Real> > >("internal.hpcp");
  string key;
  string scale;
  Real strength;
  Real firstToSecondRelativeStrength;

  // This is very strange, because we jump by a single frame each time, not by
  // the defined windowSize. Is that the expected behavior or is it a bug?
  // eaylon: windowSize is not intended for advancing, but for searching
  // nwack: maybe it could be a smart idea to jump from 1 beat to another instead
  //        of a fixed amount a time (arbitrary frame size)

  for (int i=0; i<(int)hpcp.size(); i++) {

    int indexStart = max(0, i - _numFramesWindow/2);
    int indexEnd = min(i + _numFramesWindow/2, (int)hpcp.size());

    vector<Real> hpcpAverage = meanFrames(hpcp, indexStart, indexEnd);
    normalize(hpcpAverage);

    _chordsAlgo->input("pcp").set(hpcpAverage);
    _chordsAlgo->output("key").set(key);
    _chordsAlgo->output("scale").set(scale);
    _chordsAlgo->output("strength").set(strength);
    _chordsAlgo->output("firstToSecondRelativeStrength").set(firstToSecondRelativeStrength);
    _chordsAlgo->compute();

    if (scale == "minor") {
      _chords.push(key + 'm');
    }
    else {
      _chords.push(key);
    }

    _strength.push(strength);
  }

  return FINISHED;
}

void ChordsDetection::reset() {
  AlgorithmComposite::reset();
  _chordsAlgo->reset();
}

} // namespace streaming
} // namespace essentia
<|endoftext|>


<commit_before>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#ifdef HAVE_BOOST_DATE_TIME
	#include <boost/date_time.hpp>
#endif
#include "function.h"
#include "function_info.h"
#include "profile_writer_html.h"
#include "performance_counter.h"

namespace amx_profiler {

ProfileWriterHtml::ProfileWriterHtml(std::ostream *stream, const std::string script_name)
	: stream_(stream)
	, script_name_(script_name)
{
}

void ProfileWriterHtml::Write(const std::vector<std::shared_ptr<FunctionInfo>> &stats)
{
	*stream_ <<
	"\n"
	"\n"
	"	<title>" << "Profile of '" << script_name_ << "'</title>\n"
	"\n"
	"\n"
	"
\n" <<
	"		Profile of '" << script_name_ << "'\n"
	"
\n"
	"
\n"
	"
\n"
	"
\n"
	"				Type	\n"
	"				Name	\n"
	"				Calls	\n"
	"				Self Time	\n"
	"				Total Time	\n"
	"
\n"
	"
\n"
	"
\n"
	;

	TimeInterval time_all = 0;
	std::for_each(stats.begin(), stats.end(), [&](const std::shared_ptr<FunctionInfo> &info) {
		time_all += info->total_time() - info->child_time();
	});

	TimeInterval total_time_all = 0;
	std::for_each(stats.begin(), stats.end(), [&](const std::shared_ptr<FunctionInfo> &info) {
		total_time_all += info->total_time();
	});

	std::for_each(stats.begin(), stats.end(), [&](const std::shared_ptr<FunctionInfo> &info) {
		*stream_
		<< "
\n"
		<< "			" << info->function()->type() << "	\n"
		<< "			" << info->function()->name() << "	\n"
		<< "			" << info->num_calls() << "	\n"
		<< "			" << std::fixed << std::setprecision(2)
			<< static_cast<double>(info->GetSelfTime() * 100) / time_all << "	\n"
		<< "			" << std::fixed << std::setprecision(2)
			<< static_cast<double>(info->total_time() * 100) / total_time_all << "	\n"
		<< "
\n";
	});

	*stream_ <<
	"
\n"
	"
\n"
	;

	*stream_ <<
	"	\n"
	"	\n"
	"	\n"
	#ifdef HAVE_BOOST_DATE_TIME
	"
\n"
	"	\n"
	"		Generated on " << boost::posix_time::second_clock::local_time() << "\n"
	"	\n"
	#endif
	"\n"
	"\n"
	;
}

} // namespace amx_profiler
<commit_msg>changed the tablesorter URL to one that works<commit_after>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#ifdef HAVE_BOOST_DATE_TIME
	#include <boost/date_time.hpp>
#endif
#include "function.h"
#include "function_info.h"
#include "profile_writer_html.h"
#include "performance_counter.h"

namespace amx_profiler {

ProfileWriterHtml::ProfileWriterHtml(std::ostream *stream, const std::string script_name)
	: stream_(stream)
	, script_name_(script_name)
{
}

void ProfileWriterHtml::Write(const std::vector<std::shared_ptr<FunctionInfo>> &stats)
{
	*stream_ <<
	"\n"
	"\n"
	"	<title>" << "Profile of '" << script_name_ << "'</title>\n"
	"\n"
	"\n"
	"
\n" <<
	"		Profile of '" << script_name_ << "'\n"
	"
\n"
	"
\n"
	"
\n"
	"
\n"
	"				Type	\n"
	"				Name	\n"
	"				Calls	\n"
	"				Self Time	\n"
	"				Total Time	\n"
	"
\n"
	"
\n"
	"
\n"
	;

	TimeInterval time_all = 0;
	std::for_each(stats.begin(), stats.end(), [&](const std::shared_ptr<FunctionInfo> &info) {
		time_all += info->total_time() - info->child_time();
	});

	TimeInterval total_time_all = 0;
	std::for_each(stats.begin(), stats.end(), [&](const std::shared_ptr<FunctionInfo> &info) {
		total_time_all += info->total_time();
	});

	std::for_each(stats.begin(), stats.end(), [&](const std::shared_ptr<FunctionInfo> &info) {
		*stream_
		<< "
\n"
		<< "			" << info->function()->type() << "	\n"
		<< "			" << info->function()->name() << "	\n"
		<< "			" << info->num_calls() << "	\n"
		<< "			" << std::fixed << std::setprecision(2)
			<< static_cast<double>(info->GetSelfTime() * 100) / time_all << "	\n"
		<< "			" << std::fixed << std::setprecision(2)
			<< static_cast<double>(info->total_time() * 100) / total_time_all << "	\n"
		<< "
\n";
	});

	*stream_ <<
	"
\n"
	"
\n"
	;

	*stream_ <<
	"	\n"
	"	\n"
	"	\n"
	#ifdef HAVE_BOOST_DATE_TIME
	"
\n"
	"	\n"
	"		Generated on " << boost::posix_time::second_clock::local_time() << "\n"
	"	\n"
	#endif
	"\n"
	"\n"
	;
}

} // namespace amx_profiler
<|endoftext|>


<commit_before>
// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_MATCHING_METRIC_H
#define OPENMVG_MATCHING_METRIC_H

#include "openMVG/matching/metric_hamming.hpp"
#include "openMVG/numeric/accumulator_trait.hpp"
#include <cstddef>

namespace openMVG {
namespace matching {

/// Squared Euclidean distance functor.
template<class T>
struct L2_Simple
{
  typedef T ElementType;
  typedef typename Accumulator<T>::Type ResultType;

  template <typename Iterator1, typename Iterator2>
  inline ResultType operator()(Iterator1 a, Iterator2 b, size_t size) const
  {
    ResultType result = ResultType();
    ResultType diff;
    for(size_t i = 0; i < size; ++i ) {
      diff = *a++ - *b++;
      result += diff*diff;
    }
    return result;
  }
};

/// Squared Euclidean distance functor (vectorized version)
template<class T>
struct L2_Vectorized
{
  typedef T ElementType;
  typedef typename Accumulator<T>::Type ResultType;

  template <typename Iterator1, typename Iterator2>
  inline ResultType operator()(Iterator1 a, Iterator2 b, size_t size) const
  {
    ResultType result = ResultType();
    ResultType diff0, diff1, diff2, diff3;
    Iterator1 last = a + size;
    Iterator1 lastgroup = last - 3;

    // Process 4 items with each loop for efficiency.
    while (a < lastgroup) {
      diff0 = a[0] - b[0];
      diff1 = a[1] - b[1];
      diff2 = a[2] - b[2];
      diff3 = a[3] - b[3];
      result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
      a += 4;
      b += 4;
    }
    // Process last 0-3 pixels.  Not needed for standard vector lengths.
    while (a < last) {
      diff0 = *a++ - *b++;
      result += diff0 * diff0;
    }
    return result;
  }
};

#ifdef OPENVMG_USE_SSE

namespace optim_ss2{

#include <xmmintrin.h>

  /// Union to switch between SSE and float array
  union sseRegisterHelper
  {
      __m128 m;
      float f[4];
  };

  // Euclidean distance (SSE method) (squared result)
  inline float l2_sse(float * b1, float * b2, int size)
  {
    float* b1Pt = (float*)b1;
    float* b2Pt = (float*)b2;
    if(size%4 == 0)
    {
      __m128 srcA, srcB, temp, cumSum;
      float zeros[4] = {0.f,0.f,0.f,0.f};
      cumSum = _mm_load_ps( zeros );
      for(int i = 0 ; i < size; i+=4)
      {
        srcA = _mm_load_ps(b1Pt+i);
        srcB = _mm_load_ps(b2Pt+i);
        //-- Subtract
        temp = _mm_sub_ps( srcA, srcB );
        //-- Multiply
        temp =  _mm_mul_ps( temp, temp );
        //-- sum
        cumSum = _mm_add_ps( cumSum, temp );
      }
      sseRegisterHelper res;
      res.m = cumSum;
      return (res.f[0]+res.f[1]+res.f[2]+res.f[3]);
    }
    else
    {
      std::cerr <<"\n/!\\ size is not modulus 4,"
        << " distance cannot be performed in SSE"<< std::endl;
      return 0.0f;
    }
  }
} // namespace optim_ss2

// Template specification to run SSE L2 squared distance
//  on float vector
template<>
struct L2_Vectorized<float>
{
  typedef float ElementType;
  typedef Accumulator<float>::Type ResultType;

  template <typename Iterator1, typename Iterator2>
  inline ResultType operator()(Iterator1 a, Iterator2 b, size_t size) const
  {
    return optim_ss2::l2_sse(a,b,size);
  }
};

#endif // OPENVMG_USE_SSE

}  // namespace matching
}  // namespace openMVG

#endif // OPENMVG_MATCHING_METRIC_H
<commit_msg>[matching] Fix a typo in the preprocessor used to detect SSE support - This L2 distance specialization is only used for floating point based descriptors. - So the impact will be visible only if you are using AKAZE_FLOAT. - Fast experiments show that SSE distance can be up to 40% faster.<commit_after>
// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_MATCHING_METRIC_H
#define OPENMVG_MATCHING_METRIC_H

#include "openMVG/matching/metric_hamming.hpp"
#include "openMVG/numeric/accumulator_trait.hpp"
#include <cstddef>

namespace openMVG {
namespace matching {

/// Squared Euclidean distance functor.
template<class T>
struct L2_Simple
{
  typedef T ElementType;
  typedef typename Accumulator<T>::Type ResultType;

  template <typename Iterator1, typename Iterator2>
  inline ResultType operator()(Iterator1 a, Iterator2 b, size_t size) const
  {
    ResultType result = ResultType();
    ResultType diff;
    for(size_t i = 0; i < size; ++i ) {
      diff = *a++ - *b++;
      result += diff*diff;
    }
    return result;
  }
};

/// Squared Euclidean distance functor (vectorized version)
template<class T>
struct L2_Vectorized
{
  typedef T ElementType;
  typedef typename Accumulator<T>::Type ResultType;

  template <typename Iterator1, typename Iterator2>
  inline ResultType operator()(Iterator1 a, Iterator2 b, size_t size) const
  {
    ResultType result = ResultType();
    ResultType diff0, diff1, diff2, diff3;
    Iterator1 last = a + size;
    Iterator1 lastgroup = last - 3;

    // Process 4 items with each loop for efficiency.
    while (a < lastgroup) {
      diff0 = a[0] - b[0];
      diff1 = a[1] - b[1];
      diff2 = a[2] - b[2];
      diff3 = a[3] - b[3];
      result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
      a += 4;
      b += 4;
    }
    // Process last 0-3 pixels.  Not needed for standard vector lengths.
    while (a < last) {
      diff0 = *a++ - *b++;
      result += diff0 * diff0;
    }
    return result;
  }
};

#ifdef OPENMVG_USE_SSE

namespace optim_ss2{

#include <xmmintrin.h>

  /// Union to switch between SSE and float array
  union sseRegisterHelper
  {
      __m128 m;
      float f[4];
  };

  // Euclidean distance (SSE method) (squared result)
  inline float l2_sse(const float * b1, const float * b2, int size)
  {
    float* b1Pt = (float*)b1;
    float* b2Pt = (float*)b2;
    if(size%4 == 0)
    {
      __m128 srcA, srcB, temp, cumSum;
      float zeros[4] = {0.f,0.f,0.f,0.f};
      cumSum = _mm_load_ps( zeros );
      for(int i = 0 ; i < size; i+=4)
      {
        srcA = _mm_load_ps(b1Pt+i);
        srcB = _mm_load_ps(b2Pt+i);
        //-- Subtract
        temp = _mm_sub_ps( srcA, srcB );
        //-- Multiply
        temp =  _mm_mul_ps( temp, temp );
        //-- sum
        cumSum = _mm_add_ps( cumSum, temp );
      }
      sseRegisterHelper res;
      res.m = cumSum;
      return (res.f[0]+res.f[1]+res.f[2]+res.f[3]);
    }
    else
    {
      std::cerr <<"\n/!\\ size is not modulus 4,"
        << " distance cannot be performed in SSE"<< std::endl;
      return 0.0f;
    }
  }
} // namespace optim_ss2

// Template specification to run SSE L2 squared distance
//  on float vector
template<>
struct L2_Vectorized<float>
{
  typedef float ElementType;
  typedef Accumulator<float>::Type ResultType;

  template <typename Iterator1, typename Iterator2>
  inline ResultType operator()(Iterator1 a, Iterator2 b, size_t size) const
  {
    return optim_ss2::l2_sse(a,b,size);
  }
};

#endif // OPENMVG_USE_SSE

}  // namespace matching
}  // namespace openMVG

#endif // OPENMVG_MATCHING_METRIC_H
<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(n)

// Binary search solution with STL.
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> LIS;

        for (const auto& num : nums) {
            insert(&LIS, num);
        }

        return LIS.size();
    }

private:
    void insert(vector<int> *LIS, const int target) {
        // Find the first index "left" which satisfies LIS[left] >= target
        auto it = lower_bound(LIS->begin(), LIS->end(), target);

        // If not found, append the target.
        if (it != LIS->end()) {
            *it = target;
        } else {
            LIS->emplace_back(target);
        }
    }
};

// Binary search solution.
class Solution2 {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> LIS;

        for (const auto& num : nums) {
            insert(&LIS, num);
        }

        return LIS.size();
    }

private:
    void insert(vector<int> *LIS, const int target) {
        int left = 0, right = LIS->size() - 1;
        auto comp = [](int x, int target) { return x >= target; };

        // Find the first index "left" which satisfies LIS[left] >= target
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (comp((*LIS)[mid], target)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }

        // If not found, append the target.
        if (left == LIS->size()) {
            LIS->emplace_back(target);
        } else {
            (*LIS)[left] = target;
        }
    }
};

// Time:  O(n^2)
// Space: O(n)
// Traditional DP solution.
class Solution3 {
public:
    int lengthOfLIS(vector<int>& nums) {
        const int n = nums.size();
        vector<int> dp(n, 1);
        int res = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (nums[j] < nums[i]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            res = max(res, dp[i]);
        }
        return res;
    }
};
<commit_msg>Update longest-increasing-subsequence.cpp<commit_after>// Time:  O(nlogn)
// Space: O(n)

// Binary search solution with STL.
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> LIS;

        for (const auto& num : nums) {
            insert(&LIS, num);
        }

        return LIS.size();
    }

private:
    void insert(vector<int> *LIS, const int target) {
        // Find the first index "left" which satisfies LIS[left] >= target
        auto it = lower_bound(LIS->begin(), LIS->end(), target);

        // If not found, append the target.
        if (it != LIS->end()) {
            *it = target;
        } else {
            LIS->emplace_back(target);
        }
    }
};

// Binary search solution.
class Solution2 {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> LIS;

        for (const auto& num : nums) {
            insert(&LIS, num);
        }

        return LIS.size();
    }

private:
    void insert(vector<int> *LIS, const int target) {
        int left = 0, right = LIS->size() - 1;
        auto comp = [](int x, int target) { return x >= target; };

        // Find the first index "left" which satisfies LIS[left] >= target
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (comp((*LIS)[mid], target)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }

        // If not found, append the target.
        if (left == LIS->size()) {
            LIS->emplace_back(target);
        } else {
            (*LIS)[left] = target;
        }
    }
};

// Time:  O(n^2)
// Space: O(n)
// Traditional DP solution.
class Solution3 {
public:
    int lengthOfLIS(vector<int>& nums) {
        const int n = nums.size();
        vector<int> dp(n, 1);  // dp[i]: the length of LIS ends with nums[i]
        int res = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (nums[j] < nums[i]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            res = max(res, dp[i]);
        }
        return res;
    }
};
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Facebook, Inc.
 *
 * 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 <folly/ThreadLocal.h>

namespace folly { namespace threadlocal_detail {

PthreadKeyUnregister PthreadKeyUnregister::instance_;

}}
<commit_msg>Add MAX_STATIC_CONSTRUCTOR_PRIORITY to PthreadKeyUnregister<commit_after>/*
 * Copyright 2015 Facebook, Inc.
 *
 * 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 <folly/ThreadLocal.h>

namespace folly { namespace threadlocal_detail {

MAX_STATIC_CONSTRUCTOR_PRIORITY
PthreadKeyUnregister PthreadKeyUnregister::instance_;

}}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <memory>
#include <thread>

#include <folly/Function.h>
#include <folly/SharedMutex.h>
#include <folly/Singleton.h>
#include <folly/executors/CPUThreadPoolExecutor.h>
#include <folly/executors/GlobalExecutor.h>
#include <folly/executors/IOExecutor.h>
#include <folly/executors/IOThreadPoolExecutor.h>
#include <folly/system/HardwareConcurrency.h>

using namespace folly;

namespace {

class GlobalTag {};

// aka InlineExecutor
class DefaultCPUExecutor : public Executor {
 public:
  FOLLY_NOINLINE void add(Func f) override {
    f();
  }
};

Singleton<std::shared_ptr<DefaultCPUExecutor>> gDefaultGlobalCPUExecutor([] {
  return new std::shared_ptr<DefaultCPUExecutor>(new DefaultCPUExecutor{});
});

Singleton<std::shared_ptr<CPUThreadPoolExecutor>, GlobalTag>
    gImmutableGlobalCPUExecutor([] {
      return new std::shared_ptr<CPUThreadPoolExecutor>(
          new CPUThreadPoolExecutor(
              folly::hardware_concurrency(),
              std::make_shared<NamedThreadFactory>("GlobalCPUThreadPool")));
    });

Singleton<std::shared_ptr<IOThreadPoolExecutor>, GlobalTag>
    gImmutableGlobalIOExecutor([] {
      return new std::shared_ptr<IOThreadPoolExecutor>(new IOThreadPoolExecutor(
          folly::hardware_concurrency(),
          std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")));
    });

template <class ExecutorBase>
std::shared_ptr<ExecutorBase> getImmutable();

template <>
std::shared_ptr<Executor> getImmutable() {
  if (auto executorPtrPtr = gImmutableGlobalCPUExecutor.try_get()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <>
std::shared_ptr<IOExecutor> getImmutable() {
  if (auto executorPtrPtr = gImmutableGlobalIOExecutor.try_get()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <class ExecutorBase>
class GlobalExecutor {
 public:
  explicit GlobalExecutor(
      Function<std::shared_ptr<ExecutorBase>()> constructDefault)
      : getDefault_(std::move(constructDefault)) {}

  std::shared_ptr<ExecutorBase> get() {
    SharedMutex::ReadHolder guard(mutex_);
    if (auto executor = executor_.lock()) {
      return executor; // Fast path.
    }

    return getDefault_();
  }

  void set(std::weak_ptr<ExecutorBase> executor) {
    SharedMutex::WriteHolder guard(mutex_);
    executor_.swap(executor);
  }

  // Replace the constructDefault function to use the immutable singleton
  // rather than the default singleton
  void setFromImmutable() {
    SharedMutex::WriteHolder guard(mutex_);

    getDefault_ = [] { return getImmutable<ExecutorBase>(); };
    executor_ = std::weak_ptr<ExecutorBase>{};
  }

 private:
  SharedMutex mutex_;
  std::weak_ptr<ExecutorBase> executor_;
  Function<std::shared_ptr<ExecutorBase>()> getDefault_;
};

LeakySingleton<GlobalExecutor<Executor>> gGlobalCPUExecutor([] {
  return new GlobalExecutor<Executor>(
      // Default global CPU executor is an InlineExecutor.
      [] {
        if (auto executorPtrPtr = gDefaultGlobalCPUExecutor.try_get()) {
          return *executorPtrPtr;
        }
        return std::shared_ptr<DefaultCPUExecutor>{};
      });
});

LeakySingleton<GlobalExecutor<IOExecutor>> gGlobalIOExecutor([] {
  return new GlobalExecutor<IOExecutor>(
      // Default global IO executor is an IOThreadPoolExecutor.
      [] { return getImmutable<IOExecutor>(); });
});

} // namespace

namespace folly {

Executor::KeepAlive<> getGlobalCPUExecutor() {
  auto executorPtr = getImmutable<Executor>();
  if (!executorPtr) {
    throw std::runtime_error("Requested global CPU executor during shutdown.");
  }
  return folly::getKeepAliveToken(executorPtr.get());
}

Executor::KeepAlive<> getGlobalIOExecutor() {
  auto executorPtr = getImmutable<IOExecutor>();
  if (!executorPtr) {
    throw std::runtime_error("Requested global IO executor during shutdown.");
  }
  return folly::getKeepAliveToken(executorPtr.get());
}

std::shared_ptr<Executor> getCPUExecutor() {
  auto& singleton = gGlobalCPUExecutor.get();
  return singleton.get();
}

void setCPUExecutorToGlobalCPUExecutor() {
  gGlobalCPUExecutor.get().setFromImmutable();
}

void setCPUExecutor(std::weak_ptr<Executor> executor) {
  gGlobalCPUExecutor.get().set(std::move(executor));
}

std::shared_ptr<IOExecutor> getIOExecutor() {
  return gGlobalIOExecutor.get().get();
}

void setIOExecutor(std::weak_ptr<IOExecutor> executor) {
  gGlobalIOExecutor.get().set(std::move(executor));
}

EventBase* getEventBase() {
  auto executor = getIOExecutor();
  if (FOLLY_LIKELY(!!executor)) {
    return executor->getEventBase();
  }

  return nullptr;
}

} // namespace folly
<commit_msg>Add tracing to global executors<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <memory>
#include <thread>

#include <folly/Function.h>
#include <folly/SharedMutex.h>
#include <folly/Singleton.h>
#include <folly/detail/AsyncTrace.h>
#include <folly/executors/CPUThreadPoolExecutor.h>
#include <folly/executors/GlobalExecutor.h>
#include <folly/executors/IOExecutor.h>
#include <folly/executors/IOThreadPoolExecutor.h>
#include <folly/system/HardwareConcurrency.h>

using namespace folly;

namespace {

class GlobalTag {};

// aka InlineExecutor
class DefaultCPUExecutor : public Executor {
 public:
  FOLLY_NOINLINE void add(Func f) override {
    f();
  }
};

Singleton<std::shared_ptr<DefaultCPUExecutor>> gDefaultGlobalCPUExecutor([] {
  return new std::shared_ptr<DefaultCPUExecutor>(new DefaultCPUExecutor{});
});

Singleton<std::shared_ptr<CPUThreadPoolExecutor>, GlobalTag>
    gImmutableGlobalCPUExecutor([] {
      return new std::shared_ptr<CPUThreadPoolExecutor>(
          new CPUThreadPoolExecutor(
              folly::hardware_concurrency(),
              std::make_shared<NamedThreadFactory>("GlobalCPUThreadPool")));
    });

Singleton<std::shared_ptr<IOThreadPoolExecutor>, GlobalTag>
    gImmutableGlobalIOExecutor([] {
      return new std::shared_ptr<IOThreadPoolExecutor>(new IOThreadPoolExecutor(
          folly::hardware_concurrency(),
          std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")));
    });

template <class ExecutorBase>
std::shared_ptr<ExecutorBase> getImmutable();

template <>
std::shared_ptr<Executor> getImmutable() {
  if (auto executorPtrPtr = gImmutableGlobalCPUExecutor.try_get()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <>
std::shared_ptr<IOExecutor> getImmutable() {
  if (auto executorPtrPtr = gImmutableGlobalIOExecutor.try_get()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <class ExecutorBase>
class GlobalExecutor {
 public:
  explicit GlobalExecutor(
      Function<std::shared_ptr<ExecutorBase>()> constructDefault)
      : getDefault_(std::move(constructDefault)) {}

  std::shared_ptr<ExecutorBase> get() {
    SharedMutex::ReadHolder guard(mutex_);
    if (auto executor = executor_.lock()) {
      return executor; // Fast path.
    }

    return getDefault_();
  }

  void set(std::weak_ptr<ExecutorBase> executor) {
    SharedMutex::WriteHolder guard(mutex_);
    executor_.swap(executor);
  }

  // Replace the constructDefault function to use the immutable singleton
  // rather than the default singleton
  void setFromImmutable() {
    SharedMutex::WriteHolder guard(mutex_);

    getDefault_ = [] { return getImmutable<ExecutorBase>(); };
    executor_ = std::weak_ptr<ExecutorBase>{};
  }

 private:
  SharedMutex mutex_;
  std::weak_ptr<ExecutorBase> executor_;
  Function<std::shared_ptr<ExecutorBase>()> getDefault_;
};

LeakySingleton<GlobalExecutor<Executor>> gGlobalCPUExecutor([] {
  return new GlobalExecutor<Executor>(
      // Default global CPU executor is an InlineExecutor.
      [] {
        if (auto executorPtrPtr = gDefaultGlobalCPUExecutor.try_get()) {
          return *executorPtrPtr;
        }
        return std::shared_ptr<DefaultCPUExecutor>{};
      });
});

LeakySingleton<GlobalExecutor<IOExecutor>> gGlobalIOExecutor([] {
  return new GlobalExecutor<IOExecutor>(
      // Default global IO executor is an IOThreadPoolExecutor.
      [] { return getImmutable<IOExecutor>(); });
});

} // namespace

namespace folly {

Executor::KeepAlive<> getGlobalCPUExecutor() {
  auto executorPtr = getImmutable<Executor>();
  if (!executorPtr) {
    throw std::runtime_error("Requested global CPU executor during shutdown.");
  }
  async_tracing::logGetImmutableCPUExecutor(executorPtr.get());
  return folly::getKeepAliveToken(executorPtr.get());
}

Executor::KeepAlive<> getGlobalIOExecutor() {
  auto executorPtr = getImmutable<IOExecutor>();
  if (!executorPtr) {
    throw std::runtime_error("Requested global IO executor during shutdown.");
  }
  async_tracing::logGetImmutableIOExecutor(executorPtr.get());
  return folly::getKeepAliveToken(executorPtr.get());
}

std::shared_ptr<Executor> getCPUExecutor() {
  auto& singleton = gGlobalCPUExecutor.get();
  auto executor = singleton.get();
  async_tracing::logGetGlobalCPUExecutor(executor.get());
  return executor;
}

void setCPUExecutorToGlobalCPUExecutor() {
  async_tracing::logSetGlobalCPUExecutorToImmutable();
  gGlobalCPUExecutor.get().setFromImmutable();
}

void setCPUExecutor(std::weak_ptr<Executor> executor) {
  async_tracing::logSetGlobalCPUExecutor(executor.lock().get());
  gGlobalCPUExecutor.get().set(std::move(executor));
}

std::shared_ptr<IOExecutor> getIOExecutor() {
  auto& singleton = gGlobalIOExecutor.get();
  auto executor = singleton.get();
  async_tracing::logGetGlobalCPUExecutor(executor.get());
  return executor;
}

void setIOExecutor(std::weak_ptr<IOExecutor> executor) {
  async_tracing::logSetGlobalIOExecutor(executor.lock().get());
  gGlobalIOExecutor.get().set(std::move(executor));
}

EventBase* getEventBase() {
  auto executor = getIOExecutor();
  if (FOLLY_LIKELY(!!executor)) {
    return executor->getEventBase();
  }

  return nullptr;
}

} // namespace folly
<|endoftext|>


<commit_before>//==============================================================================
// ASM76/VM.cpp
//==============================================================================
// Virtual Machine
//==============================================================================

#include "ASM76.hpp"

namespace ASM76 {

	uint8_t* global_memory;

	void init_environment() {
		// 4MB program useable
		// 12MB IO interface
		printf("Init ASM76 env\n");
		global_memory = new uint8_t[0x1000000];
		memset(global_memory, 0, 0x1000000);
	}

	VM::VM(Instruct* program, size_t prg_size) {
		// 16K local memory in default
		local_memory = new uint8_t[local_mem_size];
		memset(local_memory, 0, local_mem_size);
		instruct_memory = (Instruct*) local_memory;
		printf("init memory with program sized %zu\n", prg_size);
		memcpy(instruct_memory, program, prg_size);

		// 99 registers
		reg = new uint8_t[100];
		memset(reg, 0, 99);

		// Setup registers
		// Instruction pointer
		REG(uint32_t, 86) = 0x1000000;
		// Stack bottom pointer
		REG(uint32_t, 90) = 0x1003000;

		REG86 = (uint32_t*) (reg + 86);
		REG90 = (uint32_t*) (reg + 90);
		REG97 = (uint8_t*) (reg + 97);
		REG98 = (uint8_t*) (reg + 98);
		REG99 = (uint8_t*) (reg + 99);
	}

	#define OPC(code) (now->opcode == code)

	void VM::execute() {
		Instruct* now = memfetch<Instruct>(*REG86);
		while (!OPC(_HLT)) {
			printf("%x : %x, %x, %x\n", *REG86, now->opcode, now->f, now->t);

			// ===========================
			//  76-Base
			// ===========================
			// LCMM
			if OPC(LCMM) {
				uint8_t* new_mem = new uint8_t[now->f];
				memset(new_mem, 0, now->f);
				size_t copied_size = now->f < local_mem_size ? now->f : local_mem_size;
				memcpy(new_mem, local_memory, copied_size);
				free(local_memory);
				local_mem_size = now->f;
				local_memory = new_mem;
				instruct_memory = (Instruct*) new_mem;

				printf("Changed local size to %zu bytes\n", local_mem_size);
			}
			// Load Data
			else if OPC(LDLA) {
				REG(uint64_t, now->t) = *memfetch<uint64_t>(now->f);
			} else if OPC(LDIA) {
				REG(uint32_t, now->t) = *memfetch<uint32_t>(now->f);
			} else if OPC(LDBA) {
				REG(uint8_t, now->t) = *memfetch<uint8_t>(now->f);
			} else if OPC(LDLR) {
				REG(uint64_t, now->t) = *memfetch<uint64_t>(REG(uint32_t, now->f));
			} else if OPC(LDIR) {
				REG(uint32_t, now->t) = *memfetch<uint32_t>(REG(uint32_t, now->f));
			} else if OPC(LDBR) {
				REG(uint8_t, now->t) = *memfetch<uint8_t>(REG(uint32_t, now->f));
			}
			// Store data
			else if OPC(SLLA) {
				*memfetch<uint64_t>(now->f) = REG(uint64_t, now->t);
			} else if OPC(SLIA) {
				*memfetch<uint32_t>(now->f) = REG(uint32_t, now->t);
			} else if OPC(SLBA) {
				*memfetch<uint8_t>(now->f) = REG(uint8_t, now->t);
			} else if OPC(SLLR) {
				*memfetch<uint64_t>(REG(uint32_t, now->f)) = REG(uint64_t, now->t);
			} else if OPC(SLIR) {
				*memfetch<uint32_t>(REG(uint32_t, now->f)) = REG(uint32_t, now->t);
			} else if OPC(SLBR) {
				*memfetch<uint8_t>(REG(uint32_t, now->f)) = REG(uint8_t, now->t);
			} else if OPC(DATI) {
				REG(uint32_t, now->t) = (uint32_t) now->f;
			} else if OPC(DATB) {
				REG(uint8_t, now->t) = (uint8_t) now->f;
			}
			// Mem operation
			else if OPC(MOVL) {
				*memfetch<uint64_t>(now->t) = *memfetch<uint64_t>(now->f);
			} else if OPC(MOVI) {
				*memfetch<uint32_t>(now->t) = *memfetch<uint32_t>(now->f);
			} else if OPC(MOVB) {
				*memfetch<uint8_t>(now->t) = *memfetch<uint8_t>(now->f);
			} else if OPC(MVPL) {
				*memfetch<uint64_t>(REG(uint32_t, now->t)) = *memfetch<uint64_t>(REG(uint32_t, now->f));
			} else if OPC(MVPI) {
				*memfetch<uint32_t>(REG(uint32_t, now->t)) = *memfetch<uint32_t>(REG(uint32_t, now->f));
			} else if OPC(MVPB) {
				*memfetch<uint8_t>(REG(uint32_t, now->t)) = *memfetch<uint8_t>(REG(uint32_t, now->f));
			} else if OPC(MVRL) {
				REG(uint64_t, now->t) = REG(uint64_t, now->f);
			} else if OPC(MVRI) {
				REG(uint32_t, now->t) = REG(uint32_t, now->f);
			} else if OPC(MVRB) {
				REG(uint8_t, now->t) = REG(uint8_t, now->f);
			}
			// Basic Algebra
			else if OPC(ADDL) {
				REG(uint64_t, now->f) += REG(uint64_t, now->t);
			} else if OPC(ADDI) {
				REG(uint32_t, now->f) += REG(uint32_t, now->t);
			} else if OPC(ADDB) {
				REG(uint8_t, now->f) += REG(uint8_t, now->t);
			} else if OPC(MINL) {
				REG(uint64_t, now->f) -= REG(uint64_t, now->t);
			} else if OPC(MINI) {
				REG(uint32_t, now->f) -= REG(uint32_t, now->t);
			} else if OPC(MINB) {
				REG(uint8_t, now->f) -= REG(uint8_t, now->t);
			} else if OPC(MTPL) {
				REG(uint64_t, now->f) *= REG(uint64_t, now->t);
			} else if OPC(MTPI) {
				REG(uint32_t, now->f) *= REG(uint32_t, now->t);
			} else if OPC(MTPB) {
				REG(uint8_t, now->f) *= REG(uint8_t, now->t);
			} else if OPC(DIVL) {
				REG(uint64_t, now->f) /= REG(uint64_t, now->t);
			} else if OPC(DIVI) {
				REG(uint32_t, now->f) /= REG(uint32_t, now->t);
			} else if OPC(DIVB) {
				REG(uint8_t, now->f) /= REG(uint8_t, now->t);
			} else if OPC(MODL) {
				REG(uint64_t, now->f) = REG(uint64_t, now->f) % REG(uint64_t, now->t);
			} else if OPC(MODI) {
				REG(uint32_t, now->f) = REG(uint32_t, now->t) % REG(uint32_t, now->t);
			} else if OPC(MODB) {
				REG(uint8_t, now->f) = REG(uint8_t, now->t) % REG(uint8_t, now->t);
			}
			// ===========================
			//  Logistics & Flow control
			// ===========================
			if (now->opcode >= ANDL) {
				if OPC(ANDL) {

				}
			}

			*REG86 += sizeof(Instruct);
			now = memfetch<Instruct>(*REG86);
		}
	}

	void VM::dump_registers() {
		printf("Registers: \n");
		for (int i = 1; i < 100; i++) {
			printf("%02x ", reg[i]);
			if (i % 10 == 0) printf("\n");
		}
		printf("\n");
	}

	void VM::dump_memory() {
		printf("Local Memory: \n");
		for (uint32_t i = 1; i < local_mem_size / 8; i++) {
			printf("%08x ", *((uint32_t*)local_memory + i));
			if (i % 8 == 0) printf("\n");
		}
		printf("\n");
	}

	char* VM::decompile(Instruct* prg) {
		return NULL;
	}

	Instruct* VM::compile(const char* prg) {
		return NULL;
	}

	VM::~VM() {
		free(local_memory);
		free(reg);
	}

}
<commit_msg>完成逻辑运算和CMP<commit_after>//==============================================================================
// ASM76/VM.cpp
//==============================================================================
// Virtual Machine
//==============================================================================

#include "ASM76.hpp"

namespace ASM76 {

	uint8_t* global_memory;

	void init_environment() {
		// 4MB program useable
		// 12MB IO interface
		printf("Init ASM76 env\n");
		global_memory = new uint8_t[0x1000000];
		memset(global_memory, 0, 0x1000000);
	}

	VM::VM(Instruct* program, size_t prg_size) {
		// 16K local memory in default
		local_memory = new uint8_t[local_mem_size];
		memset(local_memory, 0, local_mem_size);
		instruct_memory = (Instruct*) local_memory;
		printf("init memory with program sized %zu\n", prg_size);
		memcpy(instruct_memory, program, prg_size);

		// 99 registers
		reg = new uint8_t[100];
		memset(reg, 0, 99);

		// Setup registers
		// Instruction pointer
		REG(uint32_t, 86) = 0x1000000;
		// Stack bottom pointer
		REG(uint32_t, 90) = 0x1003000;

		REG86 = (uint32_t*) (reg + 86);
		REG90 = (uint32_t*) (reg + 90);
		REG97 = (uint8_t*) (reg + 97);
		REG98 = (uint8_t*) (reg + 98);
		REG99 = (uint8_t*) (reg + 99);
	}

	#define OPC(code) (now->opcode == code)

	void VM::execute() {
		Instruct* now = memfetch<Instruct>(*REG86);
		while (!OPC(_HLT)) {
			printf("%08x : %04x, %x, %x\n", *REG86, now->opcode, now->f, now->t);

			// ===========================
			//  76-Base
			// ===========================
			// LCMM
			if OPC(LCMM) {
				uint8_t* new_mem = new uint8_t[now->f];
				memset(new_mem, 0, now->f);
				size_t copied_size = now->f < local_mem_size ? now->f : local_mem_size;
				memcpy(new_mem, local_memory, copied_size);
				free(local_memory);
				local_mem_size = now->f;
				local_memory = new_mem;
				instruct_memory = (Instruct*) new_mem;

				printf("Changed local size to %zu bytes\n", local_mem_size);
			}
			// Load Data
			else if OPC(LDLA) {
				REG(uint64_t, now->t) = *memfetch<uint64_t>(now->f);
			} else if OPC(LDIA) {
				REG(uint32_t, now->t) = *memfetch<uint32_t>(now->f);
			} else if OPC(LDBA) {
				REG(uint8_t, now->t) = *memfetch<uint8_t>(now->f);
			} else if OPC(LDLR) {
				REG(uint64_t, now->t) = *memfetch<uint64_t>(REG(uint32_t, now->f));
			} else if OPC(LDIR) {
				REG(uint32_t, now->t) = *memfetch<uint32_t>(REG(uint32_t, now->f));
			} else if OPC(LDBR) {
				REG(uint8_t, now->t) = *memfetch<uint8_t>(REG(uint32_t, now->f));
			}
			// Store data
			else if OPC(SLLA) {
				*memfetch<uint64_t>(now->f) = REG(uint64_t, now->t);
			} else if OPC(SLIA) {
				*memfetch<uint32_t>(now->f) = REG(uint32_t, now->t);
			} else if OPC(SLBA) {
				*memfetch<uint8_t>(now->f) = REG(uint8_t, now->t);
			} else if OPC(SLLR) {
				*memfetch<uint64_t>(REG(uint32_t, now->f)) = REG(uint64_t, now->t);
			} else if OPC(SLIR) {
				*memfetch<uint32_t>(REG(uint32_t, now->f)) = REG(uint32_t, now->t);
			} else if OPC(SLBR) {
				*memfetch<uint8_t>(REG(uint32_t, now->f)) = REG(uint8_t, now->t);
			} else if OPC(DATI) {
				REG(uint32_t, now->t) = (uint32_t) now->f;
			} else if OPC(DATB) {
				REG(uint8_t, now->t) = (uint8_t) now->f;
			}
			// Mem operation
			else if OPC(MOVL) {
				*memfetch<uint64_t>(now->t) = *memfetch<uint64_t>(now->f);
			} else if OPC(MOVI) {
				*memfetch<uint32_t>(now->t) = *memfetch<uint32_t>(now->f);
			} else if OPC(MOVB) {
				*memfetch<uint8_t>(now->t) = *memfetch<uint8_t>(now->f);
			} else if OPC(MVPL) {
				*memfetch<uint64_t>(REG(uint32_t, now->t)) = *memfetch<uint64_t>(REG(uint32_t, now->f));
			} else if OPC(MVPI) {
				*memfetch<uint32_t>(REG(uint32_t, now->t)) = *memfetch<uint32_t>(REG(uint32_t, now->f));
			} else if OPC(MVPB) {
				*memfetch<uint8_t>(REG(uint32_t, now->t)) = *memfetch<uint8_t>(REG(uint32_t, now->f));
			} else if OPC(MVRL) {
				REG(uint64_t, now->t) = REG(uint64_t, now->f);
			} else if OPC(MVRI) {
				REG(uint32_t, now->t) = REG(uint32_t, now->f);
			} else if OPC(MVRB) {
				REG(uint8_t, now->t) = REG(uint8_t, now->f);
			}
			// Basic Algebra
			else if OPC(ADDL) {
				REG(uint64_t, now->f) += REG(uint64_t, now->t);
			} else if OPC(ADDI) {
				REG(uint32_t, now->f) += REG(uint32_t, now->t);
			} else if OPC(ADDB) {
				REG(uint8_t, now->f) += REG(uint8_t, now->t);
			} else if OPC(MINL) {
				REG(uint64_t, now->f) -= REG(uint64_t, now->t);
			} else if OPC(MINI) {
				REG(uint32_t, now->f) -= REG(uint32_t, now->t);
			} else if OPC(MINB) {
				REG(uint8_t, now->f) -= REG(uint8_t, now->t);
			} else if OPC(MTPL) {
				REG(uint64_t, now->f) *= REG(uint64_t, now->t);
			} else if OPC(MTPI) {
				REG(uint32_t, now->f) *= REG(uint32_t, now->t);
			} else if OPC(MTPB) {
				REG(uint8_t, now->f) *= REG(uint8_t, now->t);
			} else if OPC(DIVL) {
				REG(uint64_t, now->f) /= REG(uint64_t, now->t);
			} else if OPC(DIVI) {
				REG(uint32_t, now->f) /= REG(uint32_t, now->t);
			} else if OPC(DIVB) {
				REG(uint8_t, now->f) /= REG(uint8_t, now->t);
			} else if OPC(MODL) {
				REG(uint64_t, now->f) = REG(uint64_t, now->f) % REG(uint64_t, now->t);
			} else if OPC(MODI) {
				REG(uint32_t, now->f) = REG(uint32_t, now->t) % REG(uint32_t, now->t);
			} else if OPC(MODB) {
				REG(uint8_t, now->f) = REG(uint8_t, now->t) % REG(uint8_t, now->t);
			}
			// ===========================
			//  Logistics & Flow control
			// ===========================
			if (now->opcode >= ANDL) {
				if OPC(ANDL) {
					REG(uint64_t, now->f) &= REG(uint64_t, now->t);
				} else if OPC(ANDI) {
					REG(uint32_t, now->f) &= REG(uint32_t, now->t);
				} else if OPC(ANDB) {
					REG(uint8_t, now->f) &= REG(uint8_t, now->t);
				} else if OPC(OR_L) {
					REG(uint64_t, now->f) |= REG(uint64_t, now->t);
				} else if OPC(OR_I) {
					REG(uint32_t, now->f) |= REG(uint32_t, now->t);
				} else if OPC(OR_B) {
					REG(uint8_t, now->f) |= REG(uint8_t, now->t);
				} else if OPC(NOTL) {
					REG(uint64_t, now->f) = !(REG(uint64_t, now->f));
				} else if OPC(NOTI) {
					REG(uint32_t, now->f) = !(REG(uint32_t, now->f));
				} else if OPC(NOTB) {
					REG(uint8_t, now->f) = !(REG(uint8_t, now->f));
				} else if OPC(XORL) {
					REG(uint64_t, now->f) ^= (REG(uint64_t, now->f));
				} else if OPC(XORI) {
					REG(uint32_t, now->f) ^= (REG(uint32_t, now->f));
				} else if OPC(XORB) {
					REG(uint8_t, now->f) ^= (REG(uint8_t, now->f));
				} else if OPC(CMPL) {
					if (REG(uint64_t, now->f) > REG(uint64_t, now->t)) {
						*REG99 = 0xFF; *REG98 = 0x0; *REG97 = 0x0;
					} else if (REG(uint64_t, now->f) == REG(uint64_t, now->t)) {
						*REG99 = 0x0; *REG98 = 0xFF; *REG97 = 0x0;
					} else {
						*REG99 = 0x0; *REG98 = 0x0; *REG97 = 0xFF;
					}
				} else if OPC(CMPI) {
					if (REG(uint32_t, now->f) > REG(uint32_t, now->t)) {
						*REG99 = 0xFF; *REG98 = 0x0; *REG97 = 0x0;
					} else if (REG(uint32_t, now->f) == REG(uint32_t, now->t)) {
						*REG99 = 0x0; *REG98 = 0xFF; *REG97 = 0x0;
					} else {
						*REG99 = 0x0; *REG98 = 0x0; *REG97 = 0xFF;
					}
				} else if OPC(CMPB) {
					if (REG(uint8_t, now->f) > REG(uint8_t, now->t)) {
						*REG99 = 0xFF; *REG98 = 0x0; *REG97 = 0x0;
					} else if (REG(uint8_t, now->f) == REG(uint8_t, now->t)) {
						*REG99 = 0x0; *REG98 = 0xFF; *REG97 = 0x0;
					} else {
						*REG99 = 0x0; *REG98 = 0x0; *REG97 = 0xFF;
					}
				}
			}

			*REG86 += sizeof(Instruct);
			now = memfetch<Instruct>(*REG86);
		}
	}

	void VM::dump_registers() {
		printf("Registers: \n");
		for (int i = 1; i < 100; i++) {
			printf("%02x ", reg[i]);
			if (i % 10 == 0) printf("\n");
		}
		printf("\n");
	}

	void VM::dump_memory() {
		printf("Local Memory: \n");
		for (uint32_t i = 1; i < local_mem_size / 8; i++) {
			printf("%08x ", *((uint32_t*)local_memory + i));
			if (i % 8 == 0) printf("\n");
		}
		printf("\n");
	}

	char* VM::decompile(Instruct* prg) {
		return NULL;
	}

	Instruct* VM::compile(const char* prg) {
		return NULL;
	}

	VM::~VM() {
		free(local_memory);
		free(reg);
	}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: Numeric.hxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _FORMS_NUMERIC_HXX_
#define _FORMS_NUMERIC_HXX_

#include "EditBase.hxx"

//.........................................................................
namespace frm
{
//.........................................................................

//==================================================================
//= ONumericModel
//==================================================================
class ONumericModel
                :public OEditBaseModel
{
private:
    ::com::sun::star::uno::Any          m_aSaveValue;
protected:
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

public:
    DECLARE_DEFAULT_LEAF_XTOR( ONumericModel );

    // ::com::sun::star::lang::XServiceInfo
    IMPLEMENTATION_NAME(ONumericModel);
    virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // ::com::sun::star::io::XPersistObject
    virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException);

    // OControlModel's property handling
    virtual void describeFixedProperties(
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
    ) const;

protected:
    // OBoundControlModel overridables
    virtual ::com::sun::star::uno::Any
                            translateDbColumnToControlValue( );
    virtual sal_Bool        commitControlValueToDbColumn( bool _bPostReset );

    virtual ::com::sun::star::uno::Any
                            getDefaultForReset() const;

    virtual sal_Bool        approveValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding );

protected:
    DECLARE_XCLONEABLE();
};

//==================================================================
//= ONumericControl
//==================================================================
class ONumericControl: public OBoundControl
{
protected:
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

public:
    ONumericControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);

    // ::com::sun::star::lang::XServiceInfo
    IMPLEMENTATION_NAME(ONumericControl);
    virtual StringSequence SAL_CALL getSupportedServiceNames() throw();
};

//.........................................................................
}   // namespace frm
//.........................................................................

#endif // _FORMS_NUMERIC_HXX_

<commit_msg>INTEGRATION: CWS dba30d (1.10.18); FILE MERGED 2008/05/27 12:28:02 fs 1.10.18.1: #i89657# refactoring, so that our binding's getValue is only called when our mutex is not locked<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: Numeric.hxx,v $
 * $Revision: 1.11 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _FORMS_NUMERIC_HXX_
#define _FORMS_NUMERIC_HXX_

#include "EditBase.hxx"

//.........................................................................
namespace frm
{
//.........................................................................

//==================================================================
//= ONumericModel
//==================================================================
class ONumericModel
                :public OEditBaseModel
{
private:
    ::com::sun::star::uno::Any          m_aSaveValue;
protected:
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

public:
    DECLARE_DEFAULT_LEAF_XTOR( ONumericModel );

    // ::com::sun::star::lang::XServiceInfo
    IMPLEMENTATION_NAME(ONumericModel);
    virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // ::com::sun::star::io::XPersistObject
    virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException);

    // OControlModel's property handling
    virtual void describeFixedProperties(
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
    ) const;

protected:
    // OBoundControlModel overridables
    virtual ::com::sun::star::uno::Any
                            translateDbColumnToControlValue( );
    virtual sal_Bool        commitControlValueToDbColumn( bool _bPostReset );

    virtual ::com::sun::star::uno::Any
                            getDefaultForReset() const;

protected:
    DECLARE_XCLONEABLE();
};

//==================================================================
//= ONumericControl
//==================================================================
class ONumericControl: public OBoundControl
{
protected:
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

public:
    ONumericControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);

    // ::com::sun::star::lang::XServiceInfo
    IMPLEMENTATION_NAME(ONumericControl);
    virtual StringSequence SAL_CALL getSupportedServiceNames() throw();
};

//.........................................................................
}   // namespace frm
//.........................................................................

#endif // _FORMS_NUMERIC_HXX_

<|endoftext|>