<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2017, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "ContextAlgoBinding.h"

#include "GafferSceneUI/ContextAlgo.h"

#include "GafferScene/ScenePlug.h"

#include "IECorePython/ScopedGILRelease.h"

using namespace boost::python;
using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;
using namespace GafferSceneUI::ContextAlgo;

namespace
{

PathMatcher expandDescendantsWrapper( Context &context, PathMatcher &paths, ScenePlug &scene, int depth )
{
	IECorePython::ScopedGILRelease gilRelease;
	return expandDescendants( &context, paths, &scene, depth );
}

} // namespace

void GafferSceneUIModule::bindContextAlgo()
{
	object module( borrowed( PyImport_AddModule( "GafferSceneUI.ContextAlgo" ) ) );
	scope().attr( "ContextAlgo" ) = module;
	scope moduleScope( module );

	def( "setExpandedPaths", &setExpandedPaths );
	def( "getExpandedPaths", &getExpandedPaths );
	def( "affectsExpandedPaths", &affectsExpandedPaths );
	def( "expand", &expand, ( arg( "expandAncestors" ) = true ) );
	def( "expandDescendants", &expandDescendantsWrapper, ( arg( "context" ), arg( "paths" ), arg( "scene" ), arg( "depth" ) = Imath::limits<int>::max() ) );
	def( "clearExpansion", &clearExpansion );
	def( "setSelectedPaths", &setSelectedPaths );
	def( "getSelectedPaths", &getSelectedPaths );
	def( "affectsSelectedPaths", &affectsSelectedPaths );

}
<commit_msg>GafferSceneUI::ContextAlgo bindings : Fix GIL management<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2017, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "ContextAlgoBinding.h"

#include "GafferSceneUI/ContextAlgo.h"

#include "GafferScene/ScenePlug.h"

#include "IECorePython/ScopedGILRelease.h"

using namespace boost::python;
using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;
using namespace GafferSceneUI::ContextAlgo;

namespace
{

void setExpandedPathsWrapper( Context &context, const IECore::PathMatcher &paths )
{
	IECorePython::ScopedGILRelease gilRelease;
	setExpandedPaths( &context, paths );
}

void expandWrapper( Context &context, const IECore::PathMatcher &paths, bool expandAncestors )
{
	IECorePython::ScopedGILRelease gilRelease;
	expand( &context, paths, expandAncestors );
}

PathMatcher expandDescendantsWrapper( Context &context, PathMatcher &paths, ScenePlug &scene, int depth )
{
	IECorePython::ScopedGILRelease gilRelease;
	return expandDescendants( &context, paths, &scene, depth );
}

void clearExpansionWrapper( Context &context )
{
	IECorePython::ScopedGILRelease gilRelease;
	clearExpansion( &context );
}

void setSelectedPathsWrapper( Context &context, const IECore::PathMatcher &paths )
{
	IECorePython::ScopedGILRelease gilRelease;
	setSelectedPaths( &context, paths );
}

} // namespace

void GafferSceneUIModule::bindContextAlgo()
{
	object module( borrowed( PyImport_AddModule( "GafferSceneUI.ContextAlgo" ) ) );
	scope().attr( "ContextAlgo" ) = module;
	scope moduleScope( module );

	def( "setExpandedPaths", &setExpandedPathsWrapper );
	def( "getExpandedPaths", &getExpandedPaths );
	def( "affectsExpandedPaths", &affectsExpandedPaths );
	def( "expand", &expandWrapper, ( arg( "expandAncestors" ) = true ) );
	def( "expandDescendants", &expandDescendantsWrapper, ( arg( "context" ), arg( "paths" ), arg( "scene" ), arg( "depth" ) = Imath::limits<int>::max() ) );
	def( "clearExpansion", &clearExpansionWrapper );
	def( "setSelectedPaths", &setSelectedPathsWrapper );
	def( "getSelectedPaths", &getSelectedPaths );
	def( "affectsSelectedPaths", &affectsSelectedPaths );

}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 *
 */

#include "webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h"

#include "vpx/vpx_codec.h"
#include "vpx/vpx_decoder.h"
#include "vpx/vpx_frame_buffer.h"

#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"

namespace webrtc {

uint8_t* Vp9FrameBufferPool::Vp9FrameBuffer::GetData() {
  return data_.data<uint8_t>();
}

size_t Vp9FrameBufferPool::Vp9FrameBuffer::GetDataSize() const {
  return data_.size();
}

void Vp9FrameBufferPool::Vp9FrameBuffer::SetSize(size_t size) {
  data_.SetSize(size);
}

bool Vp9FrameBufferPool::InitializeVpxUsePool(
    vpx_codec_ctx* vpx_codec_context) {
  RTC_DCHECK(vpx_codec_context);
  // Tell libvpx to use this pool.
  if (vpx_codec_set_frame_buffer_functions(
          // In which context to use these callback functions.
          vpx_codec_context,
          // Called by libvpx when it needs another frame buffer.
          &Vp9FrameBufferPool::VpxGetFrameBuffer,
          // Called by libvpx when it no longer uses a frame buffer.
          &Vp9FrameBufferPool::VpxReleaseFrameBuffer,
          // |this| will be passed as |user_priv| to VpxGetFrameBuffer.
          this)) {
    // Failed to configure libvpx to use Vp9FrameBufferPool.
    return false;
  }
  return true;
}

rtc::scoped_refptr<Vp9FrameBufferPool::Vp9FrameBuffer>
Vp9FrameBufferPool::GetFrameBuffer(size_t min_size) {
  RTC_DCHECK_GT(min_size, 0);
  rtc::scoped_refptr<Vp9FrameBuffer> available_buffer = nullptr;
  {
    rtc::CritScope cs(&buffers_lock_);
    // Do we have a buffer we can recycle?
    for (const auto& buffer : allocated_buffers_) {
      if (buffer->HasOneRef()) {
        available_buffer = buffer;
        break;
      }
    }
    // Otherwise create one.
    if (available_buffer == nullptr) {
      available_buffer = new rtc::RefCountedObject<Vp9FrameBuffer>();
      allocated_buffers_.push_back(available_buffer);
      if (allocated_buffers_.size() > max_num_buffers_) {
        LOG(LS_WARNING)
            << allocated_buffers_.size() << " Vp9FrameBuffers have been "
            << "allocated by a Vp9FrameBufferPool (exceeding what is "
            << "considered reasonable, " << max_num_buffers_ << ").";
        RTC_NOTREACHED();
      }
    }
  }

  available_buffer->SetSize(min_size);
  return available_buffer;
}

int Vp9FrameBufferPool::GetNumBuffersInUse() const {
  int num_buffers_in_use = 0;
  rtc::CritScope cs(&buffers_lock_);
  for (const auto& buffer : allocated_buffers_) {
    if (!buffer->HasOneRef())
      ++num_buffers_in_use;
  }
  return num_buffers_in_use;
}

void Vp9FrameBufferPool::ClearPool() {
  rtc::CritScope cs(&buffers_lock_);
  allocated_buffers_.clear();
}

// static
int32_t Vp9FrameBufferPool::VpxGetFrameBuffer(void* user_priv,
                                              size_t min_size,
                                              vpx_codec_frame_buffer* fb) {
  RTC_DCHECK(user_priv);
  RTC_DCHECK(fb);
  Vp9FrameBufferPool* pool = static_cast<Vp9FrameBufferPool*>(user_priv);

  rtc::scoped_refptr<Vp9FrameBuffer> buffer = pool->GetFrameBuffer(min_size);
  fb->data = buffer->GetData();
  fb->size = buffer->GetDataSize();
  // Store Vp9FrameBuffer* in |priv| for use in VpxReleaseFrameBuffer.
  // This also makes vpx_codec_get_frame return images with their |fb_priv| set
  // to |buffer| which is important for external reference counting.
  // Release from refptr so that the buffer's |ref_count_| remains 1 when
  // |buffer| goes out of scope.
  fb->priv = static_cast<void*>(buffer.release());
  return 0;
}

// static
int32_t Vp9FrameBufferPool::VpxReleaseFrameBuffer(void* user_priv,
                                                  vpx_codec_frame_buffer* fb) {
  RTC_DCHECK(user_priv);
  RTC_DCHECK(fb);
  Vp9FrameBuffer* buffer = static_cast<Vp9FrameBuffer*>(fb->priv);
  if (buffer != nullptr) {
    buffer->Release();
    // When libvpx fails to decode and you continue to try to decode (and fail)
    // libvpx can for some reason try to release the same buffer multiple times.
    // Setting |priv| to null protects against trying to Release multiple times.
    fb->priv = nullptr;
  }
  return 0;
}

}  // namespace webrtc
<commit_msg>Reland of Disabling NOTREACHED which we're hitting flakily in browser tests. (patchset #1 id:1 of https://codereview.webrtc.org/2585183002/ )<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 *
 */

#include "webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h"

#include "vpx/vpx_codec.h"
#include "vpx/vpx_decoder.h"
#include "vpx/vpx_frame_buffer.h"

#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"

namespace webrtc {

uint8_t* Vp9FrameBufferPool::Vp9FrameBuffer::GetData() {
  return data_.data<uint8_t>();
}

size_t Vp9FrameBufferPool::Vp9FrameBuffer::GetDataSize() const {
  return data_.size();
}

void Vp9FrameBufferPool::Vp9FrameBuffer::SetSize(size_t size) {
  data_.SetSize(size);
}

bool Vp9FrameBufferPool::InitializeVpxUsePool(
    vpx_codec_ctx* vpx_codec_context) {
  RTC_DCHECK(vpx_codec_context);
  // Tell libvpx to use this pool.
  if (vpx_codec_set_frame_buffer_functions(
          // In which context to use these callback functions.
          vpx_codec_context,
          // Called by libvpx when it needs another frame buffer.
          &Vp9FrameBufferPool::VpxGetFrameBuffer,
          // Called by libvpx when it no longer uses a frame buffer.
          &Vp9FrameBufferPool::VpxReleaseFrameBuffer,
          // |this| will be passed as |user_priv| to VpxGetFrameBuffer.
          this)) {
    // Failed to configure libvpx to use Vp9FrameBufferPool.
    return false;
  }
  return true;
}

rtc::scoped_refptr<Vp9FrameBufferPool::Vp9FrameBuffer>
Vp9FrameBufferPool::GetFrameBuffer(size_t min_size) {
  RTC_DCHECK_GT(min_size, 0);
  rtc::scoped_refptr<Vp9FrameBuffer> available_buffer = nullptr;
  {
    rtc::CritScope cs(&buffers_lock_);
    // Do we have a buffer we can recycle?
    for (const auto& buffer : allocated_buffers_) {
      if (buffer->HasOneRef()) {
        available_buffer = buffer;
        break;
      }
    }
    // Otherwise create one.
    if (available_buffer == nullptr) {
      available_buffer = new rtc::RefCountedObject<Vp9FrameBuffer>();
      allocated_buffers_.push_back(available_buffer);
      if (allocated_buffers_.size() > max_num_buffers_) {
        LOG(LS_WARNING)
            << allocated_buffers_.size() << " Vp9FrameBuffers have been "
            << "allocated by a Vp9FrameBufferPool (exceeding what is "
            << "considered reasonable, " << max_num_buffers_ << ").";

        // TODO(phoglund): this limit is being hit in tests since Oct 5 2016.
        // See https://bugs.chromium.org/p/webrtc/issues/detail?id=6484.
        // RTC_NOTREACHED();
      }
    }
  }

  available_buffer->SetSize(min_size);
  return available_buffer;
}

int Vp9FrameBufferPool::GetNumBuffersInUse() const {
  int num_buffers_in_use = 0;
  rtc::CritScope cs(&buffers_lock_);
  for (const auto& buffer : allocated_buffers_) {
    if (!buffer->HasOneRef())
      ++num_buffers_in_use;
  }
  return num_buffers_in_use;
}

void Vp9FrameBufferPool::ClearPool() {
  rtc::CritScope cs(&buffers_lock_);
  allocated_buffers_.clear();
}

// static
int32_t Vp9FrameBufferPool::VpxGetFrameBuffer(void* user_priv,
                                              size_t min_size,
                                              vpx_codec_frame_buffer* fb) {
  RTC_DCHECK(user_priv);
  RTC_DCHECK(fb);
  Vp9FrameBufferPool* pool = static_cast<Vp9FrameBufferPool*>(user_priv);

  rtc::scoped_refptr<Vp9FrameBuffer> buffer = pool->GetFrameBuffer(min_size);
  fb->data = buffer->GetData();
  fb->size = buffer->GetDataSize();
  // Store Vp9FrameBuffer* in |priv| for use in VpxReleaseFrameBuffer.
  // This also makes vpx_codec_get_frame return images with their |fb_priv| set
  // to |buffer| which is important for external reference counting.
  // Release from refptr so that the buffer's |ref_count_| remains 1 when
  // |buffer| goes out of scope.
  fb->priv = static_cast<void*>(buffer.release());
  return 0;
}

// static
int32_t Vp9FrameBufferPool::VpxReleaseFrameBuffer(void* user_priv,
                                                  vpx_codec_frame_buffer* fb) {
  RTC_DCHECK(user_priv);
  RTC_DCHECK(fb);
  Vp9FrameBuffer* buffer = static_cast<Vp9FrameBuffer*>(fb->priv);
  if (buffer != nullptr) {
    buffer->Release();
    // When libvpx fails to decode and you continue to try to decode (and fail)
    // libvpx can for some reason try to release the same buffer multiple times.
    // Setting |priv| to null protects against trying to Release multiple times.
    fb->priv = nullptr;
  }
  return 0;
}

}  // namespace webrtc
<|endoftext|>


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

