<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 7/5/2020, 8:50:18 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

int main()
{
  ll n;
  cin >> n;
  vector<ll> u(n), v(n);
  for (auto i{0}; i < n - 1; ++i)
  {
    cin >> u[i] >> v[i];
    u[i]--;
    v[i]--;
    if (u[i] > v[i])
    {
      swap(u[i], v[i]);
    }
  }
  ll ans{n * n * (n - 1) / 2};
  for (auto i{0}; i < n - 1; ++i)
  {
    ans -= (u[i] + 1) * (n - v[i]);
  }
  cout << ans << endl;
}
<commit_msg>tried F.cpp to 'F'<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 7/5/2020, 8:50:18 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

int main()
{
  ll n;
  cin >> n;
  vector<ll> u(n), v(n);
  for (auto i{0}; i < n - 1; ++i)
  {
    cin >> u[i] >> v[i];
    u[i]--;
    v[i]--;
    if (u[i] > v[i])
    {
      swap(u[i], v[i]);
    }
  }
  ll Ne{0}, Nv{0};
  for (auto i{0}; i < n - 1; ++i)
  {
    Nv += (u[i] + 1) * (n - v[i]);
  }
#if DEBUG == 1
  cerr << "Nv = " << Nv << endl;
#endif
  cout << Nv - Ne << endl;
}
<|endoftext|>


<commit_before>#include "db.hh"
#include "redis_commands.hh"
namespace redis {

static constexpr double default_slab_growth_factor = 1.25;
static constexpr uint64_t default_slab_page_size = 1UL*MB;
static constexpr uint64_t default_per_cpu_slab_size = 512UL; // zero means reclaimer is enabled.
__thread slab_allocator<item>* _slab;
__thread redis_commands* _redis_commands_ptr;
db::db() : _store(new dict())
{
  _slab = new slab_allocator<item>(default_slab_growth_factor, default_per_cpu_slab_size, default_slab_page_size,
      [this](item& item_ref) {  });
  _redis_commands_ptr = new redis_commands();
}
db::~db()
{
  if (_store != nullptr) {
    delete _store;
  }
}

}
<commit_msg>add header for db.cc<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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 "db.hh"
#include "redis_commands.hh"
namespace redis {

static constexpr double default_slab_growth_factor = 1.25;
static constexpr uint64_t default_slab_page_size = 1UL*MB;
static constexpr uint64_t default_per_cpu_slab_size = 512UL; // zero means reclaimer is enabled.
__thread slab_allocator<item>* _slab;
__thread redis_commands* _redis_commands_ptr;
db::db() : _store(new dict())
{
  _slab = new slab_allocator<item>(default_slab_growth_factor, default_per_cpu_slab_size, default_slab_page_size,
      [this](item& item_ref) {  });
  _redis_commands_ptr = new redis_commands();
}
db::~db()
{
  if (_store != nullptr) {
    delete _store;
  }
}

}
<|endoftext|>


<commit_before>#include "VolumeOSD.h"

#include "..\SoundPlayer.h"

#include <string>

#include "..\HotkeyInfo.h"
#include "..\MeterWnd\Meters\CallbackMeter.h"
#include "..\Monitor.h"
#include "..\Skin.h"
#include "..\SkinManager.h"
#include "..\Slider\VolumeSlider.h"

#define MENU_SETTINGS 0
#define MENU_MIXER 1
#define MENU_EXIT 2
#define MENU_DEVICE 0xF000

VolumeOSD::VolumeOSD() :
OSD(L"3RVX-VolumeDispatcher"),
_mWnd(L"3RVX-MasterVolumeOSD", L"3RVX-MasterVolumeOSD"),
_muteWnd(L"3RVX-MasterMuteOSD", L"3RVX-MasterMuteOSD") {

    LoadSkin();
    Settings *settings = Settings::Instance();

    /* Start the volume controller */
    _volumeCtrl = new CoreAudio(_hWnd);
    std::wstring device = settings->AudioDeviceID();
    _volumeCtrl->Init(device);
    _selectedDesc = _volumeCtrl->DeviceDesc();

    /* Set up volume state variables */
    _lastVolume = _volumeCtrl->Volume();
    _muted = _volumeCtrl->Muted();

    if (settings->SoundEffectsEnabled()) {
        _sounds = true;
    }

    /* Create the slider */
    _volumeSlider = new VolumeSlider(*_volumeCtrl);

    /* Set up context menu */
    if (settings->NotifyIconEnabled()) {
        _menu = CreatePopupMenu();
        _deviceMenu = CreatePopupMenu();

        InsertMenu(_menu, -1, MF_ENABLED, MENU_SETTINGS, L"Settings");
        InsertMenu(_menu, -1, MF_POPUP, UINT(_deviceMenu), L"Audio Device");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_MIXER, L"Mixer");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_EXIT, L"Exit");

        _menuFlags = TPM_RIGHTBUTTON;
        if (GetSystemMetrics(SM_MENUDROPALIGNMENT) != 0) {
            _menuFlags |= TPM_RIGHTALIGN;
        } else {
            _menuFlags |= TPM_LEFTALIGN;
        }

        UpdateDeviceMenu();
    }

    _mWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _mWnd.VisibleDuration(settings->HideDelay());

    _muteWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _muteWnd.VisibleDuration(settings->HideDelay());

    UpdateIcon();
    float v = _volumeCtrl->Volume();
    MeterLevels(v);
    _volumeSlider->MeterLevels(v);

    /* TODO: check whether we should show the OSD on startup or not. If so, post
     * a MSG_VOL_CHNG so that the volume level (or mute) is displayed: */
    SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
}

VolumeOSD::~VolumeOSD() {
    DestroyMenu(_deviceMenu);
    DestroyMenu(_menu);
    delete _icon;
    delete _volumeSlider;
    delete _callbackMeter;
    _volumeCtrl->Dispose();
}

void VolumeOSD::UpdateDeviceMenu() {
    if (_menu == NULL || _deviceMenu == NULL) {
        return;
    }

    /* Remove any devices currently in the menu first */
    for (unsigned int i = 0; i < _deviceList.size(); ++i) {
        RemoveMenu(_deviceMenu, 0, MF_BYPOSITION);
    }
    _deviceList.clear();

    std::list<VolumeController::DeviceInfo> devices
        = _volumeCtrl->ListDevices();
    std::wstring currentDeviceId = _volumeCtrl->DeviceId();

    int menuItem = MENU_DEVICE;
    for (VolumeController::DeviceInfo device : devices) {
        unsigned int flags = MF_ENABLED;
        if (currentDeviceId == device.id) {
            flags |= MF_CHECKED;
        }

        InsertMenu(_deviceMenu, -1, flags, menuItem++, device.name.c_str());
        _deviceList.push_back(device);
    }
}

void VolumeOSD::LoadSkin() {
    Settings *settings = Settings::Instance();
    Skin *skin = SkinManager::Instance()->CurrentSkin();

    /* Volume OSD */
    /* TODO: should make sure this isn't NULL! */
    _mWnd.BackgroundImage(skin->volumeBackground);

    if (skin->volumeMask != NULL) {
        _mWnd.GlassMask(skin->volumeMask);
    }

    for (Meter *m : skin->volumeMeters) {
        _mWnd.AddMeter(m);
    }

    /* Add a callback meter with the default volume increment for sounds */
    _callbackMeter = new CallbackMeter(
        skin->DefaultVolumeUnits(), *this);
    _mWnd.AddMeter(_callbackMeter);

    /* Default volume increment */
    _defaultIncrement = (float) (10000 / skin->DefaultVolumeUnits()) / 10000.0f;
    CLOG(L"Default volume increment: %f", _defaultIncrement);

    _mWnd.Update();

    /* Mute OSD */
    /* TODO: NULL check*/
    _muteWnd.BackgroundImage(skin->muteBackground);

    if (skin->muteMask != NULL) {
        _muteWnd.GlassMask(skin->muteMask);
    }
    _muteWnd.Update();

    UpdateWindowPositions(ActiveMonitors());

    /* Set up notification icon */
    if (settings->NotifyIconEnabled()) {
        _iconImages = skin->volumeIconset;
        if (_iconImages.size() > 0) {
            _icon = new NotifyIcon(_hWnd, L"3RVX", _iconImages[0]);
        }
    }

    /* Enable sound effects, if any */
    if (settings->SoundEffectsEnabled()) {
        if (skin->volumeSound) {
            _soundPlayer = skin->volumeSound;
        }
    }
}

void VolumeOSD::MeterLevels(float level) {
    _mWnd.MeterLevels(level);
    _mWnd.Update();
}

void VolumeOSD::MeterChangeCallback(int units) {
    if (_soundPlayer) {
        _soundPlayer->Play();
    }
}

void VolumeOSD::Hide() {
    _mWnd.Hide(false);
    _muteWnd.Hide(false);
}

void VolumeOSD::HideIcon() {
    delete _icon;
}

void VolumeOSD::UpdateIcon() {
    UpdateIconImage();
    UpdateIconTip();
}

void VolumeOSD::UpdateIconImage() {
    if (_icon == NULL) {
        return;
    }

    int icon = 0;
    if (_volumeCtrl->Muted() == false) {
        int vUnits = _iconImages.size() - 1;
        icon = (int) ceil(_volumeCtrl->Volume() * vUnits);
    }

    if (icon != _lastIcon) {
        _icon->UpdateIcon(_iconImages[icon]);
        _lastIcon = icon;
    }
}

void VolumeOSD::UpdateIconTip() {
    if (_icon == NULL) {
        return;
    }

    if (_volumeCtrl->Muted()) {
        _icon->UpdateToolTip(_selectedDesc + L": Muted");
    } else {
        float v = _volumeCtrl->Volume();
        std::wstring perc = std::to_wstring((int) (v * 100.0f));
        std::wstring level = _selectedDesc + L": " + perc + L"%";
        _icon->UpdateToolTip(level);
    }
}

void VolumeOSD::UnMute() {
    if (_volumeCtrl->Muted() == true) {
        _volumeCtrl->Muted(false);
    }
}

void VolumeOSD::ProcessHotkeys(HotkeyInfo &hki) {
    int currentUnit = _callbackMeter->CalcUnits();
    if (_volumeCtrl->Volume() == 0.0000f) {
        currentUnit = 0;
    }
    switch (hki.action) {
    case HotkeyInfo::IncreaseVolume:
        UnMute();
        _volumeCtrl->Volume((float) (currentUnit + 1) * _defaultIncrement);
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::DecreaseVolume:
        UnMute();
        _volumeCtrl->Volume((float) (currentUnit - 1) * _defaultIncrement);
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::Mute:
        _volumeCtrl->ToggleMute();
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::VolumeSlider:
        if (_volumeSlider->Visible()) {
            /* If the slider is already visible, user must want to close it. */
            _volumeSlider->Hide();
        } else {
            SendMessage(_hWnd, MSG_NOTIFYICON, NULL, WM_LBUTTONUP);
        }
        break;
    }
}

