<commit_before>#include <Python.h>
#include <string>
#include <iostream>
#include <vector>

void* init_string(char*, int64_t);
void* init_string_const(char* in_str);
const char* get_c_str(std::string* s);
void* str_concat(std::string* s1, std::string* s2);
bool str_equal(std::string* s1, std::string* s2);
void* str_split(std::string* str, std::string* sep, int64_t *size);
void* str_substr_int(std::string* str, int64_t index);
int64_t str_to_int64(std::string* str);
double str_to_float64(std::string* str);
int64_t get_str_len(std::string* str);
void allocate_string_array(uint32_t **offsets, char **data, int64_t num_strings,
                                                            int64_t total_size);

void setitem_string_array(uint32_t *offsets, char *data, std::string* str,
                                                                int64_t index);

PyMODINIT_FUNC PyInit_hstr_ext(void) {
    PyObject *m;
    static struct PyModuleDef moduledef = {
            PyModuleDef_HEAD_INIT, "hstr_ext", "No docs", -1, NULL, };
    m = PyModule_Create(&moduledef);
    if (m == NULL)
        return NULL;

    PyObject_SetAttrString(m, "init_string",
                            PyLong_FromVoidPtr((void*)(&init_string)));
    PyObject_SetAttrString(m, "init_string_const",
                            PyLong_FromVoidPtr((void*)(&init_string_const)));
    PyObject_SetAttrString(m, "get_c_str",
                            PyLong_FromVoidPtr((void*)(&get_c_str)));
    PyObject_SetAttrString(m, "str_concat",
                            PyLong_FromVoidPtr((void*)(&str_concat)));
    PyObject_SetAttrString(m, "str_equal",
                            PyLong_FromVoidPtr((void*)(&str_equal)));
    PyObject_SetAttrString(m, "str_split",
                            PyLong_FromVoidPtr((void*)(&str_split)));
    PyObject_SetAttrString(m, "str_substr_int",
                            PyLong_FromVoidPtr((void*)(&str_substr_int)));
    PyObject_SetAttrString(m, "str_to_int64",
                            PyLong_FromVoidPtr((void*)(&str_to_int64)));
    PyObject_SetAttrString(m, "str_to_float64",
                            PyLong_FromVoidPtr((void*)(&str_to_float64)));
    PyObject_SetAttrString(m, "get_str_len",
                            PyLong_FromVoidPtr((void*)(&get_str_len)));
    PyObject_SetAttrString(m, "allocate_string_array",
                            PyLong_FromVoidPtr((void*)(&allocate_string_array)));
    PyObject_SetAttrString(m, "setitem_string_array",
                            PyLong_FromVoidPtr((void*)(&setitem_string_array)));
    return m;
}

void* init_string(char* in_str, int64_t size)
{
    // std::cout<<"init str: "<<in_str<<" "<<size<<std::endl;
    return new std::string(in_str, size);
}

void* init_string_const(char* in_str)
{
    // std::cout<<"init str: "<<in_str<<" "<<size<<std::endl;
    return new std::string(in_str);
}

const char* get_c_str(std::string* s)
{
    // printf("in get %s\n", s->c_str());
    return s->c_str();
}

void* str_concat(std::string* s1, std::string* s2)
{
    // printf("in concat %s %s\n", s1->c_str(), s2->c_str());
    std::string* res = new std::string((*s1)+(*s2));
    return res;
}

bool str_equal(std::string* s1, std::string* s2)
{
    // printf("in str_equal %s %s\n", s1->c_str(), s2->c_str());
    return s1->compare(*s2)==0;
}

void* str_split(std::string* str, std::string* sep, int64_t *size)
{
    // std::cout << *str << " " << *sep << std::endl;
    std::vector<std::string*> res;

    size_t last = 0;
    size_t next = 0;
    while ((next = str->find(*sep, last)) != std::string::npos) {
        std::string *token = new std::string(str->substr(last, next-last));
        res.push_back(token);
        last = next + 1;
    }
    std::string *token = new std::string(str->substr(last));
    res.push_back(token);
    *size = res.size();
    // for(int i=0; i<*size; i++)
    //    std::cout<<*(res[i])<<std::endl;
    // TODO: avoid extra copy
    void* out = new void*[*size];
    memcpy(out, res.data(), (*size)*sizeof(void*));
    // std::cout<< *(((std::string**)(out))[1])<<std::endl;
    return out;
}

void* str_substr_int(std::string* str, int64_t index)
{
    return new std::string(*str, index, 1);
}

int64_t str_to_int64(std::string* str)
{
    return std::stoll(*str);
}

double str_to_float64(std::string* str)
{
    return std::stod(*str);
}

int64_t get_str_len(std::string* str)
{
    std::cout << "str len called: " << *str << " " << str->length()<<std::endl;
    return str->length();
}

void allocate_string_array(uint32_t **offsets, char **data, int64_t num_strings,
                                                            int64_t total_size)
{
    std::cout << "allocating string array: " << num_strings << " " <<
                                                    total_size << std::endl;
    *offsets = new uint32_t[num_strings+1];
    *data = new char[total_size];
    // *data = (char*) new std::string("gggg");
    return;
}

void setitem_string_array(uint32_t *offsets, char *data, std::string* str,
                                                                int64_t index)
{
    std::cout << "setitem str: " << *str << " " << index << std::endl;
    if (index==0)
        offsets[index] = 0;
    uint32_t start = offsets[index];
    uint32_t len = str->length();
    std::cout << "start " << start << " len " << len << std::endl;
    memcpy(&data[start], str->c_str(), len);
    offsets[index+1] = start+len;
    return;
}
<commit_msg>str array getitem<commit_after>#include <Python.h>
#include <string>
#include <iostream>
#include <vector>

void* init_string(char*, int64_t);
void* init_string_const(char* in_str);
const char* get_c_str(std::string* s);
void* str_concat(std::string* s1, std::string* s2);
bool str_equal(std::string* s1, std::string* s2);
void* str_split(std::string* str, std::string* sep, int64_t *size);
void* str_substr_int(std::string* str, int64_t index);
int64_t str_to_int64(std::string* str);
double str_to_float64(std::string* str);
int64_t get_str_len(std::string* str);
void allocate_string_array(uint32_t **offsets, char **data, int64_t num_strings,
                                                            int64_t total_size);

void setitem_string_array(uint32_t *offsets, char *data, std::string* str,
                                                                int64_t index);
char* getitem_string_array(uint32_t *offsets, char *data, int64_t index);
void print_int(int64_t val);

PyMODINIT_FUNC PyInit_hstr_ext(void) {
    PyObject *m;
    static struct PyModuleDef moduledef = {
            PyModuleDef_HEAD_INIT, "hstr_ext", "No docs", -1, NULL, };
    m = PyModule_Create(&moduledef);
    if (m == NULL)
        return NULL;

    PyObject_SetAttrString(m, "init_string",
                            PyLong_FromVoidPtr((void*)(&init_string)));
    PyObject_SetAttrString(m, "init_string_const",
                            PyLong_FromVoidPtr((void*)(&init_string_const)));
    PyObject_SetAttrString(m, "get_c_str",
                            PyLong_FromVoidPtr((void*)(&get_c_str)));
    PyObject_SetAttrString(m, "str_concat",
                            PyLong_FromVoidPtr((void*)(&str_concat)));
    PyObject_SetAttrString(m, "str_equal",
                            PyLong_FromVoidPtr((void*)(&str_equal)));
    PyObject_SetAttrString(m, "str_split",
                            PyLong_FromVoidPtr((void*)(&str_split)));
    PyObject_SetAttrString(m, "str_substr_int",
                            PyLong_FromVoidPtr((void*)(&str_substr_int)));
    PyObject_SetAttrString(m, "str_to_int64",
                            PyLong_FromVoidPtr((void*)(&str_to_int64)));
    PyObject_SetAttrString(m, "str_to_float64",
                            PyLong_FromVoidPtr((void*)(&str_to_float64)));
    PyObject_SetAttrString(m, "get_str_len",
                            PyLong_FromVoidPtr((void*)(&get_str_len)));
    PyObject_SetAttrString(m, "allocate_string_array",
                            PyLong_FromVoidPtr((void*)(&allocate_string_array)));
    PyObject_SetAttrString(m, "setitem_string_array",
                            PyLong_FromVoidPtr((void*)(&setitem_string_array)));
    PyObject_SetAttrString(m, "getitem_string_array",
                            PyLong_FromVoidPtr((void*)(&getitem_string_array)));
    PyObject_SetAttrString(m, "print_int",
                            PyLong_FromVoidPtr((void*)(&print_int)));
    return m;
}

void* init_string(char* in_str, int64_t size)
{
    // std::cout<<"init str: "<<in_str<<" "<<size<<std::endl;
    return new std::string(in_str, size);
}

void* init_string_const(char* in_str)
{
    // std::cout<<"init str: "<<in_str<<" "<<size<<std::endl;
    return new std::string(in_str);
}

const char* get_c_str(std::string* s)
{
    // printf("in get %s\n", s->c_str());
    return s->c_str();
}

void* str_concat(std::string* s1, std::string* s2)
{
    // printf("in concat %s %s\n", s1->c_str(), s2->c_str());
    std::string* res = new std::string((*s1)+(*s2));
    return res;
}

bool str_equal(std::string* s1, std::string* s2)
{
    // printf("in str_equal %s %s\n", s1->c_str(), s2->c_str());
    return s1->compare(*s2)==0;
}

void* str_split(std::string* str, std::string* sep, int64_t *size)
{
    // std::cout << *str << " " << *sep << std::endl;
    std::vector<std::string*> res;

    size_t last = 0;
    size_t next = 0;
    while ((next = str->find(*sep, last)) != std::string::npos) {
        std::string *token = new std::string(str->substr(last, next-last));
        res.push_back(token);
        last = next + 1;
    }
    std::string *token = new std::string(str->substr(last));
    res.push_back(token);
    *size = res.size();
    // for(int i=0; i<*size; i++)
    //    std::cout<<*(res[i])<<std::endl;
    // TODO: avoid extra copy
    void* out = new void*[*size];
    memcpy(out, res.data(), (*size)*sizeof(void*));
    // std::cout<< *(((std::string**)(out))[1])<<std::endl;
    return out;
}

