<commit_before>// -*- c++ -*-

/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOpenGLExtensionManager.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.

  Copyright 2003 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
  license for use of this work by or on behalf of the
  U.S. Government. Redistribution and use in source and binary forms, with
  or without modification, are permitted provided that this Notice and any
  statement of authorship are reproduced on all copies.

=========================================================================*/

#include "vtkOpenGLExtensionManager.h"
#include "vtkOpenGLExtensionManagerConfigure.h"
#include "vtkgl.h"

#include "vtkRenderWindow.h"
#include "vtkObjectFactory.h"

#include <string.h>

#include <vtkstd/string>

#ifdef VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE
extern "C" vtkglX::__GLXextFuncPtr glXGetProcAddressARB(const GLubyte *);
#endif //VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE

#ifdef VTK_USE_VTK_DYNAMIC_LOADER
#include "vtkDynamicLoader.h"
#include <vtkstd/string>
#include <vtkstd/list>
#endif

#ifdef VTK_USE_APPLE_LOADER
#include <mach-o/dyld.h>
#endif //VTK_USE_APPLE_LOADER

// GLU is currently not linked in VTK.  We do not support it here.
#define GLU_SUPPORTED   0

vtkCxxRevisionMacro(vtkOpenGLExtensionManager, "1.17");
vtkStandardNewMacro(vtkOpenGLExtensionManager);

vtkOpenGLExtensionManager::vtkOpenGLExtensionManager()
{
  this->RenderWindow = NULL;
  this->ExtensionsString = NULL;

  this->Modified();
}

vtkOpenGLExtensionManager::~vtkOpenGLExtensionManager()
{
  this->SetRenderWindow(NULL);
  if (this->ExtensionsString)
    {
    delete[] this->ExtensionsString;
    }
}

void vtkOpenGLExtensionManager::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "RenderWindow: (" << this->RenderWindow << ")" << endl;
  os << indent << "BuildTime: " << this->BuildTime << endl;
  os << indent << "ExtensionsString: "
     << (this->ExtensionsString ? this->ExtensionsString : "(NULL)") << endl;
}

void vtkOpenGLExtensionManager::SetRenderWindow(vtkRenderWindow *renwin)
{
  if (renwin == this->RenderWindow)
    {
    return;
    }

  vtkDebugMacro("Setting RenderWindow to " << renwin);

  if (this->RenderWindow)
    {
    this->RenderWindow->UnRegister(this);
    }

  this->RenderWindow = renwin;
  if (this->RenderWindow)
    {
    this->RenderWindow->Register(this);
    }

  this->Modified();
}

void vtkOpenGLExtensionManager::Update()
{
  if (this->BuildTime > this->MTime)
    {
    return;
    }

  vtkDebugMacro("Update");

  if (this->ExtensionsString)
    {
    delete[] this->ExtensionsString;
    this->ExtensionsString = NULL;
    }

  this->ReadOpenGLExtensions();

  this->BuildTime.Modified();
}

int vtkOpenGLExtensionManager::ExtensionSupported(const char *name)
{
  this->Update();

  const char *p = this->ExtensionsString;
  int NameLen = strlen(name);
  int result = 0;

  for(;;)
    {
    int n;
    while (*p == ' ') p++;
    if (*p == '\0')
      {
      result = 0;
      break;
      }
    n = strcspn(p, " ");
    if ((NameLen == n) && (strncmp(name, p, n) == 0))
      {
      result = 1;
      break;
      }
    p += n;
    }
  return result;
}

vtkOpenGLExtensionManagerFunctionPointer
vtkOpenGLExtensionManager::GetProcAddress(const char *fname)
{
  vtkDebugMacro(<< "Trying to load OpenGL function " << fname);

#ifdef VTK_USE_WGL_GET_PROC_ADDRESS
  return reinterpret_cast<vtkOpenGLExtensionManagerFunctionPointer>(wglGetProcAddress(fname));
#endif //VTK_USE_WGL_GET_PROC_ADDRESS

#ifdef VTK_USE_APPLE_LOADER
  NSSymbol symbol = NULL;
  char *mangled_fname = new char[strlen(fname)+2];
  // Prepend a '_' to the function name.
  strcpy(mangled_fname+1, fname);
  mangled_fname[0] = '_';
  if (NSIsSymbolNameDefined(mangled_fname))
    {
    symbol = NSLookupAndBindSymbol(mangled_fname);
    }
  else
    {
    vtkDebugMacro("Could not load " << mangled_fname);
    }
  delete[] mangled_fname;
  if (symbol)
    {
    return (vtkOpenGLExtensionManagerFunctionPointer)NSAddressOfSymbol(symbol);
    }
  else
    {
    vtkDebugMacro("Could not load " << mangled_fname);
    return NULL;
    }
#endif //VTK_USE_APPLE_LOADER

#ifdef VTK_USE_GLX_GET_PROC_ADDRESS
  return (vtkOpenGLExtensionManagerFunctionPointer)glXGetProcAddress((const GLubyte *)fname);
#endif //VTK_USE_GLX_GET_PROC_ADDRESS
#ifdef VTK_USE_GLX_GET_PROC_ADDRESS_ARB
  return (vtkOpenGLExtensionManagerFunctionPointer)glXGetProcAddressARB((const GLubyte *)fname);
#endif //VTK_USE_GLX_GET_PROC_ADDRESS_ARB

#ifdef VTK_USE_VTK_DYNAMIC_LOADER
  // If the GLX implementation cannot load procedures for us, load them
  // directly from the dynamic libraries.
  static vtkstd::list<vtkstd::string> ogl_libraries;

  if (ogl_libraries.empty())
    {
    const char *ext = vtkDynamicLoader::LibExtension();
    vtkstd::string::size_type ext_size = strlen(ext);
    // Must be the first function we tried to load.  Fill this list with
    // the OpenGL libraries we linked against.
    vtkstd::string l(OPENGL_LIBRARIES);
    vtkstd::string::size_type filename_start = 0;
    while (1)
      {
      vtkstd::string::size_type filename_end = l.find(';', filename_start);
      if (filename_end == vtkstd::string::npos)
        {
        break;
        }
      vtkstd::string possible_file = l.substr(filename_start,
                                              filename_end-filename_start);
      // Make sure this is actually a library.  Do this by making sure it
      // has an appropriate extension.  This is by no means definitive, but
      // it1 should do.
      if (   (possible_file.length() > ext_size)
          && (possible_file.substr(possible_file.length()-ext_size) == ext) )
        {
        ogl_libraries.push_back(possible_file);
        }

      filename_start = filename_end + 1;
      }
    }

  // Look for the function in each library.
  for (vtkstd::list<vtkstd::string>::iterator i = ogl_libraries.begin();
       i != ogl_libraries.end(); i++)
    {
    vtkLibHandle lh = vtkDynamicLoader::OpenLibrary((*i).c_str());
    void *f = vtkDynamicLoader::GetSymbolAddress(lh, fname);
    vtkDynamicLoader::CloseLibrary(lh);
    if (f) return (vtkOpenGLExtensionManagerFunctionPointer)f;
    }

  // Could not find the function.
  return NULL;
#endif //VTK_USE_VTK_DYNAMIC_LOADER

#ifdef VTK_NO_EXTENSION_LOADING
  return NULL;
#endif //VTK_NO_EXTENSION_LOADING
}

void vtkOpenGLExtensionManager::LoadExtension(const char *name)
{
  if (!this->ExtensionSupported(name))
    {
    vtkWarningMacro("Attempting to load " << name
                    << ", which is not supported.");
    }

  int success = vtkgl::LoadExtension(name, this);

  if (!success)
    {
    vtkErrorMacro("Extension " << name << " could not be loaded.");
    }
}

void vtkOpenGLExtensionManager::ReadOpenGLExtensions()
{
  vtkDebugMacro("ReadOpenGLExtensions");

#ifdef VTK_NO_EXTENSION_LOADING

  this->ExtensionsString = new char[1];
  this->ExtensionsString[0] = '\0';
  return;

#else //!VTK_NO_EXTENSION_LOADING

  if (this->RenderWindow)
    {
    if (!this->RenderWindow->IsA("vtkOpenGLRenderWindow"))
      {
      // If the render window is not OpenGL, then it obviously has no
      // extensions.
      this->ExtensionsString = new char[1];
      this->ExtensionsString[0] = '\0';
      return;
      }
    if (this->RenderWindow->GetNeverRendered())
      {
      this->RenderWindow->Render();
      }
    this->RenderWindow->MakeCurrent();
    }

  vtkstd::string extensions_string;

  const char *gl_extensions;
  const char *glu_extensions = "";
  const char *win_extensions;

  gl_extensions = (const char *)glGetString(GL_EXTENSIONS);

  if (gl_extensions == NULL)
    {
    gl_extensions = "";
    }

  if (!this->RenderWindow && (gl_extensions[0] == '\0'))
    {
    vtkDebugMacro("No window active?  Attaching default render window.");
    vtkRenderWindow *renwin = vtkRenderWindow::New();
    renwin->SetSize(1, 1);
    this->SetRenderWindow(renwin);
    renwin->Delete();
    this->ReadOpenGLExtensions();
    return;
    }

  extensions_string = gl_extensions;

#if GLU_SUPPORTED
  glu_extensions = (const char *)gluGetString(GLU_EXTENSIONS);
#endif
  if (glu_extensions != NULL)
    {
    extensions_string += " ";
    extensions_string += glu_extensions;
    }

#if defined(WIN32)
  // Don't use this->LoadExtension or we will go into an infinite loop.
  vtkgl::LoadExtension("WGL_ARB_extensions_string", this);
  if (vtkwgl::GetExtensionsStringARB)
    {
    win_extensions = vtkwgl::GetExtensionsStringARB(wglGetCurrentDC());
    }
  else
    {
    //vtkWarningMacro("Could not query WGL extensions.");
    win_extensions = "";
    }
#elif defined(__APPLE__)
//   vtkWarningMacro("Does APPLE have a windows extension string?");
  win_extensions = "";
#else
  win_extensions = glXGetClientString(glXGetCurrentDisplay(),
                                      GLX_EXTENSIONS);
#endif

  if (win_extensions != NULL)
    {
    extensions_string += " ";
    extensions_string += win_extensions;
    }

  // We build special extension identifiers for OpenGL versions.  Check to
  // see which are supported.
  vtkstd::string version_extensions;
  vtkstd::string::size_type beginpos, endpos;

  version_extensions = vtkgl::GLVersionExtensionsString();
  endpos = 0;
  while (endpos != vtkstd::string::npos)
    {
    beginpos = version_extensions.find_first_not_of(' ', endpos);
    if (beginpos == vtkstd::string::npos) break;
    endpos = version_extensions.find_first_of(' ', beginpos);

    vtkstd::string ve = version_extensions.substr(beginpos, endpos-beginpos);
    if (vtkgl::LoadExtension(ve.c_str(), this))
      {
      extensions_string += " ";
      extensions_string += ve;
      }
    }

#ifdef VTK_USE_X
  version_extensions = vtkgl::GLXVersionExtensionsString();
  endpos = 0;
  while (endpos != vtkstd::string::npos)
    {
    beginpos = version_extensions.find_first_not_of(' ', endpos);
    if (beginpos == vtkstd::string::npos) break;
    endpos = version_extensions.find_first_of(' ', beginpos);

    vtkstd::string ve = version_extensions.substr(beginpos, endpos-beginpos);
    if (vtkgl::LoadExtension(ve.c_str(), this))
      {
      extensions_string += " ";
      extensions_string += ve;
      }
    }
#endif //VTK_USE_X

  // Store extensions string.
  this->ExtensionsString = new char[extensions_string.length()+1];
  strcpy(this->ExtensionsString, extensions_string.c_str());

#endif //!VTK_NO_EXTENSION_LOADING
}
<commit_msg><commit_after>// -*- c++ -*-