#include <graphene/protocol/config.hpp>
#include <graphene/protocol/pts_address.hpp>

#include <fc/array.hpp>
#include <fc/crypto/ripemd160.hpp>

namespace fc { namespace ecc {
    class public_key;
    typedef fc::array<char,33>  public_key_data;
} } // fc::ecc

namespace graphene { namespace protocol {

   struct public_key_type;

   /**
    *  @brief a 160 bit hash of a public key
    *
    *  An address can be converted to or from a base58 string with 32 bit checksum.
    *
    *  An address is calculated as ripemd160( sha512( compressed_ecc_public_key ) )
    *
    *  When converted to a string, checksum calculated as the first 4 bytes ripemd160( address ) is
    *  appended to the binary address before converting to base58.
    */
   class address
   {
      public:
       address(); ///< constructs empty / null address
       explicit address( const std::string& base58str );   ///< converts to binary, validates checksum
       address( const fc::ecc::public_key& pub ); ///< converts to binary
       explicit address( const fc::ecc::public_key_data& pub ); ///< converts to binary
       address( const pts_address& pub ); ///< converts to binary
       address( const public_key_type& pubkey );

       static bool is_valid( const std::string& base58str, const std::string& prefix = GRAPHENE_ADDRESS_PREFIX );

       explicit operator std::string()const; ///< converts to base58 + checksum

       friend size_t hash_value( const address& v ) {
          const void* tmp = static_cast<const void*>(v.addr._hash+2);

          const size_t* tmp2 = reinterpret_cast<const size_t*>(tmp);
          return *tmp2;
       }
       fc::ripemd160 addr;
   };
   inline bool operator == ( const address& a, const address& b ) { return a.addr == b.addr; }
   inline bool operator != ( const address& a, const address& b ) { return a.addr != b.addr; }
   inline bool operator <  ( const address& a, const address& b ) { return a.addr <  b.addr; }

} } // namespace graphene::protocol

namespace fc
{
   void to_variant( const graphene::protocol::address& var,  fc::variant& vo, uint32_t max_depth = 1 );
   void from_variant( const fc::variant& var,  graphene::protocol::address& vo, uint32_t max_depth = 1 );
}

namespace std
{
   template<>
   struct hash<graphene::protocol::address>
   {
       public:
         size_t operator()(const graphene::protocol::address &a) const
         {
            return (uint64_t(a.addr._hash[0])<<32) | uint64_t( a.addr._hash[0] );
         }
   };
}

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

#include <graphene/protocol/config.hpp>
#include <graphene/protocol/pts_address.hpp>

#include <fc/array.hpp>
#include <fc/crypto/ripemd160.hpp>

namespace fc { namespace ecc {
    class public_key;
    typedef fc::array<char,33>  public_key_data;
} } // fc::ecc

namespace graphene { namespace protocol {

   struct public_key_type;

   /**
    *  @brief a 160 bit hash of a public key
    *
    *  An address can be converted to or from a base58 string with 32 bit checksum.
    *
    *  An address is calculated as ripemd160( sha512( compressed_ecc_public_key ) )
    *
    *  When converted to a string, checksum calculated as the first 4 bytes ripemd160( address ) is
    *  appended to the binary address before converting to base58.
    */
   class address
   {
      public:
       address(); ///< constructs empty / null address
       explicit address( const std::string& base58str );   ///< converts to binary, validates checksum
       address( const fc::ecc::public_key& pub ); ///< converts to binary
       explicit address( const fc::ecc::public_key_data& pub ); ///< converts to binary
       address( const pts_address& pub ); ///< converts to binary
       address( const public_key_type& pubkey );

       static bool is_valid( const std::string& base58str, const std::string& prefix = GRAPHENE_ADDRESS_PREFIX );

       explicit operator std::string()const; ///< converts to base58 + checksum

       fc::ripemd160 addr;
   };
   inline bool operator == ( const address& a, const address& b ) { return a.addr == b.addr; }
   inline bool operator != ( const address& a, const address& b ) { return a.addr != b.addr; }
   inline bool operator <  ( const address& a, const address& b ) { return a.addr <  b.addr; }

} } // namespace graphene::protocol

namespace fc
{
   void to_variant( const graphene::protocol::address& var,  fc::variant& vo, uint32_t max_depth = 1 );
   void from_variant( const fc::variant& var,  graphene::protocol::address& vo, uint32_t max_depth = 1 );
}

#include <fc/reflect/reflect.hpp>
FC_REFLECT( graphene::protocol::address, (addr) )
<|endoftext|>


<commit_before>#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "allocore/system/al_Config.h"
#include "allocore/graphics/al_Mesh.hpp"
#include "allocore/graphics/al_Graphics.hpp"

namespace al{

Mesh& Mesh::reset() {
	vertices().reset();
	normals().reset();
	colors().reset();
	coloris().reset();
	texCoord2s().reset();
	texCoord3s().reset();
	indices().reset();
	return *this;
}

void Mesh::decompress(){
	int Ni = indices().size();
	if(Ni){
		#define DECOMPRESS(buf, Type)\
		{\
			int N = buf.size();\
			if(N){\
				std::vector<Type> old(N);\
				std::copy(&buf[0], (&buf[0]) + N, old.begin());\
				buf.size(Ni);\
				for(int i=0; i<Ni; ++i)	buf[i] = old[indices()[i]];\
			}\
		}
		DECOMPRESS(vertices(), Vertex)
		DECOMPRESS(colors(), Color)
		DECOMPRESS(coloris(), Color)
		DECOMPRESS(normals(), Normal)
		DECOMPRESS(texCoord2s(), TexCoord2)
		DECOMPRESS(texCoord3s(), TexCoord3)
		#undef DECOMPRESS

		indices().reset();
	}
}

void Mesh::equalizeBuffers() {
	const int Nv = vertices().size();
	const int Nn = normals().size();
	const int Nc = colors().size();
	const int Nci= coloris().size();
	const int Nt2= texCoord2s().size();
	const int Nt3= texCoord3s().size();

	if(Nn){
		for(int i=Nn; i<Nv; ++i){
			normals().append(normals()[Nn-1]);
		}
	}
	if(Nc){
		for(int i=Nc; i<Nv; ++i){
			colors().append(colors()[Nc-1]);
		}
	}
	else if(Nci){
		for(int i=Nci; i<Nv; ++i){
			coloris().append(coloris()[Nci-1]);
		}
	}
	if(Nt2){
		for(int i=Nt2; i<Nv; ++i){
			texCoord2s().append(texCoord2s()[Nt2-1]);
		}
	}
	if(Nt3){
		for(int i=Nt3; i<Nv; ++i){
			texCoord3s().append(texCoord3s()[Nt3-1]);
		}
	}
}

class TriFace {
public:
	Mesh::Vertex vertices[3];
	Vec3f norm;

