text:
/**
 * @file llgesture.cpp
 *
 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"

#include "indra_constants.h"

#include "llgesture.h"
#include "llendianswizzle.h"
#include "message.h"
#include <boost/tokenizer.hpp>

// for allocating serialization buffers - these need to be updated when members change
const S32 LLGestureList::SERIAL_HEADER_SIZE = sizeof(S32);
const S32 LLGesture::MAX_SERIAL_SIZE = sizeof(KEY) + sizeof(MASK) + 16 + 26 + 41 + 41;

LLGesture::LLGesture()
:	mKey(KEY_NONE),
	mMask(MASK_NONE),
	mTrigger(),
	mTriggerLower(),
	mSoundItemID(),
	mAnimation(),
	mOutputString()
{ }

LLGesture::LLGesture(KEY key, MASK mask, const std::string &trigger,
					 const LLUUID &sound_item_id,
					 const std::string &animation,
					 const std::string &output_string)
:
	mKey(key),
	mMask(mask),
	mTrigger(trigger),
	mTriggerLower(trigger),
	mSoundItemID(sound_item_id),
	mAnimation(animation),
	mOutputString(output_string)
{
	mTriggerLower = utf8str_tolower(mTriggerLower);
}

LLGesture::LLGesture(U8 **buffer, S32 max_size)
{
	*buffer = deserialize(*buffer, max_size);
}

LLGesture::LLGesture(const LLGesture &rhs)
{
	mKey			= rhs.mKey;
	mMask			= rhs.mMask;
	mTrigger		= rhs.mTrigger;
	mTriggerLower	= rhs.mTriggerLower;
	mSoundItemID	= rhs.mSoundItemID;
	mAnimation		= rhs.mAnimation;
	mOutputString	= rhs.mOutputString;
}

const LLGesture &LLGesture::operator =(const LLGesture &rhs)
{
	mKey			= rhs.mKey;
	mMask			= rhs.mMask;
	mTrigger		= rhs.mTrigger;
	mTriggerLower	= rhs.mTriggerLower;
	mSoundItemID	= rhs.mSoundItemID;
	mAnimation		= rhs.mAnimation;
	mOutputString	= rhs.mOutputString;
	return (*this);
}

BOOL LLGesture::trigger(KEY key, MASK mask)
{
	LL_WARNS() << "Parent class trigger called: you probably didn't mean this." << LL_ENDL;
	return FALSE;
}

BOOL LLGesture::trigger(const std::string& trigger_string)
{
	LL_WARNS() << "Parent class trigger called: you probably didn't mean this." << LL_ENDL;
	return FALSE;
}

// NOT endian-neutral
U8 *LLGesture::serialize(U8 *buffer) const
{
	htonmemcpy(buffer, &mKey, MVT_S8, 1);
	buffer += sizeof(mKey);
	htonmemcpy(buffer, &mMask, MVT_U32, 4);
	buffer += sizeof(mMask);
	htonmemcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16);
	buffer += 16;

	memcpy(buffer, mTrigger.c_str(), mTrigger.length() + 1);		/* Flawfinder: ignore */
	buffer += mTrigger.length() + 1;
	memcpy(buffer, mAnimation.c_str(), mAnimation.length() + 1);		/* Flawfinder: ignore */
	buffer += mAnimation.length() + 1;
	memcpy(buffer, mOutputString.c_str(), mOutputString.length() + 1);		/* Flawfinder: ignore */
	buffer += mOutputString.length() + 1;

	return buffer;
}

U8 *LLGesture::deserialize(U8 *buffer, S32 max_size)
{
	U8 *tmp = buffer;

	if (tmp + sizeof(mKey) + sizeof(mMask) + 16 > buffer + max_size)
	{
		LL_WARNS() << "Attempt to read past end of buffer, bad data!!!!" << LL_ENDL;
		return buffer;
	}

	htonmemcpy(&mKey, tmp, MVT_S8, 1);
	tmp += sizeof(mKey);
	htonmemcpy(&mMask, tmp, MVT_U32, 4);
	tmp += sizeof(mMask);
	htonmemcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16);
	tmp += 16;

	mTrigger.assign((char *)tmp);
	mTriggerLower = mTrigger;
	mTriggerLower = utf8str_tolower(mTriggerLower);
	tmp += mTrigger.length() + 1;
	mAnimation.assign((char *)tmp);
	//RN: force animation names to lower case
	// must do this for backwards compatibility
	mAnimation = utf8str_tolower(mAnimation);
	tmp += mAnimation.length() + 1;
	mOutputString.assign((char *)tmp);
	tmp += mOutputString.length() + 1;

	if (tmp > buffer + max_size)
	{
		LL_WARNS() << "Read past end of buffer, bad data!!!!" << LL_ENDL;
		return tmp;
	}

	return tmp;
}