/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOpenGLExtensionManager.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.

  Copyright 2003 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
  license for use of this work by or on behalf of the
  U.S. Government. Redistribution and use in source and binary forms, with
  or without modification, are permitted provided that this Notice and any
  statement of authorship are reproduced on all copies.

=========================================================================*/

#include "vtkOpenGLExtensionManager.h"
#include "vtkOpenGLExtensionManagerConfigure.h"
#include "vtkgl.h"

#include "vtkRenderWindow.h"
#include "vtkObjectFactory.h"

#include <string.h>

#include <vtkstd/string>

#ifdef VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE
extern "C" vtkglX::__GLXextFuncPtr glXGetProcAddressARB(const GLubyte *);
#endif //VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE

#ifdef VTK_USE_VTK_DYNAMIC_LOADER
#include "vtkDynamicLoader.h"
#include <vtkstd/string>
#include <vtkstd/list>
#endif

#ifdef VTK_USE_APPLE_LOADER
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
#include <dlfcn.h>
#else
#include <mach-o/dyld.h>
#endif
#endif //VTK_USE_APPLE_LOADER

// GLU is currently not linked in VTK.  We do not support it here.
#define GLU_SUPPORTED   0

vtkCxxRevisionMacro(vtkOpenGLExtensionManager, "1.18");
vtkStandardNewMacro(vtkOpenGLExtensionManager);

vtkOpenGLExtensionManager::vtkOpenGLExtensionManager()
{
  this->RenderWindow = NULL;
  this->ExtensionsString = NULL;

  this->Modified();
}

vtkOpenGLExtensionManager::~vtkOpenGLExtensionManager()
{
  this->SetRenderWindow(NULL);
  if (this->ExtensionsString)
    {
    delete[] this->ExtensionsString;
    }
}

void vtkOpenGLExtensionManager::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "RenderWindow: (" << this->RenderWindow << ")" << endl;
  os << indent << "BuildTime: " << this->BuildTime << endl;
  os << indent << "ExtensionsString: "
     << (this->ExtensionsString ? this->ExtensionsString : "(NULL)") << endl;
}

void vtkOpenGLExtensionManager::SetRenderWindow(vtkRenderWindow *renwin)
{
  if (renwin == this->RenderWindow)
    {
    return;
    }

  vtkDebugMacro("Setting RenderWindow to " << renwin);

  if (this->RenderWindow)
    {
    this->RenderWindow->UnRegister(this);
    }

  this->RenderWindow = renwin;
  if (this->RenderWindow)
    {
    this->RenderWindow->Register(this);
    }

  this->Modified();
}

void vtkOpenGLExtensionManager::Update()
{
  if (this->BuildTime > this->MTime)
    {
    return;
    }

  vtkDebugMacro("Update");

  if (this->ExtensionsString)
    {
    delete[] this->ExtensionsString;
    this->ExtensionsString = NULL;
    }

  this->ReadOpenGLExtensions();

  this->BuildTime.Modified();
}

int vtkOpenGLExtensionManager::ExtensionSupported(const char *name)
{
  this->Update();

  const char *p = this->ExtensionsString;
  int NameLen = strlen(name);
  int result = 0;

  for(;;)
    {
    int n;
    while (*p == ' ') p++;
    if (*p == '\0')
      {
      result = 0;
      break;
      }
    n = strcspn(p, " ");
    if ((NameLen == n) && (strncmp(name, p, n) == 0))
      {
      result = 1;
      break;
      }
    p += n;
    }
  return result;
}

vtkOpenGLExtensionManagerFunctionPointer
vtkOpenGLExtensionManager::GetProcAddress(const char *fname)
{
  vtkDebugMacro(<< "Trying to load OpenGL function " << fname);

#ifdef VTK_USE_WGL_GET_PROC_ADDRESS
  return reinterpret_cast<vtkOpenGLExtensionManagerFunctionPointer>(wglGetProcAddress(fname));
#endif //VTK_USE_WGL_GET_PROC_ADDRESS

#ifdef VTK_USE_APPLE_LOADER

#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3

  void* globalsymbolobject = dlopen(NULL, RTLD_GLOBAL);
  if(globalsymbolobject)
    {
    void* dlsymbol = dlsym(globalsymbolobject, fname);
    dlclose(globalsymbolobject);
    if(!dlsymbol)
      {
      vtkDebugMacro("Could not load " << fname);
      }
    return (vtkOpenGLExtensionManagerFunctionPointer)(dlsymbol);
    }
  else
    {
    vtkDebugMacro("Could not load " << fname);
    return NULL;
    }

#else

  NSSymbol symbol = NULL;
  char *mangled_fname = new char[strlen(fname)+2];
  // Prepend a '_' to the function name.
  strcpy(mangled_fname+1, fname);
  mangled_fname[0] = '_';
  if (NSIsSymbolNameDefined(mangled_fname))
    {
    symbol = NSLookupAndBindSymbol(mangled_fname);
    }
  else
    {
    vtkDebugMacro("Could not load " << mangled_fname);
    }
  delete[] mangled_fname;
  if (symbol)
    {
    return (vtkOpenGLExtensionManagerFunctionPointer)NSAddressOfSymbol(symbol);
    }
  else
    {
    vtkDebugMacro("Could not load " << mangled_fname);
    return NULL;
    }

#endif //MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
#endif //VTK_USE_APPLE_LOADER

#ifdef VTK_USE_GLX_GET_PROC_ADDRESS
  return (vtkOpenGLExtensionManagerFunctionPointer)glXGetProcAddress((const GLubyte *)fname);
#endif //VTK_USE_GLX_GET_PROC_ADDRESS
#ifdef VTK_USE_GLX_GET_PROC_ADDRESS_ARB
  return (vtkOpenGLExtensionManagerFunctionPointer)glXGetProcAddressARB((const GLubyte *)fname);
#endif //VTK_USE_GLX_GET_PROC_ADDRESS_ARB

#ifdef VTK_USE_VTK_DYNAMIC_LOADER
  // If the GLX implementation cannot load procedures for us, load them
  // directly from the dynamic libraries.
  static vtkstd::list<vtkstd::string> ogl_libraries;

  if (ogl_libraries.empty())
    {
    const char *ext = vtkDynamicLoader::LibExtension();
    vtkstd::string::size_type ext_size = strlen(ext);
    // Must be the first function we tried to load.  Fill this list with
    // the OpenGL libraries we linked against.
    vtkstd::string l(OPENGL_LIBRARIES);
    vtkstd::string::size_type filename_start = 0;
    while (1)
      {
      vtkstd::string::size_type filename_end = l.find(';', filename_start);
      if (filename_end == vtkstd::string::npos)
        {
        break;
        }
      vtkstd::string possible_file = l.substr(filename_start,
                                              filename_end-filename_start);
      // Make sure this is actually a library.  Do this by making sure it
      // has an appropriate extension.  This is by no means definitive, but
      // it1 should do.
      if (   (possible_file.length() > ext_size)
          && (possible_file.substr(possible_file.length()-ext_size) == ext) )
        {
        ogl_libraries.push_back(possible_file);
        }

      filename_start = filename_end + 1;
      }
    }

  // Look for the function in each library.
  for (vtkstd::list<vtkstd::string>::iterator i = ogl_libraries.begin();
       i != ogl_libraries.end(); i++)
    {
    vtkLibHandle lh = vtkDynamicLoader::OpenLibrary((*i).c_str());
    void *f = vtkDynamicLoader::GetSymbolAddress(lh, fname);
    vtkDynamicLoader::CloseLibrary(lh);
    if (f) return (vtkOpenGLExtensionManagerFunctionPointer)f;
    }

  // Could not find the function.
  return NULL;
#endif //VTK_USE_VTK_DYNAMIC_LOADER

#ifdef VTK_NO_EXTENSION_LOADING
  return NULL;
#endif //VTK_NO_EXTENSION_LOADING
}

void vtkOpenGLExtensionManager::LoadExtension(const char *name)
{
  if (!this->ExtensionSupported(name))
    {
    vtkWarningMacro("Attempting to load " << name
                    << ", which is not supported.");
    }

  int success = vtkgl::LoadExtension(name, this);

  if (!success)
    {
    vtkErrorMacro("Extension " << name << " could not be loaded.");
    }
}