	TriFace(const TriFace& cpy)
	: norm(cpy.norm) {
		vertices[0] = cpy.vertices[0];
		vertices[1] = cpy.vertices[1];
		vertices[2] = cpy.vertices[2];
	}
	TriFace(Mesh::Vertex p0, Mesh::Vertex p1, Mesh::Vertex p2)
	{
		vertices[0] = p0;
		vertices[1] = p1;
		vertices[2] = p2;
		// calculate norm for this face:
		normal<float>(norm, p0, p1, p2);
	}
};

void Mesh::createNormalsMesh(Mesh& mesh, float length, bool perFace) {
	if (perFace) {
		// compute vertex based normals
		if(indices().size()){
			mesh.reset();
			mesh.primitive(Graphics::LINES);

			int Ni = indices().size();
			Ni = Ni - (Ni%3); // must be multiple of 3

			for(int i=0; i<Ni; i+=3){
				Index i1 = indices()[i+0];
				Index i2 = indices()[i+1];
				Index i3 = indices()[i+2];
				const Vertex& v1 = vertices()[i1];
				const Vertex& v2 = vertices()[i2];
				const Vertex& v3 = vertices()[i3];

				// get mean:
				const Vertex& mean = (v1 + v2 + v3)/3.f;

				// get face normal:
				Vertex facenormal = cross(v2-v1, v3-v1);
				facenormal.normalize();

				mesh.vertex(mean);
				mesh.vertex(mean + (facenormal*length));

			}
		} else {
			printf("createNormalsMesh only valid for indexed meshes\n");
		}
	} else {
		mesh.reset();
		mesh.primitive(Graphics::LINES);
		int Ni = al::min(vertices().size(), normals().size());
		for(int i=0; i<Ni; i+=3){
			const Vertex& v = vertices()[i];
			mesh.vertex(v);
			mesh.vertex(v + normals()[i]*length);
		}
	}
}

void Mesh::invertNormals() {
	int Nv = normals().size();
	for(int i=0; i<Nv; ++i) normals()[i] = -normals()[i];
}

// Old non-functional prototype...
//	// generates smoothed normals for a set of vertices
//	// will replace any normals currently in use
//	// angle - maximum angle (in degrees) to smooth across
//	void generateNormals(float angle=360);

void Mesh::generateNormals(bool normalize, bool equalWeightPerFace) {
//	/*
//		Multi-pass algorithm:
//			generate a list of faces (assume triangles?)
//				(vary according to whether mIndices is used)
//			calculate normal per face (use normal<float>(dst, p0, p1, p2))
//			vertices may be used in multiple faces; their norm should be an average of the uses
//				easy enough if indices is being used; not so easy otherwise.
//					create a lookup table by hashing on vertex x,y,z
//
//
//			write avg into corresponding normals for each vertex
//				EXCEPT: if edge is sharper than @angle, just use the face normal directly
//	*/
//	std::vector<TriFace> faces;
//
//	std::map<std::string, int> vertexHash;
//
//	int Ni = indices().size();
//	int Nv = vertices().size();
//	if (Ni) {
//		for (int i=0; i<Ni;) {
//			TriFace face(
//				mVertices[mIndices[i++]],
//				mVertices[mIndices[i++]],
//				mVertices[mIndices[i++]]
//			);
//			faces.push_back(face);
//		}
//	} else {
//		for (int i=0; i<Nv;) {
//			TriFace face(
//				mVertices[i++],
//				mVertices[i++],
//				mVertices[i++]
//			);
//			faces.push_back(face);
//		}
//	}

	int Nv = vertices().size();

	// same number of normals as vertices
	normals().size(Nv);

	// compute vertex based normals
	if(indices().size()){

		for(int i=0; i<Nv; ++i) normals()[i].set(0,0,0);

		int Ni = indices().size();

//		if(primitive() == TRIANGLES){
			Ni = Ni - (Ni%3); // must be multiple of 3

			for(int i=0; i<Ni; i+=3){
				Index i1 = indices()[i+0];
				Index i2 = indices()[i+1];
				Index i3 = indices()[i+2];
				const Vertex& v1 = vertices()[i1];
				const Vertex& v2 = vertices()[i2];
				const Vertex& v3 = vertices()[i3];

				// MWAAT (mean weighted by areas of adjacent triangles)
				Vertex vn = cross(v2-v1, v3-v1);

				// MWE (mean weighted equally)
				if (equalWeightPerFace) vn.normalize();

				// MWA (mean weighted by angle)
				// This doesn't work well with dynamic marching cubes- normals
				// pop in and out for small triangles.
//				Vertex v12= v2-v1;
//				Vertex v13= v3-v1;
//				Vertex vn = cross(v12, v13).normalize();
//				vn *= angle(v12, v13) / M_PI;

				normals()[i1] += vn;
				normals()[i2] += vn;
				normals()[i3] += vn;
			}
//		}
//		else if(primitive() == TRIANGLE_STRIP){
//			for(int i=2; i<Ni; ++i){
//				Index i1 = indices()[i-2];
//				Index i2 = indices()[i-1];
//				Index i3 = indices()[i-0];
//				const Vertex& v1 = vertices()[i1];
//				const Vertex& v2 = vertices()[i2];
//				const Vertex& v3 = vertices()[i3];
//
//				Vertex vn = cross(v2-v1, v3-v1);
//
//				normals()[i1] += vn;
//				normals()[i2] += vn;
//				normals()[i3] += vn;
//			}
//		}

		// normalize the normals
		if(normalize) for(int i=0; i<Nv; ++i) normals()[i].normalize();
	}

	// compute face based normals
	else{
//		if(primitive() == TRIANGLES){
			int N = Nv - (Nv % 3);

			for(int i=0; i<N; i+=3){
				int i1 = i+0;
				int i2 = i+1;
				int i3 = i+2;
				const Vertex& v1 = vertices()[i1];
				const Vertex& v2 = vertices()[i2];
				const Vertex& v3 = vertices()[i3];

				Vertex vn = cross(v2-v1, v3-v1);
				if(normalize) vn.normalize();

				normals()[i1] = vn;
				normals()[i2] = vn;
				normals()[i3] = vn;
			}

//		}
	}
}

void Mesh::ribbonize(float * widths, int widthsStride, bool faceBitangent){

	const int N = mVertices.size();

	if(0 == N) return;

	mVertices.size(N*2);
	mNormals.size(N*2);

	// Store last vertex since it will be overwritten eventually
	Vertex last = mVertices[N-1];

	int in = faceBitangent ? 2 : 1;
	int ib = faceBitangent ? 1 : 2;

	for(int i=N-1; i>=0; --i){
		int i1 = i;
		int i0 = i1-1; if(i0< 0) i0+=N;
		int i2 = i1+1; if(i2>=N) i2-=N;

		const Vertex& v0 = (i0==(N-1)) ? last : mVertices[i0];
		const Vertex& v1 = mVertices[i1];
		const Vertex& v2 = mVertices[i2];

		// compute Frenet frame
		Vertex f[3]; // T,N,B
		{
			const Vertex d1 = (v0 - v2)*0.5;
			const Vertex d2 = (d1 - v1)*2.0;
			//Vertex& t = f[0];
			Vertex& n = f[1];
			Vertex& b = f[2];
			b = cross(d2, d1).sgn();
			n = cross(d1, b).sgn();
			//t = d1.sgn(); // not used
		}
		f[ib] *= widths[i0*widthsStride];

		int i12 = i1<<1;
		mVertices[i12  ] = v1-f[ib];
		mVertices[i12+1] = v1+f[ib];
		mNormals [i12  ].set(f[in][0], f[in][1], f[in][2]);
		mNormals [i12+1] = mNormals[i12];
	}

	if(mColors.size()) mColors.expand<2,true>();
	if(mColoris.size()) mColoris.expand<2,true>();
}

void Mesh::merge(const Mesh& src){
//	if (indices().size() || src.indices().size()) {
//		printf("error: Mesh merging with indexed meshes not yet supported\n");
//		return;
//	}

	// TODO: only do merge if source and dest are well-formed
	// TODO: what to do when mixing float and integer colors? promote or demote?

	// TODO: indices are more complex, since the offsets may have changed.
	// we'd have to add indices.size() to all of the src.indices before adding.
	// also, both src & dst should either use or not use indices
	// tricky if src is empty...
	//indices().append(src.indices());

	// Source has indices, and I either do or don't.
	// After this block, I will have indices.
	if(src.indices().size()){
		Index Nv = vertices().size();
		Index Ni = indices().size();
		// If no indices, must create
		if(0 == Ni){
			for(Index i=0; i<Nv; ++i) index(i);
		}
		// Add source indices offset by my number of vertices
		index(src.indices().elems(), src.indices().size(), (unsigned int)Nv);
	}

	// Source doesn't have indices, but I do
	else if(indices().size()){
		int Nv = vertices().size();
		for(int i=Nv; i<Nv+src.vertices().size(); ++i) index(i);
	}

	// From here, the game is indice invariant

	//equalizeBuffers(); << TODO: must do this if we are using indices.
	vertices().append(src.vertices());
	normals().append(src.normals());
	colors().append(src.colors());
	texCoord2s().append(src.texCoord2s());
	texCoord3s().append(src.texCoord3s());
}

void Mesh::getBounds(Vertex& min, Vertex& max) const {
	if(vertices().size()){
		min.set(vertices()[0]);
		max.set(min);
		for(int v=1; v<vertices().size(); ++v){
			const Vertex& vt = vertices()[v];
			for(int i=0; i<3; ++i){
				min[i] = AL_MIN(min[i], vt[i]);
				max[i] = AL_MAX(max[i], vt[i]);
			}
		}
	}
}

Mesh::Vertex Mesh::getCenter() const {
	Vertex min(0), max(0);
	getBounds(min, max);
	return min+(max-min)*0.5;
}

void Mesh::unitize() {
	Vertex min(0), max(0);
	getBounds(min, max);
	Vertex avg = (max-min)*0.5;
	for (int v=0; v<mVertices.size(); v++) {
		Vertex& vt = mVertices[v];
		for (int i=0; i<3; i++) {
			vt[i] = -1. + (vt[i]-min[i])/avg[i];
		}
	}
}

void Mesh::translate(double x, double y, double z){
	const Vertex xfm(x,y,z);
	for(int i=0; i<vertices().size(); ++i)
		mVertices[i] += xfm;
}

void Mesh::scale(double x, double y, double z){
	const Vertex xfm(x,y,z);
	for(int i=0; i<vertices().size(); ++i)
		mVertices[i] *= xfm;
}

} // ::al
<commit_msg>fix to vertex-based createNormalsMesh (was only outputting every third vertex)<commit_after>#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "allocore/system/al_Config.h"
#include "allocore/graphics/al_Mesh.hpp"
#include "allocore/graphics/al_Graphics.hpp"

namespace al{

Mesh& Mesh::reset() {
	vertices().reset();
	normals().reset();
	colors().reset();
	coloris().reset();
	texCoord2s().reset();
	texCoord3s().reset();
	indices().reset();
	return *this;
}

void Mesh::decompress(){
	int Ni = indices().size();
	if(Ni){
		#define DECOMPRESS(buf, Type)\
		{\
			int N = buf.size();\
			if(N){\
				std::vector<Type> old(N);\
				std::copy(&buf[0], (&buf[0]) + N, old.begin());\
				buf.size(Ni);\
				for(int i=0; i<Ni; ++i)	buf[i] = old[indices()[i]];\
			}\
		}
		DECOMPRESS(vertices(), Vertex)
		DECOMPRESS(colors(), Color)
		DECOMPRESS(coloris(), Color)
		DECOMPRESS(normals(), Normal)
		DECOMPRESS(texCoord2s(), TexCoord2)
		DECOMPRESS(texCoord3s(), TexCoord3)
		#undef DECOMPRESS

		indices().reset();
	}
}

void Mesh::equalizeBuffers() {
	const int Nv = vertices().size();
	const int Nn = normals().size();
	const int Nc = colors().size();
	const int Nci= coloris().size();
	const int Nt2= texCoord2s().size();
	const int Nt3= texCoord3s().size();

	if(Nn){
		for(int i=Nn; i<Nv; ++i){
			normals().append(normals()[Nn-1]);
		}
	}
	if(Nc){
		for(int i=Nc; i<Nv; ++i){
			colors().append(colors()[Nc-1]);
		}
	}
	else if(Nci){
		for(int i=Nci; i<Nv; ++i){
			coloris().append(coloris()[Nci-1]);
		}
	}
	if(Nt2){
		for(int i=Nt2; i<Nv; ++i){
			texCoord2s().append(texCoord2s()[Nt2-1]);
		}
	}
	if(Nt3){
		for(int i=Nt3; i<Nv; ++i){
			texCoord3s().append(texCoord3s()[Nt3-1]);
		}
	}
}

class TriFace {
public:
	Mesh::Vertex vertices[3];
	Vec3f norm;