void VolumeOSD::UpdateWindowPositions(std::vector<Monitor> monitors) {
    PositionWindow(monitors[0], _mWnd);
    PositionWindow(monitors[0], _muteWnd);
}

LRESULT
VolumeOSD::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == MSG_VOL_CHNG) {
        float v = _volumeCtrl->Volume();
        bool muteState = _volumeCtrl->Muted();

        _volumeSlider->MeterLevels(v);
        UpdateIcon();

        if (wParam > 0) {
            /* We manually post a MSG_VOL_CHNG when modifying the volume with
             * hotkeys, so this CoreAudio-generated event can be ignored
             * by the OSD. */
            CLOG(L"Ignoring volume change notification generated by 3RVX");
            return DefWindowProc(hWnd, message, wParam, lParam);
        }

        CLOG(L"Volume change notification:\nNew level: %f\nPrevious: %f",
            v, _lastVolume);
        if (lParam == 0 && (muteState == _muted)) {
            if (abs(v - _lastVolume) < 0.0001f) {
                CLOG(L"No change in volume detected; ignoring event.");
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        _lastVolume = v;
        _muted = muteState;

        if (_volumeSlider->Visible() == false) {
            if (_volumeCtrl->Muted() || v == 0.0f) {
                _muteWnd.Show();
                _mWnd.Hide(false);
            } else {
                MeterLevels(v);
                _mWnd.Show();
                _muteWnd.Hide(false);
            }
            HideOthers(Volume);
        }

    } else if (message == MSG_VOL_DEVCHNG) {
        CLOG(L"Volume device change detected.");
        if (_selectedDevice == L"") {
            _volumeCtrl->SelectDefaultDevice();
        } else {
            HRESULT hr = _volumeCtrl->SelectDevice(_selectedDevice);
            if (FAILED(hr)) {
                _volumeCtrl->SelectDefaultDevice();
            }
        }
        _selectedDesc = _volumeCtrl->DeviceDesc();
        UpdateDeviceMenu();

    } else if (message == MSG_NOTIFYICON) {
        if (lParam == WM_LBUTTONUP) {
            _volumeSlider->MeterLevels(_volumeCtrl->Volume());
            _volumeSlider->Show();
        } else if (lParam == WM_RBUTTONUP) {
            POINT p;
            GetCursorPos(&p);
            SetForegroundWindow(hWnd);
            TrackPopupMenuEx(_menu, _menuFlags, p.x, p.y, _hWnd, NULL);
            PostMessage(hWnd, WM_NULL, 0, 0);
        }

    } else if (message == WM_COMMAND) {
        int menuItem = LOWORD(wParam);
        switch (menuItem) {
        case MENU_SETTINGS:
            Settings::LaunchSettingsApp();
            break;

        case MENU_MIXER: {
            CLOG(L"Menu: Mixer");
            HINSTANCE code = ShellExecute(NULL, L"open", L"sndvol",
                NULL, NULL, SW_SHOWNORMAL);
            break;
        }

        case MENU_EXIT:
            CLOG(L"Menu: Exit: %d", (int) _masterWnd);
            SendMessage(_masterWnd, WM_CLOSE, NULL, NULL);
            break;
        }

        /* Device menu items */
        if ((menuItem & MENU_DEVICE) > 0) {
            int device = menuItem & 0x0FFF;
            VolumeController::DeviceInfo selectedDev = _deviceList[device];
            if (selectedDev.id != _volumeCtrl->DeviceId()) {
                /* A different device has been selected */
                CLOG(L"Changing to volume device: %s",
                    selectedDev.name.c_str());
                _volumeCtrl->SelectDevice(selectedDev.id);
                UpdateDeviceMenu();
            }
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}<commit_msg>Implement meter cloning for volume OSD<commit_after>#include "VolumeOSD.h"

#include "..\SoundPlayer.h"

#include <string>

#include "..\HotkeyInfo.h"
#include "..\MeterWnd\Meters\CallbackMeter.h"
#include "..\MeterWnd\MeterWndClone.h"
#include "..\Monitor.h"
#include "..\Skin.h"
#include "..\SkinManager.h"
#include "..\Slider\VolumeSlider.h"

#define MENU_SETTINGS 0
#define MENU_MIXER 1
#define MENU_EXIT 2
#define MENU_DEVICE 0xF000

VolumeOSD::VolumeOSD() :
OSD(L"3RVX-VolumeDispatcher"),
_mWnd(L"3RVX-MasterVolumeOSD", L"3RVX-MasterVolumeOSD"),
_muteWnd(L"3RVX-MasterMuteOSD", L"3RVX-MasterMuteOSD") {

    LoadSkin();
    Settings *settings = Settings::Instance();

    /* Start the volume controller */
    _volumeCtrl = new CoreAudio(_hWnd);
    std::wstring device = settings->AudioDeviceID();
    _volumeCtrl->Init(device);
    _selectedDesc = _volumeCtrl->DeviceDesc();

    /* Set up volume state variables */
    _lastVolume = _volumeCtrl->Volume();
    _muted = _volumeCtrl->Muted();

    if (settings->SoundEffectsEnabled()) {
        _sounds = true;
    }

    /* Create the slider */
    _volumeSlider = new VolumeSlider(*_volumeCtrl);

    /* Set up context menu */
    if (settings->NotifyIconEnabled()) {
        _menu = CreatePopupMenu();
        _deviceMenu = CreatePopupMenu();

        InsertMenu(_menu, -1, MF_ENABLED, MENU_SETTINGS, L"Settings");
        InsertMenu(_menu, -1, MF_POPUP, UINT(_deviceMenu), L"Audio Device");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_MIXER, L"Mixer");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_EXIT, L"Exit");

        _menuFlags = TPM_RIGHTBUTTON;
        if (GetSystemMetrics(SM_MENUDROPALIGNMENT) != 0) {
            _menuFlags |= TPM_RIGHTALIGN;
        } else {
            _menuFlags |= TPM_LEFTALIGN;
        }

        UpdateDeviceMenu();
    }

    _mWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _mWnd.VisibleDuration(settings->HideDelay());

    _muteWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _muteWnd.VisibleDuration(settings->HideDelay());

    UpdateIcon();
    float v = _volumeCtrl->Volume();
    MeterLevels(v);
    _volumeSlider->MeterLevels(v);

    /* TODO: check whether we should show the OSD on startup or not. If so, post
     * a MSG_VOL_CHNG so that the volume level (or mute) is displayed: */
    SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
}

VolumeOSD::~VolumeOSD() {
    DestroyMenu(_deviceMenu);
    DestroyMenu(_menu);
    delete _icon;
    delete _volumeSlider;
    delete _callbackMeter;
    _volumeCtrl->Dispose();
}

void VolumeOSD::UpdateDeviceMenu() {
    if (_menu == NULL || _deviceMenu == NULL) {
        return;
    }

    /* Remove any devices currently in the menu first */
    for (unsigned int i = 0; i < _deviceList.size(); ++i) {
        RemoveMenu(_deviceMenu, 0, MF_BYPOSITION);
    }
    _deviceList.clear();

    std::list<VolumeController::DeviceInfo> devices
        = _volumeCtrl->ListDevices();
    std::wstring currentDeviceId = _volumeCtrl->DeviceId();

    int menuItem = MENU_DEVICE;
    for (VolumeController::DeviceInfo device : devices) {
        unsigned int flags = MF_ENABLED;
        if (currentDeviceId == device.id) {
            flags |= MF_CHECKED;
        }

        InsertMenu(_deviceMenu, -1, flags, menuItem++, device.name.c_str());
        _deviceList.push_back(device);
    }
}

void VolumeOSD::LoadSkin() {
    Settings *settings = Settings::Instance();
    Skin *skin = SkinManager::Instance()->CurrentSkin();

    /* Volume OSD */
    /* TODO: should make sure this isn't NULL! */
    _mWnd.BackgroundImage(skin->volumeBackground);

    if (skin->volumeMask != NULL) {
        _mWnd.GlassMask(skin->volumeMask);
    }

    for (Meter *m : skin->volumeMeters) {
        _mWnd.AddMeter(m);
    }

    /* Add a callback meter with the default volume increment for sounds */
    _callbackMeter = new CallbackMeter(
        skin->DefaultVolumeUnits(), *this);
    _mWnd.AddMeter(_callbackMeter);

    /* Default volume increment */
    _defaultIncrement = (float) (10000 / skin->DefaultVolumeUnits()) / 10000.0f;
    CLOG(L"Default volume increment: %f", _defaultIncrement);

    _mWnd.Update();

    /* Mute OSD */
    /* TODO: NULL check*/
    _muteWnd.BackgroundImage(skin->muteBackground);

    if (skin->muteMask != NULL) {
        _muteWnd.GlassMask(skin->muteMask);
    }
    _muteWnd.Update();

    std::vector<Monitor> monitors = ActiveMonitors();
    for (unsigned int i = 1; i < monitors.size(); ++i) {
        _mWnd.Clone();
        _muteWnd.Clone();
    }
    UpdateWindowPositions(monitors);

    /* Set up notification icon */
    if (settings->NotifyIconEnabled()) {
        _iconImages = skin->volumeIconset;
        if (_iconImages.size() > 0) {
            _icon = new NotifyIcon(_hWnd, L"3RVX", _iconImages[0]);
        }
    }

    /* Enable sound effects, if any */
    if (settings->SoundEffectsEnabled()) {
        if (skin->volumeSound) {
            _soundPlayer = skin->volumeSound;
        }
    }
}

void VolumeOSD::MeterLevels(float level) {
    _mWnd.MeterLevels(level);
    _mWnd.Update();
}

void VolumeOSD::MeterChangeCallback(int units) {
    if (_soundPlayer) {
        _soundPlayer->Play();
    }
}

void VolumeOSD::Hide() {
    _mWnd.Hide(false);
    _muteWnd.Hide(false);
}

void VolumeOSD::HideIcon() {
    delete _icon;
}

void VolumeOSD::UpdateIcon() {
    UpdateIconImage();
    UpdateIconTip();
}

void VolumeOSD::UpdateIconImage() {
    if (_icon == NULL) {
        return;
    }

    int icon = 0;
    if (_volumeCtrl->Muted() == false) {
        int vUnits = _iconImages.size() - 1;
        icon = (int) ceil(_volumeCtrl->Volume() * vUnits);
    }

    if (icon != _lastIcon) {
        _icon->UpdateIcon(_iconImages[icon]);
        _lastIcon = icon;
    }
}

void VolumeOSD::UpdateIconTip() {
    if (_icon == NULL) {
        return;
    }

    if (_volumeCtrl->Muted()) {
        _icon->UpdateToolTip(_selectedDesc + L": Muted");
    } else {
        float v = _volumeCtrl->Volume();
        std::wstring perc = std::to_wstring((int) (v * 100.0f));
        std::wstring level = _selectedDesc + L": " + perc + L"%";
        _icon->UpdateToolTip(level);
    }
}

void VolumeOSD::UnMute() {
    if (_volumeCtrl->Muted() == true) {
        _volumeCtrl->Muted(false);
    }
}

void VolumeOSD::ProcessHotkeys(HotkeyInfo &hki) {
    int currentUnit = _callbackMeter->CalcUnits();
    if (_volumeCtrl->Volume() == 0.0000f) {
        currentUnit = 0;
    }
    switch (hki.action) {
    case HotkeyInfo::IncreaseVolume:
        UnMute();
        _volumeCtrl->Volume((float) (currentUnit + 1) * _defaultIncrement);
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::DecreaseVolume:
        UnMute();
        _volumeCtrl->Volume((float) (currentUnit - 1) * _defaultIncrement);
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::Mute:
        _volumeCtrl->ToggleMute();
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::VolumeSlider:
        if (_volumeSlider->Visible()) {
            /* If the slider is already visible, user must want to close it. */
            _volumeSlider->Hide();
        } else {
            SendMessage(_hWnd, MSG_NOTIFYICON, NULL, WM_LBUTTONUP);
        }
        break;
    }
}

void VolumeOSD::UpdateWindowPositions(std::vector<Monitor> &monitors) {
    PositionWindow(monitors[0], _mWnd);
    PositionWindow(monitors[0], _muteWnd);

    std::vector<MeterWndClone *> meterClones = _mWnd.Clones();
    std::vector<MeterWndClone *> muteClones = _muteWnd.Clones();
    for (unsigned int i = 1; i < monitors.size(); ++i) {
        PositionWindow(monitors[i], meterClones[i]->MeterWindow());
        PositionWindow(monitors[i], muteClones[i]->MeterWindow());
    }
}

LRESULT
VolumeOSD::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == MSG_VOL_CHNG) {
        float v = _volumeCtrl->Volume();
        bool muteState = _volumeCtrl->Muted();

        _volumeSlider->MeterLevels(v);
        UpdateIcon();

        if (wParam > 0) {
            /* We manually post a MSG_VOL_CHNG when modifying the volume with
             * hotkeys, so this CoreAudio-generated event can be ignored
             * by the OSD. */
            CLOG(L"Ignoring volume change notification generated by 3RVX");
            return DefWindowProc(hWnd, message, wParam, lParam);
        }

        CLOG(L"Volume change notification:\nNew level: %f\nPrevious: %f",
            v, _lastVolume);
        if (lParam == 0 && (muteState == _muted)) {
            if (abs(v - _lastVolume) < 0.0001f) {
                CLOG(L"No change in volume detected; ignoring event.");
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        _lastVolume = v;
        _muted = muteState;

        if (_volumeSlider->Visible() == false) {
            if (_volumeCtrl->Muted() || v == 0.0f) {
                _muteWnd.Show();
                _mWnd.Hide(false);
            } else {
                MeterLevels(v);
                _mWnd.Show();
                _muteWnd.Hide(false);
            }
            HideOthers(Volume);
        }

    } else if (message == MSG_VOL_DEVCHNG) {
        CLOG(L"Volume device change detected.");
        if (_selectedDevice == L"") {
            _volumeCtrl->SelectDefaultDevice();
        } else {
            HRESULT hr = _volumeCtrl->SelectDevice(_selectedDevice);
            if (FAILED(hr)) {
                _volumeCtrl->SelectDefaultDevice();
            }
        }
        _selectedDesc = _volumeCtrl->DeviceDesc();
        UpdateDeviceMenu();

    } else if (message == MSG_NOTIFYICON) {
        if (lParam == WM_LBUTTONUP) {
            _volumeSlider->MeterLevels(_volumeCtrl->Volume());
            _volumeSlider->Show();
        } else if (lParam == WM_RBUTTONUP) {
            POINT p;
            GetCursorPos(&p);
            SetForegroundWindow(hWnd);
            TrackPopupMenuEx(_menu, _menuFlags, p.x, p.y, _hWnd, NULL);
            PostMessage(hWnd, WM_NULL, 0, 0);
        }

    } else if (message == WM_COMMAND) {
        int menuItem = LOWORD(wParam);
        switch (menuItem) {
        case MENU_SETTINGS:
            Settings::LaunchSettingsApp();
            break;

        case MENU_MIXER: {
            CLOG(L"Menu: Mixer");
            HINSTANCE code = ShellExecute(NULL, L"open", L"sndvol",
                NULL, NULL, SW_SHOWNORMAL);
            break;
        }

        case MENU_EXIT:
            CLOG(L"Menu: Exit: %d", (int) _masterWnd);
            SendMessage(_masterWnd, WM_CLOSE, NULL, NULL);
            break;
        }

        /* Device menu items */
        if ((menuItem & MENU_DEVICE) > 0) {
            int device = menuItem & 0x0FFF;
            VolumeController::DeviceInfo selectedDev = _deviceList[device];
            if (selectedDev.id != _volumeCtrl->DeviceId()) {
                /* A different device has been selected */
                CLOG(L"Changing to volume device: %s",
                    selectedDev.name.c_str());
                _volumeCtrl->SelectDevice(selectedDev.id);
                UpdateDeviceMenu();
            }
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/consteval.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "kernel/satgen.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>

#define NUM_INITIAL_RANDOM_TEST_VECTORS 10

namespace {

struct FreduceHelper
{
	RTLIL::Design *design;
	RTLIL::Module *module;

	ezDefaultSAT ez;
	SigMap sigmap;
	CellTypes ct;
	SatGen satgen;
	ConstEval ce;

	SigPool inputs, nodes;
	RTLIL::SigSpec input_sigs;

	SigSet<RTLIL::SigSpec> driver_inputs;
	std::vector<RTLIL::Const> test_vectors;
	std::map<RTLIL::SigSpec, RTLIL::Const> node_to_data;
	std::map<RTLIL::SigSpec, RTLIL::SigSpec> node_result;

	std::vector<RTLIL::SigSig> result_groups;
	SigPool groups_unlink;

	uint32_t xorshift32_state;

        uint32_t xorshift32() {
		xorshift32_state ^= xorshift32_state << 13;
		xorshift32_state ^= xorshift32_state >> 17;
		xorshift32_state ^= xorshift32_state << 5;
		return xorshift32_state;
	}

	FreduceHelper(RTLIL::Design *design, RTLIL::Module *module) :
			design(design), module(module), sigmap(module), satgen(&ez, design, &sigmap), ce(module)
	{
		ct.setup_internals();
		ct.setup_stdcells();

		xorshift32_state = 123456789;
		xorshift32();
		xorshift32();
		xorshift32();
	}

	void run_test(RTLIL::SigSpec test_vec)
	{
		ce.clear();
		ce.set(input_sigs, test_vec.as_const());

		for (auto &bit : nodes.bits) {
			RTLIL::SigSpec nodesig(bit.first, 1, bit.second), nodeval = nodesig;
			if (!ce.eval(nodeval))
				log_error("Evaluation of node %s failed!\n", log_signal(nodesig));
			node_to_data[nodesig].bits.push_back(nodeval.as_const().bits.at(0));
		}
	}

	void dump_node_data()
	{
		int max_node_len = 20;
		for (auto &it : node_to_data)
			max_node_len = std::max(max_node_len, int(strlen(log_signal(it.first))));
		for (auto &it : node_to_data)
			log("  %-*s %s\n", max_node_len+5, log_signal(it.first), log_signal(it.second));
	}

	void check(RTLIL::SigSpec sig1, RTLIL::SigSpec sig2)
	{
		log("  performing SAT proof:  %s == %s  ->", log_signal(sig1), log_signal(sig2));

		std::vector<int> vec1 = satgen.importSigSpec(sig1);
		std::vector<int> vec2 = satgen.importSigSpec(sig2);
		std::vector<int> model = satgen.importSigSpec(input_sigs);
		std::vector<bool> testvect;

		if (ez.solve(model, testvect, ez.vec_ne(vec1, vec2))) {
			RTLIL::SigSpec testvect_sig;
			for (int i = 0; i < input_sigs.width; i++)
				testvect_sig.append(testvect.at(i) ? RTLIL::State::S1 : RTLIL::State::S0);
			testvect_sig.optimize();
			log(" failed: %s\n", log_signal(testvect_sig));
			test_vectors.push_back(testvect_sig.as_const());
			run_test(testvect_sig);
		} else {
			log(" success.\n");
			if (!sig1.is_fully_const())
				node_result[sig1].append(sig2);
			if (!sig2.is_fully_const())
				node_result[sig2].append(sig1);
		}
	}

	void analyze_const()
	{
		for (auto &it : node_to_data)
		{
			if (node_result.count(it.first))
				continue;
			if (it.second == RTLIL::Const(RTLIL::State::S0, it.second.bits.size()))
				check(it.first, RTLIL::SigSpec(RTLIL::State::S0));
			if (it.second == RTLIL::Const(RTLIL::State::S1, it.second.bits.size()))
				check(it.first, RTLIL::SigSpec(RTLIL::State::S1));
		}
	}

	void analyze_alias()
	{
	restart:
		std::map<RTLIL::Const, RTLIL::SigSpec> reverse_map;

		for (auto &it : node_to_data) {
			if (node_result.count(it.first) && node_result.at(it.first).is_fully_const())
				continue;
			reverse_map[it.second].append(it.first);
		}

		for (auto &it : reverse_map)
		{
			if (it.second.width <= 1)
				continue;

			it.second.expand();
			for (int i = 0; i < it.second.width; i++)
			for (int j = i+1; j < it.second.width; j++) {
				RTLIL::SigSpec sig1 = it.second.chunks.at(i), sig2 = it.second.chunks.at(j);
				if (node_result.count(sig1) && node_result.count(sig2))
					continue;
				if (node_to_data.at(sig1) != node_to_data.at(sig2))
					goto restart;
				check(it.second.chunks.at(i), it.second.chunks.at(j));
			}
		}
	}

	bool topsort_helper(RTLIL::SigSpec cursor, RTLIL::SigSpec stoplist)
	{
		if (stoplist.extract(cursor).width != 0)
			return false;

		stoplist.append(cursor);
		std::set<RTLIL::SigSpec> next = driver_inputs.find(cursor);

		for (auto &it : next)
			if (!topsort_helper(it, stoplist))
				return false;

		return true;
	}

	// KISS topological sort of bits in signal. return one element of sig
	// without dependencies to the others (or empty if input is not a DAG).
	RTLIL::SigSpec topsort(RTLIL::SigSpec sig)
	{
		sig.expand();
		for (auto &c : sig.chunks) {
			RTLIL::SigSpec stoplist = sig;
			stoplist.remove(c);
			if (topsort_helper(c, stoplist))
				return c;
		}
		return RTLIL::SigSpec();
	}

	void analyze_groups()
	{
		SigMap to_group_major;
		for (auto &it : node_result) {
			it.second.expand();
			for (auto &c : it.second.chunks)
				to_group_major.add(it.first, c);
		}

		std::map<RTLIL::SigSpec, RTLIL::SigSpec> major_to_rest;
		for (auto &it : node_result)
			major_to_rest[to_group_major(it.first)].append(it.first);

		for (auto &it : major_to_rest)
		{
			RTLIL::SigSig group = it;

			if (!it.first.is_fully_const()) {
				group.first = topsort(it.second);
				if (group.first.width == 0)
					log_error("Operating on non-DAG input: failed to find topological root for `%s'.\n", log_signal(it.second));
				group.second.remove(group.first);
			}

			group.first.optimize();
			group.second.sort_and_unify();
			result_groups.push_back(group);
		}
	}

	void run()
	{
		log("\nFunctionally reduce module %s:\n", RTLIL::id2cstr(module->name));

		// find inputs and nodes (nets driven by internal cells)
		// add all internal cells to sat solver

		for (auto &cell_it : module->cells) {
			RTLIL::Cell *cell = cell_it.second;
			if (!ct.cell_known(cell->type))
				continue;
			RTLIL::SigSpec cell_inputs, cell_outputs;
			for (auto &conn : cell->connections)
				if (ct.cell_output(cell->type, conn.first)) {
					nodes.add(sigmap(conn.second));
					cell_outputs.append(sigmap(conn.second));
				} else {
					inputs.add(sigmap(conn.second));
					cell_inputs.append(sigmap(conn.second));
				}
			cell_inputs.sort_and_unify();
			cell_outputs.sort_and_unify();
			cell_inputs.expand();
			for (auto &c : cell_inputs.chunks)
				if (c.wire != NULL)
					driver_inputs.insert(cell_outputs, c);
			if (!satgen.importCell(cell))
				log_error("Failed to import cell to SAT solver: %s (%s)\n",
						RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
		}
		inputs.del(nodes);
		nodes.add(inputs);
		log("  found %d nodes (%d inputs).\n", int(nodes.size()), int(inputs.size()));

		// initialise input_sigs and add all-zero, all-one and a few random test vectors

		input_sigs = inputs.export_all();
		test_vectors.push_back(RTLIL::SigSpec(RTLIL::State::S0, input_sigs.width).as_const());
		test_vectors.push_back(RTLIL::SigSpec(RTLIL::State::S1, input_sigs.width).as_const());

		for (int i = 0; i < NUM_INITIAL_RANDOM_TEST_VECTORS; i++) {
			RTLIL::SigSpec sig;
			for (int j = 0; j < input_sigs.width; j++)
				sig.append(xorshift32() % 2 ? RTLIL::State::S1 : RTLIL::State::S0);
			sig.optimize();
			assert(sig.width == input_sigs.width);
			test_vectors.push_back(sig.as_const());
		}

		for (auto &test_vec : test_vectors)
			run_test(test_vec);

		// run the analysis

		analyze_const();
		analyze_alias();

		log("  input vector: %s\n", log_signal(input_sigs));
		for (auto &test_vec : test_vectors)
			log("  test vector: %s\n", log_signal(test_vec));

		analyze_groups();

		for (auto &it : result_groups) {
			log("  found group: %s -> %s\n", log_signal(it.first), log_signal(it.second));
			groups_unlink.add(it.second);
		}

		for (auto &cell_it : module->cells) {
			RTLIL::Cell *cell = cell_it.second;
			if (!ct.cell_known(cell->type))
				continue;
			for (auto &conn : cell->connections)
				if (ct.cell_output(cell->type, conn.first)) {
					RTLIL::SigSpec sig = sigmap(conn.second);
					sig.expand();
					bool did_something = false;
					for (auto &c : sig.chunks) {
						if (c.wire == NULL || !groups_unlink.check_any(c))
							continue;
						c.wire = new RTLIL::Wire;
						c.wire->name = NEW_ID;
						module->add(c.wire);
						assert(c.width == 1);
						c.offset = 0;
						did_something = true;
					}
					if (did_something) {
						sig.optimize();
						conn.second = sig;
					}
				}
		}

		for (auto &it : result_groups) {
			it.second.expand();
			for (auto &c : it.second.chunks)
				module->connections.push_back(RTLIL::SigSig(c, it.first));
		}
	}
};

} /* namespace */

struct FreducePass : public Pass {
	FreducePass() : Pass("freduce", "perform functional reduction") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    freduce [options] [selection]\n");
		log("\n");
		log("This pass performs functional reduction in the circuit. I.e. if two nodes are\n");
		log("equivialent, they are merged to one node and one of the redundant drivers is\n");
		log("removed.\n");
		log("\n");
		// log("    -enable_invert\n");
		// log("        also detect nodes that are inverse to each other.\n");
		// log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		bool enable_invert = false;

		log_header("Executing FREDUCE pass (perform functional reduction).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-enable_invert") {
				enable_invert = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
		{
			RTLIL::Module *module = mod_it.second;
			if (design->selected(module))
				FreduceHelper(design, module).run();
		}
	}
} FreducePass;

<commit_msg>Fixed topological ordering in freduce pass<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/consteval.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "kernel/satgen.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>

#define NUM_INITIAL_RANDOM_TEST_VECTORS 10

namespace {

struct FreduceHelper
{
	RTLIL::Design *design;
	RTLIL::Module *module;

	ezDefaultSAT ez;
	SigMap sigmap;
	CellTypes ct;
	SatGen satgen;
	ConstEval ce;

	SigPool inputs, nodes;
	RTLIL::SigSpec input_sigs;

	SigSet<RTLIL::SigSpec> source_signals;
	std::vector<RTLIL::Const> test_vectors;
	std::map<RTLIL::SigSpec, RTLIL::Const> node_to_data;
	std::map<RTLIL::SigSpec, RTLIL::SigSpec> node_result;

	uint32_t xorshift32_state;

        uint32_t xorshift32() {
		xorshift32_state ^= xorshift32_state << 13;
		xorshift32_state ^= xorshift32_state >> 17;
		xorshift32_state ^= xorshift32_state << 5;
		return xorshift32_state;
	}

	FreduceHelper(RTLIL::Design *design, RTLIL::Module *module) :
			design(design), module(module), sigmap(module), satgen(&ez, design, &sigmap), ce(module)
	{
		ct.setup_internals();
		ct.setup_stdcells();

		xorshift32_state = 123456789;
		xorshift32();
		xorshift32();
		xorshift32();
	}

	void run_test(RTLIL::SigSpec test_vec)
	{
		ce.clear();
		ce.set(input_sigs, test_vec.as_const());

		for (auto &bit : nodes.bits) {
			RTLIL::SigSpec nodesig(bit.first, 1, bit.second), nodeval = nodesig;
			if (!ce.eval(nodeval))
				log_error("Evaluation of node %s failed!\n", log_signal(nodesig));
			node_to_data[nodesig].bits.push_back(nodeval.as_const().bits.at(0));
		}
	}

	void dump_node_data()
	{
		int max_node_len = 20;
		for (auto &it : node_to_data)
			max_node_len = std::max(max_node_len, int(strlen(log_signal(it.first))));
		log("  full node fingerprints:\n");
		for (auto &it : node_to_data)
			log("    %-*s %s\n", max_node_len+5, log_signal(it.first), log_signal(it.second));
	}

	void check(RTLIL::SigSpec sig1, RTLIL::SigSpec sig2)
	{
		log("  performing SAT proof:  %s == %s  ->", log_signal(sig1), log_signal(sig2));

		std::vector<int> vec1 = satgen.importSigSpec(sig1);
		std::vector<int> vec2 = satgen.importSigSpec(sig2);
		std::vector<int> model = satgen.importSigSpec(input_sigs);
		std::vector<bool> testvect;

		if (ez.solve(model, testvect, ez.vec_ne(vec1, vec2))) {
			RTLIL::SigSpec testvect_sig;
			for (int i = 0; i < input_sigs.width; i++)
				testvect_sig.append(testvect.at(i) ? RTLIL::State::S1 : RTLIL::State::S0);
			testvect_sig.optimize();
			log(" failed: %s\n", log_signal(testvect_sig));
			test_vectors.push_back(testvect_sig.as_const());
			run_test(testvect_sig);
		} else {
			log(" success.\n");
			if (!sig1.is_fully_const())
				node_result[sig1].append(sig2);
			if (!sig2.is_fully_const())
				node_result[sig2].append(sig1);
		}
	}

	void analyze_const()
	{
		for (auto &it : node_to_data)
		{
			if (node_result.count(it.first))
				continue;
			if (it.second == RTLIL::Const(RTLIL::State::S0, it.second.bits.size()))
				check(it.first, RTLIL::SigSpec(RTLIL::State::S0));
			if (it.second == RTLIL::Const(RTLIL::State::S1, it.second.bits.size()))
				check(it.first, RTLIL::SigSpec(RTLIL::State::S1));
		}
	}

	void analyze_alias()
	{
	restart:
		std::map<RTLIL::Const, RTLIL::SigSpec> reverse_map;

		for (auto &it : node_to_data) {
			if (node_result.count(it.first) && node_result.at(it.first).is_fully_const())
				continue;
			reverse_map[it.second].append(it.first);
		}

		for (auto &it : reverse_map)
		{
			if (it.second.width <= 1)
				continue;

			it.second.expand();
			for (int i = 0; i < it.second.width; i++)
			for (int j = i+1; j < it.second.width; j++) {
				RTLIL::SigSpec sig1 = it.second.chunks.at(i), sig2 = it.second.chunks.at(j);
				if (node_result.count(sig1) && node_result.count(sig2))
					continue;
				if (node_to_data.at(sig1) != node_to_data.at(sig2))
					goto restart;
				check(it.second.chunks.at(i), it.second.chunks.at(j));
			}
		}
	}

	bool toproot_helper(RTLIL::SigSpec cursor, RTLIL::SigSpec stoplist, int level)
	{
		// log("    %*schecking %s: %s\n", level*2, "", log_signal(cursor), log_signal(stoplist));

		if (stoplist.extract(cursor).width != 0) {
			// log("    %*s  STOP\n", level*2, "");
			return false;
		}

		stoplist.append(cursor);
		std::set<RTLIL::SigSpec> next = source_signals.find(cursor);

		for (auto &it : next)
			if (!toproot_helper(it, stoplist, level+1))
				return false;

		return true;
	}

	// KISS topological sort of bits in signal. return one element of sig
	// without dependencies to the others (or empty if input is not a DAG).
	RTLIL::SigSpec toproot(RTLIL::SigSpec sig)
	{
		sig.expand();
		// log("  finding topological root in %s:\n", log_signal(sig));
		for (auto &c : sig.chunks) {
			RTLIL::SigSpec stoplist = sig;
			stoplist.remove(c);
			// log("    testing %s as root:\n", log_signal(c));
			if (toproot_helper(c, stoplist, 0))
				return c;
		}
		return RTLIL::SigSpec();
	}

	void update_design_for_group(RTLIL::SigSpec root, RTLIL::SigSpec rest)
	{
		SigPool unlink;
		unlink.add(rest);

		for (auto &cell_it : module->cells) {
			RTLIL::Cell *cell = cell_it.second;
			if (!ct.cell_known(cell->type))
				continue;
			for (auto &conn : cell->connections)
				if (ct.cell_output(cell->type, conn.first)) {
					RTLIL::SigSpec sig = sigmap(conn.second);
					sig.expand();
					bool did_something = false;
					for (auto &c : sig.chunks) {
						if (c.wire == NULL || !unlink.check_any(c))
							continue;
						c.wire = new RTLIL::Wire;
						c.wire->name = NEW_ID;
						module->add(c.wire);
						assert(c.width == 1);
						c.offset = 0;
						did_something = true;
					}
					if (did_something) {
						sig.optimize();
						conn.second = sig;
					}
				}
		}

		rest.expand();
		for (auto &c : rest.chunks) {
			if (c.wire != NULL && !root.is_fully_const()) {
				source_signals.erase(c);
				source_signals.insert(c, root);
			}
			module->connections.push_back(RTLIL::SigSig(c, root));
		}
	}

	void analyze_groups()
	{
		SigMap to_group_major;
		for (auto &it : node_result) {
			it.second.expand();
			for (auto &c : it.second.chunks)
				to_group_major.add(it.first, c);
		}

		std::map<RTLIL::SigSpec, RTLIL::SigSpec> major_to_rest;
		for (auto &it : node_result)
			major_to_rest[to_group_major(it.first)].append(it.first);

		for (auto &it : major_to_rest)
		{
			RTLIL::SigSig group = it;

			if (!it.first.is_fully_const()) {
				group.first = toproot(it.second);
				if (group.first.width == 0) {
					log("Operating on non-DAG input: failed to find topological root for `%s'.\n", log_signal(it.second));
					return;
				}
				group.second.remove(group.first);
			}

			group.first.optimize();
			group.second.sort_and_unify();

			log("  found group: %s -> %s\n", log_signal(group.first), log_signal(group.second));
			update_design_for_group(group.first, group.second);
		}
	}

	void run()
	{
		log("\nFunctionally reduce module %s:\n", RTLIL::id2cstr(module->name));

		// find inputs and nodes (nets driven by internal cells)
		// add all internal cells to sat solver

		for (auto &cell_it : module->cells) {
			RTLIL::Cell *cell = cell_it.second;
			if (!ct.cell_known(cell->type))
				continue;
			RTLIL::SigSpec cell_inputs, cell_outputs;
			for (auto &conn : cell->connections)
				if (ct.cell_output(cell->type, conn.first)) {
					nodes.add(sigmap(conn.second));
					cell_outputs.append(sigmap(conn.second));
				} else {
					inputs.add(sigmap(conn.second));
					cell_inputs.append(sigmap(conn.second));
				}
			cell_inputs.sort_and_unify();
			cell_outputs.sort_and_unify();
			cell_inputs.expand();
			for (auto &c : cell_inputs.chunks)
				if (c.wire != NULL)
					source_signals.insert(cell_outputs, c);
			if (!satgen.importCell(cell))
				log_error("Failed to import cell to SAT solver: %s (%s)\n",
						RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
		}
		inputs.del(nodes);
		nodes.add(inputs);
		log("  found %d nodes (%d inputs).\n", int(nodes.size()), int(inputs.size()));

		// initialise input_sigs and add all-zero, all-one and a few random test vectors

		input_sigs = inputs.export_all();
		test_vectors.push_back(RTLIL::SigSpec(RTLIL::State::S0, input_sigs.width).as_const());
		test_vectors.push_back(RTLIL::SigSpec(RTLIL::State::S1, input_sigs.width).as_const());

		for (int i = 0; i < NUM_INITIAL_RANDOM_TEST_VECTORS; i++) {
			RTLIL::SigSpec sig;
			for (int j = 0; j < input_sigs.width; j++)
				sig.append(xorshift32() % 2 ? RTLIL::State::S1 : RTLIL::State::S0);
			sig.optimize();
			assert(sig.width == input_sigs.width);
			test_vectors.push_back(sig.as_const());
		}

		for (auto &test_vec : test_vectors)
			run_test(test_vec);

		// run the analysis and update design

		analyze_const();
		analyze_alias();

		log("  input vector: %s\n", log_signal(input_sigs));
		for (auto &test_vec : test_vectors)
			log("  test vector: %s\n", log_signal(test_vec));

		dump_node_data();
		analyze_groups();
	}
};

} /* namespace */

struct FreducePass : public Pass {
	FreducePass() : Pass("freduce", "perform functional reduction") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    freduce [options] [selection]\n");
		log("\n");
		log("This pass performs functional reduction in the circuit. I.e. if two nodes are\n");
		log("equivialent, they are merged to one node and one of the redundant drivers is\n");
		log("removed.\n");
		log("\n");
		// log("    -enable_invert\n");
		// log("        also detect nodes that are inverse to each other.\n");
		// log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		bool enable_invert = false;

		log_header("Executing FREDUCE pass (perform functional reduction).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			if (args[argidx] == "-enable_invert") {
				enable_invert = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
		{
			RTLIL::Module *module = mod_it.second;
			if (design->selected(module))
				FreduceHelper(design, module).run();
		}
	}
} FreducePass;

<|endoftext|>


<commit_before>/*
Copyright (c) 2016,
Dan Bethell, Johannes Saam, Vahan Sosoyan, Brian Scherbinski.
All rights reserved. See COPYING.txt for more details.
*/

#include <ai.h>

#include "Data.h"
#include "Client.h"

using boost::asio::ip::tcp;

AI_DRIVER_NODE_EXPORT_METHODS(AtonDriverMtd);

struct ShaderData
{
   aton::Client* client;
};

const char* getHost()
{
    const char* aton_host = getenv("ATON_HOST");

    if (aton_host == NULL)
        aton_host = "127.0.0.1";

    char* host = new char[strlen(aton_host)+1];
    strcpy(host, aton_host);
    aton_host = host;

    return aton_host;
}

int getPort()
{
    const char* def_port = getenv("ATON_PORT");
    int aton_port;

    if (def_port == NULL)
        aton_port = 9201;
    else
        aton_port = atoi(def_port);

    return aton_port;
}

node_parameters
{
    AiParameterSTR("host", getHost());
    AiParameterINT("port", getPort());
    AiMetaDataSetStr(mds, NULL, "maya.translator", "aton");
    AiMetaDataSetStr(mds, NULL, "maya.attr_prefix", "");
    AiMetaDataSetBool(mds, NULL, "display_driver", true);
    AiMetaDataSetBool(mds, NULL, "single_layer_driver", false);
}

node_initialize
{
    AiDriverInitialize(node, true, AiMalloc(sizeof(ShaderData)));
}

node_update {}

driver_supports_pixel_type { return true; }

driver_extension { return NULL; }

driver_open
{
    // Construct full version number
    char arch[3], major[3], minor[3], fix[3];
    AiGetVersion(arch, major, minor, fix);
    int version = atoi(arch) +
                  atoi(major) * 100 +
                  atoi(minor) * 10000 +
                  atoi(fix) * 1000000;

    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);

    // Get Frame number
    AtNode* options = AiUniverseGetOptions();
    float currentFrame = AiNodeGetFlt(options, "frame");

    // Get Host and Port
    const char* host = AiNodeGetStr(node, "host");
    int port = AiNodeGetInt(node, "port");

    // Get resolution and area
    int width = display_window.maxx - display_window.minx +1;
    int height = display_window.maxy - display_window.miny +1;
    int rWidth = data_window.maxx - data_window.minx +1;
    int rHeight = data_window.maxy - data_window.miny +1;
    long long rArea = rWidth * rHeight;

    try // Now we can connect to the server and start rendering
    {
       // Create a new aton object
       data->client = new aton::Client( host, port );

       // Make image header & send to server
       aton::Data header( 0, 0, width, height, rArea, version, currentFrame);
       data->client->openImage(header);
    }
    catch (const std::exception &e)
    {
        const char *err = e.what();
        AiMsgError("Aton display driver %s", err);
    }
}

driver_needs_bucket { return true; }

driver_prepare_bucket
{
    AiMsgDebug("[Aton] prepare bucket (%d, %d)", bucket_xo, bucket_yo);
}

driver_process_bucket { }

driver_write_bucket
{
    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);

    int pixel_type;
    int spp = 0;
    const void* bucket_data;
    const char* aov_name;

    while (AiOutputIteratorGetNext(iterator, &aov_name, &pixel_type, &bucket_data))
    {
        const float* ptr = reinterpret_cast<const float*> (bucket_data);
        long long ram = AiMsgUtilGetUsedMemory();
        unsigned int time = AiMsgUtilGetElapsedTime();

        switch (pixel_type)
        {
            case(AI_TYPE_FLOAT):
                spp = 1;
                break;
            case(AI_TYPE_RGBA):
                spp = 4;
                break;
            default:
                spp = 3;
        }

        // Create our data object
        aton::Data packet(bucket_xo, bucket_yo,
                          bucket_size_x, bucket_size_y,
                          0, 0, 0, spp, ram, time, aov_name, ptr);

        // Send it to the server
        data->client->sendPixels(packet);
    }
}

driver_close
{
    AiMsgInfo("[Aton] driver close");

    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);
    try
    {
        data->client->closeImage();
    }
    catch (const std::exception &e)
    {
        AiMsgError("Error occured when trying to close connection");
    }
}

node_finish
{
    AiMsgInfo("[Aton] driver finish");

    // Release the driver
    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);
    delete data->client;

    AiFree(data);
    AiDriverDestroy(node);
}

node_loader
{
    sprintf(node->version, AI_VERSION);

    switch (i)
    {
        case 0:
            node->methods = (AtNodeMethods*) AtonDriverMtd;
            node->output_type = AI_TYPE_RGBA;
            node->name = "driver_aton";
            node->node_type = AI_NODE_DRIVER;
            break;
        default:
        return false;
    }
    return true;
}
<commit_msg>Polish<commit_after>/*
Copyright (c) 2016,
Dan Bethell, Johannes Saam, Vahan Sosoyan, Brian Scherbinski.
All rights reserved. See COPYING.txt for more details.
*/

#include <ai.h>

#include "Data.h"
#include "Client.h"

using boost::asio::ip::tcp;

AI_DRIVER_NODE_EXPORT_METHODS(AtonDriverMtd);

struct ShaderData
{
   aton::Client* client;
};

const char* getHost()
{
    const char* aton_host = getenv("ATON_HOST");

    if (aton_host == NULL)
        aton_host = "127.0.0.1";

    char* host = new char[strlen(aton_host)+1];
    strcpy(host, aton_host);
    aton_host = host;

    return aton_host;
}

int getPort()
{
    const char* def_port = getenv("ATON_PORT");
    int aton_port;

    if (def_port == NULL)
        aton_port = 9201;
    else
        aton_port = atoi(def_port);

    return aton_port;
}

node_parameters
{
    AiParameterSTR("host", getHost());
    AiParameterINT("port", getPort());
    AiMetaDataSetStr(mds, NULL, "maya.translator", "aton");
    AiMetaDataSetStr(mds, NULL, "maya.attr_prefix", "");
    AiMetaDataSetBool(mds, NULL, "display_driver", true);
    AiMetaDataSetBool(mds, NULL, "single_layer_driver", false);
}

node_initialize
{
    AiDriverInitialize(node, true, AiMalloc(sizeof(ShaderData)));
}

node_update {}

driver_supports_pixel_type { return true; }

driver_extension { return NULL; }

driver_open
{
    // Construct full version number
    char arch[3], major[3], minor[3], fix[3];
    AiGetVersion(arch, major, minor, fix);
    int version = atoi(arch) +
                  atoi(major) * 100 +
                  atoi(minor) * 10000 +
                  atoi(fix) * 1000000;

    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);

    // Get Frame number
    AtNode* options = AiUniverseGetOptions();
    float currentFrame = AiNodeGetFlt(options, "frame");

    // Get Host and Port
    const char* host = AiNodeGetStr(node, "host");
    int port = AiNodeGetInt(node, "port");

    // Get resolution and area
    int width = display_window.maxx - display_window.minx + 1;
    int height = display_window.maxy - display_window.miny + 1;
    int rWidth = data_window.maxx - data_window.minx + 1;
    int rHeight = data_window.maxy - data_window.miny + 1;
    long long rArea = rWidth * rHeight;

    try // Now we can connect to the server and start rendering
    {
       // Create a new aton object
       data->client = new aton::Client(host, port);

       // Make image header & send to server
       aton::Data header(0, 0, width, height, rArea, version, currentFrame);
       data->client->openImage(header);
    }
    catch (const std::exception &e)
    {
        const char *err = e.what();
        AiMsgError("Aton display driver %s", err);
    }
}

driver_needs_bucket { return true; }

driver_prepare_bucket
{
    AiMsgDebug("[Aton] prepare bucket (%d, %d)", bucket_xo, bucket_yo);
}

driver_process_bucket { }

driver_write_bucket
{
    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);

    int pixel_type;
    int spp = 0;
    const void* bucket_data;
    const char* aov_name;

    while (AiOutputIteratorGetNext(iterator, &aov_name, &pixel_type, &bucket_data))
    {
        const float* ptr = reinterpret_cast<const float*>(bucket_data);
        long long ram = AiMsgUtilGetUsedMemory();
        unsigned int time = AiMsgUtilGetElapsedTime();

        switch (pixel_type)
        {
            case(AI_TYPE_FLOAT):
                spp = 1;
                break;
            case(AI_TYPE_RGBA):
                spp = 4;
                break;
            default:
                spp = 3;
        }

        // Create our data object
        aton::Data packet(bucket_xo, bucket_yo,
                          bucket_size_x, bucket_size_y,
                          0, 0, 0, spp, ram, time, aov_name, ptr);

        // Send it to the server
        data->client->sendPixels(packet);
    }
}