void vtkOpenGLExtensionManager::ReadOpenGLExtensions()
{
  vtkDebugMacro("ReadOpenGLExtensions");

#ifdef VTK_NO_EXTENSION_LOADING

  this->ExtensionsString = new char[1];
  this->ExtensionsString[0] = '\0';
  return;

#else //!VTK_NO_EXTENSION_LOADING

  if (this->RenderWindow)
    {
    if (!this->RenderWindow->IsA("vtkOpenGLRenderWindow"))
      {
      // If the render window is not OpenGL, then it obviously has no
      // extensions.
      this->ExtensionsString = new char[1];
      this->ExtensionsString[0] = '\0';
      return;
      }
    if (this->RenderWindow->GetNeverRendered())
      {
      this->RenderWindow->Render();
      }
    this->RenderWindow->MakeCurrent();
    }

  vtkstd::string extensions_string;

  const char *gl_extensions;
  const char *glu_extensions = "";
  const char *win_extensions;

  gl_extensions = (const char *)glGetString(GL_EXTENSIONS);

  if (gl_extensions == NULL)
    {
    gl_extensions = "";
    }

  if (!this->RenderWindow && (gl_extensions[0] == '\0'))
    {
    vtkDebugMacro("No window active?  Attaching default render window.");
    vtkRenderWindow *renwin = vtkRenderWindow::New();
    renwin->SetSize(1, 1);
    this->SetRenderWindow(renwin);
    renwin->Delete();
    this->ReadOpenGLExtensions();
    return;
    }

  extensions_string = gl_extensions;

#if GLU_SUPPORTED
  glu_extensions = (const char *)gluGetString(GLU_EXTENSIONS);
#endif
  if (glu_extensions != NULL)
    {
    extensions_string += " ";
    extensions_string += glu_extensions;
    }

#if defined(WIN32)
  // Don't use this->LoadExtension or we will go into an infinite loop.
  vtkgl::LoadExtension("WGL_ARB_extensions_string", this);
  if (vtkwgl::GetExtensionsStringARB)
    {
    win_extensions = vtkwgl::GetExtensionsStringARB(wglGetCurrentDC());
    }
  else
    {
    //vtkWarningMacro("Could not query WGL extensions.");
    win_extensions = "";
    }
#elif defined(__APPLE__)
//   vtkWarningMacro("Does APPLE have a windows extension string?");
  win_extensions = "";
#else
  win_extensions = glXGetClientString(glXGetCurrentDisplay(),
                                      GLX_EXTENSIONS);
#endif

  if (win_extensions != NULL)
    {
    extensions_string += " ";
    extensions_string += win_extensions;
    }

  // We build special extension identifiers for OpenGL versions.  Check to
  // see which are supported.
  vtkstd::string version_extensions;
  vtkstd::string::size_type beginpos, endpos;

  version_extensions = vtkgl::GLVersionExtensionsString();
  endpos = 0;
  while (endpos != vtkstd::string::npos)
    {
    beginpos = version_extensions.find_first_not_of(' ', endpos);
    if (beginpos == vtkstd::string::npos) break;
    endpos = version_extensions.find_first_of(' ', beginpos);

    vtkstd::string ve = version_extensions.substr(beginpos, endpos-beginpos);
    if (vtkgl::LoadExtension(ve.c_str(), this))
      {
      extensions_string += " ";
      extensions_string += ve;
      }
    }

#ifdef VTK_USE_X
  version_extensions = vtkgl::GLXVersionExtensionsString();
  endpos = 0;
  while (endpos != vtkstd::string::npos)
    {
    beginpos = version_extensions.find_first_not_of(' ', endpos);
    if (beginpos == vtkstd::string::npos) break;
    endpos = version_extensions.find_first_of(' ', beginpos);

    vtkstd::string ve = version_extensions.substr(beginpos, endpos-beginpos);
    if (vtkgl::LoadExtension(ve.c_str(), this))
      {
      extensions_string += " ";
      extensions_string += ve;
      }
    }
#endif //VTK_USE_X

  // Store extensions string.
  this->ExtensionsString = new char[extensions_string.length()+1];
  strcpy(this->ExtensionsString, extensions_string.c_str());

#endif //!VTK_NO_EXTENSION_LOADING
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashGraph.
 *
 * 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 <signal.h>
#ifdef PROFILER
#include <gperftools/profiler.h>
#endif

#include "stat.h"
#include "FGlib.h"
#include "graph.h"

void int_handler(int sig_num)
{
#ifdef PROFILER
	if (!graph_conf.get_prof_file().empty())
		ProfilerStop();
#endif
	exit(0);
}

void print_usage()
{
	fprintf(stderr,
			"cc [options] conf_file graph_file index_file\n");
	fprintf(stderr, "-c confs: add more configurations to the system\n");
	fprintf(stderr, "-s size: the output min component size\n");
	fprintf(stderr, "-o file: output the component size to the file\n");
	fprintf(stderr, "-t: the type of connected components\n");
	graph_conf.print_help();
	params.print_help();
}

int main(int argc, char *argv[])
{
	int opt;
	std::string confs;
	std::string output_file;
	size_t min_comp_size = 0;
	int num_opts = 0;
	std::string type = "wcc";
	while ((opt = getopt(argc, argv, "c:s:o:t:")) != -1) {
		num_opts++;
		switch (opt) {
			case 'c':
				confs = optarg;
				num_opts++;
				break;
			case 's':
				min_comp_size = atoi(optarg);
				num_opts++;
				break;
			case 'o':
				output_file = optarg;
				num_opts++;
				break;
			case 't':
				type = optarg;
				num_opts++;
			default:
				print_usage();
		}
	}
	argv += 1 + num_opts;
	argc -= 1 + num_opts;

	if (argc < 3) {
		print_usage();
		exit(-1);
	}

	std::string conf_file = argv[0];
	std::string graph_file = argv[1];
	std::string index_file = argv[2];

	config_map::ptr configs = config_map::create(conf_file);
	assert(configs);
	configs->add_options(confs);

	signal(SIGINT, int_handler);

	FG_graph::ptr graph = FG_graph::create(graph_file, index_file, configs);
	FG_vector<vertex_id_t>::ptr comp_ids;
	if (type == "wcc")
		comp_ids = compute_wcc(graph);
	else if (type == "scc")
		comp_ids = compute_scc(graph);
	else
		assert(0);

	count_map<vertex_id_t> map;
	comp_ids->count_unique(map);
	std::pair<vertex_id_t, size_t> max_comp = map.get_max_count();
	printf("There are %ld components, and largest comp has %ld vertices\n",
			map.get_size(), max_comp.second);

	struct large_comp_apply
	{
		std::set<vertex_id_t> &large_comps;
		vsize_t threshold;
		large_comp_apply(std::set<vertex_id_t> &_comps,
				vsize_t threshold): large_comps(_comps) {
			this->threshold = threshold;
		}

		void operator()(const std::pair<vertex_id_t, size_t> &v) {
			if (v.second >= threshold)
				large_comps.insert(v.first);
		}
	};

	std::set<vertex_id_t> wanted_comps;
	map.apply(large_comp_apply(wanted_comps, min_comp_size));
	// We ignore the largest component.
	wanted_comps.erase(max_comp.first);
	printf("There are %ld components of the size larger than %ld\n",
			wanted_comps.size() + 1, min_comp_size);

	if (!output_file.empty()) {
		FILE *f = fopen(output_file.c_str(), "w");
		if (f == NULL) {
			perror("fopen");
			assert(0);
		}

		std::map<vertex_id_t, graph::ptr> clusters;
		fetch_subgraphs(graph, comp_ids, wanted_comps, clusters);

		typedef std::map<vertex_id_t, std::pair<size_t, size_t> > size_map_t;
		size_map_t cluster_sizes;
		compute_subgraph_sizes(graph, comp_ids, wanted_comps, cluster_sizes);

		BOOST_FOREACH(size_map_t::value_type v, cluster_sizes) {
			std::map<vertex_id_t, graph::ptr>::const_iterator it
				= clusters.find(v.first);
			BOOST_VERIFY(it != clusters.end());
			BOOST_VERIFY(v.second.first == it->second->get_num_vertices());
			BOOST_VERIFY(v.second.second == it->second->get_num_edges());
			fprintf(f, "comp %u: %ld, %ld\n", v.first, v.second.first,
					v.second.second);
		}

		fclose(f);

		typedef std::pair<vertex_id_t, directed_graph<>::ptr> id_graph_t;
		BOOST_FOREACH(id_graph_t v, clusters) {
			v.second->dump_as_edge_list(output_file
					+ "-" + ltoa(v.first));
		}
	}
}
<commit_msg>[Graph]: delete test_cc.<commit_after><|endoftext|>


<commit_before>/*
=========================    Cpp Console Table
| Cpp | Console | Table |    version 1.0.0
=========================    https://github.com/Oradle/CppConsoleTable

Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2017 Oradle

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
#ifndef _CPP_CONSOLE_TABLE_
#define _CPP_CONSOLE_TABLE_

#include <iostream>
#include <map>
#include <string>
#include <iomanip>
#include <algorithm>
#include <vector>

namespace samilton {
	// force declaration
	class ConsoleTable;

	class ConsoleString {
	public:
		ConsoleString &operator=(const std::string &val) {
			_str = val;
			return *this;
		}

		ConsoleString &operator=(const char *val) {
			_str = val;
			return *this;
		}

		ConsoleString &operator=(const long &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const int &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const double &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const float &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const bool &val) {
			if (val)
				_str = "true";
			else
				_str = "false";

			return *this;
		}
	private:
		friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);

		std::string _str;
	};

	class ConsoleRow {
	public:
		~ConsoleRow() {
			for (auto &element : _rowData) {
				delete element.second;
			}
		}

		ConsoleString &operator[](const size_t &column) {
			try {
				return *_rowData.at(column);
			}
			catch (...) {
				_rowData[column] = new ConsoleString;
				return *_rowData[column];
			}
		}
	private:
		friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);

		std::map<size_t, ConsoleString*> _rowData;
	};

	class ConsoleTable {
	public:
		enum class Alignment {
			left = 0,
			centre,
			right
		};

		struct TableChars {
			char topRight = 187, topLeft = 201, downRight = 188, downLeft = 200;
			char topDownSimple = 205, topSeparation = 203, downSeparation = 202;
			char leftRightSimple = 186, leftSeparation = 204, rightSeparation = 185;
			char centreSeparation = 206;
		};

		ConsoleTable() {
			_alignment = Alignment::left;
			_leftIndent = 0;
			_rightIndent = 0;
		}

		ConsoleTable(const Alignment &alignment) {
			_alignment = alignment;
			_leftIndent = 0;
			_rightIndent = 0;
		}

		ConsoleTable(const size_t &leftIndent, const size_t &rightIndent, const Alignment &alignment = Alignment::left) {
			_leftIndent = leftIndent;
			_rightIndent = rightIndent;
			_alignment = alignment;
		}

		~ConsoleTable() {
			for (auto &element : _tableData) {
				delete element.second;
			}
		}

		void setAlignment(const Alignment &alignment) {
			_alignment = alignment;
		}

		void setIndent(const size_t &leftIndent, const size_t &rightIndent)
		{
			_leftIndent = leftIndent;
			_rightIndent = rightIndent;
		}

		void setTableChars(const TableChars &chars) {
			_chars = chars;
		}

		ConsoleRow &operator[](const size_t &row) {
			try {
				return *_tableData.at(row);
			}
			catch (...) {
				_tableData[row] = new ConsoleRow;
				return *_tableData[row];
			}
		}

		friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);
	private:
		void _fillStreamByChar(std::ostream &stream, const char &fillChar, const size_t &lenght) {
			if (lenght > 0)
				stream << std::setfill(fillChar) << std::setw(lenght);
		}

		void _fillStreamByChar(std::ostream &stream, const char &fillChar, const char &endChar, const size_t &lenght) {
			if (lenght > 0)
				stream << std::setfill(fillChar) << std::setw(lenght) << endChar;
		}

		TableChars _chars;
		std::map<size_t, ConsoleRow*> _tableData;
		Alignment _alignment;
		size_t _leftIndent, _rightIndent;
	};

	inline std::ostream &operator<<(std::ostream &stream, ConsoleTable &table) {
		// Return if table is empty
		if (table._tableData.size() == 0)
			return stream;

		// Calculation row and column
		size_t row = 0;
		size_t column = 0;
		for (auto &i : table._tableData) {
			row = std::max(row, i.first);
			for (auto &j : i.second->_rowData)
				column = std::max(column, j.first);
		}
		row++;
		column++;

		// Calculation width of every column
		std::vector<size_t> columnWidth;
		for (size_t i = 0; i < column; i++) {
			size_t tmp = 1;
			for (size_t j = 0; j < row; j++) {
				if (table._tableData[j] != nullptr && table._tableData[j]->_rowData[i] != nullptr) {
					tmp = std::max(tmp, table._tableData[j]->_rowData[i]->_str.size());
				}
			}
			columnWidth.push_back(tmp);
		}

		if (table._alignment != ConsoleTable::Alignment::centre) {
			stream << std::right << table._chars.topLeft;
			table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

			if (column != 1) {
				for (size_t i = 1; i < column; i++) {
					stream << table._chars.topSeparation << std::setw(columnWidth[i] + 1 + table._leftIndent + table._rightIndent);
				}
			}
			stream << table._chars.topRight << std::endl;

			for (size_t i = 0; i < row; i++) {
				if (table._alignment == ConsoleTable::Alignment::left)
					stream << std::left;
				else if (table._alignment == ConsoleTable::Alignment::right)
					stream << std::right;

				for (size_t j = 0; j < column; j++) {
					if (table._tableData[i] != nullptr && table._tableData[i]->_rowData[j] != nullptr) {
						stream << table._chars.leftRightSimple;
						table._fillStreamByChar(stream, ' ', ' ', table._leftIndent);

						table._fillStreamByChar(stream, ' ', columnWidth[j]);
						stream << table._tableData[i]->_rowData[j]->_str;

						table._fillStreamByChar(stream, ' ', ' ', table._rightIndent);
					}
					else {
						stream << table._chars.leftRightSimple;
						table._fillStreamByChar(stream, ' ', ' ', table._leftIndent);

						table._fillStreamByChar(stream, ' ', columnWidth[j]);
						stream << ' ';

						table._fillStreamByChar(stream, ' ', ' ', table._rightIndent);
					}
				}
				stream << std::right << table._chars.leftRightSimple << std::endl;

				if (i == row - 1) {
					stream << table._chars.downLeft;
					table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

					if (column != 1) {
						for (size_t j = 1; j < column; j++) {
							stream << table._chars.downSeparation << std::setw(columnWidth[j] + 1 + table._leftIndent + table._rightIndent);
						}
					}
					stream << table._chars.downRight << std::endl;
				}
				else {
					stream << table._chars.leftSeparation;
					table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

					if (column != 1) {
						for (size_t j = 1; j < column; j++) {
							stream << table._chars.centreSeparation << std::setw(columnWidth[j] + 1 + table._leftIndent + table._rightIndent);
						}
					}
					stream << table._chars.rightSeparation << std::endl;
				}
			}
		}
		else {
			for (auto &i : table._tableData) {
				for (auto &j : i.second->_rowData) {
				}
			}
		}

		return stream;
	}
}

#endif // _CPP_CONSOLE_TABLE_<commit_msg>Added working centre alignment<commit_after>/*
=========================    Cpp Console Table
| Cpp | Console | Table |    version 1.0.0
=========================    https://github.com/Oradle/CppConsoleTable

Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2017 Oradle

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
#ifndef _CPP_CONSOLE_TABLE_
#define _CPP_CONSOLE_TABLE_

#include <iostream>
#include <map>
#include <string>
#include <iomanip>
#include <algorithm>
#include <vector>

namespace samilton {
	// force declaration
	class ConsoleTable;

	class ConsoleString {
	public:
		ConsoleString &operator=(const std::string &val) {
			_str = val;
			return *this;
		}

		ConsoleString &operator=(const char *val) {
			_str = val;
			return *this;
		}

		ConsoleString &operator=(const long &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const int &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const double &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const float &val) {
			_str = std::to_string(val);
			return *this;
		}

		ConsoleString &operator=(const bool &val) {
			if (val)
				_str = "true";
			else
				_str = "false";

			return *this;
		}
	private:
		friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);

		std::string _str;
	};

	class ConsoleRow {
	public:
		~ConsoleRow() {
			for (auto &element : _rowData) {
				delete element.second;
			}
		}

		ConsoleString &operator[](const size_t &column) {
			try {
				return *_rowData.at(column);
			}
			catch (...) {
				_rowData[column] = new ConsoleString;
				return *_rowData[column];
			}
		}
	private:
		friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);

		std::map<size_t, ConsoleString*> _rowData;
	};

	class ConsoleTable {
	public:
		enum class Alignment {
			left = 0,
			centre,
			right
		};

		struct TableChars {
			char topRight = 187, topLeft = 201, downRight = 188, downLeft = 200;
			char topDownSimple = 205, topSeparation = 203, downSeparation = 202;
			char leftRightSimple = 186, leftSeparation = 204, rightSeparation = 185;
			char centreSeparation = 206;
		};

		ConsoleTable() {
			_alignment = Alignment::left;
			_leftIndent = 0;
			_rightIndent = 0;
		}

		ConsoleTable(const Alignment &alignment) {
			_alignment = alignment;
			_leftIndent = 0;
			_rightIndent = 0;
		}

		ConsoleTable(const size_t &leftIndent, const size_t &rightIndent, const Alignment &alignment = Alignment::left) {
			_leftIndent = leftIndent;
			_rightIndent = rightIndent;
			_alignment = alignment;
		}

		~ConsoleTable() {
			for (auto &element : _tableData) {
				delete element.second;
			}
		}

		void setAlignment(const Alignment &alignment) {
			_alignment = alignment;
		}

		void setIndent(const size_t &leftIndent, const size_t &rightIndent)
		{
			_leftIndent = leftIndent;
			_rightIndent = rightIndent;
		}

		void setTableChars(const TableChars &chars) {
			_chars = chars;
		}

		ConsoleRow &operator[](const size_t &row) {
			try {
				return *_tableData.at(row);
			}
			catch (...) {
				_tableData[row] = new ConsoleRow;
				return *_tableData[row];
			}
		}

		friend std::ostream &operator<<(std::ostream &stream, ConsoleTable &table);
	private:
		void _fillStreamByChar(std::ostream &stream, const char &fillChar, const size_t &lenght) {
			if (lenght > 0)
				stream << std::setfill(fillChar) << std::setw(lenght);
		}

		void _fillStreamByChar(std::ostream &stream, const char &fillChar, const char &endChar, const size_t &lenght) {
			if (lenght > 0)
				stream << std::setfill(fillChar) << std::setw(lenght) << endChar;
		}

		TableChars _chars;
		std::map<size_t, ConsoleRow*> _tableData;
		Alignment _alignment;
		size_t _leftIndent, _rightIndent;
	};

	inline std::ostream &operator<<(std::ostream &stream, ConsoleTable &table) {
		// Return if table is empty
		if (table._tableData.size() == 0)
			return stream;

		// Calculation row and column
		size_t row = 0;
		size_t column = 0;
		for (auto &i : table._tableData) {
			row = std::max(row, i.first);
			for (auto &j : i.second->_rowData)
				column = std::max(column, j.first);
		}
		row++;
		column++;

		// Calculation width of every column
		std::vector<size_t> columnWidth;
		for (size_t i = 0; i < column; i++) {
			size_t tmp = 1;
			for (size_t j = 0; j < row; j++) {
				if (table._tableData[j] != nullptr && table._tableData[j]->_rowData[i] != nullptr) {
					tmp = std::max(tmp, table._tableData[j]->_rowData[i]->_str.size());
				}
			}
			columnWidth.push_back(tmp);
		}

		// Top border
		stream << std::right << table._chars.topLeft;
		table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

		if (column != 1) {
			for (size_t i = 1; i < column; i++) {
				stream << table._chars.topSeparation << std::setw(columnWidth[i] + 1 + table._leftIndent + table._rightIndent);
			}
		}
		stream << table._chars.topRight << std::endl;

		// Elements and middle borders
		for (size_t i = 0; i < row; i++) {
			for (size_t j = 0; j < column; j++) {
				if (table._tableData[i] != nullptr && table._tableData[i]->_rowData[j] != nullptr) {
					if (table._alignment == ConsoleTable::Alignment::centre) {
						const size_t tmp = columnWidth[j] - table._tableData[i]->_rowData[j]->_str.size();
						size_t leftAlignmentIndent, rightAlignmentIndent;
						if (tmp % 2) {
							leftAlignmentIndent = tmp / 2;
							rightAlignmentIndent = tmp / 2 + 1;
						}
						else {
							leftAlignmentIndent = rightAlignmentIndent = tmp / 2;
						}

						stream << table._chars.leftRightSimple;
						table._fillStreamByChar(stream, ' ', ' ', table._leftIndent + leftAlignmentIndent);

						stream << table._tableData[i]->_rowData[j]->_str;

						table._fillStreamByChar(stream, ' ', ' ', table._rightIndent + rightAlignmentIndent);
					}
					else {
						if (table._alignment == ConsoleTable::Alignment::left)
							stream << std::left;
						else if (table._alignment == ConsoleTable::Alignment::right)
							stream << std::right;

						stream << table._chars.leftRightSimple;
						table._fillStreamByChar(stream, ' ', ' ', table._leftIndent);

						table._fillStreamByChar(stream, ' ', columnWidth[j]);
						stream << table._tableData[i]->_rowData[j]->_str;

						table._fillStreamByChar(stream, ' ', ' ', table._rightIndent);
					}
				}
				else {
					stream << table._chars.leftRightSimple;
					table._fillStreamByChar(stream, ' ', ' ', table._leftIndent);

					table._fillStreamByChar(stream, ' ', columnWidth[j]);
					stream << ' ';

					table._fillStreamByChar(stream, ' ', ' ', table._rightIndent);
				}
			}
			stream << std::right << table._chars.leftRightSimple << std::endl;

			// Down border
			if (i == row - 1) {
				stream << table._chars.downLeft;
				table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

				if (column != 1) {
					for (size_t j = 1; j < column; j++) {
						stream << table._chars.downSeparation << std::setw(columnWidth[j] + 1 + table._leftIndent + table._rightIndent);
					}
				}
				stream << table._chars.downRight << std::endl;
			}
			else {
				stream << table._chars.leftSeparation;
				table._fillStreamByChar(stream, table._chars.topDownSimple, columnWidth[0] + 1 + table._leftIndent + table._rightIndent);

				if (column != 1) {
					for (size_t j = 1; j < column; j++) {
						stream << table._chars.centreSeparation << std::setw(columnWidth[j] + 1 + table._leftIndent + table._rightIndent);
					}
				}
				stream << table._chars.rightSeparation << std::endl;
			}
		}

		return stream;
	}
}

#endif // _CPP_CONSOLE_TABLE_<|endoftext|>


<commit_before>#include "pyToCppModelInterface.h"
#include <boost/python/stl_iterator.hpp>
#include <iostream>
#include <stdexcept>

namespace threeML {

   template< typename T > inline
       std::vector< T > to_std_vector( const boost::python::object& iterable )
         {
           return std::vector< T >( boost::python::stl_input_iterator< T >( iterable ),
                                    boost::python::stl_input_iterator< T >( ) );
         }

  pyToCppModelInterface::pyToCppModelInterface(PyObject *pyModelUninterpreted) :
       m_nPtSources(0), m_nExtSources(0), n_calls(0)
      {

        try
          {
            boost::python::object
                  o(boost::python::handle<>(boost::python::borrowed(pyModelUninterpreted)));

            m_pyModel = o;

          }
        catch (...)
          {
            throw std::runtime_error("ModelInterface: Could not interpret the LikelihoodModel class");
          }

        //TODO: add a verification of the interface for the pyObject

        try {

          m_nPtSources = boost::python::extract<int>(m_pyModel.attr("getNumberOfPointSources")());

        } catch (...) {

          throw std::runtime_error(
                      "ModelInterface: Could not use getNumberOfPointSources from python Object");

        }
      }

  bool pyToCppModelInterface::isInsideAnyExtendedSource(double j2000_ra, double j2000_dec) const
      {
        return false;
      }

  int pyToCppModelInterface::getNumberOfPointSources() const
      {

        return m_nPtSources;

      }

  void pyToCppModelInterface::getPointSourcePosition(int srcid, double *j2000_ra, double *j2000_dec) const
      {

        boost::python::object coords;

        try {

           coords = m_pyModel.attr("getPointSourcePosition")(srcid);

        } catch (...) {

          throw std::runtime_error(
                      "ModelInterface: Could not call getPointSourcePosition on the python side");

        }

        try {

          (*j2000_ra) = boost::python::extract<double>(coords[0]);
          (*j2000_dec) = boost::python::extract<double>(coords[1]);

        } catch (...) {

          throw std::runtime_error(
                    "ModelInterface: Could not convert the coordinates I got from the python side");
        }
      }

  void pyToCppModelInterface::update()
      {

         //std::cerr << "Emptying cache" << std::endl;

         //Empty the cache
         m_cache.clear();

      }

  std::vector<double>
         pyToCppModelInterface::getPointSourceFluxes(int srcid, std::vector<double> energies) const
      {

        if ( m_cache.count( srcid )==1 )
        {

          //std::cerr << "Cached" << std::endl;

          //Return cached version

          return m_cache[srcid];

        } else {

          n_calls += 1;

          //std::cerr << "Filling cache for " << srcid << " (" << n_calls << ")" << std::endl;

        }

        //Construct a generic object (instead of for example a list) so that
        //the pyModel can return any iterable (list, numpy.array, etc)

        boost::python::object fluxes;

        //try {

           fluxes = m_pyModel.attr("getPointSourceFluxes")(srcid,energies);

        //} catch (...) {

        //  throw std::runtime_error(
        //            "ModelInterface: Could not get the fluxes from the python side");

        //}

        std::vector<double> fluxes_v;

        try {

           fluxes_v = to_std_vector<double>(fluxes);

	   /*
	   for(int i=0; i < fluxes_v.size(); ++i)
	   {

	       std::cerr << "e[" << i << "] = " << fluxes_v[i] << std::endl;

	   }*/

        } catch (...) {

          throw std::runtime_error(
                    "ModelInterface: Could not convert the fluxes I got from the python side");

        }

        //Cache result

        m_cache[srcid] = fluxes_v;

        return fluxes_v;
      }

  int pyToCppModelInterface::getNumberOfExtendedSources() const
      {
        return 0;
      }

  std::vector<double>
       pyToCppModelInterface::getExtendedSourceFluxes(int srcid, double j2000_ra, double j2000_dec,
                                                 std::vector<double> energies) const
      {
        std::vector<double> fluxes;
        return fluxes;
      }

  std::string pyToCppModelInterface::getPointSourceName(int srcid) const
      {

        std::string name;

        try {

           name = boost::python::extract<std::string>(
                                  m_pyModel.attr("getPointSourceName")(srcid)
                                  );
        } catch (...) {

          throw std::runtime_error(
                    "ModelInterface: Could not get the point source name from the python side");

        }

        return name;
      }

  std::string pyToCppModelInterface::getExtendedSourceName(int srcid) const
      {
        std::string name("test");
        return name;
      }

}
<commit_msg>Correcting a problem with units. Now fluxes are per MeV, instead of per keV<commit_after>#include "pyToCppModelInterface.h"
#include <boost/python/stl_iterator.hpp>
#include <iostream>
#include <stdexcept>