void* str_substr_int(std::string* str, int64_t index)
{
    return new std::string(*str, index, 1);
}

int64_t str_to_int64(std::string* str)
{
    return std::stoll(*str);
}

double str_to_float64(std::string* str)
{
    return std::stod(*str);
}

int64_t get_str_len(std::string* str)
{
    // std::cout << "str len called: " << *str << " " << str->length()<<std::endl;
    return str->length();
}

void allocate_string_array(uint32_t **offsets, char **data, int64_t num_strings,
                                                            int64_t total_size)
{
    // std::cout << "allocating string array: " << num_strings << " " <<
    //                                                 total_size << std::endl;
    *offsets = new uint32_t[num_strings+1];
    *data = new char[total_size];
    // *data = (char*) new std::string("gggg");
    return;
}

void setitem_string_array(uint32_t *offsets, char *data, std::string* str,
                                                                int64_t index)
{
    // std::cout << "setitem str: " << *str << " " << index << std::endl;
    if (index==0)
        offsets[index] = 0;
    uint32_t start = offsets[index];
    uint32_t len = str->length();
    // std::cout << "start " << start << " len " << len << std::endl;
    memcpy(&data[start], str->c_str(), len);
    offsets[index+1] = start+len;
    return;
}

char* getitem_string_array(uint32_t *offsets, char *data, int64_t index)
{
    // printf("getitem string arr index: %d offsets: %d %d", index,
    //                                  offsets[index], offsets[index+1]);
    uint32_t size = offsets[index+1]-offsets[index]+1;
    uint32_t start = offsets[index];
    char* res = new char[size];
    res[size-1] = '\0';
    memcpy(res, &data[start], size-1);
    // printf(" res %s\n", res);
    return res;
}

void print_int(int64_t val)
{
    printf("%ld\n", val);
}
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <iostream>

// Local includes
#include "libmesh.h"
#include "auto_ptr.h"
#include "getpot.h"
#include "reference_counter.h"
#include "remote_elem.h"
#include "threads.h"

#if defined(HAVE_MPI)
# include <mpi.h>
# include "petsc_macro.h"
# if defined(HAVE_PETSC)
EXTERN_C_FOR_PETSC_BEGIN
#   include <petsc.h>
#   include <petscerror.h>
EXTERN_C_FOR_PETSC_END
# endif // #if defined(HAVE_PETSC)
# if defined(HAVE_SLEPC)
EXTERN_C_FOR_PETSC_BEGIN
#   include <slepc.h>
EXTERN_C_FOR_PETSC_END
# endif // #if defined(HAVE_SLEPC)
#endif // #if defined(HAVE_MPI)

// --------------------------------------------------------
// Local anonymous namespace to hold miscelaneous variables
namespace {
  AutoPtr<GetPot> command_line (NULL);
  AutoPtr<Threads::task_scheduler_init> task_scheduler (NULL);
#if defined(HAVE_MPI)
  bool libmesh_initialized_mpi = false;
#endif
}

// ------------------------------------------------------------
// libMeshdata initialization
#ifdef HAVE_MPI
MPI_Comm           libMesh::COMM_WORLD = MPI_COMM_NULL;
#endif

PerfLog            libMesh::perflog ("libMesh",
#ifdef ENABLE_PERFORMANCE_LOGGING
				     true
#else
				     false
#endif
				     );

const Real         libMesh::pi = 3.1415926535897932384626433832795029L;

#ifdef USE_COMPLEX_NUMBERS
const Number       libMesh::imaginary (0., 1.);
const Number       libMesh::zero      (0., 0.);
#else
const Number       libMesh::zero = 0.;
#endif

const unsigned int libMesh::invalid_uint = static_cast<unsigned int>(-1);

// ------------------------------------------------------------
// libMesh::libMeshPrivateData data initialization
int           libMesh::libMeshPrivateData::_n_processors = 1;
int           libMesh::libMeshPrivateData::_processor_id = 0;
int           libMesh::libMeshPrivateData::_n_threads = 1; /* Threads::task_scheduler_init::automatic; */
bool          libMesh::libMeshPrivateData::_is_initialized = false;
SolverPackage libMesh::libMeshPrivateData::_solver_package =
#if   defined(HAVE_PETSC)    // PETSc is the default
                                                       PETSC_SOLVERS;
#elif defined(HAVE_TRILINOS) // Use Trilinos if PETSc isn't there
                                                       TRILINOS_SOLVERS;
#elif defined(HAVE_LASPACK)  // Use LASPACK if neither are there
                                                       LASPACK_SOLVERS;
#else                        // No valid linear solver package at compile time
                                                       INVALID_SOLVER_PACKAGE;
#endif

// ------------------------------------------------------------
// libMesh functions
namespace libMesh {
#ifndef HAVE_MPI
void _init (int &argc, char** & argv)
#else
void _init (int &argc, char** & argv,
	    MPI_Comm COMM_WORLD_IN)
#endif
{
  // should _not_ be initialized already.
  libmesh_assert (!libMesh::initialized());

  // Build a command-line parser.
  command_line.reset (new GetPot (argc, argv));

  // Build a task scheduler
  {
    // Get the requested number of threads, defaults to 1 to avoid MPI and
    // multithreading competition.  If you would like to use MPI and multithreading
    // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the
    //  number of processing cores per node.
    libMesh::libMeshPrivateData::_n_threads =
      libMesh::command_line_value ("--n_threads", 1);

    task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads()));
  }

  // Construct singletons who may be at risk of the
  // "static initialization order fiasco"
  //
  // RemoteElem depends on static reference counting data
  remote_elem = new RemoteElem();

#if defined(HAVE_MPI)

  // Allow the user to bypass PETSc initialization
  if (!libMesh::on_command_line ("--disable-mpi"))
    {
      int flag;
      MPI_Initialized (&flag);

      if (!flag)
	{
	  MPI_Init (&argc, &argv);
	  libmesh_initialized_mpi = true;
	}

      // Duplicate the input communicator for internal use
      MPI_Comm_dup (COMM_WORLD_IN, &libMesh::COMM_WORLD);
      //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation
      //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD");

      MPI_Comm_rank (libMesh::COMM_WORLD, &libMeshPrivateData::_processor_id);
      MPI_Comm_size (libMesh::COMM_WORLD, &libMeshPrivateData::_n_processors);

# if defined(HAVE_PETSC)

      if (!libMesh::on_command_line ("--disable-petsc"))
	{
	  int ierr=0;

	  PETSC_COMM_WORLD = libMesh::COMM_WORLD;

#  if defined(HAVE_SLEPC)
	  ierr = SlepcInitialize  (&argc, &argv, NULL, NULL);
	         CHKERRABORT(libMesh::COMM_WORLD,ierr);
#  else
	  ierr = PetscInitialize (&argc, &argv, NULL, NULL);
	         CHKERRABORT(libMesh::COMM_WORLD,ierr);
#  endif
	}
# endif
    }
#else

  // No MPI, can only be uniprocessor
  libmesh_assert (libMeshPrivateData::_n_processors == 1);
  libmesh_assert (libMeshPrivateData::_processor_id == 0);

#endif

  // Could we have gotten bad values from the above calls?
  libmesh_assert (libMeshPrivateData::_n_processors >  0);
  libmesh_assert (libMeshPrivateData::_processor_id >= 0);

  // Re-parse the command-line arguments.  Note that PETSc and MPI
  // initialization above may have removed command line arguments
  // that are not relevant to this application in the above calls.
  // We don't want a false-positive by detecting those arguments.
  command_line->parse_command_line (argc, argv);

  // The following line is an optimization when simultaneous
  // C and C++ style access to output streams is not required.
  // The amount of benefit which occurs is probably implementation
  // defined, and may be nothing.  On the other hand, I have seen
  // some IO tests where IO peformance improves by a factor of two.
  if (!libMesh::on_command_line ("--sync-with-stdio"))
    std::ios::sync_with_stdio(false);

  // redirect std::cout to nothing on all
  // other processors unless explicitly told
  // not to via the --keep-cout command-line argument.
  if (libMesh::processor_id() != 0)
    if (!libMesh::on_command_line ("--keep-cout"))
      std::cout.rdbuf (NULL);

  // The library is now ready for use
  libMeshPrivateData::_is_initialized = true;

  // Make sure these work.  Library methods
  // depend on these being implemented properly,
  // so this is a good time to test them!
  libmesh_assert (libMesh::initialized());
  libmesh_assert (!libMesh::closed());
}

int _close ()
{
  // Delete reference counted singleton(s)
  delete remote_elem;

  // Clear the thread task manager we started
  task_scheduler.reset();

#if defined(HAVE_MPI)
  // Allow the user to bypass MPI finalization
  if (!libMesh::on_command_line ("--disable-mpi"))
    {
      // We may be here in only one process,
      // because an uncaught libmesh_error() exception
      // called the LibMeshInit destructor.
      //
      // If that's the case, we need to MPI_Abort(),
      // not just wait for other processes that
      // might never get to MPI_Finalize()
      if (libmesh_initialized_mpi &&
          std::uncaught_exception())
        {
          std::cerr << "Uncaught exception - aborting" << std::endl;
          MPI_Abort(libMesh::COMM_WORLD,1);
        }
# if defined(HAVE_PETSC)

      // Allow the user to bypass PETSc finalization
      if (!libMesh::on_command_line ("--disable-petsc"))
	{
#  if defined(HAVE_SLEPC)
	  SlepcFinalize();
#  else
	  PetscFinalize();
#  endif
	}
# endif
      MPI_Comm_free (&libMesh::COMM_WORLD);

      if (libmesh_initialized_mpi)
	MPI_Finalize();
    }
#endif

  // Force the \p ReferenceCounter to print
  // its reference count information.  This allows
  // us to find memory leaks.  By default the
  // \p ReferenceCounter only prints its information
  // when the last created object has been destroyed.
  // That does no good if we are leaking memory!
  ReferenceCounter::print_info ();

  // Print an informative message if we detect a memory leak
  if (ReferenceCounter::n_objects() != 0)
    {
      std::cerr << "Memory leak detected!"
		<< std::endl;

#if !defined(ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)

      std::cerr << "Compile in DEBUG mode with --enable-reference-counting"
		<< std::endl
		<< "for more information"
		<< std::endl;
#endif

    }

  // Reconnect the output streams
  // (don't do this, or we will get messages from objects
  //  that go out of scope after the following return)
  //std::cout.rdbuf(std::cerr.rdbuf());

  // Set the initialized() flag to false
  libMeshPrivateData::_is_initialized = false;

  // Return the number of outstanding objects.
  // This is equivalent to return 0 if all of
  // the reference counted objects have been
  // deleted.
  return static_cast<int>(ReferenceCounter::n_objects());
}
}