driver_close
{
    AiMsgInfo("[Aton] driver close");

    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);
    try
    {
        data->client->closeImage();
    }
    catch (const std::exception &e)
    {
        AiMsgError("Error occured when trying to close connection");
    }
}

node_finish
{
    AiMsgInfo("[Aton] driver finish");

    // Release the driver
    ShaderData* data = (ShaderData*)AiDriverGetLocalData(node);
    delete data->client;

    AiFree(data);
    AiDriverDestroy(node);
}

node_loader
{
    sprintf(node->version, AI_VERSION);

    switch (i)
    {
        case 0:
            node->methods = (AtNodeMethods*) AtonDriverMtd;
            node->output_type = AI_TYPE_RGBA;
            node->name = "driver_aton";
            node->node_type = AI_NODE_DRIVER;
            break;
        default:
        return false;
    }
    return true;
}
<|endoftext|>


<commit_before>#include "EditorScene.hpp"

EditorScene* EditorScene::activeScene = nullptr;

// ---------------------------------------------------------------------------
//  Prolog Interface to Scene Editing Commands
// ---------------------------------------------------------------------------
// TODO: Move to appropriate modules

PREDICATE0(pd_save) { return false; }

PREDICATE(pd_saveas, 1) { return false; }

PREDICATE0(pd_exit) { return false; }