namespace threeML {

   template< typename T > inline
       std::vector< T > to_std_vector( const boost::python::object& iterable )
         {
           return std::vector< T >( boost::python::stl_input_iterator< T >( iterable ),
                                    boost::python::stl_input_iterator< T >( ) );
         }

  pyToCppModelInterface::pyToCppModelInterface(PyObject *pyModelUninterpreted) :
       m_nPtSources(0), m_nExtSources(0), n_calls(0)
      {

        try
          {
            boost::python::object
                  o(boost::python::handle<>(boost::python::borrowed(pyModelUninterpreted)));

            m_pyModel = o;

          }
        catch (...)
          {
            throw std::runtime_error("ModelInterface: Could not interpret the LikelihoodModel class");
          }

        //TODO: add a verification of the interface for the pyObject

        try {

          m_nPtSources = boost::python::extract<int>(m_pyModel.attr("getNumberOfPointSources")());

        } catch (...) {

          throw std::runtime_error(
                      "ModelInterface: Could not use getNumberOfPointSources from python Object");

        }
      }

  bool pyToCppModelInterface::isInsideAnyExtendedSource(double j2000_ra, double j2000_dec) const
      {
        return false;
      }

  int pyToCppModelInterface::getNumberOfPointSources() const
      {

        return m_nPtSources;

      }