	TriFace(const TriFace& cpy)
	: norm(cpy.norm) {
		vertices[0] = cpy.vertices[0];
		vertices[1] = cpy.vertices[1];
		vertices[2] = cpy.vertices[2];
	}
	TriFace(Mesh::Vertex p0, Mesh::Vertex p1, Mesh::Vertex p2)
	{
		vertices[0] = p0;
		vertices[1] = p1;
		vertices[2] = p2;
		// calculate norm for this face:
		normal<float>(norm, p0, p1, p2);
	}
};

void Mesh::createNormalsMesh(Mesh& mesh, float length, bool perFace){

	struct F{
		static void initMesh(Mesh& m, int n){
			m.vertices().size(n*2);
			m.reset();
			m.primitive(Graphics::LINES);
		}
	};

	if (perFace) {
		// compute vertex based normals
		if(indices().size()){

			int Ni = indices().size();
			Ni = Ni - (Ni%3); // must be multiple of 3
			F::initMesh(mesh, (Ni/3)*2);

			for(int i=0; i<Ni; i+=3){
				Index i1 = indices()[i+0];
				Index i2 = indices()[i+1];
				Index i3 = indices()[i+2];
				const Vertex& v1 = vertices()[i1];
				const Vertex& v2 = vertices()[i2];
				const Vertex& v3 = vertices()[i3];

				// get mean:
				const Vertex mean = (v1 + v2 + v3)/3.f;

				// get face normal:
				Vertex facenormal = cross(v2-v1, v3-v1);
				facenormal.normalize();

				mesh.vertex(mean);
				mesh.vertex(mean + (facenormal*length));
			}
		} else {
			printf("createNormalsMesh only valid for indexed meshes\n");
		}
	} else {
		int Ni = al::min(vertices().size(), normals().size());
		F::initMesh(mesh, Ni*2);

		for(int i=0; i<Ni; ++i){
			const Vertex& v = vertices()[i];
			mesh.vertex(v);
			mesh.vertex(v + normals()[i]*length);
		}
	}
}

void Mesh::invertNormals() {
	int Nv = normals().size();
	for(int i=0; i<Nv; ++i) normals()[i] = -normals()[i];
}

// Old non-functional prototype...
//	// generates smoothed normals for a set of vertices
//	// will replace any normals currently in use
//	// angle - maximum angle (in degrees) to smooth across
//	void generateNormals(float angle=360);

void Mesh::generateNormals(bool normalize, bool equalWeightPerFace) {
//	/*
//		Multi-pass algorithm:
//			generate a list of faces (assume triangles?)
//				(vary according to whether mIndices is used)
//			calculate normal per face (use normal<float>(dst, p0, p1, p2))
//			vertices may be used in multiple faces; their norm should be an average of the uses
//				easy enough if indices is being used; not so easy otherwise.
//					create a lookup table by hashing on vertex x,y,z
//
//
//			write avg into corresponding normals for each vertex
//				EXCEPT: if edge is sharper than @angle, just use the face normal directly
//	*/
//	std::vector<TriFace> faces;
//
//	std::map<std::string, int> vertexHash;
//
//	int Ni = indices().size();
//	int Nv = vertices().size();
//	if (Ni) {
//		for (int i=0; i<Ni;) {
//			TriFace face(
//				mVertices[mIndices[i++]],
//				mVertices[mIndices[i++]],
//				mVertices[mIndices[i++]]
//			);
//			faces.push_back(face);
//		}
//	} else {
//		for (int i=0; i<Nv;) {
//			TriFace face(
//				mVertices[i++],
//				mVertices[i++],
//				mVertices[i++]
//			);
//			faces.push_back(face);
//		}
//	}

	int Nv = vertices().size();

	// same number of normals as vertices
	normals().size(Nv);

	// compute vertex based normals
	if(indices().size()){

		for(int i=0; i<Nv; ++i) normals()[i].set(0,0,0);

		int Ni = indices().size();

//		if(primitive() == TRIANGLES){
			Ni = Ni - (Ni%3); // must be multiple of 3

			for(int i=0; i<Ni; i+=3){
				Index i1 = indices()[i+0];
				Index i2 = indices()[i+1];
				Index i3 = indices()[i+2];
				const Vertex& v1 = vertices()[i1];
				const Vertex& v2 = vertices()[i2];
				const Vertex& v3 = vertices()[i3];

				// MWAAT (mean weighted by areas of adjacent triangles)
				Vertex vn = cross(v2-v1, v3-v1);

				// MWE (mean weighted equally)
				if (equalWeightPerFace) vn.normalize();

				// MWA (mean weighted by angle)
				// This doesn't work well with dynamic marching cubes- normals
				// pop in and out for small triangles.
//				Vertex v12= v2-v1;
//				Vertex v13= v3-v1;
//				Vertex vn = cross(v12, v13).normalize();
//				vn *= angle(v12, v13) / M_PI;

				normals()[i1] += vn;
				normals()[i2] += vn;
				normals()[i3] += vn;
			}
//		}
//		else if(primitive() == TRIANGLE_STRIP){
//			for(int i=2; i<Ni; ++i){
//				Index i1 = indices()[i-2];
//				Index i2 = indices()[i-1];
//				Index i3 = indices()[i-0];
//				const Vertex& v1 = vertices()[i1];
//				const Vertex& v2 = vertices()[i2];
//				const Vertex& v3 = vertices()[i3];
//
//				Vertex vn = cross(v2-v1, v3-v1);
//
//				normals()[i1] += vn;
//				normals()[i2] += vn;
//				normals()[i3] += vn;
//			}
//		}

		// normalize the normals
		if(normalize) for(int i=0; i<Nv; ++i) normals()[i].normalize();
	}

	// compute face based normals
	else{
//		if(primitive() == TRIANGLES){
			int N = Nv - (Nv % 3);

			for(int i=0; i<N; i+=3){
				int i1 = i+0;
				int i2 = i+1;
				int i3 = i+2;
				const Vertex& v1 = vertices()[i1];
				const Vertex& v2 = vertices()[i2];
				const Vertex& v3 = vertices()[i3];

				Vertex vn = cross(v2-v1, v3-v1);
				if(normalize) vn.normalize();

				normals()[i1] = vn;
				normals()[i2] = vn;
				normals()[i3] = vn;
			}

//		}
	}
}

void Mesh::ribbonize(float * widths, int widthsStride, bool faceBitangent){

	const int N = mVertices.size();

	if(0 == N) return;

	mVertices.size(N*2);
	mNormals.size(N*2);

	// Store last vertex since it will be overwritten eventually
	const Vertex last = mVertices[N-1];

	int in = faceBitangent ? 2 : 1;
	int ib = faceBitangent ? 1 : 2;

	for(int i=N-1; i>=0; --i){
		int i1 = i;
		int i0 = i1-1; if(i0< 0) i0+=N;
		int i2 = i1+1; if(i2>=N) i2-=N;

		const Vertex& v0 = (i0==(N-1)) ? last : mVertices[i0];
		const Vertex& v1 = mVertices[i1];
		const Vertex& v2 = mVertices[i2];

		// compute Frenet frame
		Vertex f[3]; // T,N,B
		{
			const Vertex d1 = (v0 - v2)*0.5;
			const Vertex d2 = (d1 - v1)*2.0;
			//Vertex& t = f[0];
			Vertex& n = f[1];
			Vertex& b = f[2];
			b = cross(d2,d1).sgn();
			n = cross(d1, b).sgn();
			//t = d1.sgn(); // not used
		}
		f[ib] *= widths[i0*widthsStride];

		int i12 = i1<<1;
		// v1 is ref, so we must write in reverse to properly handle i=0
		mVertices[i12+1] = v1+f[ib];
		mVertices[i12  ] = v1-f[ib];

		mNormals [i12  ].set(f[in][0], f[in][1], f[in][2]);
		mNormals [i12+1] = mNormals[i12];
	}

	if(mColors.size()) mColors.expand<2,true>();
	if(mColoris.size()) mColoris.expand<2,true>();
}

void Mesh::merge(const Mesh& src){
//	if (indices().size() || src.indices().size()) {
//		printf("error: Mesh merging with indexed meshes not yet supported\n");
//		return;
//	}

	// TODO: only do merge if source and dest are well-formed
	// TODO: what to do when mixing float and integer colors? promote or demote?

	// TODO: indices are more complex, since the offsets may have changed.
	// we'd have to add indices.size() to all of the src.indices before adding.
	// also, both src & dst should either use or not use indices
	// tricky if src is empty...
	//indices().append(src.indices());

	// Source has indices, and I either do or don't.
	// After this block, I will have indices.
	if(src.indices().size()){
		Index Nv = vertices().size();
		Index Ni = indices().size();
		// If no indices, must create
		if(0 == Ni){
			for(Index i=0; i<Nv; ++i) index(i);
		}
		// Add source indices offset by my number of vertices
		index(src.indices().elems(), src.indices().size(), (unsigned int)Nv);
	}

	// Source doesn't have indices, but I do
	else if(indices().size()){
		int Nv = vertices().size();
		for(int i=Nv; i<Nv+src.vertices().size(); ++i) index(i);
	}

	// From here, the game is indice invariant

	//equalizeBuffers(); << TODO: must do this if we are using indices.
	vertices().append(src.vertices());
	normals().append(src.normals());
	colors().append(src.colors());
	texCoord2s().append(src.texCoord2s());
	texCoord3s().append(src.texCoord3s());
}

void Mesh::getBounds(Vertex& min, Vertex& max) const {
	if(vertices().size()){
		min.set(vertices()[0]);
		max.set(min);
		for(int v=1; v<vertices().size(); ++v){
			const Vertex& vt = vertices()[v];
			for(int i=0; i<3; ++i){
				min[i] = AL_MIN(min[i], vt[i]);
				max[i] = AL_MAX(max[i], vt[i]);
			}
		}
	}
}

Mesh::Vertex Mesh::getCenter() const {
	Vertex min(0), max(0);
	getBounds(min, max);
	return min+(max-min)*0.5;
}

void Mesh::unitize() {
	Vertex min(0), max(0);
	getBounds(min, max);
	Vertex avg = (max-min)*0.5;
	for (int v=0; v<mVertices.size(); v++) {
		Vertex& vt = mVertices[v];
		for (int i=0; i<3; i++) {
			vt[i] = -1. + (vt[i]-min[i])/avg[i];
		}
	}
}

void Mesh::translate(double x, double y, double z){
	const Vertex xfm(x,y,z);
	for(int i=0; i<vertices().size(); ++i)
		mVertices[i] += xfm;
}

void Mesh::scale(double x, double y, double z){
	const Vertex xfm(x,y,z);
	for(int i=0; i<vertices().size(); ++i)
		mVertices[i] *= xfm;
}

} // ::al
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractBlock.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkExtractBlock.h"

#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkDataSet.h"
#include "vtkCompositeDataIterator.h"
#include "vtkInformationIntegerKey.h"
#include "vtkMultiPieceDataSet.h"

#include <vtkstd/set>

class vtkExtractBlock::vtkSet : public vtkstd::set<unsigned int>
{
};

vtkStandardNewMacro(vtkExtractBlock);
vtkCxxRevisionMacro(vtkExtractBlock, "1.5");
vtkInformationKeyMacro(vtkExtractBlock, DONT_PRUNE, Integer);
//----------------------------------------------------------------------------
vtkExtractBlock::vtkExtractBlock()
{
  this->Indices = new vtkExtractBlock::vtkSet();
  this->ActiveIndices = new vtkExtractBlock::vtkSet();
  this->PruneOutput = 1;
}

//----------------------------------------------------------------------------
vtkExtractBlock::~vtkExtractBlock()
{
  delete this->Indices;
  delete this->ActiveIndices;
}

