<commit_before>//
//  paddle.cc
//  AirHockey
//
//  Created by Jonathan Sharkey on 10-04-12.
//  Copyright 2010 Sharkable. All rights reserved.
//

#include "airhockey/entities/paddle.h"

#include <cmath>

#include "airhockey/entities/puck.h"
#include "gameengine/game_engine.h"
#include "gameengine/resource_loader.h"
#include "soundengine/sound_player.h"

Paddle::Paddle(sp<GameEngine> game_engine, int player_id, PaddleSize size, bool player_controlled,
               ComputerAI ai_level, vector<sp<Puck> > &pucks)
    : RoundThing(game_engine),
      player_id_(player_id),
      player_controlled_(player_controlled),
      ready_to_play_(true),
      ai_level_(ai_level),
      pucks_(pucks),
      target_left_corner_(false),
      target_right_corner_(false),
      target_away_from_corner_(false) {
  if (player_id == PLAYER_1) {
    switch (size) {
      case psSmall:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_1_small"));
        break;
      case psMedium:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_1_medium"));
        break;
      case psLarge:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_1_large"));
        break;
    }
  } else {
    switch (size) {
      case psSmall:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_2_small"));
        break;
      case psMedium:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_2_medium"));
        break;
      case psLarge:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_2_large"));
        break;
    }
  }

  radius_ = PADDLE_RADIUS[size];
  mass_ = PADDLE_MASS;
  friction_ = player_controlled_ ? PADDLE_FRICTION : PADDLE_AI_FRICTION;
}

void Paddle::SetInitialPositionForPlayer(int playerId) {
  switch (player_id_) {
    case PLAYER_1: {
      x_ = PADDLE_1_X;
      y_ = PADDLE_1_Y;
      break;
    }
    case PLAYER_2: {
      x_ = PADDLE_2_X;
      y_ = PADDLE_2_Y;
      break;
    }
  }
}

void Paddle::KeepInPlayerBounds() {
  switch (player_id_) {
    case PLAYER_1: {
      if (y_ + radius_ > RINK_BOTTOM_Y) {
        y_ = RINK_BOTTOM_Y - radius_;
        vy_ = 0;
      } else if (y_ - radius_ < SCREEN_HEIGHT/2+1) {
        y_ = SCREEN_HEIGHT/2+1 + radius_;
        vy_ = 0;
      }
      break;
    }
    case PLAYER_2: {
      if (y_ - radius_ < RINK_TOP_Y) {
        y_ = RINK_TOP_Y + radius_;
        vy_ = 0;
      } else if (y_ + radius_ > SCREEN_HEIGHT/2-1) {
        y_ = SCREEN_HEIGHT/2-1 - radius_;
        vy_ = 0;
      }
      break;
    }
  }
  if (x_ - radius_ < RINK_LEFT_X) {
    x_ = RINK_LEFT_X + radius_;
    vx_ = 0;
  } else if (x_ + radius_ > RINK_RIGHT_X) {
    x_ = RINK_RIGHT_X - radius_;
    vx_ = 0;
  }
}

void Paddle::RunAITick() {
  double speed = 0;
  switch (ai_level_) {
    case caiBad:
      speed = 1;
      break;
    case caiGood:
      speed = 1.5;
      break;
    case caiExcellent:
      speed = 2;
      break;
    case caiAmazing:
      speed = 4.5;
      break;
  }

  // Find the puck that will reach the paddle first.
  Puck *target = NULL;
  double bestTime;

  for (int i = 0; i < pucks_.size(); i++) {
    Puck *puck = pucks_[i].get();
    if (!puck->is_active()) {
      continue;
    }
    if (puck->vy() > 4) {
      continue;
    }
    double timeToReach = 999999;
    if (puck->vy() < 0) {
      timeToReach = fabs((y_ - puck->y()) / puck->vy());
    }
    if (puck->y() - puck->radius() > SCREEN_HEIGHT/2) {
      continue;
    }
    if (target == NULL || timeToReach < bestTime ||
        (timeToReach == bestTime && puck->y() < target->y())) {
      target = puck;
      bestTime = timeToReach;
    }
  }

  if (!target) {
    target_left_corner_ = target_right_corner_ = target_away_from_corner_ = false;
  }

  double targetX;
  double targetY;

  if (!target_away_from_corner_ && target && target->y() <= RINK_TOP_Y + radius_ &&
      fabs(target->vx()) < 5 && fabs(target->vy()) < 5) {
    if (target->x() < SCREEN_WIDTH / 2) {
      target_left_corner_ = true;
    } else {
      target_right_corner_ = true;
    }
  }

  if (target_left_corner_) {
    targetX = RINK_LEFT_X + radius_;
    targetY = RINK_TOP_Y + radius_;
    if (Overlaps(target)) {
      target_left_corner_ = false;
      target_away_from_corner_ = true;
    }
  } else if (target_right_corner_) {
    targetX = RINK_RIGHT_X - radius_;
    targetY = RINK_TOP_Y + radius_;
    if (Overlaps(target)) {
      target_right_corner_ = false;
      target_away_from_corner_ = true;
    }
  } else if (target_away_from_corner_) {
    targetX = SCREEN_WIDTH / 2;
    targetY = RINK_TOP_Y + radius_;
    if (x_ >= SCREEN_WIDTH / 2 - 5 && x_ <= SCREEN_WIDTH / 2 + 5) {
      target_away_from_corner_ = false;
    }
  } else if (target) {
    if (target->y() > y_) {
      targetX = target->x();
      targetY = target->y() - target->radius();
    } else {
      targetY = target->y() - target->radius() - radius_ - 20;
      if (target->x() < x_) {
        targetX = target->x() + target->radius() + radius_ + 20;
      } else {
        targetX = target->x() - target->radius() - radius_ - 20;
      }
    }
  } else if (ai_level_ >= caiExcellent) {
    targetX = PADDLE_2_X;
    targetY = PADDLE_2_Y;
  } else if (ai_level_ == caiGood) {
    targetX = PADDLE_2_X;
    targetY = y_;
  } else {
    targetX = x_;
    targetY = y_;
  }

  // Get direction of target.
  double dx = targetX - x_;
  double dy = targetY - y_;
  double adx = fabs(dx);
  double ady = fabs(dy);

  if (adx <= speed && ady <= speed) {
    vx_ = 0;
    vy_ = 0;
    x_ = targetX;
    y_ = targetY;
  } else {
    if (fabs(dx) < fabs(vx_)) {
      vx_ = dx;
    } else if (fabs(dy) < fabs(vy_)) {
      vy_ = dy;
    }

    double dL = sqrt(dx*dx + dy*dy);
    double nx = dx / dL;
    double ny = dy / dL;
    vx_ += speed * nx;
    vy_ += speed * ny;
  }
}

// ViewEntity

void Paddle::Update() {
  // Computer AI
  if (!player_controlled_) {
    RunAITick();
  }
  RoundThing::Update();
}

void Paddle::Render() {
  sprite_.Draw(game_point_make(x_ - sprite_.content_size().width/2,
                               y_ - sprite_.content_size().height/2),
               0, (is_grabbed() || !player_controlled_ ? 1.0 : 0.5), 1);
}

// RoundThing

void Paddle::DidBounceOff(ViewEntity *other) {
  if (typeid(*other) == typeid(Puck)) {
    SoundPlayer::instance()->playSound(kSoundPaddleHit);
  }
}

bool Paddle::ContainsTouch(Touch *touch) {
  GamePoint p = touch->location();
  if (p.x < 0 || p.x >= SCREEN_WIDTH) {
    return false;
  }
  switch (player_id_) {
    case PLAYER_1:
      return p.y >= SCREEN_HEIGHT/2 && p.y < SCREEN_HEIGHT;
      break;
    case PLAYER_2:
      return p.y < SCREEN_HEIGHT/2 && p.y >= 0;
      break;
  }
  return false;
}

bool Paddle::IsGrabbable() {
  return player_controlled_;
}

bool Paddle::IsMovable() {
  return ready_to_play_;
}
<commit_msg>Don't move paddle when touching the edge. This lets you hit pause button without moving the paddle.<commit_after>//
//  paddle.cc
//  AirHockey
//
//  Created by Jonathan Sharkey on 10-04-12.
//  Copyright 2010 Sharkable. All rights reserved.
//

#include "airhockey/entities/paddle.h"

#include <cmath>

#include "airhockey/entities/puck.h"
#include "gameengine/game_engine.h"
#include "gameengine/resource_loader.h"
#include "soundengine/sound_player.h"

Paddle::Paddle(sp<GameEngine> game_engine, int player_id, PaddleSize size, bool player_controlled,
               ComputerAI ai_level, vector<sp<Puck> > &pucks)
    : RoundThing(game_engine),
      player_id_(player_id),
      player_controlled_(player_controlled),
      ready_to_play_(true),
      ai_level_(ai_level),
      pucks_(pucks),
      target_left_corner_(false),
      target_right_corner_(false),
      target_away_from_corner_(false) {
  if (player_id == PLAYER_1) {
    switch (size) {
      case psSmall:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_1_small"));
        break;
      case psMedium:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_1_medium"));
        break;
      case psLarge:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_1_large"));
        break;
    }
  } else {
    switch (size) {
      case psSmall:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_2_small"));
        break;
      case psMedium:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_2_medium"));
        break;
      case psLarge:
        sprite_.set_texture(ResourceLoader::Instance().TextureWithName("paddle_2_large"));
        break;
    }
  }

  radius_ = PADDLE_RADIUS[size];
  mass_ = PADDLE_MASS;
  friction_ = player_controlled_ ? PADDLE_FRICTION : PADDLE_AI_FRICTION;
}

void Paddle::SetInitialPositionForPlayer(int playerId) {
  switch (player_id_) {
    case PLAYER_1: {
      x_ = PADDLE_1_X;
      y_ = PADDLE_1_Y;
      break;
    }
    case PLAYER_2: {
      x_ = PADDLE_2_X;
      y_ = PADDLE_2_Y;
      break;
    }
  }
}

void Paddle::KeepInPlayerBounds() {
  switch (player_id_) {
    case PLAYER_1: {
      if (y_ + radius_ > RINK_BOTTOM_Y) {
        y_ = RINK_BOTTOM_Y - radius_;
        vy_ = 0;
      } else if (y_ - radius_ < SCREEN_HEIGHT/2+1) {
        y_ = SCREEN_HEIGHT/2+1 + radius_;
        vy_ = 0;
      }
      break;
    }
    case PLAYER_2: {
      if (y_ - radius_ < RINK_TOP_Y) {
        y_ = RINK_TOP_Y + radius_;
        vy_ = 0;
      } else if (y_ + radius_ > SCREEN_HEIGHT/2-1) {
        y_ = SCREEN_HEIGHT/2-1 - radius_;
        vy_ = 0;
      }
      break;
    }
  }
  if (x_ - radius_ < RINK_LEFT_X) {
    x_ = RINK_LEFT_X + radius_;
    vx_ = 0;
  } else if (x_ + radius_ > RINK_RIGHT_X) {
    x_ = RINK_RIGHT_X - radius_;
    vx_ = 0;
  }
}

void Paddle::RunAITick() {
  double speed = 0;
  switch (ai_level_) {
    case caiBad:
      speed = 1;
      break;
    case caiGood:
      speed = 1.5;
      break;
    case caiExcellent:
      speed = 2;
      break;
    case caiAmazing:
      speed = 4.5;
      break;
  }

  // Find the puck that will reach the paddle first.
  Puck *target = NULL;
  double bestTime;

  for (int i = 0; i < pucks_.size(); i++) {
    Puck *puck = pucks_[i].get();
    if (!puck->is_active()) {
      continue;
    }
    if (puck->vy() > 4) {
      continue;
    }
    double timeToReach = 999999;
    if (puck->vy() < 0) {
      timeToReach = fabs((y_ - puck->y()) / puck->vy());
    }
    if (puck->y() - puck->radius() > SCREEN_HEIGHT/2) {
      continue;
    }
    if (target == NULL || timeToReach < bestTime ||
        (timeToReach == bestTime && puck->y() < target->y())) {
      target = puck;
      bestTime = timeToReach;
    }
  }

  if (!target) {
    target_left_corner_ = target_right_corner_ = target_away_from_corner_ = false;
  }

  double targetX;
  double targetY;

  if (!target_away_from_corner_ && target && target->y() <= RINK_TOP_Y + radius_ &&
      fabs(target->vx()) < 5 && fabs(target->vy()) < 5) {
    if (target->x() < SCREEN_WIDTH / 2) {
      target_left_corner_ = true;
    } else {
      target_right_corner_ = true;
    }
  }

  if (target_left_corner_) {
    targetX = RINK_LEFT_X + radius_;
    targetY = RINK_TOP_Y + radius_;
    if (Overlaps(target)) {
      target_left_corner_ = false;
      target_away_from_corner_ = true;
    }
  } else if (target_right_corner_) {
    targetX = RINK_RIGHT_X - radius_;
    targetY = RINK_TOP_Y + radius_;
    if (Overlaps(target)) {
      target_right_corner_ = false;
      target_away_from_corner_ = true;
    }
  } else if (target_away_from_corner_) {
    targetX = SCREEN_WIDTH / 2;
    targetY = RINK_TOP_Y + radius_;
    if (x_ >= SCREEN_WIDTH / 2 - 5 && x_ <= SCREEN_WIDTH / 2 + 5) {
      target_away_from_corner_ = false;
    }
  } else if (target) {
    if (target->y() > y_) {
      targetX = target->x();
      targetY = target->y() - target->radius();
    } else {
      targetY = target->y() - target->radius() - radius_ - 20;
      if (target->x() < x_) {
        targetX = target->x() + target->radius() + radius_ + 20;
      } else {
        targetX = target->x() - target->radius() - radius_ - 20;
      }
    }
  } else if (ai_level_ >= caiExcellent) {
    targetX = PADDLE_2_X;
    targetY = PADDLE_2_Y;
  } else if (ai_level_ == caiGood) {
    targetX = PADDLE_2_X;
    targetY = y_;
  } else {
    targetX = x_;
    targetY = y_;
  }

  // Get direction of target.
  double dx = targetX - x_;
  double dy = targetY - y_;
  double adx = fabs(dx);
  double ady = fabs(dy);

  if (adx <= speed && ady <= speed) {
    vx_ = 0;
    vy_ = 0;
    x_ = targetX;
    y_ = targetY;
  } else {
    if (fabs(dx) < fabs(vx_)) {
      vx_ = dx;
    } else if (fabs(dy) < fabs(vy_)) {
      vy_ = dy;
    }

    double dL = sqrt(dx*dx + dy*dy);
    double nx = dx / dL;
    double ny = dy / dL;
    vx_ += speed * nx;
    vy_ += speed * ny;
  }
}