  void pyToCppModelInterface::getPointSourcePosition(int srcid, double *j2000_ra, double *j2000_dec) const
      {

        boost::python::object coords;

        try {

           coords = m_pyModel.attr("getPointSourcePosition")(srcid);

        } catch (...) {

          throw std::runtime_error(
                      "ModelInterface: Could not call getPointSourcePosition on the python side");

        }

        try {

          (*j2000_ra) = boost::python::extract<double>(coords[0]);
          (*j2000_dec) = boost::python::extract<double>(coords[1]);

        } catch (...) {

          throw std::runtime_error(
                    "ModelInterface: Could not convert the coordinates I got from the python side");
        }
      }

  void pyToCppModelInterface::update()
      {

         //std::cerr << "Emptying cache" << std::endl;

         //Empty the cache
         m_cache.clear();

      }

  std::vector<double>
         pyToCppModelInterface::getPointSourceFluxes(int srcid, std::vector<double> energies) const
      {

        if ( m_cache.count( srcid )==1 )
        {

          //std::cerr << "Cached" << std::endl;

          //Return cached version

          return m_cache[srcid];

        } else {

          n_calls += 1;

          //std::cerr << "Filling cache for " << srcid << " (" << n_calls << ")" << std::endl;

        }

        //Construct a generic object (instead of for example a list) so that
        //the pyModel can return any iterable (list, numpy.array, etc)

        boost::python::object fluxes;

        //try {

           fluxes = m_pyModel.attr("getPointSourceFluxes")(srcid,energies);

        //} catch (...) {

        //  throw std::runtime_error(
        //            "ModelInterface: Could not get the fluxes from the python side");

        //}

        std::vector<double> fluxes_v;

        try {

           fluxes_v = to_std_vector<double>(fluxes);

           //Transform in ph/cm2/s/MeV from ph/cm2/s/keV

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

	       fluxes_v[i] = fluxes_v[i] / 1000.0;

	   }

        } catch (...) {

          throw std::runtime_error(
                    "ModelInterface: Could not convert the fluxes I got from the python side");

        }

        //Cache result

        m_cache[srcid] = fluxes_v;

        return fluxes_v;
      }

  int pyToCppModelInterface::getNumberOfExtendedSources() const
      {
        return 0;
      }

  std::vector<double>
       pyToCppModelInterface::getExtendedSourceFluxes(int srcid, double j2000_ra, double j2000_dec,
                                                 std::vector<double> energies) const
      {
        std::vector<double> fluxes;
        return fluxes;
      }

  std::string pyToCppModelInterface::getPointSourceName(int srcid) const
      {

        std::string name;

        try {

           name = boost::python::extract<std::string>(
                                  m_pyModel.attr("getPointSourceName")(srcid)
                                  );
        } catch (...) {

          throw std::runtime_error(
                    "ModelInterface: Could not get the point source name from the python side");

        }

        return name;
      }

  std::string pyToCppModelInterface::getExtendedSourceName(int srcid) const
      {
        std::string name("test");
        return name;
      }

}
<|endoftext|>


<commit_before>/**
@file IO/PropStateStore.hpp
@brief Prop state store.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_IO_PROPSTATESTORE_HPP_
#define HORD_IO_PROPSTATESTORE_HPP_

#include <Hord/config.hpp>
#include <Hord/utility.hpp>
#include <Hord/IO/Defs.hpp>

namespace Hord {
namespace IO {

// Forward declarations
class PropStateStore;

/**
	@addtogroup io
	@{
*/
/**
	@addtogroup prop
	@{
*/

namespace {

// FIXME: For some terrific reason Clang sees this function as
// only being *declared* if it is placed in-class before the
// anonymous enum.
static constexpr unsigned
state_fill(
	IO::PropState const state
) noexcept {
	return 0u
		| (enum_cast(state) << (enum_cast(IO::PropType::identity ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::metadata ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::scratch  ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::primary  ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::auxiliary) << 2))
	;
}

} // anonymous namespace

/**
	Prop state store.

	@note Within the state store, all unsupplied props imply
	IO::PropState::original.

	@sa IO::PropState
*/
class PropStateStore final {
private:
	static_assert(
		5u == enum_cast(PropType::LAST),
		"masks and all_have() need to be updated"
	);
	static_assert(
		4u <= sizeof(unsigned),
		"implementation requires at least 4 bytes in unsigned int"
	);