//----------------------------------------------------------------------------
void vtkExtractBlock::AddIndex(unsigned int index)
{
  this->Indices->insert(index);
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkExtractBlock::RemoveIndex(unsigned int index)
{
  this->Indices->erase(index);
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkExtractBlock::RemoveAllIndices()
{
  this->Indices->clear();
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkExtractBlock::CopySubTree(vtkCompositeDataIterator* loc,
  vtkMultiBlockDataSet* output, vtkMultiBlockDataSet* input)
{
  vtkDataObject* inputNode = input->GetDataSet(loc);
  if (!inputNode->IsA("vtkCompositeDataSet"))
    {
    vtkDataObject* clone = inputNode->NewInstance();
    clone->ShallowCopy(inputNode);
    output->SetDataSet(loc, clone);
    clone->Delete();
    }
  else
    {
    vtkCompositeDataSet* cinput = vtkCompositeDataSet::SafeDownCast(inputNode);
    vtkCompositeDataSet* coutput = vtkCompositeDataSet::SafeDownCast(
      output->GetDataSet(loc));
    vtkCompositeDataIterator* iter = cinput->NewIterator();
    iter->VisitOnlyLeavesOff();
    for (iter->InitTraversal();
      !iter->IsDoneWithTraversal() && this->ActiveIndices->size() > 0;
      iter->GoToNextItem())
      {
      vtkDataObject* curNode = iter->GetCurrentDataObject();
      vtkDataObject* clone = curNode->NewInstance();
      clone->ShallowCopy(curNode);
      coutput->SetDataSet(iter, clone);
      clone->Delete();

      this->ActiveIndices->erase(loc->GetCurrentFlatIndex() +
        iter->GetCurrentFlatIndex());
      }
    iter->Delete();
    }
}

//----------------------------------------------------------------------------
int vtkExtractBlock::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  vtkMultiBlockDataSet *input = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
  vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::GetData(outputVector, 0);

  if (this->Indices->find(0) != this->Indices->end())
    {
    // trivial case.
    output->ShallowCopy(input);
    return 1;
    }

  output->CopyStructure(input);

  (*this->ActiveIndices) = (*this->Indices);

  // Copy selected blocks over to the output.
  vtkCompositeDataIterator* iter = input->NewIterator();
  iter->VisitOnlyLeavesOff();

  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    if (this->ActiveIndices->find(iter->GetCurrentFlatIndex()) !=
      this->ActiveIndices->end())
      {
      this->ActiveIndices->erase(iter->GetCurrentFlatIndex());

      // This removed the visited indices from this->ActiveIndices.
      this->CopySubTree(iter, output, input);
      }
    }
  iter->Delete();
  this->ActiveIndices->clear();

  if (!this->PruneOutput)
    {
    return 1;
    }

  // Now prune the output tree.

  // Since in case multiple processes are involved, this process may have some
  // data-set pointers NULL. Hence, pruning cannot simply trim NULL ptrs, since
  // in that case we may end up with different structures on different
  // processess, which is a big NO-NO. Hence, we first flag nodes based on
  // whether they are being pruned or not.

  iter = output->NewIterator();
  iter->VisitOnlyLeavesOff();
  iter->SkipEmptyNodesOff();
  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    if (this->Indices->find(iter->GetCurrentFlatIndex()) != this->Indices->end())
      {
      iter->GetCurrentMetaData()->Set(DONT_PRUNE(), 1);
      }
    else if (iter->HasCurrentMetaData() && iter->GetCurrentMetaData()->Has(DONT_PRUNE()))
      {
      iter->GetCurrentMetaData()->Remove(DONT_PRUNE());
      }
    }
  iter->Delete();

  // Do the actual pruning. Only those branches are pruned which don't have
  // DON_PRUNE flag set.
  this->Prune(output);
  return 1;
}

//----------------------------------------------------------------------------
bool vtkExtractBlock::Prune(vtkDataObject* branch)
{
  if (branch->IsA("vtkMultiBlockDataSet"))
    {
    return this->Prune(vtkMultiBlockDataSet::SafeDownCast(branch));
    }
  else if (branch->IsA("vtkMultiPieceDataSet"))
    {
    return this->Prune(vtkMultiPieceDataSet::SafeDownCast(branch));
    }

  return true;
}

//----------------------------------------------------------------------------
bool vtkExtractBlock::Prune(vtkMultiPieceDataSet* mpiece)
{
  // * Remove any children on mpiece that don't have DONT_PRUNE set.
  vtkMultiPieceDataSet* clone = vtkMultiPieceDataSet::New();
  unsigned int index=0;
  unsigned int numChildren = mpiece->GetNumberOfPieces();
  for (unsigned int cc=0; cc<numChildren; cc++)
    {
    if (mpiece->HasMetaData(cc) && mpiece->GetMetaData(cc)->Has(DONT_PRUNE()))
      {
      clone->SetPiece(index, mpiece->GetPiece(cc));
      clone->GetMetaData(index)->Copy(mpiece->GetMetaData(cc));
      index++;
      }
    }
  mpiece->ShallowCopy(clone);
  clone->Delete();

  // tell caller to prune mpiece away if num of pieces is 0.
  return (mpiece->GetNumberOfPieces() == 0);
}

//----------------------------------------------------------------------------
bool vtkExtractBlock::Prune(vtkMultiBlockDataSet* mblock)
{
  vtkMultiBlockDataSet* clone = vtkMultiBlockDataSet::New();
  unsigned int index=0;
  unsigned int numChildren = mblock->GetNumberOfBlocks();
  for (unsigned int cc=0; cc < numChildren; cc++)
    {
    vtkDataObject* block = mblock->GetBlock(cc);
    if (mblock->HasMetaData(cc) && mblock->GetMetaData(cc)->Has(DONT_PRUNE()))
      {
      clone->SetBlock(index, block);
      clone->GetMetaData(index)->Copy(mblock->GetMetaData(cc));
      index++;
      }
    else if (block)
      {
      bool prune = this->Prune(block);
      if (!prune)
        {
        vtkMultiBlockDataSet* prunedBlock = vtkMultiBlockDataSet::SafeDownCast(block);
        if (prunedBlock && prunedBlock->GetNumberOfBlocks()==1)
          {
          // shrink redundant branches.
          clone->SetBlock(index, prunedBlock->GetBlock(0));
          if (prunedBlock->HasMetaData(static_cast<unsigned int>(0)))
            {
            clone->GetMetaData(index)->Copy(prunedBlock->GetMetaData(
                static_cast<unsigned int>(0)));
            }
          }
        else
          {
          clone->SetBlock(index, block);
          if (mblock->HasMetaData(cc))
            {
            clone->GetMetaData(index)->Copy(mblock->GetMetaData(cc));
            }
          }
        index++;
        }
      }
    }
  mblock->ShallowCopy(clone);
  clone->Delete();
  return (mblock->GetNumberOfBlocks() == 0);
}

//----------------------------------------------------------------------------
void vtkExtractBlock::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "PruneOutput: " << this->PruneOutput << endl;
}

<commit_msg>BUG: When parent node was selected, children were not being copied correctly. Fixed that.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractBlock.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkExtractBlock.h"

#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkDataSet.h"
#include "vtkCompositeDataIterator.h"
#include "vtkInformationIntegerKey.h"
#include "vtkMultiPieceDataSet.h"

#include <vtkstd/set>

class vtkExtractBlock::vtkSet : public vtkstd::set<unsigned int>
{
};

vtkStandardNewMacro(vtkExtractBlock);
vtkCxxRevisionMacro(vtkExtractBlock, "1.6");
vtkInformationKeyMacro(vtkExtractBlock, DONT_PRUNE, Integer);
//----------------------------------------------------------------------------
vtkExtractBlock::vtkExtractBlock()
{
  this->Indices = new vtkExtractBlock::vtkSet();
  this->ActiveIndices = new vtkExtractBlock::vtkSet();
  this->PruneOutput = 1;
}

//----------------------------------------------------------------------------
vtkExtractBlock::~vtkExtractBlock()
{
  delete this->Indices;
  delete this->ActiveIndices;
}

//----------------------------------------------------------------------------
void vtkExtractBlock::AddIndex(unsigned int index)
{
  this->Indices->insert(index);
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkExtractBlock::RemoveIndex(unsigned int index)
{
  this->Indices->erase(index);
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkExtractBlock::RemoveAllIndices()
{
  this->Indices->clear();
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkExtractBlock::CopySubTree(vtkCompositeDataIterator* loc,
  vtkMultiBlockDataSet* output, vtkMultiBlockDataSet* input)
{
  vtkDataObject* inputNode = input->GetDataSet(loc);
  if (!inputNode->IsA("vtkCompositeDataSet"))
    {
    vtkDataObject* clone = inputNode->NewInstance();
    clone->ShallowCopy(inputNode);
    output->SetDataSet(loc, clone);
    clone->Delete();
    }
  else
    {
    vtkCompositeDataSet* cinput = vtkCompositeDataSet::SafeDownCast(inputNode);
    vtkCompositeDataSet* coutput = vtkCompositeDataSet::SafeDownCast(
      output->GetDataSet(loc));
    vtkCompositeDataIterator* iter = cinput->NewIterator();
    iter->VisitOnlyLeavesOff();
    for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
      {
      vtkDataObject* curNode = iter->GetCurrentDataObject();
      vtkDataObject* clone = curNode->NewInstance();
      clone->ShallowCopy(curNode);
      coutput->SetDataSet(iter, clone);
      clone->Delete();

      this->ActiveIndices->erase(loc->GetCurrentFlatIndex() +
        iter->GetCurrentFlatIndex());
      }
    iter->Delete();
    }
}

//----------------------------------------------------------------------------
int vtkExtractBlock::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  vtkMultiBlockDataSet *input = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
  vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::GetData(outputVector, 0);

  if (this->Indices->find(0) != this->Indices->end())
    {
    // trivial case.
    output->ShallowCopy(input);
    return 1;
    }

  output->CopyStructure(input);

  (*this->ActiveIndices) = (*this->Indices);

  // Copy selected blocks over to the output.
  vtkCompositeDataIterator* iter = input->NewIterator();
  iter->VisitOnlyLeavesOff();

  for (iter->InitTraversal();
    !iter->IsDoneWithTraversal() && this->ActiveIndices->size()>0;
    iter->GoToNextItem())
    {
    if (this->ActiveIndices->find(iter->GetCurrentFlatIndex()) !=
      this->ActiveIndices->end())
      {
      this->ActiveIndices->erase(iter->GetCurrentFlatIndex());

      // This removed the visited indices from this->ActiveIndices.
      this->CopySubTree(iter, output, input);
      }
    }
  iter->Delete();
  this->ActiveIndices->clear();

  if (!this->PruneOutput)
    {
    return 1;
    }

  // Now prune the output tree.

  // Since in case multiple processes are involved, this process may have some
  // data-set pointers NULL. Hence, pruning cannot simply trim NULL ptrs, since
  // in that case we may end up with different structures on different
  // processess, which is a big NO-NO. Hence, we first flag nodes based on
  // whether they are being pruned or not.

  iter = output->NewIterator();
  iter->VisitOnlyLeavesOff();
  iter->SkipEmptyNodesOff();
  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    if (this->Indices->find(iter->GetCurrentFlatIndex()) != this->Indices->end())
      {
      iter->GetCurrentMetaData()->Set(DONT_PRUNE(), 1);
      }
    else if (iter->HasCurrentMetaData() && iter->GetCurrentMetaData()->Has(DONT_PRUNE()))
      {
      iter->GetCurrentMetaData()->Remove(DONT_PRUNE());
      }
    }
  iter->Delete();

  // Do the actual pruning. Only those branches are pruned which don't have
  // DON_PRUNE flag set.
  this->Prune(output);
  return 1;
}

//----------------------------------------------------------------------------
bool vtkExtractBlock::Prune(vtkDataObject* branch)
{
  if (branch->IsA("vtkMultiBlockDataSet"))
    {
    return this->Prune(vtkMultiBlockDataSet::SafeDownCast(branch));
    }
  else if (branch->IsA("vtkMultiPieceDataSet"))
    {
    return this->Prune(vtkMultiPieceDataSet::SafeDownCast(branch));
    }

  return true;
}

//----------------------------------------------------------------------------
bool vtkExtractBlock::Prune(vtkMultiPieceDataSet* mpiece)
{
  // * Remove any children on mpiece that don't have DONT_PRUNE set.
  vtkMultiPieceDataSet* clone = vtkMultiPieceDataSet::New();
  unsigned int index=0;
  unsigned int numChildren = mpiece->GetNumberOfPieces();
  for (unsigned int cc=0; cc<numChildren; cc++)
    {
    if (mpiece->HasMetaData(cc) && mpiece->GetMetaData(cc)->Has(DONT_PRUNE()))
      {
      clone->SetPiece(index, mpiece->GetPiece(cc));
      clone->GetMetaData(index)->Copy(mpiece->GetMetaData(cc));
      index++;
      }
    }
  mpiece->ShallowCopy(clone);
  clone->Delete();

  // tell caller to prune mpiece away if num of pieces is 0.
  return (mpiece->GetNumberOfPieces() == 0);
}

//----------------------------------------------------------------------------
bool vtkExtractBlock::Prune(vtkMultiBlockDataSet* mblock)
{
  vtkMultiBlockDataSet* clone = vtkMultiBlockDataSet::New();
  unsigned int index=0;
  unsigned int numChildren = mblock->GetNumberOfBlocks();
  for (unsigned int cc=0; cc < numChildren; cc++)
    {
    vtkDataObject* block = mblock->GetBlock(cc);
    if (mblock->HasMetaData(cc) && mblock->GetMetaData(cc)->Has(DONT_PRUNE()))
      {
      clone->SetBlock(index, block);
      clone->GetMetaData(index)->Copy(mblock->GetMetaData(cc));
      index++;
      }
    else if (block)
      {
      bool prune = this->Prune(block);
      if (!prune)
        {
        vtkMultiBlockDataSet* prunedBlock = vtkMultiBlockDataSet::SafeDownCast(block);
        if (prunedBlock && prunedBlock->GetNumberOfBlocks()==1)
          {
          // shrink redundant branches.
          clone->SetBlock(index, prunedBlock->GetBlock(0));
          if (prunedBlock->HasMetaData(static_cast<unsigned int>(0)))
            {
            clone->GetMetaData(index)->Copy(prunedBlock->GetMetaData(
                static_cast<unsigned int>(0)));
            }
          }
        else
          {
          clone->SetBlock(index, block);
          if (mblock->HasMetaData(cc))
            {
            clone->GetMetaData(index)->Copy(mblock->GetMetaData(cc));
            }
          }
        index++;
        }
      }
    }
  mblock->ShallowCopy(clone);
  clone->Delete();
  return (mblock->GetNumberOfBlocks() == 0);
}

//----------------------------------------------------------------------------
void vtkExtractBlock::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "PruneOutput: " << this->PruneOutput << endl;
}