S32 LLGesture::getMaxSerialSize()
{
	return MAX_SERIAL_SIZE;
}

//---------------------------------------------------------------------
// LLGestureList
//---------------------------------------------------------------------

LLGestureList::LLGestureList()
:	mList(0)
{}

LLGestureList::~LLGestureList()
{
	deleteAll();
}

void LLGestureList::deleteAll()
{
	delete_and_clear(mList);
}

// Iterates through space delimited tokens in string, triggering any gestures found.
// Generates a revised string that has the found tokens replaced by their replacement strings
// and (as a minor side effect) has multiple spaces in a row replaced by single spaces.
BOOL LLGestureList::triggerAndReviseString(const std::string &string, std::string* revised_string)
{
	std::string tokenized = string;

	BOOL found_gestures = FALSE;
	BOOL first_token = TRUE;

	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> sep(" ");
	tokenizer tokens(string, sep);
	tokenizer::iterator token_iter;

	for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
	{
		LLGesture* gesture = NULL;

		if( !found_gestures ) // Only pay attention to the first gesture in the string.
		{
			std::string cur_token_lower = *token_iter;
			LLStringUtil::toLower(cur_token_lower);

			for (U32 i = 0; i < mList.size(); i++)
			{
				gesture = mList.at(i);
				if (gesture->trigger(cur_token_lower))
				{
					if( !gesture->getOutputString().empty() )
					{
						if( !first_token )
						{
							revised_string->append( " " );
						}

						// Don't muck with the user's capitalization if we don't have to.
						const std::string& output = gesture->getOutputString();
						std::string output_lower = std::string(output.c_str());
						LLStringUtil::toLower(output_lower);
						if( cur_token_lower == output_lower )
						{
							revised_string->append(*token_iter);
						}
						else
						{
							revised_string->append(output);
						}

					}
					found_gestures = TRUE;
					break;
				}
				gesture = NULL;
			}
		}

		if( !gesture )
		{
			if( !first_token )
			{
				revised_string->append( " " );
			}
			revised_string->append( *token_iter );
		}

		first_token = FALSE;
	}
	return found_gestures;
}

BOOL LLGestureList::trigger(KEY key, MASK mask)
{
	for (U32 i = 0; i < mList.size(); i++)
	{
		LLGesture* gesture = mList.at(i);
		if( gesture )
		{
			if (gesture->trigger(key, mask))
			{
				return TRUE;
			}
		}
		else
		{
			LL_WARNS() << "NULL gesture in gesture list (" << i << ")" << LL_ENDL;
		}
	}
	return FALSE;
}

// NOT endian-neutral
U8 *LLGestureList::serialize(U8 *buffer) const
{
	// a single S32 serves as the header that tells us how many to read
	U32 count = mList.size();
	htonmemcpy(buffer, &count, MVT_S32, 4);
	buffer += sizeof(count);

	for (S32 i = 0; i < count; i++)
	{
		buffer = mList[i]->serialize(buffer);
	}

	return buffer;
}

const S32 MAX_GESTURES = 4096;

U8 *LLGestureList::deserialize(U8 *buffer, S32 max_size)
{
	deleteAll();

	S32 count;
	U8 *tmp = buffer;

	if (tmp + sizeof(count) > buffer + max_size)
	{
		LL_WARNS() << "Invalid max_size" << LL_ENDL;
		return buffer;
	}

	htonmemcpy(&count, tmp, MVT_S32, 4);

	if (count > MAX_GESTURES)
	{
		LL_WARNS() << "Unreasonably large gesture list count in deserialize: " << count << LL_ENDL;
		return tmp;
	}

	tmp += sizeof(count);

	mList.resize(count);

	for (S32 i = 0; i < count; i++)
	{
		mList[i] = create_gesture(&tmp, max_size - (S32)(tmp - buffer));
		if (tmp - buffer > max_size)
		{
			LL_WARNS() << "Deserialization read past end of buffer, bad data!!!!" << LL_ENDL;
			return tmp;
		}
	}

	return tmp;
}