	/*
		Bits (1-6 are props, S is whether they are supplied):
		XXSS SSSS 6666 5555 4444 3333 2222 1111

		6666 is currently unoccupied (there are only 5 props).
	*/
	enum : unsigned {
		// 4 bits per prop
		state_mask = 0x0F,
		// 5 states
		full_mask  = 0x000FFFFF,
		// 3 always-supplied props (identity, metadata, and scratch)
		base_value = 0x07000FFF,

		// (PropType << type_shift) gives the number of bits
		// to move left for the prop's state
		type_shift = 2u,
		// (PropTypeBit << flag_shift) gives the
		// is_supplied bit for the prop
		flag_shift = 24u,

		bit_primary
			= enum_cast(IO::PropTypeBit::primary)
			<< flag_shift
		,
		bit_auxiliary
			= enum_cast(IO::PropTypeBit::auxiliary)
			<< flag_shift
		,

		prop_unsupplied_implied
			= enum_cast(IO::PropState::unsupplied)
			| enum_cast(IO::PropState::original)
		,
		prop_unsupplied_single = enum_cast(IO::PropState::unsupplied),

		mask_unsupplied_implied
			= state_fill(static_cast<IO::PropState>(prop_unsupplied_implied))
		,

		all_mask_unsupplied = state_fill(IO::PropState::unsupplied),
		all_mask_original = state_fill(IO::PropState::original),
		all_mask_modified = state_fill(IO::PropState::modified),
	};

	static constexpr unsigned
	shift_up(
		unsigned const value,
		IO::PropType const prop_type,
		unsigned const mask = state_mask
	) noexcept {
		return (value & mask) << (enum_cast(prop_type) << type_shift);
	}

	static constexpr unsigned
	shift_down(
		unsigned const value,
		IO::PropType const prop_type,
		unsigned const mask = state_mask
	) noexcept {
		return (value >> (enum_cast(prop_type) << type_shift)) & mask;
	}

	static constexpr unsigned
	mask_off(
		unsigned const value,
		IO::PropType const prop_type
	) noexcept {
		return ~(state_mask << (enum_cast(prop_type) << type_shift)) & value;
	}

	unsigned m_states_supplied;
	unsigned m_states;

	PropStateStore() = delete;
	PropStateStore& operator=(PropStateStore const&) = delete;

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~PropStateStore() = default;

	/** Copy constructor. */
	PropStateStore(PropStateStore const&) = default;
	/** Move constructor. */
	PropStateStore(PropStateStore&&) = default;
	/** Move assignment operator. */
	PropStateStore& operator=(PropStateStore&&) = default;

	/**
		Constructor with object data prop availability.

		@post All supplied props are uninitialized.

		@param supplies_primary Whether IO::PropType::primary is
		supplied.
		@param supplies_auxiliary Whether IO::PropType::auxiliary is
		supplied.
	*/
	constexpr
	PropStateStore(
		bool const supplies_primary,
		bool const supplies_auxiliary
	) noexcept
		: m_states_supplied(
			base_value
			| (!supplies_primary ? 0u : (
				bit_primary |
				shift_up(state_mask, IO::PropType::primary)
			))
			| (!supplies_auxiliary ? 0u : (
				bit_auxiliary |
				shift_up(state_mask, IO::PropType::auxiliary)
			))
		)
		, m_states(
			~m_states_supplied & mask_unsupplied_implied
		)
	{}
/// @}

/** @name Properties */ /// @{
	/**
		Check if prop has a state.

		@note If @a state is a state combination, the return
		value will be @c true if any of the combined
		states are set.

		@param prop_type Prop type.
		@param state Prop state.
	*/
	bool
	has(
		IO::PropType const prop_type,
		IO::PropState const state
	) const noexcept {
		return shift_down(m_states, prop_type, enum_cast(state));
	}

	/**
		Check if any prop is modified.
	*/
	bool
	any_modified() const noexcept {
		return 0u != (m_states & all_mask_modified);
	}

	/**
		Check if all props match external storage.
	*/
	bool
	all_original() const noexcept {
		return all_mask_original == (m_states & all_mask_original);
	}

	/**
		Check if all supplied props are uninitialized.
	*/
	bool
	all_uninitialized() const noexcept {
		return 0u == (m_states & m_states_supplied);
	}

	/**
		Check if all supplied data props are initialized.
	*/
	bool
	all_data_initialized() const noexcept {
		// NB: Non-supplied props "are" original within the store
		// and all other states imply the prop is initialized
		return shift_down(m_states, IO::PropType::primary)
			&& shift_down(m_states, IO::PropType::auxiliary);
	}

	/**
		Check if prop is initialized.

		@param prop_type Prop type.
	*/
	bool
	is_initialized(
		IO::PropType const prop_type
	) const noexcept {
		return 0u != shift_down(m_states, prop_type);
	}

	/**
		Check if prop is supplied.

		@param prop_type Prop type.
	*/
	bool
	supplies(
		IO::PropType const prop_type
	) const noexcept {
		return supplies_all(IO::prop_flag(prop_type));
	}

	/**
		Check if all given props are supplied.
	*/
	bool
	supplies_all(
		IO::PropTypeBit const props
	) const noexcept {
		return
			enum_cast(props)
			== (enum_cast(get_supplied()) & enum_cast(props))
		;
	}

	/**
		Check if any given props are supplied.
	*/
	bool
	supplies_any(
		IO::PropTypeBit const props
	) const noexcept {
		return enum_cast(get_supplied()) & enum_cast(props);
	}

	/**
		Get store value.
	*/
	unsigned
	get_value() const noexcept {
		return m_states;
	}

	/**
		Get full state for prop.

		@param prop_type Prop type.
	*/
	IO::PropState
	get_state(
		IO::PropType const prop_type
	) const noexcept {
		return static_cast<IO::PropState>(
			shift_down(m_states, prop_type)
		);
	}

	/**
		Get supplied props.
	*/
	IO::PropTypeBit
	get_supplied() const noexcept {
		return static_cast<IO::PropTypeBit>(
			m_states_supplied >> flag_shift
		);
	}
/// @}

/** @name Operations */ /// @{
	/**
		Reset all states to uninitialized.

		@note Non-supplied states are not modified.

		@returns @c *this.
	*/
	PropStateStore&
	reset_all() noexcept {
		m_states = ~m_states_supplied & mask_unsupplied_implied;
		return *this;
	}

	/**
		Reset a prop state to uninitialized.

		@note If the prop is not supplied, this has no effect.

		@returns @c *this.
		@param prop_type Prop type.
	*/
	PropStateStore&
	reset(
		PropType const prop_type
	) noexcept {
		if (supplies(prop_type)) {
			m_states = mask_off(m_states, prop_type);
		}
		return *this;
	}

	/**
		Assign prop state.

		@note If the prop is not supplied, this has no effect.

		@par
		@note IO::PropState::unsupplied is masked out
		of @a state before assignment. Only the constructor can
		assign this state.

		@returns @c *this.
		@param prop_type Prop type.
		@param state Prop state.
	*/
	PropStateStore&
	assign(
		IO::PropType const prop_type,
		IO::PropState const state
	) noexcept {
		if (supplies(prop_type)) {
			m_states
				= mask_off(m_states, prop_type)
				| shift_up(
					~prop_unsupplied_single & enum_cast(state),
					prop_type
				)
			;
		}
		return *this;
	}

	PropStateStore&
	assign_all(
		IO::PropState const state
	) noexcept {
		switch (state) {
		case IO::PropState::unsupplied:
			reset_all();
			break;
		case IO::PropState::original:
			m_states
				= (~m_states_supplied & mask_unsupplied_implied)
				| (m_states_supplied & all_mask_original)
			;
			break;
		case IO::PropState::modified:
			m_states
				= (~m_states_supplied & mask_unsupplied_implied)
				| (m_states_supplied & all_mask_modified)
			;
			break;
		}
		return *this;
	}
/// @}
};

/** @} */ // end of doc-group prop
/** @} */ // end of doc-group io

} // namespace IO
} // namespace Hord

#endif // HORD_IO_PROPSTATESTORE_HPP_
<commit_msg>IO::PropStateStore: made accessors constexpr.<commit_after>/**
@file IO/PropStateStore.hpp
@brief Prop state store.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_IO_PROPSTATESTORE_HPP_
#define HORD_IO_PROPSTATESTORE_HPP_

#include <Hord/config.hpp>
#include <Hord/utility.hpp>
#include <Hord/IO/Defs.hpp>

namespace Hord {
namespace IO {

// Forward declarations
class PropStateStore;

/**
	@addtogroup io
	@{
*/
/**
	@addtogroup prop
	@{
*/

namespace {

// FIXME: For some terrific reason Clang sees this function as
// only being *declared* if it is placed in-class before the
// anonymous enum.
static constexpr unsigned
state_fill(
	IO::PropState const state
) noexcept {
	return 0u
		| (enum_cast(state) << (enum_cast(IO::PropType::identity ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::metadata ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::scratch  ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::primary  ) << 2))
		| (enum_cast(state) << (enum_cast(IO::PropType::auxiliary) << 2))
	;
}

} // anonymous namespace

/**
	Prop state store.

	@note Within the state store, all unsupplied props imply
	IO::PropState::original.

	@sa IO::PropState
*/
class PropStateStore final {
private:
	static_assert(
		5u == enum_cast(PropType::LAST),
		"masks and all_have() need to be updated"
	);
	static_assert(
		4u <= sizeof(unsigned),
		"implementation requires at least 4 bytes in unsigned int"
	);

	/*
		Bits (1-6 are props, s is whether they are supplied):
		XXss ssss 6666 5555 4444 3333 2222 1111

		6666 is currently unoccupied (there are only 5 props).
	*/
	enum : unsigned {
		// 4 bits per prop
		state_mask = 0x0F,
		// 5 states
		full_mask  = 0x000FFFFF,
		// 3 always-supplied props (identity, metadata, and scratch)
		base_value = 0x07000FFF,

		// (PropType << type_shift) gives the number of bits
		// to move left for the prop's state
		type_shift = 2u,
		// (PropTypeBit << flag_shift) gives the
		// is_supplied bit for the prop
		flag_shift = 24u,

		bit_primary
			= enum_cast(IO::PropTypeBit::primary)
			<< flag_shift
		,
		bit_auxiliary
			= enum_cast(IO::PropTypeBit::auxiliary)
			<< flag_shift
		,

		prop_unsupplied_implied
			= enum_cast(IO::PropState::unsupplied)
			| enum_cast(IO::PropState::original)
		,
		prop_unsupplied_single = enum_cast(IO::PropState::unsupplied),