#ifndef HAVE_MPI
void libMesh::init (int &argc, char** & argv)
{
  deprecated();  // Use LibMeshInit instead
  libMesh::_init(argc, argv);
}
#else
void libMesh::init (int &argc, char** & argv,
		    MPI_Comm COMM_WORLD_IN)
{
  deprecated();  // Use LibMeshInit instead
  libMesh::_init(argc, argv, COMM_WORLD_IN);
}
#endif

int libMesh::close ()
{
  deprecated();  // Use LibMeshInit instead
  return libMesh::_close();
}

#ifndef HAVE_MPI
LibMeshInit::LibMeshInit (int &argc, char** & argv)
{
  libMesh::_init(argc, argv);
}
#else
LibMeshInit::LibMeshInit (int &argc, char** & argv,
		          MPI_Comm COMM_WORLD_IN)
{
  libMesh::_init(argc, argv, COMM_WORLD_IN);
}
#endif

LibMeshInit::~LibMeshInit()
{
  libMesh::_close();
}

bool libMesh::on_command_line (const std::string& arg)
{
  // Make sure the command line parser is ready for use
  libmesh_assert (command_line.get() != NULL);

  return command_line->search (arg);
}

template <typename T>
T libMesh::command_line_value (const std::string &name, T value)
{
  // Make sure the command line parser is ready for use
  libmesh_assert (command_line.get() != NULL);

    // only if the variable exists in the file
    if (command_line->have_variable(name.c_str()))
      value = (*command_line)(name.c_str(), value);

    return value;
}

SolverPackage libMesh::default_solver_package ()
{
  libmesh_assert (libMesh::initialized());

  static bool called = false;

  // Check the command line.  Since the command line is
  // unchanging it is sufficient to do this only once.
  if (!called)
    {
      called = true;

#ifdef HAVE_PETSC
      if (libMesh::on_command_line ("--use-petsc"))
	libMeshPrivateData::_solver_package = PETSC_SOLVERS;
#endif

#ifdef HAVE_TRILINOS
      if (libMesh::on_command_line ("--use-trilinos") ||
	  libMesh::on_command_line ("--disable-petsc"))
	libMeshPrivateData::_solver_package = TRILINOS_SOLVERS;
#endif

#ifdef HAVE_LASPACK
      if (libMesh::on_command_line ("--use-laspack"  ) ||
	  libMesh::on_command_line ("--disable-petsc"))
	libMeshPrivateData::_solver_package = LASPACK_SOLVERS;
#endif

      if (libMesh::on_command_line ("--disable-laspack") &&
	  libMesh::on_command_line ("--disable-trilinos") &&
	  libMesh::on_command_line ("--disable-petsc"))
	libMeshPrivateData::_solver_package = INVALID_SOLVER_PACKAGE;
    }

  return libMeshPrivateData::_solver_package;
}

//-------------------------------------------------------------------------------
template int          libMesh::command_line_value<int>         (const std::string&, int);
template Real         libMesh::command_line_value<Real>        (const std::string&, Real);
template std::string  libMesh::command_line_value<std::string> (const std::string&, std::string);
<commit_msg>added command-line option --redirect-stdout.  When specified each processor sends std::cout and std::cerr to a file named stdout.processor.PID<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <iostream>
#include <fstream>

// Local includes
#include "libmesh.h"
#include "auto_ptr.h"
#include "getpot.h"
#include "reference_counter.h"
#include "remote_elem.h"
#include "threads.h"

#if defined(HAVE_MPI)
# include <mpi.h>
# include "petsc_macro.h"
# if defined(HAVE_PETSC)
EXTERN_C_FOR_PETSC_BEGIN
#   include <petsc.h>
#   include <petscerror.h>
EXTERN_C_FOR_PETSC_END
# endif // #if defined(HAVE_PETSC)
# if defined(HAVE_SLEPC)
EXTERN_C_FOR_PETSC_BEGIN
#   include <slepc.h>
EXTERN_C_FOR_PETSC_END
# endif // #if defined(HAVE_SLEPC)
#endif // #if defined(HAVE_MPI)

// --------------------------------------------------------
// Local anonymous namespace to hold miscelaneous variables
namespace {
  AutoPtr<GetPot> command_line (NULL);
  AutoPtr<std::ofstream> _ofstream (NULL);
  AutoPtr<Threads::task_scheduler_init> task_scheduler (NULL);
#if defined(HAVE_MPI)
  bool libmesh_initialized_mpi = false;
#endif
}

// ------------------------------------------------------------
// libMeshdata initialization
#ifdef HAVE_MPI
MPI_Comm           libMesh::COMM_WORLD = MPI_COMM_NULL;
#endif

PerfLog            libMesh::perflog ("libMesh",
#ifdef ENABLE_PERFORMANCE_LOGGING
				     true
#else
				     false
#endif
				     );

const Real         libMesh::pi = 3.1415926535897932384626433832795029L;

#ifdef USE_COMPLEX_NUMBERS
const Number       libMesh::imaginary (0., 1.);
const Number       libMesh::zero      (0., 0.);
#else
const Number       libMesh::zero = 0.;
#endif

const unsigned int libMesh::invalid_uint = static_cast<unsigned int>(-1);

// ------------------------------------------------------------
// libMesh::libMeshPrivateData data initialization
int           libMesh::libMeshPrivateData::_n_processors = 1;
int           libMesh::libMeshPrivateData::_processor_id = 0;
int           libMesh::libMeshPrivateData::_n_threads = 1; /* Threads::task_scheduler_init::automatic; */
bool          libMesh::libMeshPrivateData::_is_initialized = false;
SolverPackage libMesh::libMeshPrivateData::_solver_package =
#if   defined(HAVE_PETSC)    // PETSc is the default
                                                       PETSC_SOLVERS;
#elif defined(HAVE_TRILINOS) // Use Trilinos if PETSc isn't there
                                                       TRILINOS_SOLVERS;
#elif defined(HAVE_LASPACK)  // Use LASPACK if neither are there
                                                       LASPACK_SOLVERS;
#else                        // No valid linear solver package at compile time
                                                       INVALID_SOLVER_PACKAGE;
#endif

// ------------------------------------------------------------
// libMesh functions
namespace libMesh {
#ifndef HAVE_MPI
void _init (int &argc, char** & argv)
#else
void _init (int &argc, char** & argv,
	    MPI_Comm COMM_WORLD_IN)
#endif
{
  // should _not_ be initialized already.
  libmesh_assert (!libMesh::initialized());

  // Build a command-line parser.
  command_line.reset (new GetPot (argc, argv));

  // Build a task scheduler
  {
    // Get the requested number of threads, defaults to 1 to avoid MPI and
    // multithreading competition.  If you would like to use MPI and multithreading
    // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the
    //  number of processing cores per node.
    libMesh::libMeshPrivateData::_n_threads =
      libMesh::command_line_value ("--n_threads", 1);

    task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads()));
  }

  // Construct singletons who may be at risk of the
  // "static initialization order fiasco"
  //
  // RemoteElem depends on static reference counting data
  remote_elem = new RemoteElem();

#if defined(HAVE_MPI)

  // Allow the user to bypass PETSc initialization
  if (!libMesh::on_command_line ("--disable-mpi"))
    {
      int flag;
      MPI_Initialized (&flag);

      if (!flag)
	{
	  MPI_Init (&argc, &argv);
	  libmesh_initialized_mpi = true;
	}

      // Duplicate the input communicator for internal use
      MPI_Comm_dup (COMM_WORLD_IN, &libMesh::COMM_WORLD);
      //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation
      //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD");

      MPI_Comm_rank (libMesh::COMM_WORLD, &libMeshPrivateData::_processor_id);
      MPI_Comm_size (libMesh::COMM_WORLD, &libMeshPrivateData::_n_processors);

# if defined(HAVE_PETSC)

      if (!libMesh::on_command_line ("--disable-petsc"))
	{
	  int ierr=0;

	  PETSC_COMM_WORLD = libMesh::COMM_WORLD;

#  if defined(HAVE_SLEPC)
	  ierr = SlepcInitialize  (&argc, &argv, NULL, NULL);
	         CHKERRABORT(libMesh::COMM_WORLD,ierr);
#  else
	  ierr = PetscInitialize (&argc, &argv, NULL, NULL);
	         CHKERRABORT(libMesh::COMM_WORLD,ierr);
#  endif
	}
# endif
    }
#else

  // No MPI, can only be uniprocessor
  libmesh_assert (libMeshPrivateData::_n_processors == 1);
  libmesh_assert (libMeshPrivateData::_processor_id == 0);