// this is a helper for deserialize
// it gets overridden by LLViewerGestureList to create LLViewerGestures
// overridden by child class to use local LLGesture implementation
LLGesture *LLGestureList::create_gesture(U8 **buffer, S32 max_size)
{
	return new LLGesture(buffer, max_size);
}

S32 LLGestureList::getMaxSerialSize()
{
	return SERIAL_HEADER_SIZE + (count() * LLGesture::getMaxSerialSize());
}

ext: cpp

max_stars_repo_name: humbletim/archived-casviewer

max_issues_repo_name: humbletim/archived-casviewer

max_forks_repo_name: humbletim/archived-casviewer


text:
/*
 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Third party includes
#include <boost/format.hpp>
#include <boost/progress.hpp>

// Local private VOTCA includes
#include "neighborlist.h"

namespace votca {
namespace xtp {

bool InVector(const std::vector<std::string>& vec, const std::string& word) {
  return std::find(vec.begin(), vec.end(), word) != vec.end();
}

void Neighborlist::ParseOptions(const tools::Property& options) {

  if (options.exists(".segmentpairs")) {
    useConstantCutoff_ = false;
    std::vector<const tools::Property*> segs =
        options.Select(".segmentpairs.pair");
    for (const tools::Property* segprop : segs) {
      useConstantCutoff_ = false;
      std::vector<std::string> names =
          segprop->get("type").as<std::vector<std::string>>();
      double cutoff =
          segprop->get("cutoff").as<double>() * tools::conv::nm2bohr;

      if (names.size() != 2) {
        throw std::runtime_error(
            "ERROR: Faulty pair definition for cut-off's: Need two segment "
            "names "
            "separated by a space");
      }
      cutoffs_[names[0]][names[1]] = cutoff;
      cutoffs_[names[1]][names[0]] = cutoff;
      if (!InVector(included_segments_, names[0])) {
        included_segments_.push_back(names[0]);
      }
      if (!InVector(included_segments_, names[1])) {
        included_segments_.push_back(names[1]);
      }
    }
  } else {
    useConstantCutoff_ = true;
    constantCutoff_ =
        options.get(".constant").as<double>() * tools::conv::nm2bohr;
  }

  if (options.exists(".exciton_cutoff")) {
    useExcitonCutoff_ = true;
    excitonqmCutoff_ =
        options.get(".exciton_cutoff").as<double>() * tools::conv::nm2bohr;
  } else {
    useExcitonCutoff_ = false;
  }
}

Index Neighborlist::DetClassicalPairs(Topology& top) {
  Index classical_pairs = 0;
#pragma omp parallel for
  for (Index i = 0; i < top.NBList().size(); i++) {
    const Segment* seg1 = top.NBList()[i]->Seg1();
    const Segment* seg2 = top.NBList()[i]->Seg2();
    if (top.GetShortestDist(*seg1, *seg2) > excitonqmCutoff_) {
      top.NBList()[i]->setType(QMPair::Excitoncl);
#pragma omp critical
      { classical_pairs++; }
    } else {
      top.NBList()[i]->setType(QMPair::Hopping);
    }
  }  // Type 3 Exciton_classical approx
  return classical_pairs;
}

bool Neighborlist::Evaluate(Topology& top) {

  double min = top.getBox().diagonal().minCoeff();

  std::vector<Segment*> segs;
  for (Segment& seg : top.Segments()) {
    if (useConstantCutoff_ || InVector(included_segments_, seg.getType())) {
      segs.push_back(&seg);
      seg.getApproxSize();
    }
  }
  std::cout << std::endl;
  std::cout << "Evaluating " << segs.size() << " segments for neighborlist. ";
  if ((top.Segments().size() - segs.size()) != 0) {
    std::cout << top.Segments().size() - segs.size()
              << " segments are not taken into account as specified"
              << std::endl;
  } else {
    std::cout << std::endl;
  }
  if (!useConstantCutoff_) {
    std::cout << "The following segments are used in the neigborlist creation"
              << std::endl;
    std::cout << "\t" << std::flush;
    for (const std::string& st : included_segments_) {
      std::cout << " " << st;
    }
    std::cout << std::endl;
  }

  std::cout << "\r ... ... Evaluating " << std::flush;
  std::vector<std::string> skippedpairs;

  top.NBList().Cleanup();

  boost::progress_display progress(segs.size());
  // cache approx sizes
  std::vector<double> approxsize = std::vector<double>(segs.size(), 0.0);
#pragma omp parallel for
  for (Index i = 0; i < Index(segs.size()); i++) {
    approxsize[i] = segs[i]->getApproxSize();
  }
#pragma omp parallel for schedule(guided)
  for (Index i = 0; i < Index(segs.size()); i++) {
    const Segment* seg1 = segs[i];
    double cutoff = constantCutoff_;
    for (Index j = i + 1; j < Index(segs.size()); j++) {
      const Segment* seg2 = segs[j];
      if (!useConstantCutoff_) {
        try {
          cutoff = cutoffs_.at(seg1->getType()).at(seg2->getType());
        } catch (const std::exception&) {
          std::string pairstring = seg1->getType() + "/" + seg2->getType();
          if (!InVector(skippedpairs, pairstring)) {
#pragma omp critical
            if (!InVector(skippedpairs, pairstring)) {  // nedded because other
                                                        // thread may have
                                                        // pushed back in the
                                                        // meantime.
              skippedpairs.push_back(pairstring);
            }
          }
          continue;
        }
      }

      if (cutoff > 0.5 * min) {
        throw std::runtime_error(
            (boost::format("Cutoff is larger than half the box size. Maximum "
                           "allowed cutoff is %1$1.1f (nm)") %
             (tools::conv::bohr2nm * 0.5 * min))
                .str());
      }
      double cutoff2 = cutoff * cutoff;
      Eigen::Vector3d segdistance =
          top.PbShortestConnect(seg1->getPos(), seg2->getPos());
      double segdistance2 = segdistance.squaredNorm();
      double outside = cutoff + approxsize[i] + approxsize[j];

      if (segdistance2 < cutoff2) {
#pragma omp critical
        { top.NBList().Add(*seg1, *seg2, segdistance); }

      } else if (segdistance2 > (outside * outside)) {
        continue;
      } else {
        double R = top.GetShortestDist(*seg1, *seg2);
        if ((R * R) < cutoff2) {
#pragma omp critical
          { top.NBList().Add(*seg1, *seg2, segdistance); }
        }
      }
    } /* exit loop seg2 */