		mask_unsupplied_implied
			= state_fill(static_cast<IO::PropState>(prop_unsupplied_implied))
		,

		all_mask_unsupplied = state_fill(IO::PropState::unsupplied),
		all_mask_original = state_fill(IO::PropState::original),
		all_mask_modified = state_fill(IO::PropState::modified),
	};

	static constexpr unsigned
	shift_up(
		unsigned const value,
		IO::PropType const prop_type,
		unsigned const mask = state_mask
	) noexcept {
		return (value & mask) << (enum_cast(prop_type) << type_shift);
	}

	static constexpr unsigned
	shift_down(
		unsigned const value,
		IO::PropType const prop_type,
		unsigned const mask = state_mask
	) noexcept {
		return (value >> (enum_cast(prop_type) << type_shift)) & mask;
	}

	static constexpr unsigned
	mask_off(
		unsigned const value,
		IO::PropType const prop_type
	) noexcept {
		return ~(state_mask << (enum_cast(prop_type) << type_shift)) & value;
	}

	unsigned m_states_supplied;
	unsigned m_states;

	PropStateStore() = delete;
	PropStateStore& operator=(PropStateStore const&) = delete;

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~PropStateStore() = default;

	/** Copy constructor. */
	PropStateStore(PropStateStore const&) = default;
	/** Move constructor. */
	PropStateStore(PropStateStore&&) = default;
	/** Move assignment operator. */
	PropStateStore& operator=(PropStateStore&&) = default;

	/**
		Constructor with object data prop availability.

		@post All supplied props are uninitialized.

		@param supplies_primary Whether IO::PropType::primary is
		supplied.
		@param supplies_auxiliary Whether IO::PropType::auxiliary is
		supplied.
	*/
	constexpr
	PropStateStore(
		bool const supplies_primary,
		bool const supplies_auxiliary
	) noexcept
		: m_states_supplied(
			base_value
			| (!supplies_primary ? 0u : (
				bit_primary |
				shift_up(state_mask, IO::PropType::primary)
			))
			| (!supplies_auxiliary ? 0u : (
				bit_auxiliary |
				shift_up(state_mask, IO::PropType::auxiliary)
			))
		)
		, m_states(
			~m_states_supplied & mask_unsupplied_implied
		)
	{}
/// @}

/** @name Properties */ /// @{
	/**
		Check if prop has a state.

		@note If @a state is a state combination, the return
		value will be @c true if any of the combined
		states are set.

		@param prop_type Prop type.
		@param state Prop state.
	*/
	constexpr bool
	has(
		IO::PropType const prop_type,
		IO::PropState const state
	) const noexcept {
		return shift_down(m_states, prop_type, enum_cast(state));
	}

	/**
		Check if any prop is modified.
	*/
	constexpr bool
	any_modified() const noexcept {
		return 0u != (m_states & all_mask_modified);
	}

	/**
		Check if all props match external storage.
	*/
	constexpr bool
	all_original() const noexcept {
		return all_mask_original == (m_states & all_mask_original);
	}

	/**
		Check if all supplied props are uninitialized.
	*/
	constexpr bool
	all_uninitialized() const noexcept {
		return 0u == (m_states & m_states_supplied);
	}

	/**
		Check if all supplied data props are initialized.
	*/
	constexpr bool
	all_data_initialized() const noexcept {
		// NB: Non-supplied props "are" original within the store
		// and all other states imply the prop is initialized
		return shift_down(m_states, IO::PropType::primary)
			&& shift_down(m_states, IO::PropType::auxiliary);
	}

	/**
		Check if prop is initialized.

		@param prop_type Prop type.
	*/
	constexpr bool
	is_initialized(
		IO::PropType const prop_type
	) const noexcept {
		return 0u != shift_down(m_states, prop_type);
	}

	/**
		Check if prop is supplied.

		@param prop_type Prop type.
	*/
	constexpr bool
	supplies(
		IO::PropType const prop_type
	) const noexcept {
		return supplies_all(IO::prop_flag(prop_type));
	}

	/**
		Check if all given props are supplied.
	*/
	constexpr bool
	supplies_all(
		IO::PropTypeBit const props
	) const noexcept {
		return
			enum_cast(props)
			== (enum_cast(get_supplied()) & enum_cast(props))
		;
	}

	/**
		Check if any given props are supplied.
	*/
	constexpr bool
	supplies_any(
		IO::PropTypeBit const props
	) const noexcept {
		return enum_cast(get_supplied()) & enum_cast(props);
	}

	/**
		Get store value.
	*/
	constexpr unsigned
	get_value() const noexcept {
		return m_states;
	}

	/**
		Get full state for prop.

		@param prop_type Prop type.
	*/
	constexpr IO::PropState
	get_state(
		IO::PropType const prop_type
	) const noexcept {
		return static_cast<IO::PropState>(
			shift_down(m_states, prop_type)
		);
	}

	/**
		Get supplied props.
	*/
	constexpr IO::PropTypeBit
	get_supplied() const noexcept {
		return static_cast<IO::PropTypeBit>(
			m_states_supplied >> flag_shift
		);
	}
/// @}

/** @name Operations */ /// @{
	/**
		Reset all states to uninitialized.

		@note Non-supplied states are not modified.

		@returns @c *this.
	*/
	PropStateStore&
	reset_all() noexcept {
		m_states = ~m_states_supplied & mask_unsupplied_implied;
		return *this;
	}

	/**
		Reset a prop state to uninitialized.

		@note If the prop is not supplied, this has no effect.

		@returns @c *this.
		@param prop_type Prop type.
	*/
	PropStateStore&
	reset(
		PropType const prop_type
	) noexcept {
		if (supplies(prop_type)) {
			m_states = mask_off(m_states, prop_type);
		}
		return *this;
	}

	/**
		Assign prop state.

		@note If the prop is not supplied, this has no effect.

		@par
		@note IO::PropState::unsupplied is masked out
		of @a state before assignment. Only the constructor can
		assign this state.

		@returns @c *this.
		@param prop_type Prop type.
		@param state Prop state.
	*/
	PropStateStore&
	assign(
		IO::PropType const prop_type,
		IO::PropState const state
	) noexcept {
		if (supplies(prop_type)) {
			m_states
				= mask_off(m_states, prop_type)
				| shift_up(
					~prop_unsupplied_single & enum_cast(state),
					prop_type
				)
			;
		}
		return *this;
	}

	PropStateStore&
	assign_all(
		IO::PropState const state
	) noexcept {
		switch (state) {
		case IO::PropState::unsupplied:
			reset_all();
			break;
		case IO::PropState::original:
			m_states
				= (~m_states_supplied & mask_unsupplied_implied)
				| (m_states_supplied & all_mask_original)
			;
			break;
		case IO::PropState::modified:
			m_states
				= (~m_states_supplied & mask_unsupplied_implied)
				| (m_states_supplied & all_mask_modified)
			;
			break;
		}
		return *this;
	}
/// @}
};

/** @} */ // end of doc-group prop
/** @} */ // end of doc-group io

} // namespace IO
} // namespace Hord

#endif // HORD_IO_PROPSTATESTORE_HPP_
<|endoftext|>


<commit_before>//
//  Copyright (C) 2013-2014 mogemimi.
//
//  Distributed under the MIT License.
//  See accompanying file LICENSE.md or copy at
//  http://enginetrouble.net/pomdog/LICENSE.md for details.
//

#ifndef POMDOG_MATHHELPER_F07877B3_827B_4997_8895_51BD6934A0B7_HPP
#define POMDOG_MATHHELPER_F07877B3_827B_4997_8895_51BD6934A0B7_HPP

#if (_MSC_VER > 1000)
#	pragma once
#endif

#include "Degree.hpp"
#include "Radian.hpp"
#include <cstdint>
#include <cfloat>
#include <type_traits>

namespace Pomdog {

template <typename T>
struct MathConstants;

template <>
struct MathConstants<float>
{
	static constexpr float Pi()         { return 3.1415926535f; }
	static constexpr float TwoPi()      { return 6.2831853071f; }
	static constexpr float OneOverPi()  { return 0.3183098861f; }
	static constexpr float OneOver2Pi() { return 0.1591549430f; }
	static constexpr float PiOver2()    { return 1.5707963267f; }
	static constexpr float PiOver4()    { return 0.7853981633f; }
};

template <>
struct MathConstants<double>
{
	static constexpr float Pi()         { return 3.14159265358979323846; }
	static constexpr float TwoPi()      { return 6.28318530717958647692; }
	static constexpr float OneOverPi()  { return 0.31830988618379067154; }
	static constexpr float OneOver2Pi() { return 0.15915494309189533576; }
	static constexpr float PiOver2()    { return 1.57079632679489661923; }
	static constexpr float PiOver4()    { return 0.78539816339744830962; }
};

namespace MathHelper {
//-------------------------------------------------------------------
template <typename T>
T Clamp(T const& x, T const& min, T const& max)
{
	static_assert(std::is_arithmetic<T>::value, "");
	POMDOG_ASSERT_MESSAGE(min < max, "In Clamp, maxval is out of range");
	if (x < min) {
		return min;
	}
	if (x > max) {
		return max;
	}
	return x;
}
//-------------------------------------------------------------------
template <typename T>
T Saturate(T const& x)
{
	static_assert(std::is_floating_point<T>::value, "T is floaing point number");
	return Clamp(x, T(0), T(1));
}
//-------------------------------------------------------------------
///@~Japanese
/// @brief 線形補間を行います。
template <typename T>
T Lerp(T const& source1, T const& source2, T const& amount)
{
	static_assert(std::is_floating_point<T>::value, "T is floaing point number");
	return source1 + amount * (source2 - source1);
}
//-------------------------------------------------------------------
///@~Japanese
/// @brief スムーズなエルミート補間を行います。
template <typename T>
T SmoothStep(T const& min, T const& max, T const& amount)
{
	static_assert(std::is_floating_point<T>::value, "T is floaing point number");
	//POMDOG_ASSERT(amount >= 0);
	//POMDOG_ASSERT(amount <= 1);
	auto x = Saturate(amount);
	auto scale = x * x * (T(3) - T(2) * x);
	return min + scale * (max - min);
}
//-------------------------------------------------------------------
template <typename T>
Radian<T> ToRadians(Degree<T> const& degrees)
{
	static_assert(std::is_floating_point<T>::value, "");
	constexpr auto scaleFactor = MathConstants<T>::Pi() * (static_cast<T>(1) / static_cast<T>(180));
	return Radian<T>(degrees.value * scaleFactor);
}
//-------------------------------------------------------------------
template <typename T>
Degree<T> ToDegrees(Radian<T> const& radians)
{
	static_assert(std::is_floating_point<T>::value, "");
	constexpr auto scaleFactor = static_cast<T>(180) * (static_cast<T>(1) / MathConstants<T>::Pi());
	return Degree<T>(radians.value * scaleFactor);
}

}// namespace MathHelper
}// namespace Pomdog