#endif

  // Could we have gotten bad values from the above calls?
  libmesh_assert (libMeshPrivateData::_n_processors >  0);
  libmesh_assert (libMeshPrivateData::_processor_id >= 0);

  // Re-parse the command-line arguments.  Note that PETSc and MPI
  // initialization above may have removed command line arguments
  // that are not relevant to this application in the above calls.
  // We don't want a false-positive by detecting those arguments.
  command_line->parse_command_line (argc, argv);

  // The following line is an optimization when simultaneous
  // C and C++ style access to output streams is not required.
  // The amount of benefit which occurs is probably implementation
  // defined, and may be nothing.  On the other hand, I have seen
  // some IO tests where IO peformance improves by a factor of two.
  if (!libMesh::on_command_line ("--sync-with-stdio"))
    std::ios::sync_with_stdio(false);

  // redirect std::cout to nothing on all
  // other processors unless explicitly told
  // not to via the --keep-cout command-line argument.
  if (libMesh::processor_id() != 0)
    if (!libMesh::on_command_line ("--keep-cout"))
      std::cout.rdbuf (NULL);

  // The library is now ready for use
  libMeshPrivateData::_is_initialized = true;

  // Make sure these work.  Library methods
  // depend on these being implemented properly,
  // so this is a good time to test them!
  libmesh_assert (libMesh::initialized());
  libmesh_assert (!libMesh::closed());
}

int _close ()
{
  // Delete reference counted singleton(s)
  delete remote_elem;

  // Clear the thread task manager we started
  task_scheduler.reset();

#if defined(HAVE_MPI)
  // Allow the user to bypass MPI finalization
  if (!libMesh::on_command_line ("--disable-mpi"))
    {
      // We may be here in only one process,
      // because an uncaught libmesh_error() exception
      // called the LibMeshInit destructor.
      //
      // If that's the case, we need to MPI_Abort(),
      // not just wait for other processes that
      // might never get to MPI_Finalize()
      if (libmesh_initialized_mpi &&
          std::uncaught_exception())
        {
          std::cerr << "Uncaught exception - aborting" << std::endl;
          MPI_Abort(libMesh::COMM_WORLD,1);
        }
# if defined(HAVE_PETSC)

      // Allow the user to bypass PETSc finalization
      if (!libMesh::on_command_line ("--disable-petsc"))
	{
#  if defined(HAVE_SLEPC)
	  SlepcFinalize();
#  else
	  PetscFinalize();
#  endif
	}
# endif
      MPI_Comm_free (&libMesh::COMM_WORLD);

      if (libmesh_initialized_mpi)
	MPI_Finalize();
    }
#endif

  // Force the \p ReferenceCounter to print
  // its reference count information.  This allows
  // us to find memory leaks.  By default the
  // \p ReferenceCounter only prints its information
  // when the last created object has been destroyed.
  // That does no good if we are leaking memory!
  ReferenceCounter::print_info ();

  // Print an informative message if we detect a memory leak
  if (ReferenceCounter::n_objects() != 0)
    {
      std::cerr << "Memory leak detected!"
		<< std::endl;

#if !defined(ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)

      std::cerr << "Compile in DEBUG mode with --enable-reference-counting"
		<< std::endl
		<< "for more information"
		<< std::endl;
#endif

    }

  // Reconnect the output streams
  // (don't do this, or we will get messages from objects
  //  that go out of scope after the following return)
  //std::cout.rdbuf(std::cerr.rdbuf());

  // Set the initialized() flag to false
  libMeshPrivateData::_is_initialized = false;

  // Return the number of outstanding objects.
  // This is equivalent to return 0 if all of
  // the reference counted objects have been
  // deleted.
  return static_cast<int>(ReferenceCounter::n_objects());
}
}

#ifndef HAVE_MPI
void libMesh::init (int &argc, char** & argv)
{
  deprecated();  // Use LibMeshInit instead
  libMesh::_init(argc, argv);
}
#else
void libMesh::init (int &argc, char** & argv,
		    MPI_Comm COMM_WORLD_IN)
{
  deprecated();  // Use LibMeshInit instead
  libMesh::_init(argc, argv, COMM_WORLD_IN);
}
#endif

int libMesh::close ()
{
  deprecated();  // Use LibMeshInit instead
  return libMesh::_close();
}

#ifndef HAVE_MPI
LibMeshInit::LibMeshInit (int &argc, char** & argv)
{
  libMesh::_init(argc, argv);
}
#else
LibMeshInit::LibMeshInit (int &argc, char** & argv,
		          MPI_Comm COMM_WORLD_IN)
{
  libMesh::_init(argc, argv, COMM_WORLD_IN);

  // Honor the --redirect-stdout command-line option.
  // When this is specified each processor sends
  // std::cout/std::cerr messages to
  // stdout.processor.####
  if (libMesh::on_command_line ("--redirect-stdout"))
    {
      char filechar[80];
      sprintf (filechar, "stdout.processor.%04d",
	       libMesh::processor_id());
      _ofstream.reset (new std::ofstream (filechar));
      std::cout.rdbuf (_ofstream->rdbuf());
      std::cerr.rdbuf (_ofstream->rdbuf());
    }
}
#endif

LibMeshInit::~LibMeshInit()
{
  libMesh::_close();
}

bool libMesh::on_command_line (const std::string& arg)
{
  // Make sure the command line parser is ready for use
  libmesh_assert (command_line.get() != NULL);

  return command_line->search (arg);
}

template <typename T>
T libMesh::command_line_value (const std::string &name, T value)
{
  // Make sure the command line parser is ready for use
  libmesh_assert (command_line.get() != NULL);

    // only if the variable exists in the file
    if (command_line->have_variable(name.c_str()))
      value = (*command_line)(name.c_str(), value);

    return value;
}

SolverPackage libMesh::default_solver_package ()
{
  libmesh_assert (libMesh::initialized());

  static bool called = false;

  // Check the command line.  Since the command line is
  // unchanging it is sufficient to do this only once.
  if (!called)
    {
      called = true;

#ifdef HAVE_PETSC
      if (libMesh::on_command_line ("--use-petsc"))
	libMeshPrivateData::_solver_package = PETSC_SOLVERS;
#endif

#ifdef HAVE_TRILINOS
      if (libMesh::on_command_line ("--use-trilinos") ||
	  libMesh::on_command_line ("--disable-petsc"))
	libMeshPrivateData::_solver_package = TRILINOS_SOLVERS;
#endif

#ifdef HAVE_LASPACK
      if (libMesh::on_command_line ("--use-laspack"  ) ||
	  libMesh::on_command_line ("--disable-petsc"))
	libMeshPrivateData::_solver_package = LASPACK_SOLVERS;
#endif

      if (libMesh::on_command_line ("--disable-laspack") &&
	  libMesh::on_command_line ("--disable-trilinos") &&
	  libMesh::on_command_line ("--disable-petsc"))
	libMeshPrivateData::_solver_package = INVALID_SOLVER_PACKAGE;
    }

  return libMeshPrivateData::_solver_package;
}

//-------------------------------------------------------------------------------
template int          libMesh::command_line_value<int>         (const std::string&, int);
template Real         libMesh::command_line_value<Real>        (const std::string&, Real);
template std::string  libMesh::command_line_value<std::string> (const std::string&, std::string);
<|endoftext|>


<commit_before>#pragma once

#include "numerics/numdiff.hh"

#include <functional>

namespace numerics {

template <typename X>
using ApplyDelta = std::function<X(const X&, const VecNd<X::DIM>&)>;

template <typename X>
using ComputeDelta = std::function<VecNd<X::DIM>(const X&, const X&)>;

template <typename X, typename Y>
using GroupFnc = std::function<Y(const X&)>;

template <typename X, typename Y>
MatNd<Y::DIM, X::DIM> group_jacobian(const VecNd<X::DIM>& x,
                                     const GroupFnc<X, Y>& fnc,
                                     const ComputeDelta<Y>& compute_delta,
                                     const ApplyDelta<X>& apply_delta) {
  const auto f_x = [&apply_delta, &compute_delta, &fnc, &x](const VecNd<X::DIM>& dx) {

    const X xplus_dx = apply_delta(x, dx);
    return compute_delta(fnc(xplus_dx), fnc(x));
  };
  return numerical_jacobian<Y::DIM>(X::Zero().eval(), f_x);
}
}  // namespace numerics<commit_msg>Add group-diff overload that uses ADL<commit_after>#pragma once

#include "numerics/numdiff.hh"

#include <functional>

namespace numerics {

template <typename X>
using ApplyDelta = std::function<X(const X&, const VecNd<X::DIM>&)>;

template <typename X>
using ComputeDelta = std::function<VecNd<X::DIM>(const X&, const X&)>;

template <typename X, typename Y>
using GroupFnc = std::function<Y(const X&)>;

template <typename X, typename Y>
MatNd<Y::DIM, X::DIM> group_jacobian(const VecNd<X::DIM>& x,
                                     const GroupFnc<X, Y>& fnc,
                                     const ComputeDelta<Y>& compute_delta,
                                     const ApplyDelta<X>& apply_delta) {
  const auto f_x = [&apply_delta, &compute_delta, &fnc, &x](const VecNd<X::DIM>& dx) {
    const X xplus_dx = apply_delta(x, dx);
    return compute_delta(fnc(xplus_dx), fnc(x));
  };
  return numerical_jacobian<Y::DIM>(X::Zero().eval(), f_x);
}

template <typename X, typename Y>
MatNd<Y::DIM, X::DIM> group_jacobian(const VecNd<X::DIM>& x, const GroupFnc<X, Y>& fnc) {
  const auto f_x = [&fnc, &x](const VecNd<X::DIM>& dx) {
    const X xplus_dx = apply_delta(x, dx);
    return compute_delta(fnc(xplus_dx), fnc(x));
  };
  return numerical_jacobian<Y::DIM>(X::Zero().eval(), f_x);
}

}  // namespace numerics<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/dom_ui/autofill_options_handler.h"

#include <vector>

#include "app/l10n_util.h"
#include "base/logging.h"
#include "base/values.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/profile.h"
#include "grit/generated_resources.h"

AutoFillOptionsHandler::AutoFillOptionsHandler()
    : personal_data_(NULL) {
}