PREDICATE(pd_add_actor, 1) {
	try {
		EditorScene::activeScene->addActor(static_cast<const char*>(A1));
	} catch(const std::exception& exception) {
		g_logger.write(Logger::LOG_ERROR, exception.what());
		return false;
	}
	return true;
}

PREDICATE(pd_select, 2) { return false; }

PREDICATE0(pd_deselect) { return false; }

PREDICATE0(pd_remove_actor) { return false; }

PREDICATE(pd_move_by, 3) { return false; }

PREDICATE(pd_move_to, 3) { return false; }

PREDICATE(pd_rotate, 3) { return false; }

PREDICATE0(pd_add_light) { return false; }

PREDICATE(pd_select_light, 1) { return false; }

PREDICATE0(pd_remove_light) { return false; }

PREDICATE0(pd_edit_light) { return false; }

PREDICATE0(pd_load_assets) { return false; }

// ---------------------------------------------------------------------------
//  Scene Overrides
// ---------------------------------------------------------------------------

EditorScene::EditorScene(const std::string& name)
  : Scene(name)
  , m_inputModel("SceneEdit")
  , m_mutex()
  , m_runConsole(true)
  , m_consoleThread([&]() {
	  while(m_runConsole) {
		  std::string command;
		  std::getline(std::cin, command);
		  if(command.at(command.size() - 1) == '\r')
			  command.resize(command.size() - 1);
		  m_mutex.lock();
		  m_commands.emplace(command);
		  m_mutex.unlock();
	  }
	}) {
	// TODO: Editor mode scene loading
	// The scene will load normally first.
	// If the scene file can't be found, we create a new one.
	// If the scene file is corrupt, we give up.
	try {
		m_defaultShader =
		  new Shader("textured.vert.glsl", "textured.frag.glsl", "");
	} catch(const std::exception& exception) {
		g_logger.write(Logger::LOG_ERROR, exception.what());
	}
}