// ViewEntity

void Paddle::Update() {
  // Computer AI
  if (!player_controlled_) {
    RunAITick();
  }
  RoundThing::Update();
}

void Paddle::Render() {
  sprite_.Draw(game_point_make(x_ - sprite_.content_size().width/2,
                               y_ - sprite_.content_size().height/2),
               0, (is_grabbed() || !player_controlled_ ? 1.0 : 0.5), 1);
}

// RoundThing

void Paddle::DidBounceOff(ViewEntity *other) {
  if (typeid(*other) == typeid(Puck)) {
    SoundPlayer::instance()->playSound(kSoundPaddleHit);
  }
}

bool Paddle::ContainsTouch(Touch *touch) {
  GamePoint p = touch->location();
  if (p.x < 0 || p.x >= SCREEN_WIDTH) {
    return false;
  }
  switch (player_id_) {
    case PLAYER_1:
      return p.y >= SCREEN_HEIGHT / 2 && p.y < RINK_BOTTOM_Y && p.x >= RINK_LEFT_X &&
          p.x < RINK_RIGHT_X;
      break;
    case PLAYER_2:
      return p.y < SCREEN_HEIGHT / 2 && p.y >= RINK_TOP_Y && p.x >= RINK_LEFT_X &&
          p.x < RINK_RIGHT_X;
      break;
  }
  return false;
}

bool Paddle::IsGrabbable() {
  return player_controlled_;
}

bool Paddle::IsMovable() {
  return ready_to_play_;
}
<|endoftext|>


<commit_before>#include "Text.h"

namespace hm
{
	Text::Text()
	{
        text = "Hume Library";
        setPosition(0, 0);
	}

	Text::Text(std::string text, Font& font)
	{
		this->text = text;
        setText(text, font);
        setPosition(0, 0);
	}

    Text::~Text()
    {
        std::cout << "Freeing sdltext surface..." << std::endl;
        SDL_FreeSurface(sdltext);
    }

	SDL_Surface* Text::getSurface()
	{
		return sdltext;
	}

	void Text::setText(std::string text, Font& font)
	{
        std::cout << "Font: " << font.getFont() << std::endl;
        std::cout << "RM: " << font.getRenderMode() << std::endl;
		this->text = text;

		// Check for font.
		if(font.getFont() == NULL)
		{
			std::cout << "Can't set text. Font is NULL." << std::endl;
			return;
        }

        RenderMode rm = font.getRenderMode();
        if(rm == SOLID)
            sdltext = TTF_RenderText_Solid(font.getFont(), text.c_str(), font.getColor());
        if(rm == SHADED)
            sdltext = TTF_RenderText_Shaded(font.getFont(), text.c_str(), font.getColor(), font.getbColor());
        if(rm == BLENDED)
            sdltext = TTF_RenderText_Blended(font.getFont(), text.c_str(), font.getColor());
        optimize();

		return;
	}

	std::string Text::getText()
	{
		return text;
    }

    void Text::setPosition(int x, int y)
    {
        position.x = x;
        position.y = y;
        return;
    }

	SDL_Rect* Text::getPosition()
    {
		return &position;
	}

    void Text::optimize()
    {
        SDL_Surface* unoptimizedText = sdltext;
        sdltext = SDL_DisplayFormat(unoptimizedText);
        SDL_FreeSurface(unoptimizedText);

        return;
    }
}
<commit_msg>Adding checking in the Text class before freeing the SDL_Surface in the destructor.<commit_after>#include "Text.h"

namespace hm
{
	Text::Text()
	{
        text = "Hume Library";
        setPosition(0, 0);
	}

	Text::Text(std::string text, Font& font)
	{
		this->text = text;
        setText(text, font);
        setPosition(0, 0);
	}

    Text::~Text()
    {
        if(sdltext != NULL)
        {
            SDL_FreeSurface(sdltext);
            sdltext = NULL;
        }
    }

	SDL_Surface* Text::getSurface()
	{
		return sdltext;
	}

	void Text::setText(std::string text, Font& font)
	{
        std::cout << "Font: " << font.getFont() << std::endl;
        std::cout << "RM: " << font.getRenderMode() << std::endl;
		this->text = text;

		// Check for font.
		if(font.getFont() == NULL)
		{
			std::cout << "Can't set text. Font is NULL." << std::endl;
			return;
        }

        RenderMode rm = font.getRenderMode();
        if(rm == SOLID)
            sdltext = TTF_RenderText_Solid(font.getFont(), text.c_str(), font.getColor());
        if(rm == SHADED)
            sdltext = TTF_RenderText_Shaded(font.getFont(), text.c_str(), font.getColor(), font.getbColor());
        if(rm == BLENDED)
            sdltext = TTF_RenderText_Blended(font.getFont(), text.c_str(), font.getColor());
        optimize();

		return;
	}

	std::string Text::getText()
	{
		return text;
    }

    void Text::setPosition(int x, int y)
    {
        position.x = x;
        position.y = y;
        return;
    }

	SDL_Rect* Text::getPosition()
    {
		return &position;
	}

    void Text::optimize()
    {
        SDL_Surface* unoptimizedText = sdltext;
        sdltext = SDL_DisplayFormat(unoptimizedText);
        SDL_FreeSurface(unoptimizedText);

        return;
    }
}
<|endoftext|>


<commit_before>#pragma once

#include "clonable.hpp"
#include "../builtin/container/native/tnarr.hpp"
#include "validable.hpp"

namespace wrd {

	class ases;

    /// node provides common API to manipulate its sub nodes.
    class node : public instance, public clonable, public validable {
        WRD(INTERFACE(node, instance))

    public:
        node& operator[](const std::string& name) const { return sub(name); }

    public:
        wbool isSub(const type& it) const { return getType().isSub(it); }
        wbool isSuper(const type& it) const { return getType().isSuper(it); }
        template <typename T>
        wbool isSub() const { return getType().isSub<T>(); }
        template <typename T>
        wbool isSuper() const { return getType().isSuper<T>(); }

        virtual ncontainer& subs() = 0;
        const ncontainer& subs() const WRD_UNCONST_FUNC(subs())

        template <typename T>
        node& sub(std::function<wbool(const T&)> l) const {
            return subs().get<T>(l);
        }
        node& sub(const std::string& name) const;
        node& sub(const std::string& name, const ncontainer& args);
        node& sub(const std::string& name, const wtypes& types);
        node& sub(const std::string& name, const ncontainer& args) const;
        node& sub(const std::string& name, const wtypes& types) const;

        template <typename T>
        tnarr<T> subAll(std::function<wbool(const T&)> l) const {
            return subs().getAll<T>(l);
        }
        narr subAll(const std::string& name) const;
        narr subAll(const std::string& name, const ncontainer& args);
        narr subAll(const std::string& name, const wtypes& types);
        narr subAll(const std::string& name, const ncontainer& args) const;
        narr subAll(const std::string& name, const wtypes& types) const;

        virtual wbool canRun(const wtypes& typs) const = 0;
        wbool canRun(const containable& args) const {
            return canRun(createTypesFromArgs(args));
        }

        virtual str run(const containable& args) = 0;
        str run();

        /// release all holding resources and ready to be terminated.
        /// @remark some class won't be able to reinitialize after rel() got called.
        virtual void rel() {}

        virtual const std::string& getName() const {
            static std::string dummy = "";
            return dummy;
        }

        template <typename T>
        wbool is() const {
            return is(ttype<T>::get());
        }
        wbool is(const type& to) const {
			return getType().is(to);
        }
        template <typename T>
        tstr<T> as() const {
            return as(ttype<T>::get());
        }
        str as(const type& to) const {
			return getType().as(*this, to);
		}

        template <typename T>
        wbool isImpli() const {
            return isImpli(ttype<T>::get());
        }
        wbool isImpli(const type& to) const {
			return getType().isImpli(to);
        }
        template <typename T>
        tstr<T> asImpli() const {
			return asImpli(ttype<T>::get());
		}
        str asImpli(const type& to) const {
			return getType().asImpli(*this, to);
		}

        wbool isValid() const override {
            return true;
        }

        /// getType() returns what it is. opposite to it, this returns what this class will
        /// represents after evaluation.
        ///
        /// for example, the 'expr' class has derived from this node class. and if an user call the
        /// funcs to get type of it, class 'wtype' of 'expr' will be returned.
        /// but if that user call the 'getEvalType()' then the 'expr' object evaluate its terms and
        /// returns type of the output. it could be integer if it was 'addExpr' and all terms are
        /// constructed with integers.
        virtual const wtype& getEvalType() const {
            return getType();
        }

        static wtypes createTypesFromArgs(const containable& args) {
            wtypes ret;
            for(iter e=args.begin(); e ;e++)
                ret.push_back((wtype*) &e->getEvalType());
            return ret;
        }
    };

    /// managed object.
    /*class NObj : public obj {
        WRD(CLASS(NObj, obj))

    public:
        NObj(): super("", new narr()) {}
    };*/

    /*
    // iteration #1:
    // 강제로 func를 상속한 c++ 클래스를 만들고 그 안에서 hello world 찍기
    // * node의 기본적인 API의 틀만 적기
    // * 아무런 구현이 없는 wtype클래스의 injection
    // * func.run()의 가구현
    // * ref 구현
    class node : public instance, public containable {
        WRD(CLASS(node, instance))

    public:
        wbool isInit() {
            return _isInit;
        }

        virtual wbool init() {
            if(isInit()) return true;

            _setInit(true)
            return true;
        }

        virtual void rel() {
            _setInit(false);
        }

        void _setInit(wbool newVal) { _isInit = newVal; }
        virtual SequentialContainer getSubs() = 0;

        using containable::get;
        template <typename T>
        tarr<T> get(std::string name, wtype... args);
        arr get(std::string name, wtype... args);
        template <typename T>
        tarr<T&> get(std::string name, wtype args[]);
        arr get(std::string name, wtype args[]);
        template <typename T>
        tarr<T> get(std::string);
        arr get(std::string);

        /// @param args nullable.
        virtual ret<ref> run(arr& args);
        ret<ref> run() { return run(nulOf<arr>()); }

        node& getOrigin();

    protected:
        wbool del(node& it) override;
        wbool add(node& it) override;

    private:
        wbool _isInit;
    };

    class ref : public node, tbindable<node> {
        WRD(CLASS(tref, node))

        node& _get() override { return *_ptr; }
        // override get() funcs...
        // isInit...

        wbool isBind() { return _ptr.isBind(); }
        // override tbindable...

        ret<ref> run(arr& args) override;

        str _ptr;
    };

    template <typename T>
    class tref : public ref {
    };

    class func : public scope {
        WRD(CLASS(func, scope))

    public:
        ret<ref> run(arr& args) override;
    };

    // iteration #2:
    // 강제로 AST를 조직함. Console 이라는 obj 안에 있는 void print(msg str)를 실행하는 callExpr 실행
    // 강제로 obj를 scope에 등록을 해둔 상태에서 callexpr를 실행함.
    // * obj
    // * str
    // * wtype의 묵시적 형변환
    // * 묵시적 형변환을 수행하는 func.run()
    // * scope의 obj scope 등록 기능
    // * obj의 scope 등록
   class obj : public scope {
   };
    class str : public obj {
    };
    class Chain {
    };
    class frame : ? {
    };
    class stackFrame : public ?? {
    };
    class Expr : public node {
    };
    class CallExpr : public Expr {
    };
   class wtype : public type {
   };

    // iteration #3:
    // BlockExpr 로 앞선 callExpr를 하도록 AST를 작성. 변수의 정의, 접근을 수행하는 expr 추가.
    // sys 라는 module 을 강제로 만들고 그 안에 console obj를 둠. origin obj를 정의함.
    // * module scope 기반으로 한 origin obj의 scope 구성
    class Module : ? {
    };
    class Moduler : ? {
    };
    class BlockExpr : {
    };
    class AccessExpr : ? {
    };
    class DeclExpr : ? {
    };

    // iteration #4:
    // bridge API를 만들어서 외부의 test c++ 클래스를 불러와 moduler에 넣을 수 있도록 함.
    // 매우 단순한 test c++ 모듈 1개 작성
    // * module import.

    // iteration #5:
    // Visitation과 bison을 활용해서 func 호출과 정의 할 수있게 만듬
    // * bison, lex
    // * Visitor, visitation
    // * funcDefExpr
    class Visitable {
    };
    class Visitation : public instance, public Visitable {
    };
    template <typename T, typename S = Visitation>
    class TVisitation : public S {
    };
    class Visitor : public Thing, public Visitable {
    };
    template <typename T>
    class TVisitor : public Visitor {
    };

    // iteration #5:
    // 간단한 메인함수 안에 test 모듈의 print(msg str)를 호출 하게 .wrd파일의 interpreting
    // * importExpr
    // * moduler는 시작시 scanning
    // * 만든걸 모두 연동
    // * 코드를 수행하는 thread
    class ImportExpr : public Expr {
    };
    class thread : public ? {
    }; */
}
<commit_msg>wrd: style: remove codes of prototype version<commit_after>#pragma once