AutoFillOptionsHandler::~AutoFillOptionsHandler() {
  if (personal_data_)
    personal_data_->RemoveObserver(this);
}

/////////////////////////////////////////////////////////////////////////////
// OptionsUIHandler implementation:
void AutoFillOptionsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);

  localized_strings->SetString("autoFillOptionsTitle",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_TITLE));
  localized_strings->SetString("autoFillEnabled",
      l10n_util::GetStringUTF16(IDS_OPTIONS_AUTOFILL_ENABLE));
  localized_strings->SetString("addressesHeader",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESSES_GROUP_NAME));
  localized_strings->SetString("creditCardsHeader",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_CREDITCARDS_GROUP_NAME));
  localized_strings->SetString("addAddressButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_ADD_ADDRESS_BUTTON));
  localized_strings->SetString("addCreditCardButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_ADD_CREDITCARD_BUTTON));
  localized_strings->SetString("editButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_BUTTON));
  localized_strings->SetString("deleteButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_DELETE_BUTTON));
  localized_strings->SetString("helpButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_HELP_LABEL));
}

void AutoFillOptionsHandler::Initialize() {
  personal_data_ = dom_ui_->GetProfile()->GetPersonalDataManager();
  personal_data_->SetObserver(this);

  LoadAutoFillData();
}

/////////////////////////////////////////////////////////////////////////////
// PersonalDataManager::Observer implementation:
void  AutoFillOptionsHandler::OnPersonalDataLoaded() {
  LoadAutoFillData();
}

void AutoFillOptionsHandler::OnPersonalDataChanged() {
  LoadAutoFillData();
}

void AutoFillOptionsHandler::RegisterMessages() {
}

void AutoFillOptionsHandler::LoadAutoFillData() {
  if (!personal_data_->IsDataLoaded())
    return;

  ListValue addresses;
  for (std::vector<AutoFillProfile*>::const_iterator i =
           personal_data_->profiles().begin();
       i != personal_data_->profiles().end(); ++i) {
    DictionaryValue* address = new DictionaryValue();
    address->SetString("label", (*i)->PreviewSummary());
    addresses.Append(address);
  }

  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.updateAddresses",
                                  addresses);

  ListValue credit_cards;
  for (std::vector<CreditCard*>::const_iterator i =
           personal_data_->credit_cards().begin();
       i != personal_data_->credit_cards().end(); ++i) {
    DictionaryValue* credit_card = new DictionaryValue();
    credit_card->SetString("label", (*i)->PreviewSummary());
    credit_cards.Append(credit_card);
  }

  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.updateCreditCards",
                                  credit_cards);
}
<commit_msg>DOMUI: Use the OriginalProfile() to load the PersonalDataManager for AutoFill settings.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/dom_ui/autofill_options_handler.h"

#include <vector>

#include "app/l10n_util.h"
#include "base/logging.h"
#include "base/values.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/profile.h"
#include "grit/generated_resources.h"

AutoFillOptionsHandler::AutoFillOptionsHandler()
    : personal_data_(NULL) {
}

AutoFillOptionsHandler::~AutoFillOptionsHandler() {
  if (personal_data_)
    personal_data_->RemoveObserver(this);
}

/////////////////////////////////////////////////////////////////////////////
// OptionsUIHandler implementation:
void AutoFillOptionsHandler::GetLocalizedValues(
    DictionaryValue* localized_strings) {
  DCHECK(localized_strings);

  localized_strings->SetString("autoFillOptionsTitle",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_TITLE));
  localized_strings->SetString("autoFillEnabled",
      l10n_util::GetStringUTF16(IDS_OPTIONS_AUTOFILL_ENABLE));
  localized_strings->SetString("addressesHeader",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESSES_GROUP_NAME));
  localized_strings->SetString("creditCardsHeader",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_CREDITCARDS_GROUP_NAME));
  localized_strings->SetString("addAddressButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_ADD_ADDRESS_BUTTON));
  localized_strings->SetString("addCreditCardButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_ADD_CREDITCARD_BUTTON));
  localized_strings->SetString("editButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_BUTTON));
  localized_strings->SetString("deleteButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_DELETE_BUTTON));
  localized_strings->SetString("helpButton",
      l10n_util::GetStringUTF16(IDS_AUTOFILL_HELP_LABEL));
}

void AutoFillOptionsHandler::Initialize() {
  personal_data_ =
      dom_ui_->GetProfile()->GetOriginalProfile()->GetPersonalDataManager();
  personal_data_->SetObserver(this);

  LoadAutoFillData();
}

/////////////////////////////////////////////////////////////////////////////
// PersonalDataManager::Observer implementation:
void  AutoFillOptionsHandler::OnPersonalDataLoaded() {
  LoadAutoFillData();
}

void AutoFillOptionsHandler::OnPersonalDataChanged() {
  LoadAutoFillData();
}

void AutoFillOptionsHandler::RegisterMessages() {
}

void AutoFillOptionsHandler::LoadAutoFillData() {
  if (!personal_data_->IsDataLoaded())
    return;

  ListValue addresses;
  for (std::vector<AutoFillProfile*>::const_iterator i =
           personal_data_->profiles().begin();
       i != personal_data_->profiles().end(); ++i) {
    DictionaryValue* address = new DictionaryValue();
    address->SetString("label", (*i)->PreviewSummary());
    addresses.Append(address);
  }

  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.updateAddresses",
                                  addresses);

  ListValue credit_cards;
  for (std::vector<CreditCard*>::const_iterator i =
           personal_data_->credit_cards().begin();
       i != personal_data_->credit_cards().end(); ++i) {
    DictionaryValue* credit_card = new DictionaryValue();
    credit_card->SetString("label", (*i)->PreviewSummary());
    credit_cards.Append(credit_card);
  }

  dom_ui_->CallJavascriptFunction(L"AutoFillOptions.updateCreditCards",
                                  credit_cards);
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkContourFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkContourFilter.h"
#include "vtkScalars.h"
#include "vtkCell.h"
#include "vtkMergePoints.h"
#include "vtkContourValues.h"
#include "vtkScalarTree.h"

#ifdef VTK_USE_PATENTED
#include "vtkMarchingSquares.h"
#include "vtkMarchingCubes.h"
#include "vtkImageMarchingCubes.h"
#endif

// Description:
// Construct object with initial range (0,1) and single contour value
// of 0.0.
vtkContourFilter::vtkContourFilter()
{
  this->ContourValues = vtkContourValues::New();

  this->ComputeNormals = 1;
  this->ComputeGradients = 0;
  this->ComputeScalars = 1;

  this->Locator = NULL;

  this->UseScalarTree = 0;
  this->ScalarTree = NULL;
}

vtkContourFilter::~vtkContourFilter()
{
  this->ContourValues->Delete();
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( this->ScalarTree ) this->ScalarTree->Delete();
}

// Description:
// Overload standard modified time function. If contour values are modified,
// then this object is modified as well.
unsigned long vtkContourFilter::GetMTime()
{
  unsigned long mTime=this->vtkDataSetToPolyDataFilter::GetMTime();
  unsigned long time;

  if (this->ContourValues)
    {
    time = this->ContourValues->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }
  if (this->Locator)
    {
    time = this->Locator->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

//
// General contouring filter.  Handles arbitrary input.
//
void vtkContourFilter::Execute()
{
  int cellId, i;
  vtkIdList *cellPts;
  vtkScalars *inScalars;
  vtkCell *cell;
  float range[2];
  vtkCellArray *newVerts, *newLines, *newPolys;
  vtkPoints *newPts;
  vtkDataSet *input=this->GetInput();
  vtkPolyData *output=this->GetOutput();
  int numCells, estimatedSize;
  vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData();
  vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData();
  int numContours=this->ContourValues->GetNumberOfContours();
  float *values=this->ContourValues->GetValues();
  vtkScalars cellScalars;
  cellScalars.ReferenceCountingOff(); cellScalars.Allocate(VTK_CELL_SIZE);

  vtkDebugMacro(<< "Executing contour filter");

  numCells = input->GetNumberOfCells();
  inScalars = input->GetPointData()->GetScalars();
  if ( ! inScalars || numCells < 1 )
    {
    vtkErrorMacro(<<"No data to contour");
    return;
    }

  // If structured points, use more efficient algorithms
#ifdef VTK_USE_PATENTED
  if ( input->GetDataSetType() == VTK_STRUCTURED_POINTS )
    {
    int dim = input->GetCell(0)->GetCellDimension();

    if ( input->GetCell(0)->GetCellDimension() >= 2 )
      {
      this->StructuredPointsContour(dim);
      return;
      }
    }
#endif

  inScalars->GetRange(range);
//
// Create objects to hold output of contour operation. First estimate allocation size.
//
  estimatedSize = (int) pow ((double) numCells, .75);
  estimatedSize *= numContours;
  estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024
  if (estimatedSize < 1024) estimatedSize = 1024;

  newPts = vtkPoints::New();
  newPts->Allocate(estimatedSize,estimatedSize);
  newVerts = vtkCellArray::New();
  newVerts->Allocate(estimatedSize,estimatedSize);
  newLines = vtkCellArray::New();
  newLines->Allocate(estimatedSize,estimatedSize);
  newPolys = vtkCellArray::New();
  newPolys->Allocate(estimatedSize,estimatedSize);

  // locator used to merge potentially duplicate points
  if ( this->Locator == NULL ) this->CreateDefaultLocator();
  this->Locator->InitPointInsertion (newPts, input->GetBounds());

  // interpolate data along edge
  outPd->InterpolateAllocate(inPd,estimatedSize,estimatedSize);
  outCd->CopyAllocate(inCd,estimatedSize,estimatedSize);

  // If enabled, build a scalar tree to accelerate search
  //
  if ( !this->UseScalarTree )
    {
    for (cellId=0; cellId < numCells; cellId++)
      {
      cell = input->GetCell(cellId);
      cellPts = cell->GetPointIds();
      inScalars->GetScalars(*cellPts,cellScalars);

      for (i=0; i < numContours; i++)
        {
        cell->Contour(values[i], &cellScalars, this->Locator,
                      newVerts, newLines, newPolys, inPd, outPd,
		      inCd, cellId, outCd);

        } // for all contour values
      } // for all cells
    } //if using scalar tree
  else
    {
    if ( this->ScalarTree == NULL ) this->ScalarTree = new vtkScalarTree;
    this->ScalarTree->SetDataSet(input);
    //
    // Loop over all contour values.  Then for each contour value,
    // loop over all cells.
    //
    for (i=0; i < numContours; i++)
      {
      for ( this->ScalarTree->InitTraversal(values[i]);
      (cell=this->ScalarTree->GetNextCell(cellId,cellPts,cellScalars)) != NULL; )
        {
        cell->Contour(values[i], &cellScalars, this->Locator,
                      newVerts, newLines, newPolys, inPd, outPd,
		      inCd, cellId, outCd);

        } //for all cells
      } //for all contour values
    } //using scalar tree

  vtkDebugMacro(<<"Created: "
               << newPts->GetNumberOfPoints() << " points, "
               << newVerts->GetNumberOfCells() << " verts, "
               << newLines->GetNumberOfCells() << " lines, "
               << newPolys->GetNumberOfCells() << " triangles");
//
// Update ourselves.  Because we don't know up front how many verts, lines,
// polys we've created, take care to reclaim memory.
//
  output->SetPoints(newPts);
  newPts->Delete();

  if (newVerts->GetNumberOfCells()) output->SetVerts(newVerts);
  newVerts->Delete();

  if (newLines->GetNumberOfCells()) output->SetLines(newLines);
  newLines->Delete();

  if (newPolys->GetNumberOfCells()) output->SetPolys(newPolys);
  newPolys->Delete();

  this->Locator->Initialize();//releases leftover memory
  output->Squeeze();
}

//
// Special method handles structured points
//
#ifndef VTK_USE_PATENTED
void vtkContourFilter::StructuredPointsContour(int vtkNotUsed(dim)) { }
#else
void vtkContourFilter::StructuredPointsContour(int dim)
{
  vtkPolyData *output;
  vtkPolyData *thisOutput = (vtkPolyData *)this->Output;
  int numContours=this->ContourValues->GetNumberOfContours();
  float *values=this->ContourValues->GetValues();

  if ( dim == 2 ) //marching squares
    {
    static vtkMarchingSquares msquares;
    int i;

    msquares.SetInput((vtkStructuredPoints *)this->Input);
    msquares.SetDebug(this->Debug);
    msquares.SetNumberOfContours(numContours);
    for (i=0; i < numContours; i++)
      msquares.SetValue(i,values[i]);

    msquares.Update();
    output = msquares.GetOutput();
    }

  else //marching cubes
    {
    static vtkMarchingCubes mcubes;
    int i;

    mcubes.SetInput((vtkStructuredPoints *)this->Input);
    mcubes.SetComputeNormals (this->ComputeNormals);
    mcubes.SetComputeGradients (this->ComputeGradients);
    mcubes.SetComputeScalars (this->ComputeScalars);
    mcubes.SetDebug(this->Debug);
    mcubes.SetNumberOfContours(numContours);
    for (i=0; i < numContours; i++)
      mcubes.SetValue(i,values[i]);

    mcubes.Update();
    output = mcubes.GetOutput();
    }

  thisOutput->CopyStructure(output);
  thisOutput->GetPointData()->ShallowCopy(*output->GetPointData());
  output->Initialize();
}
#endif

// Description:
// Specify a spatial locator for merging points. By default,
// an instance of vtkMergePoints is used.
void vtkContourFilter::SetLocator(vtkPointLocator *locator)
{
  if ( this->Locator == locator )
    {
    return;
    }
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( locator )
    {
    locator->Register(this);
    }
  this->Locator = locator;
  this->Modified();
}

void vtkContourFilter::CreateDefaultLocator()
{
  if ( this->Locator == NULL )
    {
    this->Locator = vtkMergePoints::New();
    }
}

void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);

  this->ContourValues->PrintSelf(os,indent);

  if ( this->Locator )
    {
    os << indent << "Locator: " << this->Locator << "\n";
    }
  else
    {
    os << indent << "Locator: (none)\n";
    }
}

<commit_msg>ENH: some performance enhancements<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkContourFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkContourFilter.h"
#include "vtkScalars.h"
#include "vtkCell.h"
#include "vtkMergePoints.h"
#include "vtkContourValues.h"
#include "vtkScalarTree.h"

#ifdef VTK_USE_PATENTED
#include "vtkMarchingSquares.h"
#include "vtkMarchingCubes.h"
#include "vtkImageMarchingCubes.h"
#endif

// Description:
// Construct object with initial range (0,1) and single contour value
// of 0.0.
vtkContourFilter::vtkContourFilter()
{
  this->ContourValues = vtkContourValues::New();

  this->ComputeNormals = 1;
  this->ComputeGradients = 0;
  this->ComputeScalars = 1;

  this->Locator = NULL;

  this->UseScalarTree = 0;
  this->ScalarTree = NULL;
}

vtkContourFilter::~vtkContourFilter()
{
  this->ContourValues->Delete();
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( this->ScalarTree ) this->ScalarTree->Delete();
}

// Description:
// Overload standard modified time function. If contour values are modified,
// then this object is modified as well.
unsigned long vtkContourFilter::GetMTime()
{
  unsigned long mTime=this->vtkDataSetToPolyDataFilter::GetMTime();
  unsigned long time;

  if (this->ContourValues)
    {
    time = this->ContourValues->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }
  if (this->Locator)
    {
    time = this->Locator->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

//
// General contouring filter.  Handles arbitrary input.
//
void vtkContourFilter::Execute()
{
  int cellId, i;
  vtkIdList *cellPts;
  vtkScalars *inScalars;
  vtkCell *cell;
  float range[2];
  vtkCellArray *newVerts, *newLines, *newPolys;
  vtkPoints *newPts;
  vtkDataSet *input=this->GetInput();
  vtkPolyData *output=this->GetOutput();
  int numCells, estimatedSize;
  vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData();
  vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData();
  int numContours=this->ContourValues->GetNumberOfContours();
  float *values=this->ContourValues->GetValues();
  vtkScalars cellScalars;
  cellScalars.ReferenceCountingOff(); cellScalars.Allocate(VTK_CELL_SIZE);

  vtkDebugMacro(<< "Executing contour filter");

  numCells = input->GetNumberOfCells();
  inScalars = input->GetPointData()->GetScalars();
  if ( ! inScalars || numCells < 1 )
    {
    vtkErrorMacro(<<"No data to contour");
    return;
    }

  // If structured points, use more efficient algorithms
#ifdef VTK_USE_PATENTED
  if ( input->GetDataSetType() == VTK_STRUCTURED_POINTS )
    {
    int dim = input->GetCell(0)->GetCellDimension();

    if ( input->GetCell(0)->GetCellDimension() >= 2 )
      {
      this->StructuredPointsContour(dim);
      return;
      }
    }
#endif

  inScalars->GetRange(range);
//
// Create objects to hold output of contour operation. First estimate allocation size.
//
  estimatedSize = (int) pow ((double) numCells, .75);
  estimatedSize *= numContours;
  estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024
  if (estimatedSize < 1024) estimatedSize = 1024;

  newPts = vtkPoints::New();
  newPts->Allocate(estimatedSize,estimatedSize);
  newVerts = vtkCellArray::New();
  newVerts->Allocate(estimatedSize,estimatedSize);
  newLines = vtkCellArray::New();
  newLines->Allocate(estimatedSize,estimatedSize);
  newPolys = vtkCellArray::New();
  newPolys->Allocate(estimatedSize,estimatedSize);

  // locator used to merge potentially duplicate points
  if ( this->Locator == NULL ) this->CreateDefaultLocator();
  this->Locator->InitPointInsertion (newPts, input->GetBounds(), estimatedSize);

  // interpolate data along edge
  outPd->InterpolateAllocate(inPd,estimatedSize,estimatedSize);
  outCd->CopyAllocate(inCd,estimatedSize,estimatedSize);

  // If enabled, build a scalar tree to accelerate search
  //
  if ( !this->UseScalarTree )
    {
    for (cellId=0; cellId < numCells; cellId++)
      {
      cell = input->GetCell(cellId);
      cellPts = cell->GetPointIds();
      inScalars->GetScalars(*cellPts,cellScalars);

      for (i=0; i < numContours; i++)
        {
        cell->Contour(values[i], &cellScalars, this->Locator,
                      newVerts, newLines, newPolys, inPd, outPd,
		      inCd, cellId, outCd);

        } // for all contour values
      } // for all cells
    } //if using scalar tree
  else
    {
    if ( this->ScalarTree == NULL ) this->ScalarTree = new vtkScalarTree;
    this->ScalarTree->SetDataSet(input);
    //
    // Loop over all contour values.  Then for each contour value,
    // loop over all cells.
    //
    for (i=0; i < numContours; i++)
      {
      for ( this->ScalarTree->InitTraversal(values[i]);
      (cell=this->ScalarTree->GetNextCell(cellId,cellPts,cellScalars)) != NULL; )
        {
        cell->Contour(values[i], &cellScalars, this->Locator,
                      newVerts, newLines, newPolys, inPd, outPd,
		      inCd, cellId, outCd);

        } //for all cells
      } //for all contour values
    } //using scalar tree

  vtkDebugMacro(<<"Created: "
               << newPts->GetNumberOfPoints() << " points, "
               << newVerts->GetNumberOfCells() << " verts, "
               << newLines->GetNumberOfCells() << " lines, "
               << newPolys->GetNumberOfCells() << " triangles");
//
// Update ourselves.  Because we don't know up front how many verts, lines,
// polys we've created, take care to reclaim memory.
//
  output->SetPoints(newPts);
  newPts->Delete();

  if (newVerts->GetNumberOfCells()) output->SetVerts(newVerts);
  newVerts->Delete();

  if (newLines->GetNumberOfCells()) output->SetLines(newLines);
  newLines->Delete();

  if (newPolys->GetNumberOfCells()) output->SetPolys(newPolys);
  newPolys->Delete();

  this->Locator->Initialize();//releases leftover memory
  output->Squeeze();
}

//
// Special method handles structured points
//
#ifndef VTK_USE_PATENTED
void vtkContourFilter::StructuredPointsContour(int vtkNotUsed(dim)) { }
#else
void vtkContourFilter::StructuredPointsContour(int dim)
{
  vtkPolyData *output;
  vtkPolyData *thisOutput = (vtkPolyData *)this->Output;
  int numContours=this->ContourValues->GetNumberOfContours();
  float *values=this->ContourValues->GetValues();

  if ( dim == 2 ) //marching squares
    {
    static vtkMarchingSquares msquares;
    int i;

    msquares.SetInput((vtkStructuredPoints *)this->Input);
    msquares.SetDebug(this->Debug);
    msquares.SetNumberOfContours(numContours);
    for (i=0; i < numContours; i++)
      msquares.SetValue(i,values[i]);

    msquares.Update();
    output = msquares.GetOutput();
    }

  else //marching cubes
    {
    static vtkMarchingCubes mcubes;
    int i;

    mcubes.SetInput((vtkStructuredPoints *)this->Input);
    mcubes.SetComputeNormals (this->ComputeNormals);
    mcubes.SetComputeGradients (this->ComputeGradients);
    mcubes.SetComputeScalars (this->ComputeScalars);
    mcubes.SetDebug(this->Debug);
    mcubes.SetNumberOfContours(numContours);
    for (i=0; i < numContours; i++)
      mcubes.SetValue(i,values[i]);

    mcubes.Update();
    output = mcubes.GetOutput();
    }

  thisOutput->CopyStructure(output);
  thisOutput->GetPointData()->ShallowCopy(*output->GetPointData());
  output->Initialize();
}
#endif

// Description:
// Specify a spatial locator for merging points. By default,
// an instance of vtkMergePoints is used.
void vtkContourFilter::SetLocator(vtkPointLocator *locator)
{
  if ( this->Locator == locator )
    {
    return;
    }
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( locator )
    {
    locator->Register(this);
    }
  this->Locator = locator;
  this->Modified();
}

void vtkContourFilter::CreateDefaultLocator()
{
  if ( this->Locator == NULL )
    {
    this->Locator = vtkMergePoints::New();
    }
}

void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);

  this->ContourValues->PrintSelf(os,indent);

  if ( this->Locator )
    {
    os << indent << "Locator: " << this->Locator << "\n";
    }
  else
    {
    os << indent << "Locator: (none)\n";
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/prerender/prerender_field_trial.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"

namespace prerender {

namespace {

int omnibox_exact_group_id = 0;
int omnibox_exact_full_group_id = 0;

const char* kOmniboxHeuristicNames[] = {
  "Exact",
  "Exact_Full"
};
COMPILE_ASSERT(arraysize(kOmniboxHeuristicNames) == OMNIBOX_HEURISTIC_MAX,
               OmniboxHeuristic_name_count_mismatch);

const char kPrerenderFromOmniboxTrialName[] = "PrerenderFromOmnibox";
const char kPrerenderFromOmniboxHeuristicTrialName[] =
    "PrerenderFromOmniboxHeuristic";

const char* NameFromOmniboxHeuristic(OmniboxHeuristic heuristic) {
  DCHECK_LT(static_cast<unsigned int>(heuristic),
            arraysize(kOmniboxHeuristicNames));
  return kOmniboxHeuristicNames[heuristic];
}

}  // end namespace

void ConfigurePrerenderFromOmnibox();

void ConfigurePrefetchAndPrerender(const CommandLine& command_line) {
  enum PrerenderOption {
    PRERENDER_OPTION_AUTO,
    PRERENDER_OPTION_DISABLED,
    PRERENDER_OPTION_ENABLED,
    PRERENDER_OPTION_PREFETCH_ONLY,
  };

  PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
  if (command_line.HasSwitch(switches::kPrerenderMode)) {
    const std::string switch_value =
        command_line.GetSwitchValueASCII(switches::kPrerenderMode);

    if (switch_value == switches::kPrerenderModeSwitchValueAuto) {
      prerender_option = PRERENDER_OPTION_AUTO;
    } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) {
      prerender_option = PRERENDER_OPTION_DISABLED;
    } else if (switch_value.empty() ||
               switch_value == switches::kPrerenderModeSwitchValueEnabled) {
      // The empty string means the option was provided with no value, and that
      // means enable.
      prerender_option = PRERENDER_OPTION_ENABLED;
    } else if (switch_value ==
               switches::kPrerenderModeSwitchValuePrefetchOnly) {
      prerender_option = PRERENDER_OPTION_PREFETCH_ONLY;
    } else {
      prerender_option = PRERENDER_OPTION_DISABLED;
      LOG(ERROR) << "Invalid --prerender option received on command line: "
                 << switch_value;
      LOG(ERROR) << "Disabling prerendering!";
    }
  }

  switch (prerender_option) {
    case PRERENDER_OPTION_AUTO: {
      base::FieldTrial::Probability divisor = 1000;
      base::FieldTrial::Probability exp1_probability = 200;
      base::FieldTrial::Probability control1_probability = 200;
      base::FieldTrial::Probability no_use1_probability = 100;
      base::FieldTrial::Probability exp2_probability = 200;
      base::FieldTrial::Probability control2_probability = 200;
      base::FieldTrial::Probability no_use2_probability = 100;
      chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
      if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
          channel == chrome::VersionInfo::CHANNEL_BETA) {
        exp1_probability = 495;
        control1_probability = 5;
        no_use1_probability = 0;
        exp2_probability = 495;
        control2_probability = 5;
        no_use2_probability = 0;
      }
      CHECK_EQ(divisor, exp1_probability + control1_probability +
               no_use1_probability + exp2_probability +
               control2_probability + no_use2_probability);
      scoped_refptr<base::FieldTrial> trial(
          new base::FieldTrial("Prefetch", divisor,
                               "ContentPrefetchPrerender1", 2012, 6, 30));

      const int kPrerenderExperiment1Group = trial->kDefaultGroupNumber;
      const int kPrerenderControl1Group =
          trial->AppendGroup("ContentPrefetchPrerenderControl1",
                             control1_probability);
      const int kPrerenderNoUse1Group =
          trial->AppendGroup("ContentPrefetchPrerenderNoUse1",
                             no_use1_probability);
      const int kPrerenderExperiment2Group =
          trial->AppendGroup("ContentPrefetchPrerender2",
                             exp2_probability);
      const int kPrerenderControl2Group =
          trial->AppendGroup("ContentPrefetchPrerenderControl2",
                             control2_probability);
      const int kPrerenderNoUse2Group =
          trial->AppendGroup("ContentPrefetchPrerenderNoUse2",
                             no_use2_probability);
      const int trial_group = trial->group();
      if (trial_group == kPrerenderExperiment1Group ||
                 trial_group == kPrerenderExperiment2Group) {
        ResourceDispatcherHost::set_is_prefetch_enabled(false);
        PrerenderManager::SetMode(
            PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
      } else if (trial_group == kPrerenderControl1Group ||
                 trial_group == kPrerenderControl2Group) {
        ResourceDispatcherHost::set_is_prefetch_enabled(false);
        PrerenderManager::SetMode(
            PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
      } else if (trial_group == kPrerenderNoUse1Group ||
                 trial_group == kPrerenderNoUse2Group) {
        ResourceDispatcherHost::set_is_prefetch_enabled(false);
        PrerenderManager::SetMode(
            PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
      } else {
        NOTREACHED();
      }
      break;
    }
    case PRERENDER_OPTION_DISABLED:
      ResourceDispatcherHost::set_is_prefetch_enabled(false);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    case PRERENDER_OPTION_ENABLED:
      ResourceDispatcherHost::set_is_prefetch_enabled(false);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
      break;
    case PRERENDER_OPTION_PREFETCH_ONLY:
      ResourceDispatcherHost::set_is_prefetch_enabled(true);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    default:
      NOTREACHED();
  }

  UMA_HISTOGRAM_ENUMERATION("Prerender.Sessions",
                            PrerenderManager::GetMode(),
                            PrerenderManager::PRERENDER_MODE_MAX);

  ConfigurePrerenderFromOmnibox();
}

void ConfigurePrerenderFromOmnibox() {
  // Field trial to see if we're enabled.
  const base::FieldTrial::Probability kDivisor = 100;

  const base::FieldTrial::Probability kEnabledProbability = 90;
  scoped_refptr<base::FieldTrial> enabled_trial(
      new base::FieldTrial(kPrerenderFromOmniboxTrialName, kDivisor,
                           "OmniboxPrerenderDisabled", 2012, 8, 30));
  enabled_trial->AppendGroup("OmniboxPrerenderEnabled", kEnabledProbability);

  // Field trial to see which heuristic to use.
  const base::FieldTrial::Probability kExactFullProbability = 50;
  scoped_refptr<base::FieldTrial> heuristic_trial(
      new base::FieldTrial(kPrerenderFromOmniboxHeuristicTrialName, kDivisor,
                           "OriginalAlgorithm", 2012, 8, 30));
  omnibox_exact_group_id = base::FieldTrial::kDefaultGroupNumber;
  omnibox_exact_full_group_id =
      heuristic_trial->AppendGroup("ExactFullAlgorithm", kExactFullProbability);
}

bool IsOmniboxEnabled(Profile* profile) {
  if (!profile || profile->IsOffTheRecord())
    return false;

  if (!PrerenderManager::IsPrerenderingPossible())
    return false;

  // Override any field trial groups if the user has set a command line flag.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kPrerenderFromOmnibox)) {
    const std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kPrerenderFromOmnibox);

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled)
      return true;

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled)
      return false;

    DCHECK(switch_value == switches::kPrerenderFromOmniboxSwitchValueAuto);
  }

  if (!MetricsServiceHelper::IsMetricsReportingEnabled())
    return false;

  const int group =
      base::FieldTrialList::FindValue(kPrerenderFromOmniboxTrialName);
  return group != base::FieldTrial::kNotFinalized &&
         group != base::FieldTrial::kDefaultGroupNumber;
}

OmniboxHeuristic GetOmniboxHeuristicToUse() {
  const int group =
      base::FieldTrialList::FindValue(kPrerenderFromOmniboxHeuristicTrialName);
  if (group == omnibox_exact_group_id)
    return OMNIBOX_HEURISTIC_EXACT;
  if (group == omnibox_exact_full_group_id)
    return OMNIBOX_HEURISTIC_EXACT_FULL;

  // If we don't have a group just return the exact heuristic.
  return OMNIBOX_HEURISTIC_EXACT;
}

std::string GetOmniboxHistogramSuffix() {
  return NameFromOmniboxHeuristic(prerender::GetOmniboxHeuristicToUse());
}

}  // namespace prerender
<commit_msg>Increase Exact Full trial to 90%.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/prerender/prerender_field_trial.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"

namespace prerender {

namespace {

int omnibox_exact_group_id = 0;
int omnibox_exact_full_group_id = 0;

const char* kOmniboxHeuristicNames[] = {
  "Exact",
  "Exact_Full"
};
COMPILE_ASSERT(arraysize(kOmniboxHeuristicNames) == OMNIBOX_HEURISTIC_MAX,
               OmniboxHeuristic_name_count_mismatch);

const char kPrerenderFromOmniboxTrialName[] = "PrerenderFromOmnibox";
const char kPrerenderFromOmniboxHeuristicTrialName[] =
    "PrerenderFromOmniboxHeuristic";

const char* NameFromOmniboxHeuristic(OmniboxHeuristic heuristic) {
  DCHECK_LT(static_cast<unsigned int>(heuristic),
            arraysize(kOmniboxHeuristicNames));
  return kOmniboxHeuristicNames[heuristic];
}

}  // end namespace

void ConfigurePrerenderFromOmnibox();

void ConfigurePrefetchAndPrerender(const CommandLine& command_line) {
  enum PrerenderOption {
    PRERENDER_OPTION_AUTO,
    PRERENDER_OPTION_DISABLED,
    PRERENDER_OPTION_ENABLED,
    PRERENDER_OPTION_PREFETCH_ONLY,
  };

  PrerenderOption prerender_option = PRERENDER_OPTION_AUTO;
  if (command_line.HasSwitch(switches::kPrerenderMode)) {
    const std::string switch_value =
        command_line.GetSwitchValueASCII(switches::kPrerenderMode);

    if (switch_value == switches::kPrerenderModeSwitchValueAuto) {
      prerender_option = PRERENDER_OPTION_AUTO;
    } else if (switch_value == switches::kPrerenderModeSwitchValueDisabled) {
      prerender_option = PRERENDER_OPTION_DISABLED;
    } else if (switch_value.empty() ||
               switch_value == switches::kPrerenderModeSwitchValueEnabled) {
      // The empty string means the option was provided with no value, and that
      // means enable.
      prerender_option = PRERENDER_OPTION_ENABLED;
    } else if (switch_value ==
               switches::kPrerenderModeSwitchValuePrefetchOnly) {
      prerender_option = PRERENDER_OPTION_PREFETCH_ONLY;
    } else {
      prerender_option = PRERENDER_OPTION_DISABLED;
      LOG(ERROR) << "Invalid --prerender option received on command line: "
                 << switch_value;
      LOG(ERROR) << "Disabling prerendering!";
    }
  }

  switch (prerender_option) {
    case PRERENDER_OPTION_AUTO: {
      base::FieldTrial::Probability divisor = 1000;
      base::FieldTrial::Probability exp1_probability = 200;
      base::FieldTrial::Probability control1_probability = 200;
      base::FieldTrial::Probability no_use1_probability = 100;
      base::FieldTrial::Probability exp2_probability = 200;
      base::FieldTrial::Probability control2_probability = 200;
      base::FieldTrial::Probability no_use2_probability = 100;
      chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
      if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
          channel == chrome::VersionInfo::CHANNEL_BETA) {
        exp1_probability = 495;
        control1_probability = 5;
        no_use1_probability = 0;
        exp2_probability = 495;
        control2_probability = 5;
        no_use2_probability = 0;
      }
      CHECK_EQ(divisor, exp1_probability + control1_probability +
               no_use1_probability + exp2_probability +
               control2_probability + no_use2_probability);
      scoped_refptr<base::FieldTrial> trial(
          new base::FieldTrial("Prefetch", divisor,
                               "ContentPrefetchPrerender1", 2012, 6, 30));

      const int kPrerenderExperiment1Group = trial->kDefaultGroupNumber;
      const int kPrerenderControl1Group =
          trial->AppendGroup("ContentPrefetchPrerenderControl1",
                             control1_probability);
      const int kPrerenderNoUse1Group =
          trial->AppendGroup("ContentPrefetchPrerenderNoUse1",
                             no_use1_probability);
      const int kPrerenderExperiment2Group =
          trial->AppendGroup("ContentPrefetchPrerender2",
                             exp2_probability);
      const int kPrerenderControl2Group =
          trial->AppendGroup("ContentPrefetchPrerenderControl2",
                             control2_probability);
      const int kPrerenderNoUse2Group =
          trial->AppendGroup("ContentPrefetchPrerenderNoUse2",
                             no_use2_probability);
      const int trial_group = trial->group();
      if (trial_group == kPrerenderExperiment1Group ||
                 trial_group == kPrerenderExperiment2Group) {
        ResourceDispatcherHost::set_is_prefetch_enabled(false);
        PrerenderManager::SetMode(
            PrerenderManager::PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP);
      } else if (trial_group == kPrerenderControl1Group ||
                 trial_group == kPrerenderControl2Group) {
        ResourceDispatcherHost::set_is_prefetch_enabled(false);
        PrerenderManager::SetMode(
            PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
      } else if (trial_group == kPrerenderNoUse1Group ||
                 trial_group == kPrerenderNoUse2Group) {
        ResourceDispatcherHost::set_is_prefetch_enabled(false);
        PrerenderManager::SetMode(
            PrerenderManager::PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP);
      } else {
        NOTREACHED();
      }
      break;
    }
    case PRERENDER_OPTION_DISABLED:
      ResourceDispatcherHost::set_is_prefetch_enabled(false);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    case PRERENDER_OPTION_ENABLED:
      ResourceDispatcherHost::set_is_prefetch_enabled(false);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
      break;
    case PRERENDER_OPTION_PREFETCH_ONLY:
      ResourceDispatcherHost::set_is_prefetch_enabled(true);
      PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_DISABLED);
      break;
    default:
      NOTREACHED();
  }

  UMA_HISTOGRAM_ENUMERATION("Prerender.Sessions",
                            PrerenderManager::GetMode(),
                            PrerenderManager::PRERENDER_MODE_MAX);

  ConfigurePrerenderFromOmnibox();
}

void ConfigurePrerenderFromOmnibox() {
  // Field trial to see if we're enabled.
  const base::FieldTrial::Probability kDivisor = 100;

  const base::FieldTrial::Probability kEnabledProbability = 90;
  scoped_refptr<base::FieldTrial> enabled_trial(
      new base::FieldTrial(kPrerenderFromOmniboxTrialName, kDivisor,
                           "OmniboxPrerenderDisabled", 2012, 8, 30));
  enabled_trial->AppendGroup("OmniboxPrerenderEnabled", kEnabledProbability);

  // Field trial to see which heuristic to use.
  const base::FieldTrial::Probability kExactFullProbability = 90;
  scoped_refptr<base::FieldTrial> heuristic_trial(
      new base::FieldTrial(kPrerenderFromOmniboxHeuristicTrialName, kDivisor,
                           "OriginalAlgorithm", 2012, 8, 30));
  omnibox_exact_group_id = base::FieldTrial::kDefaultGroupNumber;
  omnibox_exact_full_group_id =
      heuristic_trial->AppendGroup("ExactFullAlgorithm", kExactFullProbability);
}

bool IsOmniboxEnabled(Profile* profile) {
  if (!profile || profile->IsOffTheRecord())
    return false;

  if (!PrerenderManager::IsPrerenderingPossible())
    return false;

  // Override any field trial groups if the user has set a command line flag.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kPrerenderFromOmnibox)) {
    const std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kPrerenderFromOmnibox);

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueEnabled)
      return true;

    if (switch_value == switches::kPrerenderFromOmniboxSwitchValueDisabled)
      return false;

    DCHECK(switch_value == switches::kPrerenderFromOmniboxSwitchValueAuto);
  }

  if (!MetricsServiceHelper::IsMetricsReportingEnabled())
    return false;

  const int group =
      base::FieldTrialList::FindValue(kPrerenderFromOmniboxTrialName);
  return group != base::FieldTrial::kNotFinalized &&
         group != base::FieldTrial::kDefaultGroupNumber;
}

OmniboxHeuristic GetOmniboxHeuristicToUse() {
  const int group =
      base::FieldTrialList::FindValue(kPrerenderFromOmniboxHeuristicTrialName);
  if (group == omnibox_exact_group_id)
    return OMNIBOX_HEURISTIC_EXACT;
  if (group == omnibox_exact_full_group_id)
    return OMNIBOX_HEURISTIC_EXACT_FULL;

  // If we don't have a group just return the exact heuristic.
  return OMNIBOX_HEURISTIC_EXACT;
}

std::string GetOmniboxHistogramSuffix() {
  return NameFromOmniboxHeuristic(prerender::GetOmniboxHeuristicToUse());
}

}  // namespace prerender
<|endoftext|>