<|endoftext|>


<commit_before>// $Id$

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Authors:                                                               *
 *          for The ALICE HLT Project.                                    *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//  @file   AliHLTTRDCluster.cxx
//  @author Theodor Rascanu
//  @date
//  @brief  A datacontainer for clusters fitting component for the HLT.
//

#include "AliHLTTRDCluster.h"
#include <cstring>

/**
 * Default Constructor
 */
//============================================================================
AliHLTTRDCluster::AliHLTTRDCluster():
  fSignals(0),
  fPadCol(0),
  fPadRow(0),
  fPadTime(0),
  fBits(0)
{
}

/**
 * Main Constructor
 */
//============================================================================
AliHLTTRDCluster::AliHLTTRDCluster(const AliTRDcluster* const inCluster):
  fSignals(0),
  fPadCol(inCluster->fPadCol),
  fPadRow(inCluster->fPadRow),
  fPadTime(inCluster->fPadTime),
  fBits(0)
{

  fSignals = inCluster->fSignals[2];
  fSignals|= inCluster->fSignals[3]<<10;
  fSignals|= inCluster->fSignals[4]<<20;

  fBits = UInt_t(inCluster->TestBits(-1)) >> 14;
}

/**
 * Copy data to the output TRDcluster
 */
//============================================================================
void AliHLTTRDCluster::ExportTRDCluster(AliTRDcluster* const outCluster) const
{
  outCluster->fPadCol=fPadCol;
  outCluster->fPadRow=fPadRow;
  outCluster->fPadTime=fPadTime;

  outCluster->fSignals[2] = 0x3ff & fSignals;
  outCluster->fSignals[3] = 0x3ff & fSignals>>10;
  outCluster->fSignals[4] = 0x3ff & fSignals>>20;

  for(int i=0; i<3; i++){
    outCluster->fQ+=outCluster->fSignals[i];
  }

  outCluster->SetBit(UInt_t(fBits)<<14);
}

/**
 * Default Constructor
 */
//============================================================================
AliHLTTRDExtCluster::AliHLTTRDExtCluster():
  AliHLTTRDCluster(),
  fX(0),
  fY(0),
  fZ(0)
{
}

/**
 * Main Constructor
 */
//============================================================================
AliHLTTRDExtCluster::AliHLTTRDExtCluster(const AliTRDcluster* const inCluster):
  AliHLTTRDCluster(inCluster),
  fX(inCluster->GetX()),
  fY(inCluster->GetY()),
  fZ(inCluster->GetZ())
{
}

/**
 * Copy data to the output TRDcluster
 */
//============================================================================
void AliHLTTRDExtCluster::ExportTRDCluster(AliTRDcluster* const outCluster) const
{
  AliHLTTRDCluster::ExportTRDCluster(outCluster);
  outCluster->SetX(fX);
  outCluster->SetY(fY);
  outCluster->SetZ(fZ);
}

/**
 * Prints main info about cluster
 */
//============================================================================
void AliHLTTRDExtCluster::Print() const
{
  printf("   --hltCluster-- addr %p; sizeof(*this) %i\n", (void*)this, (int)sizeof(*this));
  printf("     fX %f; fY %f; fZ %f\n",fX,fY,fZ);
}

/**
 * Save cluster at block position
 */
//============================================================================
AliHLTUInt32_t AliHLTTRDCluster::SaveAt(AliHLTUInt8_t *const block, const AliTRDcluster* const inClust)
{
  AliHLTUInt32_t size=0;

  memcpy(block,inClust,sizeof(AliTRDcluster));
  size+=sizeof(AliTRDcluster);

  return size;
}

/**
 * Read cluster from block
 */
//============================================================================
AliHLTUInt32_t AliHLTTRDCluster::LoadFrom(AliTRDcluster *const outClust, const AliHLTUInt8_t *const block)
{
  AliHLTUInt32_t size=0;

  memcpy(((AliHLTUInt8_t*)outClust)+sizeof(void*),block+sizeof(void*),sizeof(AliTRDcluster)-sizeof(void*));
  size+=sizeof(AliTRDcluster);

  return size;
}
<commit_msg>HLT TRD bugfix: correct calculation of the total charge of the cluster (Theo)<commit_after>// $Id$

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Authors:                                                               *
 *          for The ALICE HLT Project.                                    *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//  @file   AliHLTTRDCluster.cxx
//  @author Theodor Rascanu
//  @date
//  @brief  A datacontainer for clusters fitting component for the HLT.
//

#include "AliHLTTRDCluster.h"
#include <cstring>

/**
 * Default Constructor
 */
//============================================================================
AliHLTTRDCluster::AliHLTTRDCluster():
  fSignals(0),
  fPadCol(0),
  fPadRow(0),
  fPadTime(0),
  fBits(0)
{
}

/**
 * Main Constructor
 */
//============================================================================
AliHLTTRDCluster::AliHLTTRDCluster(const AliTRDcluster* const inCluster):
  fSignals(0),
  fPadCol(inCluster->fPadCol),
  fPadRow(inCluster->fPadRow),
  fPadTime(inCluster->fPadTime),
  fBits(0)
{

  fSignals = inCluster->fSignals[2];
  fSignals|= inCluster->fSignals[3]<<10;
  fSignals|= inCluster->fSignals[4]<<21;

  fBits = UInt_t(inCluster->TestBits(-1)) >> 14;
}

/**
 * Copy data to the output TRDcluster
 */
//============================================================================
void AliHLTTRDCluster::ExportTRDCluster(AliTRDcluster* const outCluster) const
{
  outCluster->fPadCol=fPadCol;
  outCluster->fPadRow=fPadRow;
  outCluster->fPadTime=fPadTime;

  outCluster->fSignals[2] = 0x3ff & fSignals;
  outCluster->fSignals[3] = 0x7ff & fSignals>>10;
  outCluster->fSignals[4] = 0x3ff & fSignals>>21;

  for(int i=2; i<5; i++){
    outCluster->fQ+=outCluster->fSignals[i];
  }

  outCluster->SetBit(UInt_t(fBits)<<14);
}

/**
 * Default Constructor
 */
//============================================================================
AliHLTTRDExtCluster::AliHLTTRDExtCluster():
  AliHLTTRDCluster(),
  fX(0),
  fY(0),
  fZ(0)
{
}

/**
 * Main Constructor
 */
//============================================================================
AliHLTTRDExtCluster::AliHLTTRDExtCluster(const AliTRDcluster* const inCluster):
  AliHLTTRDCluster(inCluster),
  fX(inCluster->GetX()),
  fY(inCluster->GetY()),
  fZ(inCluster->GetZ())
{
}

/**
 * Copy data to the output TRDcluster
 */
//============================================================================
void AliHLTTRDExtCluster::ExportTRDCluster(AliTRDcluster* const outCluster) const
{
  AliHLTTRDCluster::ExportTRDCluster(outCluster);
  outCluster->SetX(fX);
  outCluster->SetY(fY);
  outCluster->SetZ(fZ);
}

/**
 * Prints main info about cluster
 */
//============================================================================
void AliHLTTRDExtCluster::Print() const
{
  printf("   --hltCluster-- addr %p; sizeof(*this) %i\n", (void*)this, (int)sizeof(*this));
  printf("     fX %f; fY %f; fZ %f\n",fX,fY,fZ);
}

/**
 * Save cluster at block position
 */
//============================================================================
AliHLTUInt32_t AliHLTTRDCluster::SaveAt(AliHLTUInt8_t *const block, const AliTRDcluster* const inClust)
{
  AliHLTUInt32_t size=0;

  memcpy(block,inClust,sizeof(AliTRDcluster));
  size+=sizeof(AliTRDcluster);

  return size;
}

/**
 * Read cluster from block
 */
//============================================================================
AliHLTUInt32_t AliHLTTRDCluster::LoadFrom(AliTRDcluster *const outClust, const AliHLTUInt8_t *const block)
{
  AliHLTUInt32_t size=0;

  memcpy(((AliHLTUInt8_t*)outClust)+sizeof(void*),block+sizeof(void*),sizeof(AliTRDcluster)-sizeof(void*));
  size+=sizeof(AliTRDcluster);

  return size;
}
<|endoftext|>


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

#include "p_extract_clips.h"
#include "diskreadmda32.h"
#include "diskreadmda.h"
#include "extract_clips.h"
#include "pca.h"

#include <diskwritemda.h>

namespace P_extract_clips {
Mda32 extract_channels_from_chunk(const Mda32& chunk, const QList<int>& channels);
}