#include "clonable.hpp"
#include "../builtin/container/native/tnarr.hpp"
#include "validable.hpp"

namespace wrd {

	class ases;

    /// node provides common API to manipulate its sub nodes.
    class node : public instance, public clonable, public validable {
        WRD(INTERFACE(node, instance))

    public:
        node& operator[](const std::string& name) const { return sub(name); }

    public:
        wbool isSub(const type& it) const { return getType().isSub(it); }
        wbool isSuper(const type& it) const { return getType().isSuper(it); }
        template <typename T>
        wbool isSub() const { return getType().isSub<T>(); }
        template <typename T>
        wbool isSuper() const { return getType().isSuper<T>(); }

        virtual ncontainer& subs() = 0;
        const ncontainer& subs() const WRD_UNCONST_FUNC(subs())

        template <typename T>
        node& sub(std::function<wbool(const T&)> l) const {
            return subs().get<T>(l);
        }
        node& sub(const std::string& name) const;
        node& sub(const std::string& name, const ncontainer& args);
        node& sub(const std::string& name, const wtypes& types);
        node& sub(const std::string& name, const ncontainer& args) const;
        node& sub(const std::string& name, const wtypes& types) const;

        template <typename T>
        tnarr<T> subAll(std::function<wbool(const T&)> l) const {
            return subs().getAll<T>(l);
        }
        narr subAll(const std::string& name) const;
        narr subAll(const std::string& name, const ncontainer& args);
        narr subAll(const std::string& name, const wtypes& types);
        narr subAll(const std::string& name, const ncontainer& args) const;
        narr subAll(const std::string& name, const wtypes& types) const;

        virtual wbool canRun(const wtypes& typs) const = 0;
        wbool canRun(const containable& args) const {
            return canRun(createTypesFromArgs(args));
        }

        virtual str run(const containable& args) = 0;
        str run();

        /// release all holding resources and ready to be terminated.
        /// @remark some class won't be able to reinitialize after rel() got called.
        virtual void rel() {}

        virtual const std::string& getName() const {
            static std::string dummy = "";
            return dummy;
        }

        template <typename T>
        wbool is() const {
            return is(ttype<T>::get());
        }
        wbool is(const type& to) const {
			return getType().is(to);
        }
        template <typename T>
        tstr<T> as() const {
            return as(ttype<T>::get());
        }
        str as(const type& to) const {
			return getType().as(*this, to);
		}

        template <typename T>
        wbool isImpli() const {
            return isImpli(ttype<T>::get());
        }
        wbool isImpli(const type& to) const {
			return getType().isImpli(to);
        }
        template <typename T>
        tstr<T> asImpli() const {
			return asImpli(ttype<T>::get());
		}
        str asImpli(const type& to) const {
			return getType().asImpli(*this, to);
		}

        wbool isValid() const override {
            return true;
        }

        /// getType() returns what it is. opposite to it, this returns what this class will
        /// represents after evaluation.
        ///
        /// for example, the 'expr' class has derived from this node class. and if an user call the
        /// funcs to get type of it, class 'wtype' of 'expr' will be returned.
        /// but if that user call the 'getEvalType()' then the 'expr' object evaluate its terms and
        /// returns type of the output. it could be integer if it was 'addExpr' and all terms are
        /// constructed with integers.
        virtual const wtype& getEvalType() const {
            return getType();
        }

        static wtypes createTypesFromArgs(const containable& args) {
            wtypes ret;
            for(iter e=args.begin(); e ;e++)
                ret.push_back((wtype*) &e->getEvalType());
            return ret;
        }
    };
}
<|endoftext|>


<commit_before>#include "joedb/concurrency/Embedded_Connection.h"
#include "joedb/journal/File.h"
#include "joedb/io/main_exception_catcher.h"
#include "joedb/io/run_interpreted_client.h"

namespace joedb
{
 /////////////////////////////////////////////////////////////////////////////
 static int main(int argc, char **argv)
 /////////////////////////////////////////////////////////////////////////////
 {
  if (argc != 3)
  {
   std::cerr << "usage: " << argv[0] << " <client.joedb> <server.joedb>\n";
   return 1;
  }
  else
  {
   const char * const client_file_name = argv[1];
   const char * const server_file_name = argv[2];

   File server_file(server_file_name, Open_Mode::write_existing_or_create_new);
   Embedded_Connection connection(server_file);
   Interpreted_Client client(connection, server_file);
   run_interpreted_client(connection, client_file_name);
  }

  return 0;
 }
}

/////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
/////////////////////////////////////////////////////////////////////////////
{
 return joedb::main_exception_catcher(joedb::main, argc, argv);
}
<commit_msg>switch client<->server on the command line for joedb_embedded_client<commit_after>#include "joedb/concurrency/Embedded_Connection.h"
#include "joedb/journal/File.h"
#include "joedb/io/main_exception_catcher.h"
#include "joedb/io/run_interpreted_client.h"

namespace joedb
{
 /////////////////////////////////////////////////////////////////////////////
 static int main(int argc, char **argv)
 /////////////////////////////////////////////////////////////////////////////
 {
  if (argc != 3)
  {
   std::cerr << "usage: " << argv[0] << " <server.joedb> <client.joedb>\n";
   return 1;
  }
  else
  {
   const char * const server_file_name = argv[1];
   const char * const client_file_name = argv[2];

   File server_file(server_file_name, Open_Mode::write_existing_or_create_new);
   Embedded_Connection connection(server_file);
   Interpreted_Client client(connection, server_file);
   run_interpreted_client(connection, client_file_name);
  }

  return 0;
 }
}

/////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
/////////////////////////////////////////////////////////////////////////////
{
 return joedb::main_exception_catcher(joedb::main, argc, argv);
}
<|endoftext|>


<commit_before>

AliAnalysisTaskEMCALIsoPhoton *AddTaskEMCALIsoPhoton()
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskEMCALIsoPhoton", "No analysis manager to connect to.");
    return NULL;
  }

  // Create the task and configure it.
  //===========================================================================
  AliAnalysisTaskEMCALIsoPhoton* ana = new  AliAnalysisTaskEMCALIsoPhoton("");

  ana->SelectCollisionCandidates( AliVEvent::kEMC1 | AliVEvent::kMB | AliVEvent::kEMC7 | AliVEvent::kINT7);

  Bool_t isMC = (mgr->GetMCtruthEventHandler() != NULL);

  //ana->SetClusThreshold(clusTh);
  ana->SetTrainMode(kTRUE);
  //ana->SetGridMode(kTRUE);
  // ana->SetMcMode(isMC);

  AliESDtrackCuts *cutsp = new AliESDtrackCuts;
  cutsp->SetMinNClustersTPC(70);
  cutsp->SetMinRatioCrossedRowsOverFindableClustersTPC(0.8);
  cutsp->SetMaxChi2PerClusterTPC(4);
  cutsp->SetRequireTPCRefit(kTRUE);
  cutsp->SetAcceptKinkDaughters(kFALSE);
  cutsp->SetMaxDCAToVertexZ(3.2);
  cutsp->SetMaxDCAToVertexXY(2.4);
  cutsp->SetDCAToVertex2D(kTRUE);
  cutsp->SetPtRange(0.2);
  cutsp->SetEtaRange(-1.0,1.0);
  ana->SetPrimTrackCuts(cutsp);
  ana->SetPeriod(period.Data());
  if(period.Contains("11"))
    ana->SetGeoName("EMCAL_COMPLETEV1");
  else
    ana->SetGeoName("EMCAL_FIRSTYEARV1");

  mgr->AddTask(ana);

  // Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("histosEMCALIsoPhoton",
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							    Form("%s", AliAnalysisManager::GetCommonFileName()));

  mgr->ConnectInput  (ana, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput (ana, 1, coutput1 );

  return ana;
}
<commit_msg>bugfix<commit_after>

AliAnalysisTaskEMCALIsoPhoton *AddTaskEMCALIsoPhoton(
TString period = "LHC11d"
)
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskEMCALIsoPhoton", "No analysis manager to connect to.");
    return NULL;
  }

  // Create the task and configure it.
  //===========================================================================
  AliAnalysisTaskEMCALIsoPhoton* ana = new  AliAnalysisTaskEMCALIsoPhoton("");

  ana->SelectCollisionCandidates( AliVEvent::kEMC1 | AliVEvent::kMB | AliVEvent::kEMC7 | AliVEvent::kINT7);

  Bool_t isMC = (mgr->GetMCtruthEventHandler() != NULL);

  //ana->SetClusThreshold(clusTh);

  ana->SetTrainMode(kTRUE);
  //ana->SetGridMode(kTRUE);
  // ana->SetMcMode(isMC);

  AliESDtrackCuts *cutsp = new AliESDtrackCuts;
  cutsp->SetMinNClustersTPC(70);
  cutsp->SetMinRatioCrossedRowsOverFindableClustersTPC(0.8);
  cutsp->SetMaxChi2PerClusterTPC(4);
  cutsp->SetRequireTPCRefit(kTRUE);
  cutsp->SetAcceptKinkDaughters(kFALSE);
  cutsp->SetMaxDCAToVertexZ(3.2);
  cutsp->SetMaxDCAToVertexXY(2.4);
  cutsp->SetDCAToVertex2D(kTRUE);
  cutsp->SetPtRange(0.2);
  cutsp->SetEtaRange(-1.0,1.0);
  ana->SetPrimTrackCuts(cutsp);
  ana->SetPeriod(period.Data());
  if(period.Contains("11"))
    ana->SetGeoName("EMCAL_COMPLETEV1");
  else
    ana->SetGeoName("EMCAL_FIRSTYEARV1");

  mgr->AddTask(ana);

  // Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("histosEMCALIsoPhoton",
							    TList::Class(),AliAnalysisManager::kOutputContainer,
							    Form("%s", AliAnalysisManager::GetCommonFileName()));

  mgr->ConnectInput  (ana, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput (ana, 1, coutput1 );

  return ana;
}
<|endoftext|>


<commit_before>#include "chainerx/native/native_device.h"

#include <cstdint>

#include "chainerx/array.h"
#include "chainerx/axes.h"
#include "chainerx/device.h"
#include "chainerx/dtype.h"
#include "chainerx/kernels/reduction.h"
#include "chainerx/kernels/sorting.h"
#include "chainerx/macro.h"
#include "chainerx/native/kernel_regist.h"
#include "chainerx/native/reduce.h"
#include "chainerx/numeric.h"
#include "chainerx/numeric_limits.h"
#include "chainerx/shape.h"