#pragma omp critical
    { ++progress; }
  } /* exit loop seg1 */

  if (skippedpairs.size() > 0) {
    std::cout << "WARNING: No cut-off specified for segment pairs of type "
              << std::endl;
    for (const std::string& st : skippedpairs) {
      std::cout << st << std::endl;
    }
    std::cout << "pairs were skipped" << std::endl;
  }

  std::cout << std::endl
            << " ... ... Created " << top.NBList().size() << " direct pairs.";
  if (useExcitonCutoff_) {
    std::cout << std::endl
              << " ... ... Determining classical pairs " << std::endl;
    Index classical_pairs = DetClassicalPairs(top);
    std::cout << " ... ... Found " << classical_pairs << " classical pairs "
              << std::endl;
  }

  // sort qmpairs by seg1id and then by seg2id then reindex the pair id
  // according to that.
  top.NBList().sortAndReindex([](QMPair* a, QMPair* b) {
    if (a->Seg1()->getId() != b->Seg1()->getId()) {
      return a->Seg1()->getId() < b->Seg1()->getId();
    }
    return a->Seg2()->getId() < b->Seg2()->getId();
  });

  return true;
}
}  // namespace xtp
}  // namespace votca

ext: cc

max_stars_repo_name: rubengerritsen/xtp

max_issues_repo_name: rubengerritsen/xtp

max_forks_repo_name: rubengerritsen/xtp