bool p_extract_clips(QStringList timeseries_list, QString event_times, const QList<int>& channels, QString clips_out, const QVariantMap& params)
{
    DiskReadMda32 X(2, timeseries_list);
    DiskReadMda ET(event_times);

    bigint M = X.N1();
    //bigint N = X.N2();
    bigint T = params["clip_size"].toInt();
    bigint L = ET.totalSize();

    bigint M2 = M;
    if (!channels.isEmpty()) {
        M2 = channels.count();
    }

    if (!T) {
        qWarning() << "Unexpected: Clip size is zero.";
        return false;
    }

    bigint Tmid = (bigint)((T + 1) / 2) - 1;
    printf("Extracting clips (%ld,%ld,%ld) (%ld)...\n", M, T, L, M2);
    DiskWriteMda clips;
    clips.open(MDAIO_TYPE_FLOAT32, clips_out, M2, T, L);
    for (bigint i = 0; i < L; i++) {
        bigint t1 = ET.value(i) - Tmid;
        //bigint t2 = t1 + T - 1;
        Mda32 tmp;
        if (!X.readChunk(tmp, 0, t1, M, T)) {
            qWarning() << "Problem reading chunk in extract_clips";
            return false;
        }
        if (!channels.isEmpty()) {
            tmp = P_extract_clips::extract_channels_from_chunk(tmp, channels);
        }
        if (!clips.writeChunk(tmp, 0, 0, i)) {
            qWarning() << "Problem writing chunk" << i;
            return false;
        }
    }

    return true;
}

bool p_mv_extract_clips(QStringList timeseries_list, QString firings, const QList<int>& channels, QString clips_out, const QVariantMap& params)
{
    DiskReadMda32 X(2, timeseries_list);
    DiskReadMda FF(firings);

    bigint M = X.N1();
    //bigint N = X.N2();
    bigint T = params["clip_size"].toInt();
    bigint L = FF.N2();

    bigint M2 = M;
    if (!channels.isEmpty()) {
        M2 = channels.count();
    }

    if (!T) {
        qWarning() << "Unexpected: Clip size is zero.";
        return false;
    }

    bigint Tmid = (bigint)((T + 1) / 2) - 1;
    printf("Extracting clips (%ld,%ld,%ld) (%ld)...\n", M, T, L, M2);
    DiskWriteMda clips;
    clips.open(MDAIO_TYPE_FLOAT32, clips_out, M2, T, L);
    for (bigint i = 0; i < L; i++) {
        bigint t1 = FF.value(1,i) - Tmid;
        //bigint t2 = t1 + T - 1;
        Mda32 tmp;
        if (!X.readChunk(tmp, 0, t1, M, T)) {
            qWarning() << "Problem reading chunk in extract_clips";
            return false;
        }
        if (!channels.isEmpty()) {
            tmp = P_extract_clips::extract_channels_from_chunk(tmp, channels);
        }
        if (!clips.writeChunk(tmp, 0, 0, i)) {
            qWarning() << "Problem writing chunk" << i;
            return false;
        }
    }

    return true;
}

namespace P_extract_clips {
Mda32 extract_channels_from_chunk(const Mda32& X, const QList<int>& channels)
{
    //int M=X.N1();
    int T = X.N2();
    int M2 = channels.count();
    Mda32 ret(M2, T);
    for (int t = 0; t < T; t++) {
        for (int m2 = 0; m2 < M2; m2++) {
            ret.set(X.value(channels[m2] - 1, t), m2, t);
        }
    }
    return ret;
}
}