namespace chainerx {
namespace native {
namespace {

class NativeArgMaxKernel : public ArgMaxKernel {
public:
    void Call(const Array& a, const Axes& axis, const Array& out) override {
        CHAINERX_ASSERT(std::all_of(axis.begin(), axis.end(), [&a](int8_t i) { return a.shape()[i] > 0; }));
        CHAINERX_ASSERT(internal::IsValidReductionShape(a.shape(), axis, out.shape(), false));
        a.device().CheckDevicesCompatible(a, out);

        VisitDtype(a.dtype(), [&a, &axis, &out](auto pt) {
            using T = typename decltype(pt)::type;
            struct Impl {
                struct MaxAndArgMax {
                    T max;
                    int64_t argmax;
                };

                MaxAndArgMax Identity() { return {T{}, -1}; }
                MaxAndArgMax MapIn(T in, int64_t index) { return {in, index}; }
                void Reduce(MaxAndArgMax next, MaxAndArgMax& accum) {
                    if (accum.argmax < 0 || accum.max < next.max) {
                        accum = next;
                    }
                }
                int64_t MapOut(MaxAndArgMax accum) { return accum.argmax; }
            };
            Reduce<T, int64_t>(a, axis, out, Impl{});
        });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(ArgMaxKernel, NativeArgMaxKernel);

class NativeArgMinKernel : public ArgMinKernel {
public:
    void Call(const Array& a, const Axes& axis, const Array& out) override {
        CHAINERX_ASSERT(std::all_of(axis.begin(), axis.end(), [&a](int8_t i) { return a.shape()[i] > 0; }));
        CHAINERX_ASSERT(internal::IsValidReductionShape(a.shape(), axis, out.shape(), false));
        a.device().CheckDevicesCompatible(a, out);

        VisitDtype(a.dtype(), [&a, &axis, &out](auto pt) {
            using T = typename decltype(pt)::type;
            struct Impl {
                struct MinAndArgMin {
                    T min;
                    int64_t argmin;
                };

                MinAndArgMin Identity() { return {T{}, -1}; }
                MinAndArgMin MapIn(T in, int64_t index) { return {in, index}; }
                void Reduce(MinAndArgMin next, MinAndArgMin& accum) {
                    if (accum.argmin < 0 || accum.min > next.min) {
                        accum = next;
                    }
                }
                int64_t MapOut(MinAndArgMin accum) { return accum.argmin; }
            };
            Reduce<T, int64_t>(a, axis, out, Impl{});
        });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(ArgMinKernel, NativeArgMinKernel);

class NativeSumKernel : public SumKernel {
public:
    void Call(const Array& a, const Axes& axis, const Array& out) override {
        CHAINERX_ASSERT(internal::IsValidReductionShape(a.shape(), axis, out.shape(), true));
        a.device().CheckDevicesCompatible(a, out);

        auto do_sum = [&a, &axis, &out](auto in_pt, auto out_pt) {
            using In = typename decltype(in_pt)::type;
            using Out = typename decltype(out_pt)::type;
            using Accum = std::conditional_t<std::is_same<Out, Float16>{}, float, Out>;
            struct Impl {
                Accum Identity() { return Accum{0}; }
                Accum MapIn(In in, int64_t /*index*/) { return static_cast<Accum>(in); }
                void Reduce(Accum next, Accum& accum) { accum += next; }
                Out MapOut(Accum accum) { return static_cast<Out>(accum); }
            };
            Reduce<In, Out>(a, axis, out, Impl{});
        };

        VisitDtype(out.dtype(), [a_dtype = a.dtype(), &do_sum](auto out_pt) { VisitDtype(a_dtype, do_sum, out_pt); });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(SumKernel, NativeSumKernel);

class NativeCumsumKernel : public CumsumKernel {
public:
    void Call(const Array& a, int8_t axis, const Array& out) override {
        a.device().CheckDevicesCompatible(a, out);

        VisitDtype(out.dtype(), [&a, axis, &out](auto pt) {
            using T = typename decltype(pt)::type;

            IndexableArray<const T> a_iarray{a};
            IndexableArray<T> out_iarray{out};
            Indexer<> out_indexer{out.shape()};
            Indexer<> prev_indexer{a.shape()};

            int64_t axis_dim = a.shape()[axis];

            // left: set of input dimensions lower than the axis
            // right: set of input dimensions higher than the axis
            Shape left_shape{a.shape().begin(), a.shape().begin() + axis};
            Shape right_shape{a.shape().begin() + (axis + 1), a.shape().end()};
            Shape axis_shape{axis_dim};  // always ndim==1

            Indexer<> left_indexer{left_shape};
            Indexer<> right_indexer{right_shape};
            Indexer<> indices_indexer{axis_shape};

            auto it_left = left_indexer.It(0);
            auto it_right = right_indexer.It(0);
            auto it_out = out_indexer.It(0);
            auto it_prev = prev_indexer.It(0);

            // Copy
            for (auto it = out_indexer.It(0); it; ++it) {
                out_iarray[it] = a_iarray[it];
            }

            for (auto it = indices_indexer.It(1); it; ++it) {
                int64_t index = it.raw_index();
                index = index % axis_dim;
                CHAINERX_ASSERT(0 <= index);
                CHAINERX_ASSERT(index < axis_dim);

                it_out.CopyIndex(it, it_left.ndim());

                for (it_left.Restart(); it_left; ++it_left) {
                    it_out.CopyIndex(it_left);

                    for (it_right.Restart(); it_right; ++it_right) {
                        it_out.CopyIndex(it_right, it_left.ndim() + it.ndim());
                        it_prev.CopyIndex(it_out);
                        it_prev.index()[axis] -= 1;
                        native_internal::StorageToDataType<T>(out_iarray[it_out]) +=
                                native_internal::StorageToDataType<T>(out_iarray[it_prev]);
                        it_prev.index()[axis] += 1;
                    }
                }
            }
        });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(CumsumKernel, NativeCumsumKernel);

}  // namespace
}  // namespace native
}  // namespace chainerx
<commit_msg>Add missing header<commit_after>#include "chainerx/native/native_device.h"

#include <cstdint>

#include "chainerx/array.h"
#include "chainerx/axes.h"
#include "chainerx/device.h"
#include "chainerx/dtype.h"
#include "chainerx/kernels/reduction.h"
#include "chainerx/kernels/sorting.h"
#include "chainerx/macro.h"
#include "chainerx/native/data_type.h"
#include "chainerx/native/kernel_regist.h"
#include "chainerx/native/reduce.h"
#include "chainerx/numeric.h"
#include "chainerx/numeric_limits.h"
#include "chainerx/shape.h"

namespace chainerx {
namespace native {
namespace {

class NativeArgMaxKernel : public ArgMaxKernel {
public:
    void Call(const Array& a, const Axes& axis, const Array& out) override {
        CHAINERX_ASSERT(std::all_of(axis.begin(), axis.end(), [&a](int8_t i) { return a.shape()[i] > 0; }));
        CHAINERX_ASSERT(internal::IsValidReductionShape(a.shape(), axis, out.shape(), false));
        a.device().CheckDevicesCompatible(a, out);

        VisitDtype(a.dtype(), [&a, &axis, &out](auto pt) {
            using T = typename decltype(pt)::type;
            struct Impl {
                struct MaxAndArgMax {
                    T max;
                    int64_t argmax;
                };

                MaxAndArgMax Identity() { return {T{}, -1}; }
                MaxAndArgMax MapIn(T in, int64_t index) { return {in, index}; }
                void Reduce(MaxAndArgMax next, MaxAndArgMax& accum) {
                    if (accum.argmax < 0 || accum.max < next.max) {
                        accum = next;
                    }
                }
                int64_t MapOut(MaxAndArgMax accum) { return accum.argmax; }
            };
            Reduce<T, int64_t>(a, axis, out, Impl{});
        });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(ArgMaxKernel, NativeArgMaxKernel);

class NativeArgMinKernel : public ArgMinKernel {
public:
    void Call(const Array& a, const Axes& axis, const Array& out) override {
        CHAINERX_ASSERT(std::all_of(axis.begin(), axis.end(), [&a](int8_t i) { return a.shape()[i] > 0; }));
        CHAINERX_ASSERT(internal::IsValidReductionShape(a.shape(), axis, out.shape(), false));
        a.device().CheckDevicesCompatible(a, out);

        VisitDtype(a.dtype(), [&a, &axis, &out](auto pt) {
            using T = typename decltype(pt)::type;
            struct Impl {
                struct MinAndArgMin {
                    T min;
                    int64_t argmin;
                };

                MinAndArgMin Identity() { return {T{}, -1}; }
                MinAndArgMin MapIn(T in, int64_t index) { return {in, index}; }
                void Reduce(MinAndArgMin next, MinAndArgMin& accum) {
                    if (accum.argmin < 0 || accum.min > next.min) {
                        accum = next;
                    }
                }
                int64_t MapOut(MinAndArgMin accum) { return accum.argmin; }
            };
            Reduce<T, int64_t>(a, axis, out, Impl{});
        });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(ArgMinKernel, NativeArgMinKernel);

class NativeSumKernel : public SumKernel {
public:
    void Call(const Array& a, const Axes& axis, const Array& out) override {
        CHAINERX_ASSERT(internal::IsValidReductionShape(a.shape(), axis, out.shape(), true));
        a.device().CheckDevicesCompatible(a, out);

        auto do_sum = [&a, &axis, &out](auto in_pt, auto out_pt) {
            using In = typename decltype(in_pt)::type;
            using Out = typename decltype(out_pt)::type;
            using Accum = std::conditional_t<std::is_same<Out, Float16>{}, float, Out>;
            struct Impl {
                Accum Identity() { return Accum{0}; }
                Accum MapIn(In in, int64_t /*index*/) { return static_cast<Accum>(in); }
                void Reduce(Accum next, Accum& accum) { accum += next; }
                Out MapOut(Accum accum) { return static_cast<Out>(accum); }
            };
            Reduce<In, Out>(a, axis, out, Impl{});
        };

        VisitDtype(out.dtype(), [a_dtype = a.dtype(), &do_sum](auto out_pt) { VisitDtype(a_dtype, do_sum, out_pt); });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(SumKernel, NativeSumKernel);

class NativeCumsumKernel : public CumsumKernel {
public:
    void Call(const Array& a, int8_t axis, const Array& out) override {
        a.device().CheckDevicesCompatible(a, out);

        VisitDtype(out.dtype(), [&a, axis, &out](auto pt) {
            using T = typename decltype(pt)::type;

            IndexableArray<const T> a_iarray{a};
            IndexableArray<T> out_iarray{out};
            Indexer<> out_indexer{out.shape()};
            Indexer<> prev_indexer{a.shape()};

            int64_t axis_dim = a.shape()[axis];

            // left: set of input dimensions lower than the axis
            // right: set of input dimensions higher than the axis
            Shape left_shape{a.shape().begin(), a.shape().begin() + axis};
            Shape right_shape{a.shape().begin() + (axis + 1), a.shape().end()};
            Shape axis_shape{axis_dim};  // always ndim==1

            Indexer<> left_indexer{left_shape};
            Indexer<> right_indexer{right_shape};
            Indexer<> indices_indexer{axis_shape};

            auto it_left = left_indexer.It(0);
            auto it_right = right_indexer.It(0);
            auto it_out = out_indexer.It(0);
            auto it_prev = prev_indexer.It(0);

            // Copy
            for (auto it = out_indexer.It(0); it; ++it) {
                out_iarray[it] = a_iarray[it];
            }

            for (auto it = indices_indexer.It(1); it; ++it) {
                int64_t index = it.raw_index();
                index = index % axis_dim;
                CHAINERX_ASSERT(0 <= index);
                CHAINERX_ASSERT(index < axis_dim);

                it_out.CopyIndex(it, it_left.ndim());

                for (it_left.Restart(); it_left; ++it_left) {
                    it_out.CopyIndex(it_left);

                    for (it_right.Restart(); it_right; ++it_right) {
                        it_out.CopyIndex(it_right, it_left.ndim() + it.ndim());
                        it_prev.CopyIndex(it_out);
                        it_prev.index()[axis] -= 1;
                        native_internal::StorageToDataType<T>(out_iarray[it_out]) +=
                                native_internal::StorageToDataType<T>(out_iarray[it_prev]);
                        it_prev.index()[axis] += 1;
                    }
                }
            }
        });
    }
};

CHAINERX_NATIVE_REGISTER_KERNEL(CumsumKernel, NativeCumsumKernel);

}  // namespace
}  // namespace native
}  // namespace chainerx
<|endoftext|>


<commit_before>AliAnalysisTaskSELc2V0bachelor *AddTaskLc2V0bachelor(TString finname="Lc2V0bachelorCuts.root",
						     Bool_t theMCon=kFALSE,
						     Bool_t onTheFly=kFALSE,
						     Bool_t writeVariableTree=kTRUE,
						     Int_t nTour=0,
						     Bool_t additionalChecks=kFALSE,
						     Bool_t trackRotation=kFALSE)

{

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskLc2V0bachelor", "No analysis manager to connect to.");
    return NULL;
  }

  // cuts are stored in a TFile generated by makeTFile4CutsLc2V0bachelor.C in ./macros/
  // set there the cuts!!!!!

  Bool_t stdcuts=kFALSE;
  TFile* filecuts;
  if( finname.EqualTo("") ) {
    stdcuts=kTRUE;
  } else {
      filecuts=TFile::Open(finname.Data());
      if(!filecuts ||(filecuts&& !filecuts->IsOpen())){
	AliFatal("Input file not found : check your cut object");
      }
  }

  cout << " Is it std on not std cut? " << stdcuts << endl;
  AliRDHFCutsLctoV0* RDHFCutsLctoV0anal = new AliRDHFCutsLctoV0();
  if (stdcuts) RDHFCutsLctoV0anal->SetStandardCutsPP2010();
  else RDHFCutsLctoV0anal = (AliRDHFCutsLctoV0*)filecuts->Get("LctoV0AnalysisCuts");
  RDHFCutsLctoV0anal->SetName("LctoV0AnalysisCuts");
  RDHFCutsLctoV0anal->SetMinPtCandidate(-1.);
  RDHFCutsLctoV0anal->SetMaxPtCandidate(10000.);

  // mm let's see if everything is ok
  if (!RDHFCutsLctoV0anal) {
    cout << "Specific AliRDHFCutsLctoV0 not found\n";
    return;
  }

  //CREATE THE TASK

  printf("CREATE TASK\n");
  AliAnalysisTaskSELc2V0bachelor *task = new AliAnalysisTaskSELc2V0bachelor("AliAnalysisTaskSELc2V0bachelor",RDHFCutsLctoV0anal,onTheFly,writeVariableTree,additionalChecks,trackRotation);
  task->SetAdditionalChecks(additionalChecks);
  task->SetMC(theMCon);
  task->SetK0SAnalysis(kTRUE);
  task->SetDebugLevel(0);
  mgr->AddTask(task);

  // Create and connect containers for input/output
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += ":PWG3_D2H_Lc2pK0S_";
  outputfile += nTour;

  mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());

  // ----- output data -----
  AliAnalysisDataContainer *coutput1   = mgr->CreateContainer(Form("chist%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // general histos
  mgr->ConnectOutput(task,1,coutput1);
  AliAnalysisDataContainer *coutputLc2 = mgr->CreateContainer(Form("Lc2pK0Scounter%1d",nTour),AliNormalizationCounter::Class(),AliAnalysisManager::kOutputContainer, outputfile.Data()); //counter
  mgr->ConnectOutput(task,2,coutputLc2);
  AliAnalysisDataContainer *coutputLc3 = mgr->CreateContainer(Form("Lc2pK0SCuts%1d",nTour),AliRDHFCutsLctoV0::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // cuts
  mgr->ConnectOutput(task,3,coutputLc3);
  if (!writeVariableTree) {
    AliAnalysisDataContainer *coutputLc4 = mgr->CreateContainer(Form("Lc2pK0SAll%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // production histos
    mgr->ConnectOutput(task,4,coutputLc4);
    AliAnalysisDataContainer *coutputLc5 = mgr->CreateContainer(Form("Lc2pK0SPIDBach%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer, outputfile.Data()); // analysis histos
    mgr->ConnectOutput(task,5,coutputLc5);

    if (trackRotation) {
      AliAnalysisDataContainer *coutputLc6 = mgr->CreateContainer(Form("Lc2pK0SPIDBachTR%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer, outputfile.Data()); // analysis histos
      mgr->ConnectOutput(task,6,coutputLc6);
    }

  } else {
    AliAnalysisDataContainer *coutputLc4 = mgr->CreateContainer(Form("Lc2pK0Svariables%1d",nTour),TTree::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // variables tree
    mgr->ConnectOutput(task,4,coutputLc4);
  }

  return task;

}
<commit_msg>Add flags for rotational background<commit_after>AliAnalysisTaskSELc2V0bachelor *AddTaskLc2V0bachelor(TString finname="Lc2V0bachelorCuts.root",
						     Bool_t theMCon=kFALSE,
						     Bool_t onTheFly=kFALSE,
						     Bool_t writeVariableTree=kTRUE,
						     Int_t nTour=0,
						     Bool_t additionalChecks=kFALSE,
						     Bool_t trackRotation=kFALSE,
						     Int_t nRot=9,
						     Double_t pTmin=0.,
						     Double_t pTmax=999.,
						     Double_t minRotAngle=5.*TMath::Pi()/6.,
						     Double_t maxRotAngle=7.*TMath::Pi()/6.)
{

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskLc2V0bachelor", "No analysis manager to connect to.");
    return NULL;
  }

  if (writeVariableTree && trackRotation)
    trackRotation=kFALSE;

  // cuts are stored in a TFile generated by makeTFile4CutsLc2V0bachelor.C in ./macros/
  // set there the cuts!!!!!

  Bool_t stdcuts=kFALSE;
  TFile* filecuts;
  if( finname.EqualTo("") ) {
    stdcuts=kTRUE;
  } else {
      filecuts=TFile::Open(finname.Data());
      if(!filecuts ||(filecuts&& !filecuts->IsOpen())){
	AliFatal("Input file not found : check your cut object");
      }
  }

  cout << " Is it std on not std cut? " << stdcuts << endl;
  AliRDHFCutsLctoV0* RDHFCutsLctoV0anal = new AliRDHFCutsLctoV0();
  if (stdcuts) RDHFCutsLctoV0anal->SetStandardCutsPP2010();
  else RDHFCutsLctoV0anal = (AliRDHFCutsLctoV0*)filecuts->Get("LctoV0AnalysisCuts");
  RDHFCutsLctoV0anal->SetName("LctoV0AnalysisCuts");
  RDHFCutsLctoV0anal->SetMinPtCandidate(-1.);
  RDHFCutsLctoV0anal->SetMaxPtCandidate(10000.);

  // mm let's see if everything is ok
  if (!RDHFCutsLctoV0anal) {
    cout << "Specific AliRDHFCutsLctoV0 not found\n";
    return;
  }

  //CREATE THE TASK

  printf("CREATE TASK\n");
  AliAnalysisTaskSELc2V0bachelor *task = new AliAnalysisTaskSELc2V0bachelor("AliAnalysisTaskSELc2V0bachelor",RDHFCutsLctoV0anal,onTheFly,writeVariableTree,additionalChecks,trackRotation);
  task->SetAdditionalChecks(additionalChecks);
  task->SetMC(theMCon);
  task->SetK0SAnalysis(kTRUE);
  task->SetDebugLevel(0);
  task->SetNRotations(nRot);
  task->SetPtMinToFillTheTree(pTmin);
  task->SetPtMaxToFillTheTree(pTmax);
  task->SetMinAngleForRot(minRotAngle);
  task->SetMaxAngleForRot(maxRotAngle);
  mgr->AddTask(task);

  // Create and connect containers for input/output
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += ":PWG3_D2H_Lc2pK0S_";
  outputfile += nTour;

  mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());

  // ----- output data -----
  AliAnalysisDataContainer *coutput1   = mgr->CreateContainer(Form("chist%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // general histos
  mgr->ConnectOutput(task,1,coutput1);
  AliAnalysisDataContainer *coutputLc2 = mgr->CreateContainer(Form("Lc2pK0Scounter%1d",nTour),AliNormalizationCounter::Class(),AliAnalysisManager::kOutputContainer, outputfile.Data()); //counter
  mgr->ConnectOutput(task,2,coutputLc2);
  AliAnalysisDataContainer *coutputLc3 = mgr->CreateContainer(Form("Lc2pK0SCuts%1d",nTour),AliRDHFCutsLctoV0::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // cuts
  mgr->ConnectOutput(task,3,coutputLc3);
  if (!writeVariableTree) {
    AliAnalysisDataContainer *coutputLc4 = mgr->CreateContainer(Form("Lc2pK0SAll%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // production histos
    mgr->ConnectOutput(task,4,coutputLc4);
    AliAnalysisDataContainer *coutputLc5 = mgr->CreateContainer(Form("Lc2pK0SPIDBach%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer, outputfile.Data()); // analysis histos
    mgr->ConnectOutput(task,5,coutputLc5);

    if (trackRotation) {
      AliAnalysisDataContainer *coutputLc6 = mgr->CreateContainer(Form("Lc2pK0SPIDBachTR%1d",nTour),TList::Class(),AliAnalysisManager::kOutputContainer, outputfile.Data()); // analysis histos
      mgr->ConnectOutput(task,6,coutputLc6);
    }

  } else {
    AliAnalysisDataContainer *coutputLc4 = mgr->CreateContainer(Form("Lc2pK0Svariables%1d",nTour),TTree::Class(),AliAnalysisManager::kOutputContainer,outputfile.Data()); // variables tree
    mgr->ConnectOutput(task,4,coutputLc4);
  }

  return task;

}
<|endoftext|>


<commit_before>#include <math.h>
#include <algorithm>
#include "PerPixelMesh.hpp"

PerPixelMesh::PerPixelMesh(int width, int height) : width(width), height(height), size (width * height),
		p(width * height, Point(0,0)),
		p_original(width * height, Point(0,0)),
		identity(width * height, PerPixelContext(0,0,0,0,0,0))
		{
		for (int j=0;j<height;j++)
			for(int i=0;i<width;i++)
			{
				int index = j * width + i;

						float xval=i/(float)(width-1);
						float yval=-((j/(float)(height-1))-1);

						p[index].x = xval;
						p[index].y = yval;

						p_original[index].x = xval;
						p_original[index].y = yval;

						identity[index].x= xval;
						identity[index].y= yval;

						//identity[index].x= (xval-.5)*2;
						//identity[index].y= (yval-.5)*2;

						identity[index].i= i;
						identity[index].j= j;

						identity[index].rad=hypot ( ( xval-.5 ) *2, ( yval-.5 ) *2 ) * .7071067;
						identity[index].theta=atan2 ( ( yval-.5 ) *2 ,  ( xval-.5 ) *2  );
			}
		}

void PerPixelMesh::Reset()
{
	std::copy(p_original.begin(), p_original.end(), p.begin());
}

Point::Point(float x, float y)
	: x(x), y(y) {}
PerPixelContext::PerPixelContext(float x, float y, float rad, float theta, int i, int j)
	: x(x), y(y), rad(rad), theta(theta), i(i), j(j) {}
<commit_msg>Parralellize mesh reset<commit_after>#include <math.h>
#include <algorithm>
#include "PerPixelMesh.hpp"
#include "omptl/omptl"
#include "omptl/omptl_algorithm"

PerPixelMesh::PerPixelMesh(int width, int height) : width(width), height(height), size (width * height),
		p(width * height, Point(0,0)),
		p_original(width * height, Point(0,0)),
		identity(width * height, PerPixelContext(0,0,0,0,0,0))
		{
		for (int j=0;j<height;j++)
			for(int i=0;i<width;i++)
			{
				int index = j * width + i;

						float xval=i/(float)(width-1);
						float yval=-((j/(float)(height-1))-1);

						p[index].x = xval;
						p[index].y = yval;

						p_original[index].x = xval;
						p_original[index].y = yval;

						identity[index].x= xval;
						identity[index].y= yval;

						//identity[index].x= (xval-.5)*2;
						//identity[index].y= (yval-.5)*2;

						identity[index].i= i;
						identity[index].j= j;

						identity[index].rad=hypot ( ( xval-.5 ) *2, ( yval-.5 ) *2 ) * .7071067;
						identity[index].theta=atan2 ( ( yval-.5 ) *2 ,  ( xval-.5 ) *2  );
			}
		}

void PerPixelMesh::Reset()
{
	omptl::copy(p_original.begin(), p_original.end(), p.begin());
}

Point::Point(float x, float y)
	: x(x), y(y) {}
PerPixelContext::PerPixelContext(float x, float y, float rad, float theta, int i, int j)
	: x(x), y(y), rad(rad), theta(theta), i(i), j(j) {}
<|endoftext|>


<commit_before>#include "vagdec.h"
#pragma warning(disable : 4996)

#include <vector>
#include <algorithm>

class VBStream
{
public:
	static const size_t VB_BLOCK_SIZE = 512 * 16 * 2;

	VBStream( FILE* file, int sample_rate, int stereo, int size )
		: stream( file ), fileSize( size + sizeof(VAG_HEADER) )
	{
		memset( &virtualHeader, 0, sizeof(virtualHeader) );
		virtualHeader.VAG[0] = 'V';
		virtualHeader.VAG[1] = 'A';
		virtualHeader.VAG[2] = 'G';
		virtualHeader.field_3 = 'p';

		virtualHeader.sample_rate = _byteswap_ulong(sample_rate);
		virtualHeader.stereo = _byteswap_ulong(stereo);
		virtualHeader.size = _byteswap_ulong(size);

		blockBuffer = stereo != 0 ? (U8*)AIL_mem_alloc_lock( VB_BLOCK_SIZE ) : nullptr;
	}

	VBStream( const VBStream& ) = delete;
	VBStream& operator = ( const VBStream& rhs ) = delete;

	VBStream( VBStream&& rhs ) = default;
	VBStream& operator = ( VBStream&& rhs ) = default;

	~VBStream()
	{
		if ( blockBuffer != nullptr )
		{
			AIL_mem_free_lock( blockBuffer );
			blockBuffer = nullptr;
		}
	}

	bool UsesInterleave() const { return blockBuffer != nullptr; }

	FILE* GetStream() const { return stream; }

	static S32 GetBlock(S32 offset)
	{
		// VB_BLOCK_SIZE = 2^14
		return offset >> 14;
	}

	U32 ReadFile( void FAR* Buffer, U32 Bytes )
	{
		if ( virtualCursor == 0 )
		{
			VAG_HEADER* header = (VAG_HEADER*)Buffer;
			*header = virtualHeader;

			size_t bytesRead = sizeof(VAG_HEADER);
			if ( !UsesInterleave() )
			{
				bytesRead += fread( &header[1], 1, Bytes-sizeof(*header), stream );
			}
			else
			{
				ReadBlockAndInterleave();

				memcpy( &header[1], blockBuffer, Bytes-sizeof(*header) );
				bytesRead += Bytes-sizeof(*header);
			}
			virtualCursor += bytesRead;
			return bytesRead;
		}

		if ( currentBlockCursor + Bytes >= VB_BLOCK_SIZE )
		{
			size_t firstRead = VB_BLOCK_SIZE - currentBlockCursor;

			memcpy( Buffer, blockBuffer+currentBlockCursor, firstRead );
			ReadBlockAndInterleave();
			memcpy( (U8*)Buffer+firstRead, blockBuffer, Bytes-firstRead );

			currentBlockCursor += Bytes-firstRead;
		}
		else
		{
			memcpy( Buffer, blockBuffer+currentBlockCursor, Bytes );
			currentBlockCursor += Bytes;
		}
		virtualCursor += Bytes;
		return Bytes;
	}

	S32 SeekFile( S32 Offset, U32 Type )
	{
		if ( Type == AIL_FILE_SEEK_CURRENT ) Offset += virtualCursor;
		else if ( Type == AIL_FILE_SEEK_END ) Offset = fileSize - Offset;

		S32 OffsetNoHeader = Offset - sizeof(VAG_HEADER);
		S32 CursorNoHeader = virtualCursor - sizeof(VAG_HEADER);

		if ( OffsetNoHeader <= 0 )
		{
			// Seeks to header - do nothing since next ReadFile flushes everything anyway
			fseek( stream, 0, SEEK_SET );
			virtualCursor = 0;
			return 0;
		}

		if ( UsesInterleave() )
		{
			// Is within the same block?
			if ( GetBlock(OffsetNoHeader) == GetBlock(CursorNoHeader) )
			{
				// Do nothing, just move cursor
				currentBlockCursor = OffsetNoHeader - CursorNoHeader;
			}
			else
			{
				// Read new block
				fseek( stream, OffsetNoHeader & ~(VB_BLOCK_SIZE-1), SEEK_SET );
				ReadBlockAndInterleave();
				currentBlockCursor = OffsetNoHeader & (VB_BLOCK_SIZE-1);
			}
		}
		else
		{
			fseek( stream, OffsetNoHeader, SEEK_SET );
		}
		virtualCursor = Offset;
		return virtualCursor;
	}

private:
	void ReadBlockAndInterleave( )
	{
		const size_t VB_SAMPLE_SIZE = 0x10;

		U8 buf[VB_BLOCK_SIZE];
		size_t bytesRead = fread( buf, 1, VB_BLOCK_SIZE, stream );

		// Interleave
		if ( bytesRead == VB_BLOCK_SIZE )
		{
			U8* leftChannel = buf;
			U8* rightChannel = buf+(VB_BLOCK_SIZE/2);
			U8* output = blockBuffer;

			for ( int i = 0; i < 512; ++i )
			{
				memcpy( output, leftChannel, VB_SAMPLE_SIZE );
				memcpy( output+VB_SAMPLE_SIZE, rightChannel, VB_SAMPLE_SIZE );
				leftChannel += VB_SAMPLE_SIZE;
				rightChannel += VB_SAMPLE_SIZE;
				output += 2*VB_SAMPLE_SIZE;
			}
		}
		currentBlockCursor = 0;
	}

private:
	FILE* stream;
	VAG_HEADER virtualHeader;
	U8* blockBuffer;
	S32 currentBlockCursor = 0, virtualCursor = 0;
	S32 fileSize;
};

static std::vector<FILE*> adfStreams;
static std::vector<VBStream> vbStreams;

static void XORADFStream( void FAR* Buffer, size_t size )
{
	U8* buf = (U8*)Buffer;

	while ( size != 0 && ((U32)buf & 3) != 0 )
	{
		*buf ++ ^= 0x22;
		--size;
	}

	while ( size >= 4 )
	{
		*(U32*)buf ^= 0x22222222;
		buf += 4;
		size -= 4;
	}

	while ( size != 0 )
	{
		*buf ++ ^= 0x22;
		--size;
	}
}

static U32 AILCALLBACK FAR OpenFileCB(MSS_FILE const FAR* Filename, U32 FAR* FileHandle)
{
	FILE* hFile = fopen( Filename, "rb" );
	*FileHandle = (U32)hFile;

	if ( hFile == nullptr ) return 0;

	size_t length = strlen(Filename);
	if ( Filename[length-4] == '.' &&
		( Filename[length-3] == 'a' || Filename[length-3] == 'A' ) &&
		( Filename[length-2] == 'd' || Filename[length-2] == 'D' ) &&
		( Filename[length-1] == 'f' || Filename[length-1] == 'F' )
		)
	{
		MSS_FILE FAR* name = const_cast<MSS_FILE FAR*>(Filename);
		name[length-3] = 'm';
		name[length-2] = 'p';
		name[length-1] = '3';

		adfStreams.push_back( hFile );
	}
	else if ( Filename[length-3] == '.' &&
		( Filename[length-2] == 'v' || Filename[length-2] == 'V' ) &&
		( Filename[length-1] == 'b' || Filename[length-1] == 'B' )
		)
	{
		MSS_FILE FAR* name = const_cast<MSS_FILE FAR*>(Filename);
		name[length-2] = 'v';
		name[length-1] = 'a';
		name[length] = 'g';
		name[length+1] = '\0';

		fseek( hFile, 0, SEEK_END );
		int size = ftell( hFile );
		fseek( hFile, 0, SEEK_SET );
		vbStreams.emplace_back( hFile, 32000, 1, size );
	}

	return (U32)hFile;
}

static void AILCALLBACK FAR CloseFileCB(U32 FileHandle)
{
	FILE* hFile = (FILE*)FileHandle;
	{
		auto it = std::find( adfStreams.begin(), adfStreams.end(), hFile );
		if ( it != adfStreams.end() )
		{
			adfStreams.erase( it );
			fclose( hFile );
			return;
		}
	}
	{
		auto it = std::find_if( vbStreams.begin(), vbStreams.end(), [hFile](const VBStream& s) {
			return s.GetStream() == hFile;
			} );
		if ( it != vbStreams.end() )
		{
			vbStreams.erase( it );
			fclose( hFile );
			return;
		}

	}
	fclose( hFile );
}

static S32 AILCALLBACK FAR SeekFileCB(U32 FileHandle, S32 Offset, U32 Type)
{
	FILE* hFile = (FILE*)FileHandle;
	auto it = std::find_if( vbStreams.begin(), vbStreams.end(), [hFile](const VBStream& s) {
		return s.GetStream() == hFile;
	} );
	if ( it != vbStreams.end() )
	{
		return it->SeekFile( Offset, Type );
	}

	fseek( hFile, Offset, Type );
	return ftell( hFile );
}

static U32 AILCALLBACK FAR ReadFileCB(U32 FileHandle, void FAR* Buffer, U32 Bytes)
{
	FILE* hFile = (FILE*)FileHandle;
	{
		auto it = std::find( adfStreams.begin(), adfStreams.end(), hFile );
		if ( it != adfStreams.end() )
		{
			size_t bytesRead = fread( Buffer, 1, Bytes, hFile );
			XORADFStream( Buffer, bytesRead );
			return bytesRead;
		}
	}
	{
		auto it = std::find_if( vbStreams.begin(), vbStreams.end(), [hFile](const VBStream& s) {
			return s.GetStream() == hFile;
		} );
		if ( it != vbStreams.end() )
		{
			return it->ReadFile( Buffer, Bytes );
		}
	}
	size_t bytesRead = fread( Buffer, 1, Bytes, hFile );
	return bytesRead;
}

void AttachVBCallbacks()
{
	AIL_set_file_callbacks( OpenFileCB, CloseFileCB, SeekFileCB, ReadFileCB );
}<commit_msg>per VB ini settings (optional)<commit_after>#include "vagdec.h"
#pragma warning(disable : 4996)

#include <vector>
#include <algorithm>

class VBStream
{
public:
	static const size_t VB_BLOCK_SIZE = 512 * 16 * 2;

	VBStream( FILE* file, int sample_rate, int stereo, int size )
		: stream( file ), fileSize( size + sizeof(VAG_HEADER) )
	{
		memset( &virtualHeader, 0, sizeof(virtualHeader) );
		virtualHeader.VAG[0] = 'V';
		virtualHeader.VAG[1] = 'A';
		virtualHeader.VAG[2] = 'G';
		virtualHeader.field_3 = 'p';

		virtualHeader.sample_rate = _byteswap_ulong(sample_rate);
		virtualHeader.stereo = _byteswap_ulong(stereo);
		virtualHeader.size = _byteswap_ulong(size);

		blockBuffer = stereo != 0 ? (U8*)AIL_mem_alloc_lock( VB_BLOCK_SIZE ) : nullptr;
	}

	VBStream( const VBStream& ) = delete;
	VBStream& operator = ( const VBStream& rhs ) = delete;

	VBStream( VBStream&& rhs ) = default;
	VBStream& operator = ( VBStream&& rhs ) = default;

	~VBStream()
	{
		if ( blockBuffer != nullptr )
		{
			AIL_mem_free_lock( blockBuffer );
			blockBuffer = nullptr;
		}
	}

	bool UsesInterleave() const { return blockBuffer != nullptr; }

	FILE* GetStream() const { return stream; }

	static S32 GetBlock(S32 offset)
	{
		// VB_BLOCK_SIZE = 2^14
		return offset >> 14;
	}

	U32 ReadFile( void FAR* Buffer, U32 Bytes )
	{
		if ( virtualCursor == 0 )
		{
			VAG_HEADER* header = (VAG_HEADER*)Buffer;
			*header = virtualHeader;

			size_t bytesRead = sizeof(VAG_HEADER);
			if ( !UsesInterleave() )
			{
				bytesRead += fread( &header[1], 1, Bytes-sizeof(*header), stream );
			}
			else
			{
				ReadBlockAndInterleave();

				memcpy( &header[1], blockBuffer, Bytes-sizeof(*header) );
				bytesRead += Bytes-sizeof(*header);
			}
			virtualCursor += bytesRead;
			return bytesRead;
		}

		if ( currentBlockCursor + Bytes >= VB_BLOCK_SIZE )
		{
			size_t firstRead = VB_BLOCK_SIZE - currentBlockCursor;

			memcpy( Buffer, blockBuffer+currentBlockCursor, firstRead );
			ReadBlockAndInterleave();
			memcpy( (U8*)Buffer+firstRead, blockBuffer, Bytes-firstRead );

			currentBlockCursor += Bytes-firstRead;
		}
		else
		{
			memcpy( Buffer, blockBuffer+currentBlockCursor, Bytes );
			currentBlockCursor += Bytes;
		}
		virtualCursor += Bytes;
		return Bytes;
	}

	S32 SeekFile( S32 Offset, U32 Type )
	{
		if ( Type == AIL_FILE_SEEK_CURRENT ) Offset += virtualCursor;
		else if ( Type == AIL_FILE_SEEK_END ) Offset = fileSize - Offset;

		S32 OffsetNoHeader = Offset - sizeof(VAG_HEADER);
		S32 CursorNoHeader = virtualCursor - sizeof(VAG_HEADER);

		if ( OffsetNoHeader <= 0 )
		{
			// Seeks to header - do nothing since next ReadFile flushes everything anyway
			fseek( stream, 0, SEEK_SET );
			virtualCursor = 0;
			return 0;
		}

		if ( UsesInterleave() )
		{
			// Is within the same block?
			if ( GetBlock(OffsetNoHeader) == GetBlock(CursorNoHeader) )
			{
				// Do nothing, just move cursor
				currentBlockCursor = OffsetNoHeader - CursorNoHeader;
			}
			else
			{
				// Read new block
				fseek( stream, OffsetNoHeader & ~(VB_BLOCK_SIZE-1), SEEK_SET );
				ReadBlockAndInterleave();
				currentBlockCursor = OffsetNoHeader & (VB_BLOCK_SIZE-1);
			}
		}
		else
		{
			fseek( stream, OffsetNoHeader, SEEK_SET );
		}
		virtualCursor = Offset;
		return virtualCursor;
	}

private:
	void ReadBlockAndInterleave( )
	{
		const size_t VB_SAMPLE_SIZE = 0x10;

		U8 buf[VB_BLOCK_SIZE];
		size_t bytesRead = fread( buf, 1, VB_BLOCK_SIZE, stream );

		// Interleave
		if ( bytesRead == VB_BLOCK_SIZE )
		{
			U8* leftChannel = buf;
			U8* rightChannel = buf+(VB_BLOCK_SIZE/2);
			U8* output = blockBuffer;

			for ( int i = 0; i < 512; ++i )
			{
				memcpy( output, leftChannel, VB_SAMPLE_SIZE );
				memcpy( output+VB_SAMPLE_SIZE, rightChannel, VB_SAMPLE_SIZE );
				leftChannel += VB_SAMPLE_SIZE;
				rightChannel += VB_SAMPLE_SIZE;
				output += 2*VB_SAMPLE_SIZE;
			}
		}
		currentBlockCursor = 0;
	}

private:
	FILE* stream;
	VAG_HEADER virtualHeader;
	U8* blockBuffer;
	S32 currentBlockCursor = 0, virtualCursor = 0;
	S32 fileSize;
};

static std::vector<FILE*> adfStreams;
static std::vector<VBStream> vbStreams;

static void XORADFStream( void FAR* Buffer, size_t size )
{
	U8* buf = (U8*)Buffer;

	while ( size != 0 && ((U32)buf & 3) != 0 )
	{
		*buf ++ ^= 0x22;
		--size;
	}

	while ( size >= 4 )
	{
		*(U32*)buf ^= 0x22222222;
		buf += 4;
		size -= 4;
	}

	while ( size != 0 )
	{
		*buf ++ ^= 0x22;
		--size;
	}
}

static U32 AILCALLBACK FAR OpenFileCB(MSS_FILE const FAR* Filename, U32 FAR* FileHandle)
{
	FILE* hFile = fopen( Filename, "rb" );
	*FileHandle = (U32)hFile;

	if ( hFile == nullptr ) return 0;

	size_t length = strlen(Filename);
	if ( Filename[length-4] == '.' &&
		( Filename[length-3] == 'a' || Filename[length-3] == 'A' ) &&
		( Filename[length-2] == 'd' || Filename[length-2] == 'D' ) &&
		( Filename[length-1] == 'f' || Filename[length-1] == 'F' )
		)
	{
		MSS_FILE FAR* name = const_cast<MSS_FILE FAR*>(Filename);
		name[length-3] = 'm';
		name[length-2] = 'p';
		name[length-1] = '3';

		adfStreams.push_back( hFile );
	}
	else if ( Filename[length-3] == '.' &&
		( Filename[length-2] == 'v' || Filename[length-2] == 'V' ) &&
		( Filename[length-1] == 'b' || Filename[length-1] == 'B' )
		)
	{
		MSS_FILE FAR* name = const_cast<MSS_FILE FAR*>(Filename);
		name[length-2] = 'i';
		name[length-1] = 'n';
		name[length] = 'i';
		name[length+1] = '\0';

		int samplerate = GetPrivateProfileInt( "VB", "sample_rate", 32000, name );
		int stereo = GetPrivateProfileInt( "VB", "stereo", 1, name ) != 0 ? 1 : 0;

		name[length-2] = 'v';
		name[length-1] = 'a';
		name[length] = 'g';

		fseek( hFile, 0, SEEK_END );
		int size = ftell( hFile );
		fseek( hFile, 0, SEEK_SET );
		vbStreams.emplace_back( hFile, samplerate, stereo, size );
	}

	return (U32)hFile;
}

static void AILCALLBACK FAR CloseFileCB(U32 FileHandle)
{
	FILE* hFile = (FILE*)FileHandle;
	{
		auto it = std::find( adfStreams.begin(), adfStreams.end(), hFile );
		if ( it != adfStreams.end() )
		{
			adfStreams.erase( it );
			fclose( hFile );
			return;
		}
	}
	{
		auto it = std::find_if( vbStreams.begin(), vbStreams.end(), [hFile](const VBStream& s) {
			return s.GetStream() == hFile;
			} );
		if ( it != vbStreams.end() )
		{
			vbStreams.erase( it );
			fclose( hFile );
			return;
		}

	}
	fclose( hFile );
}

static S32 AILCALLBACK FAR SeekFileCB(U32 FileHandle, S32 Offset, U32 Type)
{
	FILE* hFile = (FILE*)FileHandle;
	auto it = std::find_if( vbStreams.begin(), vbStreams.end(), [hFile](const VBStream& s) {
		return s.GetStream() == hFile;
	} );
	if ( it != vbStreams.end() )
	{
		return it->SeekFile( Offset, Type );
	}

	fseek( hFile, Offset, Type );
	return ftell( hFile );
}

static U32 AILCALLBACK FAR ReadFileCB(U32 FileHandle, void FAR* Buffer, U32 Bytes)
{
	FILE* hFile = (FILE*)FileHandle;
	{
		auto it = std::find( adfStreams.begin(), adfStreams.end(), hFile );
		if ( it != adfStreams.end() )
		{
			size_t bytesRead = fread( Buffer, 1, Bytes, hFile );
			XORADFStream( Buffer, bytesRead );
			return bytesRead;
		}
	}
	{
		auto it = std::find_if( vbStreams.begin(), vbStreams.end(), [hFile](const VBStream& s) {
			return s.GetStream() == hFile;
		} );
		if ( it != vbStreams.end() )
		{
			return it->ReadFile( Buffer, Bytes );
		}
	}
	size_t bytesRead = fread( Buffer, 1, Bytes, hFile );
	return bytesRead;
}

void AttachVBCallbacks()
{
	AIL_set_file_callbacks( OpenFileCB, CloseFileCB, SeekFileCB, ReadFileCB );
}<|endoftext|>


<commit_before>/*++

Module Name:

    BufferedAsync.cpp

Abstract:

    Double-buffered asynchronous file I/O

Environment:

    User mode service.

    This class is NOT thread safe.  It's the caller's responsibility to ensure that
    at most one thread uses an instance at any time.

--*/

#include "stdafx.h"
#include "Compat.h"
#include "BigAlloc.h"
#include "BufferedAsync.h"

using std::min;

    bool
BufferedAsyncReader::open(
    AsyncFile* file,
    size_t offset,
    size_t bytes,
    size_t i_bufferSize,
    bool async,
    void* buffer0,
    void* buffer1)
{
    _ASSERT((buffer0 == NULL) == (buffer1 == NULL)); // both null or both non-null
    waitTime = 0;
    reader[0] = file->getReader();
    reader[1] = file->getReader();
    bufferSize = i_bufferSize;
    fileSize = offset + bytes;
    ownBuffer = buffer0 == NULL;
    buffer[0] = (char*) (buffer0 != NULL ? buffer0 : BigAlloc(bufferSize));
    buffer[1] = (char*) (buffer1 != NULL ? buffer1 : BigAlloc(bufferSize));
    if (reader[0] == NULL || reader[1] == NULL || buffer[0] == NULL || buffer[1] == NULL) {
        fprintf(stderr, "unable to setup temp file reader\n");
        return false;
    }
    length[0] = min(bytes, bufferSize);
    reader[0]->beginRead(buffer[0],length[0], offset, NULL);
    if (bytes > bufferSize) {
        length[1] = min(bytes - bufferSize, bufferSize);
        reader[1]->beginRead(buffer[1], length[1], offset + bufferSize, NULL);
    } else {
        length[1] = 0;
    }
    reading = 0;
    readOffset = 0;
    nextFileOffset = offset + min(bytes, 2 * bufferSize);
    if (! async) {
        endOpen();
    }
    return true;
}

    void
BufferedAsyncReader::endOpen()
{
    _int64 start = timeInNanos();
    reader[reading]->waitForCompletion();
    waitTime += timeInNanos() - start;
}

    bool
BufferedAsyncReader::atEnd()
{
    return length[reading] == 0;
}

    bool
BufferedAsyncReader::read(
    void* data,
    size_t bytes)
{
    if (bytes == 0) {
        return true;
    }
    if (atEnd()) {
        return false;
    }
    size_t first = min(bytes, length[reading] - readOffset);
    memcpy(data, buffer[reading] + readOffset, first);
    data = (char*) data + first;
    readOffset += bytes;
    if (readOffset >= length[reading]) {
        // switch buffers
        readOffset -= length[reading];
        reading = 1 - reading;
        _int64 start = timeInNanos();
        reader[reading]->waitForCompletion();
        waitTime += timeInNanos() - start;
        if (readOffset > 0) {
            // copy second part of read segment
            // todo: allow for longer reads
            if (readOffset > length[reading]) {
                fprintf(stderr, "read length too big\n");
                return false;
            }
            memcpy(data, buffer[reading], readOffset);
        }
        // begin read of next block
        if (nextFileOffset < fileSize) {
            length[1 - reading] = min(fileSize - nextFileOffset, bufferSize);
            reader[1 - reading]->beginRead(buffer[1 - reading], length[1 - reading], nextFileOffset, NULL);
            nextFileOffset += length[1 - reading];
        } else {
            length[1 - reading] = 0;
        }
    }
    return true;
}

    bool
BufferedAsyncReader::close()
{
    delete reader[0];
    delete reader[1];
    if (ownBuffer) {
        BigDealloc(buffer[0]);
        BigDealloc(buffer[1]);
    }
    return true;
}

    bool
BufferedAsyncWriter::open(
    AsyncFile* file,
    size_t i_bufferSize,
    volatile _int64* sharedOffset)
{
    waitTime = 0;
    writer[0] = file->getWriter();
    writer[1] = file->getWriter();
    bufferSize = i_bufferSize;
    buffer[0] = (char*) BigAlloc(bufferSize);
    buffer[1] = (char*) BigAlloc(bufferSize);
    writeOffset = 0;
    writing = 0;
    privateFileOffset = 0;
    nextFileOffset = sharedOffset != NULL ? sharedOffset : &privateFileOffset;
    return writer[0] != NULL && writer[1] != NULL && buffer[0] != NULL && buffer[1] != NULL;
}

    bool
BufferedAsyncWriter::write(
    void* data,
    size_t bytes)
{
    void* p = forWrite(bytes);
    if (p == NULL) {
        // todo: allow bytes > bufferSize using synchronous writes
        return false;
    }
    memcpy(p, data, bytes);
    return true;
}

    void*
BufferedAsyncWriter::forWrite(
    size_t bytes)
{
    bool ok = true;
    if (writeOffset + bytes <= bufferSize) {
        writeOffset += bytes;
        return buffer[writing] + writeOffset - bytes;
    } else {
        _int64 fileOffset = InterlockedAdd64AndReturnNewValue(nextFileOffset, writeOffset) - writeOffset;
        ok = writer[writing]->beginWrite(buffer[writing], writeOffset, fileOffset, NULL);
        _int64 start = timeInNanos();
        ok &= writer[1 - writing]->waitForCompletion();
        waitTime += timeInNanos() - start;
        writing = 1 - writing;
        if (! ok) {
            fprintf(stderr, "BufferedAsyncWriter write failed\n");
            return NULL;
        }
        if (bytes <= bufferSize) {
            writeOffset = bytes;
            return buffer[writing];
        } else {
            // too big to be async
            fprintf(stderr, "BufferedAsyncWriter write too large\n");
            return NULL;
        }
    }
}

    bool
BufferedAsyncWriter::close()
{
    _int64 start = timeInNanos();
    bool ok = writer[1 - writing]->waitForCompletion();
    waitTime += timeInNanos() - start;
    if (writeOffset > 0) {
        _int64 fileOffset = InterlockedAdd64AndReturnNewValue(nextFileOffset, writeOffset) - writeOffset;
        ok &= writer[writing]->beginWrite(buffer[writing], writeOffset, fileOffset, NULL);
        _int64 start = timeInNanos();
        ok &= writer[writing]->waitForCompletion();
        waitTime += timeInNanos() - start;
    }
    delete writer[0];
    delete writer[1];
    BigDealloc(buffer[0]);
    BigDealloc(buffer[1]);
    return ok;
}
    <commit_msg>Wait time measurement<commit_after>/*++

Module Name:

    BufferedAsync.cpp

Abstract:

    Double-buffered asynchronous file I/O

Environment:

    User mode service.

    This class is NOT thread safe.  It's the caller's responsibility to ensure that
    at most one thread uses an instance at any time.

--*/

#include "stdafx.h"
#include "Compat.h"
#include "BigAlloc.h"
#include "BufferedAsync.h"

using std::min;

    bool
BufferedAsyncReader::open(
    AsyncFile* file,
    size_t offset,
    size_t bytes,
    size_t i_bufferSize,
    bool async,
    void* buffer0,
    void* buffer1)
{
    _ASSERT((buffer0 == NULL) == (buffer1 == NULL)); // both null or both non-null
    waitTime = 0;
    reader[0] = file->getReader();
    reader[1] = file->getReader();
    bufferSize = i_bufferSize;
    fileSize = offset + bytes;
    ownBuffer = buffer0 == NULL;
    buffer[0] = (char*) (buffer0 != NULL ? buffer0 : BigAlloc(bufferSize));
    buffer[1] = (char*) (buffer1 != NULL ? buffer1 : BigAlloc(bufferSize));
    if (reader[0] == NULL || reader[1] == NULL || buffer[0] == NULL || buffer[1] == NULL) {
        fprintf(stderr, "unable to setup temp file reader\n");
        return false;
    }
    length[0] = min(bytes, bufferSize);
    _int64 start = timeInNanos();
    reader[0]->beginRead(buffer[0],length[0], offset, NULL);
    if (bytes > bufferSize) {
        length[1] = min(bytes - bufferSize, bufferSize);
        reader[1]->beginRead(buffer[1], length[1], offset + bufferSize, NULL);
    } else {
        length[1] = 0;
    }
    waitTime += timeInNanos() - start;
    reading = 0;
    readOffset = 0;
    nextFileOffset = offset + min(bytes, 2 * bufferSize);
    if (! async) {
        endOpen();
    }
    return true;
}

    void
BufferedAsyncReader::endOpen()
{
    _int64 start = timeInNanos();
    reader[reading]->waitForCompletion();
    waitTime += timeInNanos() - start;
}

    bool
BufferedAsyncReader::atEnd()
{
    return length[reading] == 0;
}

    bool
BufferedAsyncReader::read(
    void* data,
    size_t bytes)
{
    if (bytes == 0) {
        return true;
    }
    if (atEnd()) {
        return false;
    }
    size_t first = min(bytes, length[reading] - readOffset);
    memcpy(data, buffer[reading] + readOffset, first);
    data = (char*) data + first;
    readOffset += bytes;
    if (readOffset >= length[reading]) {
        // switch buffers
        readOffset -= length[reading];
        reading = 1 - reading;
        _int64 start = timeInNanos();
        reader[reading]->waitForCompletion();
        waitTime += timeInNanos() - start;
        if (readOffset > 0) {
            // copy second part of read segment
            // todo: allow for longer reads
            if (readOffset > length[reading]) {
                fprintf(stderr, "read length too big\n");
                return false;
            }
            memcpy(data, buffer[reading], readOffset);
        }
        // begin read of next block
        if (nextFileOffset < fileSize) {
            length[1 - reading] = min(fileSize - nextFileOffset, bufferSize);
            start = timeInNanos();
            reader[1 - reading]->beginRead(buffer[1 - reading], length[1 - reading], nextFileOffset, NULL);
            waitTime += timeInNanos() - start;
            nextFileOffset += length[1 - reading];
        } else {
            length[1 - reading] = 0;
        }
    }
    return true;
}

    bool
BufferedAsyncReader::close()
{
    delete reader[0];
    delete reader[1];
    if (ownBuffer) {
        BigDealloc(buffer[0]);
        BigDealloc(buffer[1]);
    }
    return true;
}

    bool
BufferedAsyncWriter::open(
    AsyncFile* file,
    size_t i_bufferSize,
    volatile _int64* sharedOffset)
{
    waitTime = 0;
    writer[0] = file->getWriter();
    writer[1] = file->getWriter();
    bufferSize = i_bufferSize;
    buffer[0] = (char*) BigAlloc(bufferSize);
    buffer[1] = (char*) BigAlloc(bufferSize);
    writeOffset = 0;
    writing = 0;
    privateFileOffset = 0;
    nextFileOffset = sharedOffset != NULL ? sharedOffset : &privateFileOffset;
    return writer[0] != NULL && writer[1] != NULL && buffer[0] != NULL && buffer[1] != NULL;
}

    bool
BufferedAsyncWriter::write(
    void* data,
    size_t bytes)
{
    void* p = forWrite(bytes);
    if (p == NULL) {
        // todo: allow bytes > bufferSize using synchronous writes
        return false;
    }
    memcpy(p, data, bytes);
    return true;
}

    void*
BufferedAsyncWriter::forWrite(
    size_t bytes)
{
    bool ok = true;
    if (writeOffset + bytes <= bufferSize) {
        writeOffset += bytes;
        return buffer[writing] + writeOffset - bytes;
    } else {
        _int64 fileOffset = InterlockedAdd64AndReturnNewValue(nextFileOffset, writeOffset) - writeOffset;
        _int64 start = timeInNanos();
        ok = writer[writing]->beginWrite(buffer[writing], writeOffset, fileOffset, NULL);
        ok &= writer[1 - writing]->waitForCompletion();
        waitTime += timeInNanos() - start;
        writing = 1 - writing;
        if (! ok) {
            fprintf(stderr, "BufferedAsyncWriter write failed\n");
            return NULL;
        }
        if (bytes <= bufferSize) {
            writeOffset = bytes;
            return buffer[writing];
        } else {
            // too big to be async
            fprintf(stderr, "BufferedAsyncWriter write too large\n");
            return NULL;
        }
    }
}

    bool
BufferedAsyncWriter::close()
{
    _int64 start = timeInNanos();
    bool ok = writer[1 - writing]->waitForCompletion();
    waitTime += timeInNanos() - start;
    if (writeOffset > 0) {
        _int64 fileOffset = InterlockedAdd64AndReturnNewValue(nextFileOffset, writeOffset) - writeOffset;
        _int64 start = timeInNanos();
        ok &= writer[writing]->beginWrite(buffer[writing], writeOffset, fileOffset, NULL);
        ok &= writer[writing]->waitForCompletion();
        waitTime += timeInNanos() - start;
    }
    delete writer[0];
    delete writer[1];
    BigDealloc(buffer[0]);
    BigDealloc(buffer[1]);
    return ok;
}
    <|endoftext|>


<commit_before>#pragma once

#include <exception>
#include <regex>
#include <iostream>

#include "acmacs-base/throw.hh"

// ----------------------------------------------------------------------

namespace virus_name
{
    namespace _internal
    {
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#endif

        const std::regex cdc{"^([A-Z][A-Z][A-Z]?) "};

        constexpr const char* re_international_name = "^(?:([AB][^/]*)/)?(?:([^/]+)/)?([^/]+)/0*([^/]+)/(19|20)?(\\d\\d)";
        constexpr const char* re_reassortant_passage = "(?:(?:\\s+|__)(.+))?";

          // [1] - type+subtype, [2] - host, [3] - location, [4] - isolation-number (omitting leading zeros), [5] - century, [6] - year (2 last digit), [7] - reassortant and passage
          // const std::regex international{"^([AB][^/]*)/(?:([^/]+)/)?([^/]+)/0*([^/]+)/(19|20)?(\\d\\d)(?:(?:\\s+|__)(.+))?$"};
        const std::regex international{std::string(re_international_name) + re_reassortant_passage + "$"};
        const std::regex international_name{re_international_name};

#pragma GCC diagnostic pop

        inline std::string make_year(const std::smatch& m)
        {
            std::string year;
            if (m[5].length())
                year = m[5].str() + m[6].str();
            else if (m[6].str()[0] > '2')
                year = "19" + m[6].str();
            else
                year = "20" + m[6].str();
            return year;
        }

        constexpr const size_t international_name_suffix_size = 9; // len(lo/isolation-number/year) >= 9

        inline std::string location_human(std::string name, size_t prefix_size)
        {
            const auto end = name.find('/', prefix_size);
            return name.substr(prefix_size, end - prefix_size);
        }
    }

// ----------------------------------------------------------------------

    class Unrecognized : public std::runtime_error { public: using std::runtime_error::runtime_error; };

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

    using location_func_t = std::string (*)(std::string);

      // returned cdc abbreviation starts with #
    inline std::string location(std::string name)
    {
        using namespace _internal;
        std::string location;
        std::smatch m;
        if (std::regex_match(name, m, international))
            location = m[3].str();
        else if (std::regex_search(name, m, cdc))
            location = "#" + m[1].str();
        else
            THROW(Unrecognized{"No location in " + name}, std::string{});
        return location;
    }

      // Faster version of location() for A(H3N2)/ and A(H1N1)/ names without host field
    inline std::string location_human_a(std::string name)
    {
        constexpr const size_t prefix_size = 8;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

      // Faster version of location() for B/ names without host field
    inline std::string location_human_b(std::string name)
    {
        constexpr const size_t prefix_size = 2;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

// ----------------------------------------------------------------------

    inline std::string virus_type(std::string name)
    {
        using namespace _internal;
        std::string virus_type;
        std::smatch m;
        if (std::regex_match(name, m, international))
            virus_type = m[1].str();
        else
            THROW(Unrecognized{"No virus_type in " + name}, std::string{});
        return virus_type;

    } // AntigenSerum::virus_type

// ----------------------------------------------------------------------

    inline std::string year(std::string name)
    {
        using namespace _internal;
        std::string year;
        std::smatch m;
        if (std::regex_match(name, m, international))
            year = make_year(m);
        else
            THROW(Unrecognized{"No year in " + name}, std::string{});
        return year;

    } // AntigenSerum::year

// ----------------------------------------------------------------------

    inline void split(std::string name, std::string& virus_type, std::string& host, std::string& location, std::string& isolation, std::string& year, std::string& passage)
    {
        std::smatch m;
        if (std::regex_match(name, m, _internal::international)) {
            virus_type = m[1].str();
            host = m[2].str();
            location = m[3].str();
            isolation = m[4].str();
            year = _internal::make_year(m);
            passage = m[7].str();
        }
        else
            THROW_OR_VOID(Unrecognized{"Cannot split " + name});
    }

// ----------------------------------------------------------------------

      // Extracts virus name without passage, reassortant, extra,
      // etc. and calculates match threshold (to use with
      // acmacs_chart::Antigens::find_by_name_matching), match threshold is a square
      // of virus name length.
    inline size_t match_threshold(std::string name)
    {
        size_t result = 0;
        std::smatch m;
        if (std::regex_search(name, m, _internal::international_name)) {
              // find end of year (m[6])
            const auto end_of_year_offset = static_cast<size_t>(m[6].second - name.begin());
            result = end_of_year_offset * end_of_year_offset;
              // std::cerr << "INFO: match_threshold: end_of_year_offset:" << end_of_year_offset << " name:" << name << std::endl;
        }
        return result;
    }

// ----------------------------------------------------------------------

}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>international virus name splitting fixed<commit_after>#pragma once

#include <exception>
#include <regex>
#include <iostream>

#include "acmacs-base/throw.hh"

// ----------------------------------------------------------------------

namespace virus_name
{
    namespace _internal
    {
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#endif

        const std::regex cdc{"^([A-Z][A-Z][A-Z]?) "};

        constexpr const char* re_international_name = "^(?:([AB][^/]*)/)?(?:([^/]+)/)?([^/]{2,})/0*([^/]+)/(19|20)?(\\d\\d)";
        constexpr const char* re_reassortant_passage = "(?:(?:\\s+|__)(.+))?";

          // [1] - type+subtype, [2] - host, [3] - location, [4] - isolation-number (omitting leading zeros), [5] - century, [6] - year (2 last digit), [7] - reassortant and passage
          // const std::regex international{"^([AB][^/]*)/(?:([^/]+)/)?([^/]+)/0*([^/]+)/(19|20)?(\\d\\d)(?:(?:\\s+|__)(.+))?$"};
        const std::regex international{std::string(re_international_name) + re_reassortant_passage + "$"};
        const std::regex international_name{re_international_name};

#pragma GCC diagnostic pop

        inline std::string make_year(const std::smatch& m)
        {
            std::string year;
            if (m[5].length())
                year = m[5].str() + m[6].str();
            else if (m[6].str()[0] > '2')
                year = "19" + m[6].str();
            else
                year = "20" + m[6].str();
            return year;
        }

        constexpr const size_t international_name_suffix_size = 9; // len(lo/isolation-number/year) >= 9

        inline std::string location_human(std::string name, size_t prefix_size)
        {
            const auto end = name.find('/', prefix_size);
            return name.substr(prefix_size, end - prefix_size);
        }
    }

// ----------------------------------------------------------------------

    class Unrecognized : public std::runtime_error { public: using std::runtime_error::runtime_error; };

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

    using location_func_t = std::string (*)(std::string);

      // returned cdc abbreviation starts with #
    inline std::string location(std::string name)
    {
        using namespace _internal;
        std::string location;
        std::smatch m;
        if (std::regex_match(name, m, international))
            location = m[3].str();
        else if (std::regex_search(name, m, cdc))
            location = "#" + m[1].str();
        else
            THROW(Unrecognized{"No location in " + name}, std::string{});
        return location;
    }

      // Faster version of location() for A(H3N2)/ and A(H1N1)/ names without host field
    inline std::string location_human_a(std::string name)
    {
        constexpr const size_t prefix_size = 8;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

      // Faster version of location() for B/ names without host field
    inline std::string location_human_b(std::string name)
    {
        constexpr const size_t prefix_size = 2;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

// ----------------------------------------------------------------------

    inline std::string virus_type(std::string name)
    {
        using namespace _internal;
        std::string virus_type;
        std::smatch m;
        if (std::regex_match(name, m, international))
            virus_type = m[1].str();
        else
            THROW(Unrecognized{"No virus_type in " + name}, std::string{});
        return virus_type;

    } // AntigenSerum::virus_type

// ----------------------------------------------------------------------

    inline std::string year(std::string name)
    {
        using namespace _internal;
        std::string year;
        std::smatch m;
        if (std::regex_match(name, m, international))
            year = make_year(m);
        else
            THROW(Unrecognized{"No year in " + name}, std::string{});
        return year;

    } // AntigenSerum::year

// ----------------------------------------------------------------------

    inline void split(std::string name, std::string& virus_type, std::string& host, std::string& location, std::string& isolation, std::string& year, std::string& passage)
    {
        std::smatch m;
        if (std::regex_match(name, m, _internal::international)) {
            virus_type = m[1].str();
            host = m[2].str();
            location = m[3].str();
            isolation = m[4].str();
            year = _internal::make_year(m);
            passage = m[7].str();
        }
        else
            THROW_OR_VOID(Unrecognized{"Cannot split " + name});
    }

// ----------------------------------------------------------------------

      // Extracts virus name without passage, reassortant, extra,
      // etc. and calculates match threshold (to use with
      // acmacs_chart::Antigens::find_by_name_matching), match threshold is a square
      // of virus name length.
    inline size_t match_threshold(std::string name)
    {
        size_t result = 0;
        std::smatch m;
        if (std::regex_search(name, m, _internal::international_name)) {
              // find end of year (m[6])
            const auto end_of_year_offset = static_cast<size_t>(m[6].second - name.begin());
            result = end_of_year_offset * end_of_year_offset;
              // std::cerr << "INFO: match_threshold: end_of_year_offset:" << end_of_year_offset << " name:" << name << std::endl;
        }
        return result;
    }

// ----------------------------------------------------------------------

}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>