EditorScene::~EditorScene() {
	m_runConsole = false;
	std::cout << "Press ENTER to quit.\n";
	m_consoleThread.join();
	delete m_defaultShader;
}

// The editor works with the initial moment of a scene.
// We don't want these functions to do anything.
void EditorScene::update(std::chrono::milliseconds) {}
void EditorScene::simulate(std::chrono::milliseconds) {}

// Similarly, we don't want the Actors processing any input.
// Input processing is limited to editor and camera input.
void EditorScene::processInput(GLFWwindow& window) {
	m_inputModel.update(window);
	m_editorCamera.processInput(window);

	// Process command queue
	EditorScene::activeScene = this;
	std::lock_guard<std::mutex> lock(m_mutex);
	while(!m_commands.empty()) {
		std::string command = m_commands.front();
		std::cout << (PlCall("do_command", {{command.c_str()}}) ?
		                "Command Succeeded" :
		                "Command Failed")
		          << "\n";
		m_commands.pop();
	}
	EditorScene::activeScene = nullptr;
}

// The scene should draw as per usual, though.
//void EditorScene::draw() { Scene::draw(); }

void EditorScene::draw() {
	glm::mat4 projectionMatrix =
	  glm::perspective(45.0f,
	                   static_cast<float>(g_renderer.width()) /
	                     static_cast<float>(g_renderer.height()),
	                   0.1f,
	                   10000.0f);
	for(auto actor = m_actors.begin(); actor != m_actors.end(); ++actor) {
		m_defaultShader->setAmbience(m_ambience);

		// Send camera position to the GPU.
		for(auto camera : m_cameras) {
			m_defaultShader->setViewMatrix(camera.getViewMatrix());
			m_defaultShader->setEyePosition(glm::vec3(camera.getPosition()));
		}

		m_defaultShader->setProjectionMatrix(projectionMatrix);
		m_defaultShader->setObjectID(actor->first);
		actor->second->draw(*m_defaultShader);
	}
}