bool p_mv_extract_clips_features(QString timeseries_path, QString firings_path, QString features_out_path, int clip_size, int num_features, int subtract_mean)
{
    DiskReadMda32 X(timeseries_path);
    DiskReadMda F(firings_path);
    QVector<double> times;
    for (int i = 0; i < F.N2(); i++) {
        times << F.value(1, i);
    }
    Mda32 clips = extract_clips(X, times, clip_size);
    int M = clips.N1();
    int T = clips.N2();
    int L = clips.N3();
    Mda clips_reshaped(M * T, L);
    int NNN = M * T * L;
    for (int iii = 0; iii < NNN; iii++) {
        clips_reshaped.set(clips.get(iii), iii);
    }
    Mda CC, FF, sigma;
    pca(CC, FF, sigma, clips_reshaped, num_features, subtract_mean);
    return FF.write32(features_out_path);
}
<commit_msg>return error when ms3.extract_clips is given a non-vector<commit_after>/*
 * Copyright 2016-2017 Flatiron Institute, Simons Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "p_extract_clips.h"
#include "diskreadmda32.h"
#include "diskreadmda.h"
#include "extract_clips.h"
#include "pca.h"

#include <diskwritemda.h>

namespace P_extract_clips {
Mda32 extract_channels_from_chunk(const Mda32& chunk, const QList<int>& channels);
}

bool p_extract_clips(QStringList timeseries_list, QString event_times, const QList<int>& channels, QString clips_out, const QVariantMap& params)
{
    DiskReadMda32 X(2, timeseries_list);
    DiskReadMda ET(event_times);

    bigint M = X.N1();
    //bigint N = X.N2();
    bigint T = params["clip_size"].toInt();
    bigint L = ET.totalSize();

    if ((ET.N1()>1)&&(ET.N2()>1)) {
        qWarning() << "Error: the input (event times) must be a vector.";
        return false;
    }

    bigint M2 = M;
    if (!channels.isEmpty()) {
        M2 = channels.count();
    }

    if (!T) {
        qWarning() << "Unexpected: Clip size is zero.";
        return false;
    }

    bigint Tmid = (bigint)((T + 1) / 2) - 1;
    printf("Extracting clips (%ld,%ld,%ld) (%ld)...\n", M, T, L, M2);
    DiskWriteMda clips;
    clips.open(MDAIO_TYPE_FLOAT32, clips_out, M2, T, L);
    for (bigint i = 0; i < L; i++) {
        bigint t1 = ET.value(i) - Tmid;
        //bigint t2 = t1 + T - 1;
        Mda32 tmp;
        if (!X.readChunk(tmp, 0, t1, M, T)) {
            qWarning() << "Problem reading chunk in extract_clips";
            return false;
        }
        if (!channels.isEmpty()) {
            tmp = P_extract_clips::extract_channels_from_chunk(tmp, channels);
        }
        if (!clips.writeChunk(tmp, 0, 0, i)) {
            qWarning() << "Problem writing chunk" << i;
            return false;
        }
    }

    return true;
}

bool p_mv_extract_clips(QStringList timeseries_list, QString firings, const QList<int>& channels, QString clips_out, const QVariantMap& params)
{
    DiskReadMda32 X(2, timeseries_list);
    DiskReadMda FF(firings);

    bigint M = X.N1();
    //bigint N = X.N2();
    bigint T = params["clip_size"].toInt();
    bigint L = FF.N2();

    bigint M2 = M;
    if (!channels.isEmpty()) {
        M2 = channels.count();
    }

    if (!T) {
        qWarning() << "Unexpected: Clip size is zero.";
        return false;
    }

    bigint Tmid = (bigint)((T + 1) / 2) - 1;
    printf("Extracting clips (%ld,%ld,%ld) (%ld)...\n", M, T, L, M2);
    DiskWriteMda clips;
    clips.open(MDAIO_TYPE_FLOAT32, clips_out, M2, T, L);
    for (bigint i = 0; i < L; i++) {
        bigint t1 = FF.value(1,i) - Tmid;
        //bigint t2 = t1 + T - 1;
        Mda32 tmp;
        if (!X.readChunk(tmp, 0, t1, M, T)) {
            qWarning() << "Problem reading chunk in extract_clips";
            return false;
        }
        if (!channels.isEmpty()) {
            tmp = P_extract_clips::extract_channels_from_chunk(tmp, channels);
        }
        if (!clips.writeChunk(tmp, 0, 0, i)) {
            qWarning() << "Problem writing chunk" << i;
            return false;
        }
    }

    return true;
}

namespace P_extract_clips {
Mda32 extract_channels_from_chunk(const Mda32& X, const QList<int>& channels)
{
    //int M=X.N1();
    int T = X.N2();
    int M2 = channels.count();
    Mda32 ret(M2, T);
    for (int t = 0; t < T; t++) {
        for (int m2 = 0; m2 < M2; m2++) {
            ret.set(X.value(channels[m2] - 1, t), m2, t);
        }
    }
    return ret;
}
}

bool p_mv_extract_clips_features(QString timeseries_path, QString firings_path, QString features_out_path, int clip_size, int num_features, int subtract_mean)
{
    DiskReadMda32 X(timeseries_path);
    DiskReadMda F(firings_path);
    QVector<double> times;
    for (int i = 0; i < F.N2(); i++) {
        times << F.value(1, i);
    }
    Mda32 clips = extract_clips(X, times, clip_size);
    int M = clips.N1();
    int T = clips.N2();
    int L = clips.N3();
    Mda clips_reshaped(M * T, L);
    int NNN = M * T * L;
    for (int iii = 0; iii < NNN; iii++) {
        clips_reshaped.set(clips.get(iii), iii);
    }
    Mda CC, FF, sigma;
    pca(CC, FF, sigma, clips_reshaped, num_features, subtract_mean);
    return FF.write32(features_out_path);
}
<|endoftext|>


<commit_before>#include <starmap.hpp>

#include "helpers.hpp"

#include <iterator>
#include <list>
#include <string>
#include <vector>

#include "catch.hpp"

using iter::starmap;

namespace {
  long f(long d, int i) {
    return d * i;
  }

  std::string g(const std::string& s, int i, char c) {
    std::stringstream ss;
    ss << s << ' ' << i << ' ' << c;
    return ss.str();
  }

  struct Callable {
    int operator()(int a, int b, int c) {
      return a + b + c;
    }

    int operator()(int a, int b) {
      return a + b;
    }

    int operator()(int a) {
      return a;
    }
  };
}

TEST_CASE("starmap: works with function pointer and lambda", "[starmap]") {
  using Vec = const std::vector<int>;
  const std::vector<std::pair<double, int>> v1 = {{1l, 2}, {3l, 11}, {6l, 7}};
  Vec vc = {2l, 33l, 42l};

  std::vector<int> v;
  SECTION("with function") {
    SECTION("Normal call") {
      auto sm = starmap(f, v1);
      v.assign(std::begin(sm), std::end(sm));
    }
    SECTION("pipe") {
      auto sm = v1 | starmap(f);
      v.assign(std::begin(sm), std::end(sm));
    }
  }

  SECTION("with lambda") {
    auto sm = starmap([](long a, int b) { return a * b; }, v1);
    v.assign(std::begin(sm), std::end(sm));
  }
  REQUIRE(v == vc);
}

TEST_CASE("starmap: vector of pairs const iteration", "[starmap][const]") {
  using Vec = const std::vector<int>;
  const std::vector<std::pair<double, int>> v1 = {{1l, 2}, {3l, 11}, {6l, 7}};

  const auto sm = starmap(Callable{}, v1);
  std::vector<int> v(std::begin(sm), std::end(sm));
  Vec vc = {3, 14, 13};
  REQUIRE(v == vc);
}

TEST_CASE(
    "starmap: vector of pairs const iterators can be compared to non-const "
    "iterators",
    "[starmap][const]") {
  const std::vector<std::pair<double, int>> v1;
  auto sm = starmap(Callable{}, v1);
  const auto& csm = sm;
  (void)(std::begin(sm) == std::end(csm));
}

TEST_CASE("starmap: Works with different begin and end types", "[starmap]") {
  IntCharPairRange icr{{3, 'd'}};
  using Vec = std::vector<std::string>;
  auto sm = starmap([](int i, char c) { return std::to_string(i) + c; }, icr);
  Vec v(sm.begin(), sm.end());
  Vec vc{"0a", "1b", "2c"};
  REQUIRE(v == vc);
}

TEST_CASE("starmap: tuple of tuples const iteration", "[starmap][const]") {
  using Vec = const std::vector<int>;
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  const auto sm = starmap(Callable{}, tup);
  Vec v(std::begin(sm), std::end(sm));
}

TEST_CASE(
    "starmap: tuple of tuples const iterators can be compared to non-const "
    "iterator",
    "[starmap][const]") {
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  auto sm = starmap(Callable{}, tup);
  const auto& csm = sm;
  (void)(std::begin(sm) == std::end(csm));
  (void)(std::begin(csm) == std::end(sm));
}

TEST_CASE("starmap: list of tuples", "[starmap]") {
  using Vec = const std::vector<std::string>;
  using T = std::tuple<std::string, int, double>;
  std::list<T> li = {T{"hey", 42, 'a'}, T{"there", 3, 'b'}, T{"yall", 5, 'c'}};

  auto sm = starmap(g, li);
  Vec v(std::begin(sm), std::end(sm));
  Vec vc = {"hey 42 a", "there 3 b", "yall 5 c"};

  REQUIRE(v == vc);
}

TEST_CASE("starmap: tuple of tuples", "[starmap]") {
  using Vec = const std::vector<int>;
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  std::vector<int> v;
  SECTION("Normal call") {
    auto sm = starmap(Callable{}, tup);
    v.assign(std::begin(sm), std::end(sm));
  }
  SECTION("Pipe") {
    auto sm = tup | starmap(Callable{});
    v.assign(std::begin(sm), std::end(sm));
  }

  Vec vc = {89, 7};
  REQUIRE(v == vc);
}

TEST_CASE("starmap: tuple of pairs", "[starmap]") {
  using Vec = const std::vector<int>;
  auto p =
      std::make_pair(std::array<int, 3>{{15, 100, 2000}}, std::make_tuple(16));
  Callable c;
  auto sm = starmap(c, p);

  Vec v(std::begin(sm), std::end(sm));
  Vec vc = {2115, 16};

  REQUIRE(v == vc);
}

TEST_CASE("starmap: moves rvalues, binds to lvalues", "[starmap]") {
  itertest::BasicIterable<std::tuple<int>> bi{};
  starmap(Callable{}, bi);
  REQUIRE_FALSE(bi.was_moved_from());
  starmap(Callable{}, std::move(bi));
  REQUIRE(bi.was_moved_from());
}

TEST_CASE("starmap: iterator meets requirements", "[starmap]") {
  std::string s{};
  const std::vector<std::pair<double, int>> v1;
  auto sm = starmap([](long a, int b) { return a * b; }, v1);
  REQUIRE(itertest::IsIterator<decltype(std::begin(sm))>::value);
}

TEST_CASE(
    "starmap:  tuple of tuples iterator meets requirements", "[starmap]") {
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  auto sm = starmap(Callable{}, tup);
  REQUIRE(itertest::IsIterator<decltype(std::begin(sm))>::value);
}
<commit_msg>Tests starmap with pointer-to-member<commit_after>#include <starmap.hpp>

#include "helpers.hpp"

#include <iterator>
#include <list>
#include <string>
#include <vector>

#include "catch.hpp"

using iter::starmap;

namespace {
  long f(long d, int i) {
    return d * i;
  }

  std::string g(const std::string& s, int i, char c) {
    std::stringstream ss;
    ss << s << ' ' << i << ' ' << c;
    return ss.str();
  }

  struct Callable {
    int operator()(int a, int b, int c) {
      return a + b + c;
    }

    int operator()(int a, int b) {
      return a + b;
    }

    int operator()(int a) {
      return a;
    }
  };
}

TEST_CASE("starmap: works with function pointer and lambda", "[starmap]") {
  using Vec = const std::vector<int>;
  const std::vector<std::pair<double, int>> v1 = {{1l, 2}, {3l, 11}, {6l, 7}};
  Vec vc = {2l, 33l, 42l};

  std::vector<int> v;
  SECTION("with function") {
    SECTION("Normal call") {
      auto sm = starmap(f, v1);
      v.assign(std::begin(sm), std::end(sm));
    }
    SECTION("pipe") {
      auto sm = v1 | starmap(f);
      v.assign(std::begin(sm), std::end(sm));
    }
  }

  SECTION("with lambda") {
    auto sm = starmap([](long a, int b) { return a * b; }, v1);
    v.assign(std::begin(sm), std::end(sm));
  }
  REQUIRE(v == vc);
}

TEST_CASE("starmap: works with pointer to member function", "[starmap]") {
  using itertest::Point;
  std::vector<std::pair<Point, std::string>> tup = {
      {{10, 20}, "a"}, {{6, 8}, "point"}, {{3, 15}, "pos"}};
  auto sm = starmap(&Point::prefix, tup);
  std::vector<std::string> v(std::begin(sm), std::end(sm));
  const std::vector<std::string> vc = {
      "a(10, 20)", "point(6, 8)", "pos(3, 15)"};
  REQUIRE(v == vc);
}

TEST_CASE("starmap: vector of pairs const iteration", "[starmap][const]") {
  using Vec = const std::vector<int>;
  const std::vector<std::pair<double, int>> v1 = {{1l, 2}, {3l, 11}, {6l, 7}};

  const auto sm = starmap(Callable{}, v1);
  std::vector<int> v(std::begin(sm), std::end(sm));
  Vec vc = {3, 14, 13};
  REQUIRE(v == vc);
}

TEST_CASE(
    "starmap: vector of pairs const iterators can be compared to non-const "
    "iterators",
    "[starmap][const]") {
  const std::vector<std::pair<double, int>> v1;
  auto sm = starmap(Callable{}, v1);
  const auto& csm = sm;
  (void)(std::begin(sm) == std::end(csm));
}

TEST_CASE("starmap: Works with different begin and end types", "[starmap]") {
  IntCharPairRange icr{{3, 'd'}};
  using Vec = std::vector<std::string>;
  auto sm = starmap([](int i, char c) { return std::to_string(i) + c; }, icr);
  Vec v(sm.begin(), sm.end());
  Vec vc{"0a", "1b", "2c"};
  REQUIRE(v == vc);
}

TEST_CASE("starmap: tuple of tuples const iteration", "[starmap][const]") {
  using Vec = const std::vector<int>;
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  const auto sm = starmap(Callable{}, tup);
  Vec v(std::begin(sm), std::end(sm));
}

TEST_CASE(
    "starmap: tuple of tuples const iterators can be compared to non-const "
    "iterator",
    "[starmap][const]") {
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  auto sm = starmap(Callable{}, tup);
  const auto& csm = sm;
  (void)(std::begin(sm) == std::end(csm));
  (void)(std::begin(csm) == std::end(sm));
}

TEST_CASE("starmap: list of tuples", "[starmap]") {
  using Vec = const std::vector<std::string>;
  using T = std::tuple<std::string, int, double>;
  std::list<T> li = {T{"hey", 42, 'a'}, T{"there", 3, 'b'}, T{"yall", 5, 'c'}};

  auto sm = starmap(g, li);
  Vec v(std::begin(sm), std::end(sm));
  Vec vc = {"hey 42 a", "there 3 b", "yall 5 c"};

  REQUIRE(v == vc);
}

TEST_CASE("starmap: tuple of tuples", "[starmap]") {
  using Vec = const std::vector<int>;
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  std::vector<int> v;
  SECTION("Normal call") {
    auto sm = starmap(Callable{}, tup);
    v.assign(std::begin(sm), std::end(sm));
  }
  SECTION("Pipe") {
    auto sm = tup | starmap(Callable{});
    v.assign(std::begin(sm), std::end(sm));
  }

  Vec vc = {89, 7};
  REQUIRE(v == vc);
}

TEST_CASE("starmap: tuple of pairs", "[starmap]") {
  using Vec = const std::vector<int>;
  auto p =
      std::make_pair(std::array<int, 3>{{15, 100, 2000}}, std::make_tuple(16));
  Callable c;
  auto sm = starmap(c, p);

  Vec v(std::begin(sm), std::end(sm));
  Vec vc = {2115, 16};

  REQUIRE(v == vc);
}

TEST_CASE("starmap: moves rvalues, binds to lvalues", "[starmap]") {
  itertest::BasicIterable<std::tuple<int>> bi{};
  starmap(Callable{}, bi);
  REQUIRE_FALSE(bi.was_moved_from());
  starmap(Callable{}, std::move(bi));
  REQUIRE(bi.was_moved_from());
}

TEST_CASE("starmap: iterator meets requirements", "[starmap]") {
  std::string s{};
  const std::vector<std::pair<double, int>> v1;
  auto sm = starmap([](long a, int b) { return a * b; }, v1);
  REQUIRE(itertest::IsIterator<decltype(std::begin(sm))>::value);
}

TEST_CASE(
    "starmap:  tuple of tuples iterator meets requirements", "[starmap]") {
  auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7));
  auto sm = starmap(Callable{}, tup);
  REQUIRE(itertest::IsIterator<decltype(std::begin(sm))>::value);
}
<|endoftext|>


<commit_before>#include "PhLight.h"

using namespace phoenix;

PhLight::PhLight(PhLightManager* l, PhTexture* t, PhVector2d p, PhColor c, float s): lmgr(l), texture(t), position(p), color(c), scale(s)
{
    lmgr->addLight(this);
}

PhLight::~PhLight()
{
    lmgr->removeLight(this);
}

void PhLight::draw()
{
    lmgr->getSceneManager()->getRenderSystem()->drawTexture(texture,position,0.0f,0.0f,scale,color);
}

PhTexture* PhLight::getTexture()
{
    return texture;
}

void PhLight::setTexture(PhTexture* t)
{
    texture = t;
}

PhVector2d PhLight::getPosition()
{
    return position;
}

void PhLight::setPosition(PhVector2d p)
{
    position = p;
}

PhColor PhLight::getColor()
{
    return color;
}

void PhLight::setColor(PhColor c)
{
    color = c;
}

float PhLight::getScale()
{
    return scale;
}

void PhLight::setScale(float s)
{
    scale = s;
}
<commit_msg>Made the light class automatically adjust for position discrepancies. <commit_after>#include "PhLight.h"

using namespace phoenix;

PhLight::PhLight(PhLightManager* l, PhTexture* t, PhVector2d p, PhColor c, float s): lmgr(l), texture(t), position(p-PhVector2d(63.64f,63.64f)), color(c), scale(s)
{
    lmgr->addLight(this);
}

PhLight::~PhLight()
{
    lmgr->removeLight(this);
}

void PhLight::draw()
{
    lmgr->getSceneManager()->getRenderSystem()->drawTexture(texture,position,0.0f,0.0f,scale,color);
}

PhTexture* PhLight::getTexture()
{
    return texture;
}

void PhLight::setTexture(PhTexture* t)
{
    texture = t;
}

PhVector2d PhLight::getPosition()
{
    //compensate for the fact that our method skews positions slightly.
    return position+PhVector2d(63.64f,63.64f);
}

void PhLight::setPosition(PhVector2d p)
{
    //compensate for the fact that our method skews positions slightly.
    position = p-PhVector2d(63.64f,63.64f);
}

PhColor PhLight::getColor()
{
    return color;
}

void PhLight::setColor(PhColor c)
{
    color = c;
}

float PhLight::getScale()
{
    return scale;
}

void PhLight::setScale(float s)
{
    scale = s;
}
<|endoftext|>