#endif // !defined(POMDOG_MATHHELPER_F07877B3_827B_4997_8895_51BD6934A0B7_HPP)
<commit_msg>Fix result type<commit_after>//
//  Copyright (C) 2013-2014 mogemimi.
//
//  Distributed under the MIT License.
//  See accompanying file LICENSE.md or copy at
//  http://enginetrouble.net/pomdog/LICENSE.md for details.
//

#ifndef POMDOG_MATHHELPER_F07877B3_827B_4997_8895_51BD6934A0B7_HPP
#define POMDOG_MATHHELPER_F07877B3_827B_4997_8895_51BD6934A0B7_HPP

#if (_MSC_VER > 1000)
#	pragma once
#endif

#include "Degree.hpp"
#include "Radian.hpp"
#include <cstdint>
#include <cfloat>
#include <type_traits>

namespace Pomdog {

template <typename T>
struct MathConstants;

template <>
struct MathConstants<float>
{
	static constexpr float Pi()         { return 3.1415926535f; }
	static constexpr float TwoPi()      { return 6.2831853071f; }
	static constexpr float OneOverPi()  { return 0.3183098861f; }
	static constexpr float OneOver2Pi() { return 0.1591549430f; }
	static constexpr float PiOver2()    { return 1.5707963267f; }
	static constexpr float PiOver4()    { return 0.7853981633f; }
};

template <>
struct MathConstants<double>
{
	static constexpr double Pi()         { return 3.14159265358979323846; }
	static constexpr double TwoPi()      { return 6.28318530717958647692; }
	static constexpr double OneOverPi()  { return 0.31830988618379067154; }
	static constexpr double OneOver2Pi() { return 0.15915494309189533576; }
	static constexpr double PiOver2()    { return 1.57079632679489661923; }
	static constexpr double PiOver4()    { return 0.78539816339744830962; }
};

namespace MathHelper {
//-------------------------------------------------------------------
template <typename T>
T Clamp(T const& x, T const& min, T const& max)
{
	static_assert(std::is_arithmetic<T>::value, "");
	POMDOG_ASSERT_MESSAGE(min < max, "In Clamp, maxval is out of range");
	if (x < min) {
		return min;
	}
	if (x > max) {
		return max;
	}
	return x;
}
//-------------------------------------------------------------------
template <typename T>
T Saturate(T const& x)
{
	static_assert(std::is_floating_point<T>::value, "T is floaing point number");
	return Clamp(x, T(0), T(1));
}
//-------------------------------------------------------------------
///@~Japanese
/// @brief 線形補間を行います。
template <typename T>
T Lerp(T const& source1, T const& source2, T const& amount)
{
	static_assert(std::is_floating_point<T>::value, "T is floaing point number");
	return source1 + amount * (source2 - source1);
}
//-------------------------------------------------------------------
///@~Japanese
/// @brief スムーズなエルミート補間を行います。
template <typename T>
T SmoothStep(T const& min, T const& max, T const& amount)
{
	static_assert(std::is_floating_point<T>::value, "T is floaing point number");
	//POMDOG_ASSERT(amount >= 0);
	//POMDOG_ASSERT(amount <= 1);
	auto x = Saturate(amount);
	auto scale = x * x * (T(3) - T(2) * x);
	return min + scale * (max - min);
}
//-------------------------------------------------------------------
template <typename T>
Radian<T> ToRadians(Degree<T> const& degrees)
{
	static_assert(std::is_floating_point<T>::value, "");
	constexpr auto scaleFactor = MathConstants<T>::Pi() * (static_cast<T>(1) / static_cast<T>(180));
	return Radian<T>(degrees.value * scaleFactor);
}
//-------------------------------------------------------------------
template <typename T>
Degree<T> ToDegrees(Radian<T> const& radians)
{
	static_assert(std::is_floating_point<T>::value, "");
	constexpr auto scaleFactor = static_cast<T>(180) * (static_cast<T>(1) / MathConstants<T>::Pi());
	return Degree<T>(radians.value * scaleFactor);
}

}// namespace MathHelper
}// namespace Pomdog

#endif // !defined(POMDOG_MATHHELPER_F07877B3_827B_4997_8895_51BD6934A0B7_HPP)
<|endoftext|>


<commit_before>/*
** File Name: circular_shift.hpp
** Author:    Aditya Ramesh
** Date:      03/20/2015
** Contact:   _@adityaramesh.com
**
** XXX: Clang seems to be buggy in compiling the inline assembly below in
** certain situations.
*/

#ifndef ZC5D2A64A_2B75_4209_B5EE_48410B26BFAE
#define ZC5D2A64A_2B75_4209_B5EE_48410B26BFAE

#include <type_traits>
#include <ccbase/platform/attributes.hpp>
#include <ccbase/platform/identification.hpp>

#if !(PLATFORM_ARCH == PLATFORM_ARCH_X86 &&           \
     (PLATFORM_COMPILER == PLATFORM_COMPILER_CLANG || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_GCC   || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_ICC))
	#warning "Unsupported platform for cc::rotl and cc::rotr."
	#warning "The operation will not use intrinsics."
#endif

namespace cc {

#if  (PLATFORM_ARCH == PLATFORM_ARCH_X86 &&           \
     (PLATFORM_COMPILER == PLATFORM_COMPILER_CLANG || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_GCC   || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_ICC))

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint8_t rotl(uint8_t x, Integer shift)
noexcept
{
	auto res = uint8_t{};
	asm("rolb %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint16_t rotl(uint16_t x, Integer shift)
noexcept
{
	auto res = uint16_t{};
	asm("rolw %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint32_t rotl(uint32_t x, Integer shift)
noexcept
{
	auto res = uint32_t{};
	asm("roll %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint64_t rotl(uint64_t x, Integer shift)
noexcept
{
	auto res = uint64_t{};
	asm("rolq %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint8_t rotr(uint8_t x, Integer shift)
noexcept
{
	auto res = uint8_t{};
	asm("rorb %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint16_t rotr(uint16_t x, Integer shift)
noexcept
{
	auto res = uint16_t{};
	asm("rorw %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint32_t rotr(uint32_t x, Integer shift)
noexcept
{
	auto res = uint32_t{};
	asm("rorl %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint64_t rotr(uint64_t x, Integer shift)
noexcept
{
	auto res = uint64_t{};
	asm("rorq %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

#else

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 unsafe_rotl(Integer1 x, Integer2 shift)
noexcept
{
	return (x << shift) | (x >> (8 * sizeof(Integer1) - shift));
}

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 unsafe_rotr(Integer1 x, Integer2 shift)
noexcept
{
	return (x >> shift) | (x << (8 * sizeof(Integer1) - shift));
}

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 rotl(Integer1 x, Integer2 shift)
noexcept
{
	return unsafe_rotl(x, shift % (sizeof(Integer1) - 1));
}

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 rotr(Integer1 x, Integer2 shift)
noexcept
{
	return unsafe_rotr(x, shift % (sizeof(Integer1) - 1));
}

#endif

}

#endif
<commit_msg>Updated name in header.<commit_after>/*
** File Name: rotate.hpp
** Author:    Aditya Ramesh
** Date:      03/20/2015
** Contact:   _@adityaramesh.com
**
** XXX: Clang seems to be buggy in compiling the inline assembly below in
** certain situations.
*/

#ifndef ZC5D2A64A_2B75_4209_B5EE_48410B26BFAE
#define ZC5D2A64A_2B75_4209_B5EE_48410B26BFAE

#include <type_traits>
#include <ccbase/platform/attributes.hpp>
#include <ccbase/platform/identification.hpp>

#if !(PLATFORM_ARCH == PLATFORM_ARCH_X86 &&           \
     (PLATFORM_COMPILER == PLATFORM_COMPILER_CLANG || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_GCC   || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_ICC))
	#warning "Unsupported platform for cc::rotl and cc::rotr."
	#warning "The operation will not use intrinsics."
#endif

namespace cc {

#if  (PLATFORM_ARCH == PLATFORM_ARCH_X86 &&           \
     (PLATFORM_COMPILER == PLATFORM_COMPILER_CLANG || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_GCC   || \
      PLATFORM_COMPILER == PLATFORM_COMPILER_ICC))

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint8_t rotl(uint8_t x, Integer shift)
noexcept
{
	auto res = uint8_t{};
	asm("rolb %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint16_t rotl(uint16_t x, Integer shift)
noexcept
{
	auto res = uint16_t{};
	asm("rolw %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint32_t rotl(uint32_t x, Integer shift)
noexcept
{
	auto res = uint32_t{};
	asm("roll %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint64_t rotl(uint64_t x, Integer shift)
noexcept
{
	auto res = uint64_t{};
	asm("rolq %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint8_t rotr(uint8_t x, Integer shift)
noexcept
{
	auto res = uint8_t{};
	asm("rorb %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint16_t rotr(uint16_t x, Integer shift)
noexcept
{
	auto res = uint16_t{};
	asm("rorw %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint32_t rotr(uint32_t x, Integer shift)
noexcept
{
	auto res = uint32_t{};
	asm("rorl %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

template <
	class Integer,
	typename std::enable_if<
		std::is_unsigned<Integer>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE
uint64_t rotr(uint64_t x, Integer shift)
noexcept
{
	auto res = uint64_t{};
	asm("rorq %%cl, %0"
		: "=r" (res)
		: "c" (shift), "0" (x)
	);
	return res;
}

#else

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 unsafe_rotl(Integer1 x, Integer2 shift)
noexcept
{
	return (x << shift) | (x >> (8 * sizeof(Integer1) - shift));
}

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 unsafe_rotr(Integer1 x, Integer2 shift)
noexcept
{
	return (x >> shift) | (x << (8 * sizeof(Integer1) - shift));
}

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 rotl(Integer1 x, Integer2 shift)
noexcept
{
	return unsafe_rotl(x, shift % (sizeof(Integer1) - 1));
}

template <
	class Integer1,
	class Integer2,
	typename std::enable_if<
		std::is_unsigned<Integer1>::value &&
		std::is_unsigned<Integer2>::value, int
	>::type = 0
>
CC_ALWAYS_INLINE constexpr
Integer1 rotr(Integer1 x, Integer2 shift)
noexcept
{
	return unsafe_rotr(x, shift % (sizeof(Integer1) - 1));
}

#endif

}

#endif
<|endoftext|>