// ---------------------------------------------------------------------------
//  Editor Functionality
// ---------------------------------------------------------------------------

void EditorScene::addActor(const std::string& name) {
	try {
		m_actors.emplace(
		  std::make_pair(++m_highestID, std::make_unique<Actor>(name)));
	} catch(const std::exception& exception) {
		g_logger.write(Logger::LOG_ERROR, exception.what());
		throw std::runtime_error("Failed to load Actor");
	}
}
<commit_msg>Draw using editor-specific camera<commit_after>#include "EditorScene.hpp"

EditorScene* EditorScene::activeScene = nullptr;

// ---------------------------------------------------------------------------
//  Prolog Interface to Scene Editing Commands
// ---------------------------------------------------------------------------
// TODO: Move to appropriate modules

PREDICATE0(pd_save) { return false; }

PREDICATE(pd_saveas, 1) { return false; }

PREDICATE0(pd_exit) { return false; }

PREDICATE(pd_add_actor, 1) {
	try {
		EditorScene::activeScene->addActor(static_cast<const char*>(A1));
	} catch(const std::exception& exception) {
		g_logger.write(Logger::LOG_ERROR, exception.what());
		return false;
	}
	return true;
}

PREDICATE(pd_select, 2) { return false; }

PREDICATE0(pd_deselect) { return false; }

PREDICATE0(pd_remove_actor) { return false; }

PREDICATE(pd_move_by, 3) { return false; }

PREDICATE(pd_move_to, 3) { return false; }

PREDICATE(pd_rotate, 3) { return false; }

PREDICATE0(pd_add_light) { return false; }

PREDICATE(pd_select_light, 1) { return false; }

PREDICATE0(pd_remove_light) { return false; }

PREDICATE0(pd_edit_light) { return false; }

PREDICATE0(pd_load_assets) { return false; }

// ---------------------------------------------------------------------------
//  Scene Overrides
// ---------------------------------------------------------------------------

EditorScene::EditorScene(const std::string& name)
  : Scene(name)
  , m_inputModel("SceneEdit")
  , m_mutex()
  , m_runConsole(true)
  , m_consoleThread([&]() {
	  while(m_runConsole) {
		  std::string command;
		  std::getline(std::cin, command);
		  if(command.at(command.size() - 1) == '\r')
			  command.resize(command.size() - 1);
		  m_mutex.lock();
		  m_commands.emplace(command);
		  m_mutex.unlock();
	  }
	}) {
	// TODO: Editor mode scene loading
	// The scene will load normally first.
	// If the scene file can't be found, we create a new one.
	// If the scene file is corrupt, we give up.
	try {
		m_defaultShader = new Shader("textured.vert.glsl", "textured.frag.glsl");
	} catch(const std::exception& exception) {
		g_logger.write(Logger::LOG_ERROR, exception.what());
	}
}

EditorScene::~EditorScene() {
	m_runConsole = false;
	std::cout << "Press ENTER to quit.\n";
	m_consoleThread.join();
	delete m_defaultShader;
}

// The editor works with the initial moment of a scene.
// We don't want these functions to do anything.
void EditorScene::update(std::chrono::milliseconds) {}
void EditorScene::simulate(std::chrono::milliseconds) {}

// Similarly, we don't want the Actors processing any input.
// Input processing is limited to editor and camera input.
void EditorScene::processInput(GLFWwindow& window) {
	m_inputModel.update(window);
	m_editorCamera.processInput(window);

	// Process command queue
	EditorScene::activeScene = this;
	std::lock_guard<std::mutex> lock(m_mutex);
	while(!m_commands.empty()) {
		std::string command = m_commands.front();
		std::cout << (PlCall("do_command", {{command.c_str()}}) ?
		                "Command Succeeded" :
		                "Command Failed")
		          << "\n";
		m_commands.pop();
	}
	EditorScene::activeScene = nullptr;
}

// The scene should draw as per usual, though.
//void EditorScene::draw() { Scene::draw(); }

void EditorScene::draw() {
	glm::mat4 projectionMatrix =
	  glm::perspective(45.0f,
	                   static_cast<float>(g_renderer.width()) /
	                     static_cast<float>(g_renderer.height()),
	                   0.1f,
	                   10000.0f);
	for(auto actor = m_actors.begin(); actor != m_actors.end(); ++actor) {
		m_defaultShader->setAmbience(m_ambience);

		// Send camera position to the GPU.
		m_defaultShader->setViewMatrix(m_editorCamera.getViewMatrix());
		m_defaultShader->setEyePosition(glm::vec3(m_editorCamera.getPosition()));

		m_defaultShader->setProjectionMatrix(projectionMatrix);
		m_defaultShader->setObjectID(actor->first);
		actor->second->draw(*m_defaultShader);
	}
}

// ---------------------------------------------------------------------------
//  Editor Functionality
// ---------------------------------------------------------------------------

void EditorScene::addActor(const std::string& name) {
	try {
		m_actors.emplace(
		  std::make_pair(++m_highestID, std::make_unique<Actor>(name)));
	} catch(const std::exception& exception) {
		g_logger.write(Logger::LOG_ERROR, exception.what());
		throw std::runtime_error("Failed to load Actor");
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Shanghai Jiao Tong University.
 *     All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS
 *  IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 *  express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 * For more about this software visit:
 *
 *      http://ipads.se.sjtu.edu.cn/projects/wukong
 *
 */

#pragma once

#include <map>
#include <string>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <boost/algorithm/string/predicate.hpp>

#include "global.hpp"
#include "rdma.hpp"
#include "assertion.hpp"

using namespace std;

static bool set_immutable_config(string cfg_name, string value)
{
    if (cfg_name == "global_num_proxies") {
        global_num_proxies = atoi(value.c_str());
        ASSERT(global_num_proxies > 0);
    } else if (cfg_name == "global_num_engines") {
        global_num_engines = atoi(value.c_str());
        ASSERT(global_num_engines > 0);
    } else if (cfg_name == "global_input_folder") {
        global_input_folder = value;

        // make sure to check that the global_input_folder is non-empty.
        if (global_input_folder.length() == 0) {
            logstream(LOG_ERROR) << "the directory path of RDF data can not be empty!"
                                 << "You should set \"global_input_folder\" in config file." << LOG_endl;
            exit(-1);
        }

        // force a "/" at the end of global_input_folder.
        if (global_input_folder[global_input_folder.length() - 1] != '/')
            global_input_folder = global_input_folder + "/";
    } else if (cfg_name == "global_data_port_base") {
        global_data_port_base = atoi(value.c_str());
        ASSERT(global_data_port_base > 0);
    } else if (cfg_name == "global_ctrl_port_base") {
        global_ctrl_port_base = atoi(value.c_str());
        ASSERT(global_ctrl_port_base > 0);
    } else if (cfg_name == "global_memstore_size_gb") {
        global_memstore_size_gb = atoi(value.c_str());
        ASSERT(global_memstore_size_gb > 0);
    } else if (cfg_name == "global_rdma_buf_size_mb") {
        if (RDMA::get_rdma().has_rdma())
            global_rdma_buf_size_mb = atoi(value.c_str());
        else
            global_rdma_buf_size_mb = 0;
        ASSERT(global_rdma_buf_size_mb >= 0);
    } else if (cfg_name == "global_rdma_rbf_size_mb") {
        if (RDMA::get_rdma().has_rdma())
            global_rdma_rbf_size_mb = atoi(value.c_str());
        else
            global_rdma_buf_size_mb = 0;
        ASSERT(global_rdma_rbf_size_mb >= 0);
    } else if (cfg_name == "global_generate_statistics") {
        global_generate_statistics = atoi(value.c_str());
    }
#ifdef USE_GPU
    else if (cfg_name == "global_num_gpus") {
        global_num_gpus = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_rdma_buf_size_mb") {
        if (RDMA::get_rdma().has_rdma())
            global_gpu_rdma_buf_size_mb = atoi(value.c_str());
        else
            global_gpu_rdma_buf_size_mb = 0;
        ASSERT(global_gpu_rdma_buf_size_mb >= 0);
    } else if (cfg_name == "global_gpu_max_element") {
        char *tmp;
        global_gpu_max_element = strtoull(value.c_str(), &tmp, 10);
    } else if (cfg_name == "global_gpu_num_keys_million") {
        global_gpu_num_keys_million = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_kvcache_size_gb") {
        global_gpu_kvcache_size_gb = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_key_block_size_mb") {
        global_gpu_key_block_size_mb = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_value_block_size_mb") {
        global_gpu_value_block_size_mb = atoi(value.c_str());
    }
#endif
    else
        return false;

    return true;
}

static bool set_mutable_config(string cfg_name, string value)
{
    if (cfg_name == "global_use_rdma") {
        if (atoi(value.c_str())) {
            if (!RDMA::get_rdma().has_rdma()) {
                logstream(LOG_ERROR) << "can't enable RDMA due to building Wukong w/o RDMA support!\n"
                                     << "HINT: please disable global_use_rdma in config file." << LOG_endl;
                global_use_rdma = false; // disable RDMA if no RDMA device
                return true;
            }

            global_use_rdma = true;
        } else {
            global_use_rdma = false;
        }
    } else if (cfg_name == "global_rdma_threshold") {
        global_rdma_threshold = atoi(value.c_str());
    } else if (cfg_name == "global_mt_threshold") {
        global_mt_threshold = atoi(value.c_str());
        ASSERT(global_mt_threshold > 0);
    } else if (cfg_name == "global_enable_caching") {
        global_enable_caching = atoi(value.c_str());
    } else if (cfg_name == "global_enable_workstealing") {
        global_enable_workstealing = atoi(value.c_str());
    } else if (cfg_name == "global_silent") {
        global_silent = atoi(value.c_str());
    } else if (cfg_name == "global_enable_planner") {
        global_enable_planner = atoi(value.c_str());
    } else if (cfg_name == "global_enable_vattr") {
        global_enable_vattr = atoi(value.c_str());
    } else {
        return false;
    }

    return true;
}

static void str2items(string str, map<string, string> &items)
{
    istringstream iss(str);
    string row, val;
    while (iss >> row >> val)
        items[row] = val;
}

static void file2items(string fname, map<string, string> &items)
{
    ifstream file(fname.c_str());
    if (!file) {
        logstream(LOG_ERROR) << fname << " does not exist." << LOG_endl;
        exit(0);
    }

    string line, row, val;
    while (std::getline(file, line)) {
        if (boost::starts_with(line, "#") || line.empty())
            continue; // skip comments and blank lines

        istringstream iss(line);
        iss >> row >> val;
        items[row] = val;
    }
}

/**
 * reload config
 */
void reload_config(string str)
{
    // TODO: it should ensure that there is no outstanding queries.

    // load config file
    map<string, string> items;
    str2items(str, items);

    for (auto const &entry : items)
        set_mutable_config(entry.first, entry.second);

    // limited the number of engines
    global_mt_threshold = max(1, min(global_mt_threshold, global_num_engines));

    return;
}

/**
 * load config
 */
void load_config(string fname, int num_servers)
{
    global_num_servers = num_servers;
    ASSERT(num_servers > 0);

    // load config file
    map<string, string> items;
    file2items(fname, items);

    for (auto const &entry : items) {
        if (!(set_immutable_config(entry.first, entry.second)
                || set_mutable_config(entry.first, entry.second))) {
            logstream(LOG_WARNING) << "unsupported configuration item! ("
                                   << entry.first << ")" << LOG_endl;
        }
    }

    // set the total number of threads
    global_num_threads = global_num_engines + global_num_proxies;

    // limited the number of engines
    global_mt_threshold = max(1, min(global_mt_threshold, global_num_engines));

    return;
}

/**
 * print current config
 */
void print_config(void)
{
    logstream(LOG_INFO) << "------ global configurations ------" << LOG_endl;

    // setting by config file
    logstream(LOG_INFO) << "the number of proxies: "        << global_num_proxies           << LOG_endl;
    logstream(LOG_INFO) << "the number of engines: "        << global_num_engines           << LOG_endl;
    logstream(LOG_INFO) << "global_input_folder: "      << global_input_folder          << LOG_endl;
    logstream(LOG_INFO) << "global_data_port_base: "        << global_data_port_base        << LOG_endl;
    logstream(LOG_INFO) << "global_ctrl_port_base: "        << global_ctrl_port_base        << LOG_endl;
    logstream(LOG_INFO) << "global_memstore_size_gb: "  << global_memstore_size_gb      << LOG_endl;
    logstream(LOG_INFO) << "global_rdma_buf_size_mb: "  << global_rdma_buf_size_mb      << LOG_endl;
    logstream(LOG_INFO) << "global_rdma_rbf_size_mb: "  << global_rdma_rbf_size_mb      << LOG_endl;
    logstream(LOG_INFO) << "global_use_rdma: "          << global_use_rdma              << LOG_endl;
    logstream(LOG_INFO) << "global_enable_caching: "        << global_enable_caching        << LOG_endl;
    logstream(LOG_INFO) << "global_enable_workstealing: "   << global_enable_workstealing   << LOG_endl;
    logstream(LOG_INFO) << "global_rdma_threshold: "        << global_rdma_threshold        << LOG_endl;
    logstream(LOG_INFO) << "global_mt_threshold: "      << global_mt_threshold          << LOG_endl;
    logstream(LOG_INFO) << "global_silent: "                << global_silent                << LOG_endl;
    logstream(LOG_INFO) << "global_enable_planner: "        << global_enable_planner        << LOG_endl;
    logstream(LOG_INFO) << "global_generate_statistics: "   << global_generate_statistics   << LOG_endl;
    logstream(LOG_INFO) << "global_enable_vattr: "      << global_enable_vattr          << LOG_endl;

    #ifdef USE_GPU
    logstream(LOG_INFO) << "global_num_gpus: "        << global_num_gpus        << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_rdma_buf_size_mb: "  << global_gpu_rdma_buf_size_mb  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_max_element: "  << global_gpu_max_element  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_num_keys_million: "  << global_gpu_num_keys_million  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_kvcache_size_gb: "  << global_gpu_kvcache_size_gb  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_key_block_size_mb: "  << global_gpu_key_block_size_mb  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_value_block_size_mb: "  << global_gpu_value_block_size_mb  << LOG_endl;
    #endif

    logstream(LOG_INFO) << "--" << LOG_endl;

    // compute from other settings
    logstream(LOG_INFO) << "the number of servers: "        << global_num_servers           << LOG_endl;
    logstream(LOG_INFO) << "the number of threads: "        << global_num_threads           << LOG_endl;

}
<commit_msg>format<commit_after>/*
 * Copyright (c) 2016 Shanghai Jiao Tong University.
 *     All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS
 *  IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 *  express or implied.  See the License for the specific language
 *  governing permissions and limitations under the License.
 *
 * For more about this software visit:
 *
 *      http://ipads.se.sjtu.edu.cn/projects/wukong
 *
 */

#pragma once

#include <map>
#include <string>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <boost/algorithm/string/predicate.hpp>

#include "global.hpp"
#include "rdma.hpp"
#include "assertion.hpp"

using namespace std;

static bool set_immutable_config(string cfg_name, string value)
{
    if (cfg_name == "global_num_proxies") {
        global_num_proxies = atoi(value.c_str());
        ASSERT(global_num_proxies > 0);
    } else if (cfg_name == "global_num_engines") {
        global_num_engines = atoi(value.c_str());
        ASSERT(global_num_engines > 0);
    } else if (cfg_name == "global_input_folder") {
        global_input_folder = value;

        // make sure to check that the global_input_folder is non-empty.
        if (global_input_folder.length() == 0) {
            logstream(LOG_ERROR) << "the directory path of RDF data can not be empty!"
                                 << "You should set \"global_input_folder\" in config file." << LOG_endl;
            exit(-1);
        }

        // force a "/" at the end of global_input_folder.
        if (global_input_folder[global_input_folder.length() - 1] != '/')
            global_input_folder = global_input_folder + "/";
    } else if (cfg_name == "global_data_port_base") {
        global_data_port_base = atoi(value.c_str());
        ASSERT(global_data_port_base > 0);
    } else if (cfg_name == "global_ctrl_port_base") {
        global_ctrl_port_base = atoi(value.c_str());
        ASSERT(global_ctrl_port_base > 0);
    } else if (cfg_name == "global_memstore_size_gb") {
        global_memstore_size_gb = atoi(value.c_str());
        ASSERT(global_memstore_size_gb > 0);
    } else if (cfg_name == "global_rdma_buf_size_mb") {
        if (RDMA::get_rdma().has_rdma())
            global_rdma_buf_size_mb = atoi(value.c_str());
        else
            global_rdma_buf_size_mb = 0;
        ASSERT(global_rdma_buf_size_mb >= 0);
    } else if (cfg_name == "global_rdma_rbf_size_mb") {
        if (RDMA::get_rdma().has_rdma())
            global_rdma_rbf_size_mb = atoi(value.c_str());
        else
            global_rdma_buf_size_mb = 0;
        ASSERT(global_rdma_rbf_size_mb >= 0);
    } else if (cfg_name == "global_generate_statistics") {
        global_generate_statistics = atoi(value.c_str());
    }
#ifdef USE_GPU
    else if (cfg_name == "global_num_gpus") {
        global_num_gpus = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_rdma_buf_size_mb") {
        if (RDMA::get_rdma().has_rdma())
            global_gpu_rdma_buf_size_mb = atoi(value.c_str());
        else
            global_gpu_rdma_buf_size_mb = 0;
        ASSERT(global_gpu_rdma_buf_size_mb >= 0);
    } else if (cfg_name == "global_gpu_max_element") {
        char *tmp;
        global_gpu_max_element = strtoull(value.c_str(), &tmp, 10);
    } else if (cfg_name == "global_gpu_num_keys_million") {
        global_gpu_num_keys_million = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_kvcache_size_gb") {
        global_gpu_kvcache_size_gb = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_key_block_size_mb") {
        global_gpu_key_block_size_mb = atoi(value.c_str());
    } else if (cfg_name == "global_gpu_value_block_size_mb") {
        global_gpu_value_block_size_mb = atoi(value.c_str());
    }
#endif
    else
        return false;

    return true;
}

static bool set_mutable_config(string cfg_name, string value)
{
    if (cfg_name == "global_use_rdma") {
        if (atoi(value.c_str())) {
            if (!RDMA::get_rdma().has_rdma()) {
                logstream(LOG_ERROR) << "can't enable RDMA due to building Wukong w/o RDMA support!\n"
                                     << "HINT: please disable global_use_rdma in config file." << LOG_endl;
                global_use_rdma = false; // disable RDMA if no RDMA device
                return true;
            }

            global_use_rdma = true;
        } else {
            global_use_rdma = false;
        }
    } else if (cfg_name == "global_rdma_threshold") {
        global_rdma_threshold = atoi(value.c_str());
    } else if (cfg_name == "global_mt_threshold") {
        global_mt_threshold = atoi(value.c_str());
        ASSERT(global_mt_threshold > 0);
    } else if (cfg_name == "global_enable_caching") {
        global_enable_caching = atoi(value.c_str());
    } else if (cfg_name == "global_enable_workstealing") {
        global_enable_workstealing = atoi(value.c_str());
    } else if (cfg_name == "global_silent") {
        global_silent = atoi(value.c_str());
    } else if (cfg_name == "global_enable_planner") {
        global_enable_planner = atoi(value.c_str());
    } else if (cfg_name == "global_enable_vattr") {
        global_enable_vattr = atoi(value.c_str());
    } else {
        return false;
    }

    return true;
}

static void str2items(string str, map<string, string> &items)
{
    istringstream iss(str);
    string row, val;
    while (iss >> row >> val)
        items[row] = val;
}

static void file2items(string fname, map<string, string> &items)
{
    ifstream file(fname.c_str());
    if (!file) {
        logstream(LOG_ERROR) << fname << " does not exist." << LOG_endl;
        exit(0);
    }

    string line, row, val;
    while (std::getline(file, line)) {
        if (boost::starts_with(line, "#") || line.empty())
            continue; // skip comments and blank lines

        istringstream iss(line);
        iss >> row >> val;
        items[row] = val;
    }
}

/**
 * reload config
 */
void reload_config(string str)
{
    // TODO: it should ensure that there is no outstanding queries.

    // load config file
    map<string, string> items;
    str2items(str, items);

    for (auto const &entry : items)
        set_mutable_config(entry.first, entry.second);

    // limited the number of engines
    global_mt_threshold = max(1, min(global_mt_threshold, global_num_engines));

    return;
}

/**
 * load config
 */
void load_config(string fname, int num_servers)
{
    global_num_servers = num_servers;
    ASSERT(num_servers > 0);

    // load config file
    map<string, string> items;
    file2items(fname, items);

    for (auto const &entry : items) {
        if (!(set_immutable_config(entry.first, entry.second)
                || set_mutable_config(entry.first, entry.second))) {
            logstream(LOG_WARNING) << "unsupported configuration item! ("
                                   << entry.first << ")" << LOG_endl;
        }
    }

    // set the total number of threads
    global_num_threads = global_num_engines + global_num_proxies;

    // limited the number of engines
    global_mt_threshold = max(1, min(global_mt_threshold, global_num_engines));

    return;
}

/**
 * print current config
 */
void print_config(void)
{
    logstream(LOG_INFO) << "------ global configurations ------" << LOG_endl;

    // setting by config file
    logstream(LOG_INFO) << "the number of proxies: "        << global_num_proxies           << LOG_endl;
    logstream(LOG_INFO) << "the number of engines: "        << global_num_engines           << LOG_endl;
    logstream(LOG_INFO) << "global_input_folder: "      << global_input_folder          << LOG_endl;
    logstream(LOG_INFO) << "global_data_port_base: "        << global_data_port_base        << LOG_endl;
    logstream(LOG_INFO) << "global_ctrl_port_base: "        << global_ctrl_port_base        << LOG_endl;
    logstream(LOG_INFO) << "global_memstore_size_gb: "  << global_memstore_size_gb      << LOG_endl;
    logstream(LOG_INFO) << "global_rdma_buf_size_mb: "  << global_rdma_buf_size_mb      << LOG_endl;
    logstream(LOG_INFO) << "global_rdma_rbf_size_mb: "  << global_rdma_rbf_size_mb      << LOG_endl;
    logstream(LOG_INFO) << "global_use_rdma: "          << global_use_rdma              << LOG_endl;
    logstream(LOG_INFO) << "global_enable_caching: "        << global_enable_caching        << LOG_endl;
    logstream(LOG_INFO) << "global_enable_workstealing: "   << global_enable_workstealing   << LOG_endl;
    logstream(LOG_INFO) << "global_rdma_threshold: "        << global_rdma_threshold        << LOG_endl;
    logstream(LOG_INFO) << "global_mt_threshold: "      << global_mt_threshold          << LOG_endl;
    logstream(LOG_INFO) << "global_silent: "                << global_silent                << LOG_endl;
    logstream(LOG_INFO) << "global_enable_planner: "        << global_enable_planner        << LOG_endl;
    logstream(LOG_INFO) << "global_generate_statistics: "   << global_generate_statistics   << LOG_endl;
    logstream(LOG_INFO) << "global_enable_vattr: "      << global_enable_vattr          << LOG_endl;

#ifdef USE_GPU
    logstream(LOG_INFO) << "global_num_gpus: "        << global_num_gpus        << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_rdma_buf_size_mb: "  << global_gpu_rdma_buf_size_mb  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_max_element: "  << global_gpu_max_element  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_num_keys_million: "  << global_gpu_num_keys_million  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_kvcache_size_gb: "  << global_gpu_kvcache_size_gb  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_key_block_size_mb: "  << global_gpu_key_block_size_mb  << LOG_endl;
    logstream(LOG_INFO) << "global_gpu_value_block_size_mb: "  << global_gpu_value_block_size_mb  << LOG_endl;
#endif

    logstream(LOG_INFO) << "--" << LOG_endl;

    // compute from other settings
    logstream(LOG_INFO) << "the number of servers: "        << global_num_servers           << LOG_endl;
    logstream(LOG_INFO) << "the number of threads: "        << global_num_threads           << LOG_endl;

}
<|endoftext|>


<commit_before>void p_f(char *s, int *pi) {
  int n = strlen(s);
  for(int i = 2; i <= s; i++) {
    pi[i]=pi[i-1];
    while(p[i]>0 and s[pi[i]]!=s[i])
      pi[i]=pi[pi[i]];
    if(s[pi[i]]==s[i-1])
      pi[i]++;
  }
}
<commit_msg>Correct Prefix Function<commit_after>void p_f(char *s, int *pi) {
    int n = strlen(s);
    for(int i = 2; i <= n; i++) {
        pi[i]=pi[i-1];
        while(pi[i]>0 and s[pi[i]]!=s[i])
            pi[i]=pi[pi[i]];
        if(s[pi[i]]==s[i-1])
            pi[i]++;
    }
}
<|endoftext|>