<commit_before>#ifndef _INCLUDED_DS_TEXTDS_HPP
#define _INCLUDED_DS_TEXTDS_HPP

#include <cmath>
#include <ostream>

#include <sdsl/int_vector.hpp>

#include <tudocomp/io.hpp>
#include "forward.hpp"

#include <tudocomp/Literal.hpp>

namespace tdc {

using io::InputView;

/// Manages text related data structures.
template<
	class lcp_tt = LCPArray,
    template<typename> class isa_tt = InverseSuffixArray>
class TextDS {

public:
	typedef uint8_t value_type;
    static const uint64_t SA = 0x01;
    static const uint64_t ISA = 0x02;
    static const uint64_t Phi = 0x04;
    static const uint64_t LCP = 0x08;
	typedef TextDS<lcp_tt,isa_tt> this_t;
	typedef typename lcp_tt::template construct_t<this_t> lcp_t;
	typedef isa_tt<this_t> isa_t;
	typedef SuffixArray<this_t> sa_t;
	typedef PhiArray<this_t> phi_t;

private:
    size_t m_size;
    const value_type* m_text;

	std::unique_ptr<sa_t>  m_sa;
	std::unique_ptr<isa_t> m_isa;
	std::unique_ptr<phi_t> m_phi;
	std::unique_ptr<lcp_t> m_lcp;

    class Literals {
    protected:
        const this_t* m_text;
        size_t m_pos;

    public:
        inline Literals(const this_t& text) : m_text(&text), m_pos(0) {}

        inline bool has_next() const {
            return m_pos < m_text->size();
        }

        inline Literal next() {
            assert(has_next());

            auto i = m_pos++;
            return {(*m_text)[i], i};
        }
    };

public:
    inline TextDS(const InputView& input)
        : m_size(input.size()), m_text((const value_type*)input.data())
    {
		if(!input.is_terminal_null_ensured())
		 	throw std::logic_error("Terminal Null is not ensured. Please invoke the method ensure_null_terminator() on your input before creating TextDS");
    }

    inline TextDS(const InputView& input, uint64_t flags) : TextDS(input)
    {
		if(!input.is_terminal_null_ensured())
		 	throw std::logic_error("Terminal Null is not ensured. Please invoke the method ensure_null_terminator() on your input before creating TextDS");
        require(flags);
    }

    /// Constructs the required data structures as denoted by the given flags
    /// and releases all unwanted ones in a second step.
    inline void require(uint64_t flags) {
        //Step 1: construct
        if(flags & SA) require_sa();
        if(flags & ISA) require_isa();
        if(flags & Phi) require_phi();
        if(flags & LCP) require_lcp();

        //Step 2: release unwanted (may have been constructed beforehand)
        if(!(flags & SA)) release_sa();
        if(!(flags & ISA)) release_isa();
        if(!(flags & Phi)) release_phi();
        if(!(flags & LCP)) release_lcp();
    }

    /// Requires the Suffix Array to be constructed if not already present.
    inline const sa_t& require_sa();

    /// Requires the Phi Array to be constructed if not already present.
    inline const phi_t& require_phi();

    /// Requires the Inverse Suffix Array to be constructed if not already present.
    inline const isa_t& require_isa();

    /// Requires the LCP Array to be constructed if not already present.
    inline const lcp_t& require_lcp();

    /// Releases the suffix array if present.
    inline std::unique_ptr<sa_t> release_sa() {
        return std::move(m_sa);
    }

    /// Releases the inverse suffix array array if present.
    inline std::unique_ptr<isa_t> release_isa() {
        return std::move(m_isa);
    }

    /// Releases the Phi array if present.
    inline std::unique_ptr<phi_t> release_phi() {
        return std::move(m_phi);
    }

    /// Releases the LCP array if present.
    inline std::unique_ptr<lcp_t> release_lcp() {
        return std::move(m_lcp);
    }

    /// Accesses the input text at position i.
    inline value_type operator[](size_t i) const {
        return m_text[i];
    }

    /// Provides access to the input text.
    inline const value_type* text() const {
        return m_text;
    }

    /// Returns the size of the input text.
    inline size_t size() const {
        return m_size;
    }

    /// Prints the constructed tables.
    inline void print(std::ostream& out, size_t base = 0);

    inline Literals literals() const {
        return iterator(*this, 0);
    }
};

}//ns

#include <tudocomp/ds/SuffixArray.hpp>
#include <tudocomp/ds/InverseSuffixArray.hpp>
#include <tudocomp/ds/PhiArray.hpp>
#include <tudocomp/ds/LCPArray.hpp>

namespace tdc {

template<
	class lcp_tt,
    template<typename> class isa_tt>
inline void TextDS<lcp_tt,isa_tt>::print(std::ostream& out, size_t base) {
	size_t w = std::max(6UL, (size_t)std::log10((double)m_size) + 1);
	out << std::setfill(' ');

	//Heading
	out << std::setw(w) << "i" << " | ";
	if(m_sa) out << std::setw(w) << "SA[i]" << " | ";
	if(m_isa) out << std::setw(w) << "ISA[i]" << " | ";
	if(m_phi) out << std::setw(w) << "Phi[i]" << " | ";
	if(m_lcp) out << std::setw(w) << "LCP[i]" << " | ";
	out << std::endl;

	//Separator
	out << std::setfill('-');
	out << std::setw(w) << "" << "-|-";
	if(m_sa) out << std::setw(w) << "" << "-|-";
	if(m_isa) out << std::setw(w) << "" << "-|-";
	if(m_phi) out << std::setw(w) << "" << "-|-";
	if(m_lcp) out << std::setw(w) << "" << "-|-";
	out << std::endl;

	//Body
	out << std::setfill(' ');
	for(size_t i = 0; i < m_size + 1; i++) {
		out << std::setw(w) << (i + base) << " | ";
		if(m_sa) out << std::setw(w) << ((*m_sa)[i] + base) << " | ";
		if(m_isa) out << std::setw(w) << ((*m_isa)[i] + base) << " | ";
		if(m_phi) out << std::setw(w) << ((*m_phi)[i] + base) << " | ";
		if(m_lcp) out << std::setw(w) << (*m_lcp)[i] << " | ";
		out << std::endl;
	}
}

template<
	class lcp_tt,
    template<typename> class isa_tt>
const SuffixArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_sa() {
	if(!m_sa) {
		m_sa = std::unique_ptr<sa_t>(new sa_t());
		m_sa->construct(*this);
	}
	return *m_sa;
}

template<
	class lcp_tt,
    template<typename> class isa_tt>
const PhiArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_phi() {
	if(!m_phi) {
		m_phi = std::unique_ptr<phi_t>(new phi_t());
		m_phi->construct(*this);
	}

	return *m_phi;
}

template<
	class lcp_tt,
    template<typename> class isa_tt>
const isa_tt<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_isa() {
	if(!m_isa) {
		m_isa = std::unique_ptr<isa_t>(new isa_t());
		m_isa->construct(*this);
	}

	return *m_isa;
}

template<class lcp_tt,
    template<typename> class isa_tt>
const typename TextDS<lcp_tt,isa_tt>::lcp_t& TextDS<lcp_tt,isa_tt>::require_lcp() {
	if(!m_lcp) {
		m_lcp = std::unique_ptr<lcp_t>(new lcp_t());
		m_lcp->construct(*this);
	}
	return *m_lcp;
}

//typedef TextDS<lcp_sada<TextDS<lcp_sada,InverseSuffixArray>, InverseSuffixArray<TextDS<lcp_sada,InverseSuffixArray>> TextDSI;
typedef TextDS<LCPArray, InverseSuffixArray> TextDSI;
}//ns

#endif

<commit_msg>fix tab -> space<commit_after>#ifndef _INCLUDED_DS_TEXTDS_HPP
#define _INCLUDED_DS_TEXTDS_HPP

#include <cmath>
#include <ostream>

#include <sdsl/int_vector.hpp>

#include <tudocomp/io.hpp>
#include "forward.hpp"

#include <tudocomp/Literal.hpp>

namespace tdc {

using io::InputView;

/// Manages text related data structures.
template<
    class lcp_tt = LCPArray,
    template<typename> class isa_tt = InverseSuffixArray>
class TextDS {

public:
    typedef uint8_t value_type;
    static const uint64_t SA = 0x01;
    static const uint64_t ISA = 0x02;
    static const uint64_t Phi = 0x04;
    static const uint64_t LCP = 0x08;
    typedef TextDS<lcp_tt,isa_tt> this_t;
    typedef typename lcp_tt::template construct_t<this_t> lcp_t;
    typedef isa_tt<this_t> isa_t;
    typedef SuffixArray<this_t> sa_t;
    typedef PhiArray<this_t> phi_t;

private:
    size_t m_size;
    const value_type* m_text;

    std::unique_ptr<sa_t>  m_sa;
    std::unique_ptr<isa_t> m_isa;
    std::unique_ptr<phi_t> m_phi;
    std::unique_ptr<lcp_t> m_lcp;

    class Literals {
    protected:
        const this_t* m_text;
        size_t m_pos;

    public:
        inline Literals(const this_t& text) : m_text(&text), m_pos(0) {}

        inline bool has_next() const {
            return m_pos < m_text->size();
        }

        inline Literal next() {
            assert(has_next());

            auto i = m_pos++;
            return {(*m_text)[i], i};
        }
    };

public:
    inline TextDS(const InputView& input)
        : m_size(input.size()), m_text((const value_type*)input.data())
    {
        if(!input.is_terminal_null_ensured())
             throw std::logic_error("Terminal Null is not ensured. Please invoke the method ensure_null_terminator() on your input before creating TextDS");
    }

    inline TextDS(const InputView& input, uint64_t flags) : TextDS(input)
    {
        if(!input.is_terminal_null_ensured())
             throw std::logic_error("Terminal Null is not ensured. Please invoke the method ensure_null_terminator() on your input before creating TextDS");
        require(flags);
    }

    /// Constructs the required data structures as denoted by the given flags
    /// and releases all unwanted ones in a second step.
    inline void require(uint64_t flags) {
        //Step 1: construct
        if(flags & SA) require_sa();
        if(flags & ISA) require_isa();
        if(flags & Phi) require_phi();
        if(flags & LCP) require_lcp();

        //Step 2: release unwanted (may have been constructed beforehand)
        if(!(flags & SA)) release_sa();
        if(!(flags & ISA)) release_isa();
        if(!(flags & Phi)) release_phi();
        if(!(flags & LCP)) release_lcp();
    }

    /// Requires the Suffix Array to be constructed if not already present.
    inline const sa_t& require_sa();

    /// Requires the Phi Array to be constructed if not already present.
    inline const phi_t& require_phi();

    /// Requires the Inverse Suffix Array to be constructed if not already present.
    inline const isa_t& require_isa();

    /// Requires the LCP Array to be constructed if not already present.
    inline const lcp_t& require_lcp();

    /// Releases the suffix array if present.
    inline std::unique_ptr<sa_t> release_sa() {
        return std::move(m_sa);
    }

    /// Releases the inverse suffix array array if present.
    inline std::unique_ptr<isa_t> release_isa() {
        return std::move(m_isa);
    }

    /// Releases the Phi array if present.
    inline std::unique_ptr<phi_t> release_phi() {
        return std::move(m_phi);
    }

    /// Releases the LCP array if present.
    inline std::unique_ptr<lcp_t> release_lcp() {
        return std::move(m_lcp);
    }

    /// Accesses the input text at position i.
    inline value_type operator[](size_t i) const {
        return m_text[i];
    }

    /// Provides access to the input text.
    inline const value_type* text() const {
        return m_text;
    }

    /// Returns the size of the input text.
    inline size_t size() const {
        return m_size;
    }

    /// Prints the constructed tables.
    inline void print(std::ostream& out, size_t base = 0);

    inline Literals literals() const {
        return iterator(*this, 0);
    }
};

}//ns

#include <tudocomp/ds/SuffixArray.hpp>
#include <tudocomp/ds/InverseSuffixArray.hpp>
#include <tudocomp/ds/PhiArray.hpp>
#include <tudocomp/ds/LCPArray.hpp>

namespace tdc {

template<
    class lcp_tt,
    template<typename> class isa_tt>
inline void TextDS<lcp_tt,isa_tt>::print(std::ostream& out, size_t base) {
    size_t w = std::max(6UL, (size_t)std::log10((double)m_size) + 1);
    out << std::setfill(' ');

    //Heading
    out << std::setw(w) << "i" << " | ";
    if(m_sa) out << std::setw(w) << "SA[i]" << " | ";
    if(m_isa) out << std::setw(w) << "ISA[i]" << " | ";
    if(m_phi) out << std::setw(w) << "Phi[i]" << " | ";
    if(m_lcp) out << std::setw(w) << "LCP[i]" << " | ";
    out << std::endl;

    //Separator
    out << std::setfill('-');
    out << std::setw(w) << "" << "-|-";
    if(m_sa) out << std::setw(w) << "" << "-|-";
    if(m_isa) out << std::setw(w) << "" << "-|-";
    if(m_phi) out << std::setw(w) << "" << "-|-";
    if(m_lcp) out << std::setw(w) << "" << "-|-";
    out << std::endl;

    //Body
    out << std::setfill(' ');
    for(size_t i = 0; i < m_size + 1; i++) {
        out << std::setw(w) << (i + base) << " | ";
        if(m_sa) out << std::setw(w) << ((*m_sa)[i] + base) << " | ";
        if(m_isa) out << std::setw(w) << ((*m_isa)[i] + base) << " | ";
        if(m_phi) out << std::setw(w) << ((*m_phi)[i] + base) << " | ";
        if(m_lcp) out << std::setw(w) << (*m_lcp)[i] << " | ";
        out << std::endl;
    }
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const SuffixArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_sa() {
    if(!m_sa) {
        m_sa = std::unique_ptr<sa_t>(new sa_t());
        m_sa->construct(*this);
    }
    return *m_sa;
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const PhiArray<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_phi() {
    if(!m_phi) {
        m_phi = std::unique_ptr<phi_t>(new phi_t());
        m_phi->construct(*this);
    }

    return *m_phi;
}

template<
    class lcp_tt,
    template<typename> class isa_tt>
const isa_tt<TextDS<lcp_tt,isa_tt>>& TextDS<lcp_tt,isa_tt>::require_isa() {
    if(!m_isa) {
        m_isa = std::unique_ptr<isa_t>(new isa_t());
        m_isa->construct(*this);
    }

    return *m_isa;
}

template<class lcp_tt,
    template<typename> class isa_tt>
const typename TextDS<lcp_tt,isa_tt>::lcp_t& TextDS<lcp_tt,isa_tt>::require_lcp() {
    if(!m_lcp) {
        m_lcp = std::unique_ptr<lcp_t>(new lcp_t());
        m_lcp->construct(*this);
    }
    return *m_lcp;
}

//typedef TextDS<lcp_sada<TextDS<lcp_sada,InverseSuffixArray>, InverseSuffixArray<TextDS<lcp_sada,InverseSuffixArray>> TextDSI;
typedef TextDS<LCPArray, InverseSuffixArray> TextDSI;
}//ns

#endif

<|endoftext|>


<commit_before>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2010, 2012 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <deal.II/base/thread_management.h>
#include <deal.II/base/subscriptor.h>
#include <deal.II/base/logstream.h>

#include <typeinfo>
#include <string>
#include <iostream>

DEAL_II_NAMESPACE_OPEN

namespace
{
// create a lock that might be used to control subscription to and
// unsubscription from objects, as that might happen in parallel.
// since it should happen rather seldom that several threads try to
// operate on different objects at the same time (the usual case is
// that they subscribe to the same object right after thread
// creation), a global lock should be sufficient, rather than one that
// operates on a per-object base (in which case we would have to
// include the huge <thread_management.h> file into the
// <subscriptor.h> file).
  Threads::Mutex subscription_lock;
}

static const char *unknown_subscriber = "unknown subscriber";

Subscriptor::Subscriptor ()
  :
  counter (0),
  object_info (0)
{}

Subscriptor::Subscriptor (const Subscriptor &)
  :
  counter (0),
  object_info (0)
{}

Subscriptor::~Subscriptor ()
{
  // check whether there are still
  // subscriptions to this object. if
  // so, output the actual name of
  // the class to which this object
  // belongs, i.e. the most derived
  // class. note that the name may be
  // mangled, so it need not be the
  // clear-text class name. however,
  // you can obtain the latter by
  // running the c++filt program over
  // the output.
#ifdef DEBUG
  std::string infostring;
  for (map_iterator it = counter_map.begin(); it != counter_map.end(); ++it)
    {
      if (it->second > 0)
        infostring += std::string("\n  from Subscriber ")
                      + std::string(it->first);
    }

  // if there are still active pointers, show
  // a message and kill the program. However,
  // under some circumstances, this is not so
  // desirable. For example, in code like this
  //
  // Triangulation tria;
  // DoFHandler *dh = new DoFHandler(tria);
  // ...some function that throws an exception
  //
  // the exception will lead to the
  // destruction of the triangulation, but
  // since the dof_handler is on the heap it
  // will not be destroyed. This will trigger
  // an assertion in the triangulation. If we
  // kill the program at this point, we will
  // never be able to learn what caused the
  // problem. In this situation, just display
  // a message and continue the program.
  if (counter != 0)
    {
      if (std::uncaught_exception() == false)
        {
          Assert (counter == 0,
                  ExcInUse (counter, object_info->name(), infostring));
        }
      else
        {
          std::cerr << "---------------------------------------------------------"
                    << std::endl
                    << "An object pointed to by a SmartPointer is being destroyed."
                    << std::endl
                    << "Under normal circumstances, this would abort the program."
                    << std::endl
                    << "However, another exception is being processed at the"
                    << std::endl
                    << "moment, so the program will continue to run to allow"
                    << std::endl
                    << "this exception to be processed."
                    << std::endl
                    << "---------------------------------------------------------"
                    << std::endl;
        }
    }
  // In case we do not abort
  // on error, this will tell
  // do_unsubscribe below that the
  // object is unused now.
  counter = 0;
#endif
}

Subscriptor &Subscriptor::operator = (const Subscriptor &s)
{
  object_info = s.object_info;
  return *this;
}

// These are the implementations for debug mode. The optimized
// versions are inlined in the header file.

void Subscriptor::do_subscribe (const char *id) const
{
#ifdef DEBUG
  if (object_info == 0)
    object_info = &typeid(*this);
  Threads::Mutex::ScopedLock lock (subscription_lock);
  ++counter;

#ifndef DEAL_II_WITH_THREADS
  const char *const name = (id != 0) ? id : unknown_subscriber;

  map_iterator it = counter_map.find(name);
  if (it == counter_map.end())
    counter_map.insert(map_value_type(name, 1U));

  else
    it->second++;
#endif
#endif
}

void Subscriptor::do_unsubscribe (const char *id) const
{
#ifdef DEBUG
  const char *name = (id != 0) ? id : unknown_subscriber;
  Assert (counter>0, ExcNoSubscriber(object_info->name(), name));
  // This is for the case that we do
  // not abort after the exception
  if (counter == 0)
    return;

  Threads::Mutex::ScopedLock lock (subscription_lock);
  --counter;

#ifndef DEAL_II_WITH_THREADS
  map_iterator it = counter_map.find(name);
  Assert (it != counter_map.end(), ExcNoSubscriber(object_info->name(), name));
  Assert (it->second > 0, ExcNoSubscriber(object_info->name(), name));

  it->second--;
#endif
#endif
}

unsigned int Subscriptor::n_subscriptions () const
{
  return counter;
}

void Subscriptor::list_subscribers () const
{
#ifndef DEAL_II_WITH_THREADS
  for (map_iterator it = counter_map.begin();
       it != counter_map.end(); ++it)
    deallog << it->second << '/'
            << counter << " subscriptions from \""
            << it->first << '\"' << std::endl;
#else
  deallog << "No subscriber listing with multithreading" << std::endl;
#endif
}

DEAL_II_NAMESPACE_CLOSE
<commit_msg>Do say if there is no additional information. Move code under an if() statement as well.<commit_after>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2010, 2012, 2013 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <deal.II/base/thread_management.h>
#include <deal.II/base/subscriptor.h>
#include <deal.II/base/logstream.h>

#include <typeinfo>
#include <string>
#include <iostream>

DEAL_II_NAMESPACE_OPEN

namespace
{
// create a lock that might be used to control subscription to and
// unsubscription from objects, as that might happen in parallel.
// since it should happen rather seldom that several threads try to
// operate on different objects at the same time (the usual case is
// that they subscribe to the same object right after thread
// creation), a global lock should be sufficient, rather than one that
// operates on a per-object base (in which case we would have to
// include the huge <thread_management.h> file into the
// <subscriptor.h> file).
  Threads::Mutex subscription_lock;
}

static const char *unknown_subscriber = "unknown subscriber";

Subscriptor::Subscriptor ()
  :
  counter (0),
  object_info (0)
{}

Subscriptor::Subscriptor (const Subscriptor &)
  :
  counter (0),
  object_info (0)
{}

Subscriptor::~Subscriptor ()
{
  // check whether there are still
  // subscriptions to this object. if
  // so, output the actual name of
  // the class to which this object
  // belongs, i.e. the most derived
  // class. note that the name may be
  // mangled, so it need not be the
  // clear-text class name. however,
  // you can obtain the latter by
  // running the c++filt program over
  // the output.
#ifdef DEBUG

  // if there are still active pointers, show
  // a message and kill the program. However,
  // under some circumstances, this is not so
  // desirable. For example, in code like this
  //
  // Triangulation tria;
  // DoFHandler *dh = new DoFHandler(tria);
  // ...some function that throws an exception
  //
  // the exception will lead to the
  // destruction of the triangulation, but
  // since the dof_handler is on the heap it
  // will not be destroyed. This will trigger
  // an assertion in the triangulation. If we
  // kill the program at this point, we will
  // never be able to learn what caused the
  // problem. In this situation, just display
  // a message and continue the program.
  if (counter != 0)
    {
      if (std::uncaught_exception() == false)
        {
	  std::string infostring;
	  for (map_iterator it = counter_map.begin(); it != counter_map.end(); ++it)
	    {
	      if (it->second > 0)
		infostring += std::string("\n  from Subscriber ")
			      + std::string(it->first);
	    }

	  if (infostring == "")
	    infostring = "<none>";

          Assert (counter == 0,
                  ExcInUse (counter, object_info->name(), infostring));
        }
      else
        {
          std::cerr << "---------------------------------------------------------"
                    << std::endl
                    << "An object pointed to by a SmartPointer is being destroyed."
                    << std::endl
                    << "Under normal circumstances, this would abort the program."
                    << std::endl
                    << "However, another exception is being processed at the"
                    << std::endl
                    << "moment, so the program will continue to run to allow"
                    << std::endl
                    << "this exception to be processed."
                    << std::endl
                    << "---------------------------------------------------------"
                    << std::endl;
        }
    }
  // In case we do not abort
  // on error, this will tell
  // do_unsubscribe below that the
  // object is unused now.
  counter = 0;
#endif
}

Subscriptor &Subscriptor::operator = (const Subscriptor &s)
{
  object_info = s.object_info;
  return *this;
}

// These are the implementations for debug mode. The optimized
// versions are inlined in the header file.

void Subscriptor::do_subscribe (const char *id) const
{
#ifdef DEBUG
  if (object_info == 0)
    object_info = &typeid(*this);
  Threads::Mutex::ScopedLock lock (subscription_lock);
  ++counter;

#ifndef DEAL_II_WITH_THREADS
  const char *const name = (id != 0) ? id : unknown_subscriber;

  map_iterator it = counter_map.find(name);
  if (it == counter_map.end())
    counter_map.insert(map_value_type(name, 1U));

  else
    it->second++;
#endif
#endif
}

void Subscriptor::do_unsubscribe (const char *id) const
{
#ifdef DEBUG
  const char *name = (id != 0) ? id : unknown_subscriber;
  Assert (counter>0, ExcNoSubscriber(object_info->name(), name));
  // This is for the case that we do
  // not abort after the exception
  if (counter == 0)
    return;

  Threads::Mutex::ScopedLock lock (subscription_lock);
  --counter;

#ifndef DEAL_II_WITH_THREADS
  map_iterator it = counter_map.find(name);
  Assert (it != counter_map.end(), ExcNoSubscriber(object_info->name(), name));
  Assert (it->second > 0, ExcNoSubscriber(object_info->name(), name));

  it->second--;
#endif
#endif
}

unsigned int Subscriptor::n_subscriptions () const
{
  return counter;
}

void Subscriptor::list_subscribers () const
{
#ifndef DEAL_II_WITH_THREADS
  for (map_iterator it = counter_map.begin();
       it != counter_map.end(); ++it)
    deallog << it->second << '/'
            << counter << " subscriptions from \""
            << it->first << '\"' << std::endl;
#else
  deallog << "No subscriber listing with multithreading" << std::endl;
#endif
}

DEAL_II_NAMESPACE_CLOSE
<|endoftext|>


<commit_before><commit_msg>Prevent hang during loading of xlsm doc.<commit_after><|endoftext|>


<commit_before>//
//  IOSOpenGLContextManager.cpp
//  MWorksCore
//
//  Created by Christopher Stawarz on 2/14/17.
//
//

#include "IOSOpenGLContextManager.hpp"

#include "OpenGLUtilities.hpp"

//
// The technique for using a CAEAGLLayer-backed UIView for displaying OpenGL ES content is taken from
// Apple's "Real-time Video Processing Using AVPlayerItemVideoOutput" example project:
//
// https://developer.apple.com/library/content/samplecode/AVBasicVideoOutput/Introduction/Intro.html
//

@interface MWKEAGLView : UIView

@property(nonatomic, readonly) EAGLContext *context;

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;
- (mw::OpenGLContextLock)lockContext;
- (BOOL)prepareGL;
- (void)bindDrawable;
- (void)display;

@end

@implementation MWKEAGLView {
    mw::OpenGLContextLock::unique_lock::mutex_type mutex;
    GLuint framebuffer;
    GLuint renderbuffer;
}

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context {
    self = [super initWithFrame:frame];

    if (self) {
        _context = [context retain];
        self.layer.opaque = TRUE;
    }

    return self;
}

- (mw::OpenGLContextLock)lockContext {
    return mw::OpenGLContextLock(mw::OpenGLContextLock::unique_lock(mutex));
}

- (BOOL)prepareGL {
    glGenFramebuffers(1, &framebuffer);
    mw::gl::FramebufferBinding<GL_FRAMEBUFFER> framebufferBinding(framebuffer);

    glGenRenderbuffers(1, &renderbuffer);
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);

    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast<CAEAGLLayer *>(self.layer)];

    GLint backingWidth, backingHeight;
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
    glViewport(0, 0, backingWidth, backingHeight);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
    return (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
}

- (void)bindDrawable {
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}

- (void)display {
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}

- (void)dealloc {
    [_context release];
    [super dealloc];
}

@end

@interface MWKEAGLViewController : UIViewController
@end

@implementation MWKEAGLViewController

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (BOOL)shouldAutorotate {
    return NO;
}

@end

BEGIN_NAMESPACE_MW

IOSOpenGLContextManager::~IOSOpenGLContextManager() {
    // Calling releaseContexts here causes the application to crash at exit.  Since this class is
    // used as a singleton, it doesn't matter, anyway.
    //releaseContexts();
}

int IOSOpenGLContextManager::newFullscreenContext(int screen_number) {
    if (screen_number < 0 || screen_number >= getNumDisplays()) {
        throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                              (boost::format("Invalid screen number (%d)") % screen_number).str());
    }

    EAGLSharegroup *sharegroup = nil;
    if (contexts.count > 0) {
        sharegroup = static_cast<EAGLContext *>(contexts[0]).sharegroup;
    }

    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:sharegroup];
    if (!context) {
        throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create OpenGL ES context");
    }

    auto screen = UIScreen.screens[screen_number];
    __block bool success = false;

    dispatch_sync(dispatch_get_main_queue(), ^{
        if (UIWindow *window = [[UIWindow alloc] initWithFrame:screen.bounds]) {
            window.screen = screen;

            if (MWKEAGLViewController *viewController = [[MWKEAGLViewController alloc] init]) {
                window.rootViewController = viewController;

                if (MWKEAGLView *view = [[MWKEAGLView alloc] initWithFrame:window.bounds context:context]) {
                    viewController.view = view;
                    [EAGLContext setCurrentContext:context];

                    if ([view prepareGL]) {
                        [window makeKeyAndVisible];

                        [contexts addObject:context];
                        [views addObject:view];
                        [windows addObject:window];

                        success = true;
                    }

                    [EAGLContext setCurrentContext:nil];
                    [view release];
                }

                [viewController release];
            }

            [window release];
        }
    });

    [context release];

    if (!success) {
        throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create fullscreen window");
    }

    return (contexts.count - 1);
}

int IOSOpenGLContextManager::newMirrorContext() {
    throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Mirror windows are not supported on this OS");
}

void IOSOpenGLContextManager::releaseContexts() {
    dispatch_sync(dispatch_get_main_queue(), ^{
        for (UIWindow *window in windows) {
            window.hidden = YES;
        }
        [windows removeAllObjects];
        [views removeAllObjects];
    });

    [contexts removeAllObjects];
}

int IOSOpenGLContextManager::getNumDisplays() const {
    // At present, we support only the main display
    return 1;
}

OpenGLContextLock IOSOpenGLContextManager::setCurrent(int context_id) {
    if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
        if ([EAGLContext setCurrentContext:view.context]) {
            auto lock = [view lockContext];
            [view bindDrawable];
            return lock;
        }
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Cannot set current OpenGL ES context");
    }
    return OpenGLContextLock();
}

void IOSOpenGLContextManager::clearCurrent() {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);  // Unbind the view's drawable object
    [EAGLContext setCurrentContext:nil];
}

void IOSOpenGLContextManager::bindDefaultFramebuffer(int context_id) {
    if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
        [view bindDrawable];
    }
}

void IOSOpenGLContextManager::flush(int context_id) {
    if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
        [view display];
    }
}

END_NAMESPACE_MW

<commit_msg>Render graphics at full resolution of display on iOS<commit_after>//
//  IOSOpenGLContextManager.cpp
//  MWorksCore
//
//  Created by Christopher Stawarz on 2/14/17.
//
//

#include "IOSOpenGLContextManager.hpp"

#include "OpenGLUtilities.hpp"

//
// The technique for using a CAEAGLLayer-backed UIView for displaying OpenGL ES content is taken from
// Apple's "Real-time Video Processing Using AVPlayerItemVideoOutput" example project:
//
// https://developer.apple.com/library/content/samplecode/AVBasicVideoOutput/Introduction/Intro.html
//

@interface MWKEAGLView : UIView

@property(nonatomic, readonly) EAGLContext *context;

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;
- (mw::OpenGLContextLock)lockContext;
- (BOOL)prepareGL;
- (void)bindDrawable;
- (void)display;

@end

@implementation MWKEAGLView {
    mw::OpenGLContextLock::unique_lock::mutex_type mutex;
    GLuint framebuffer;
    GLuint renderbuffer;
}

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context {
    self = [super initWithFrame:frame];

    if (self) {
        _context = [context retain];
        self.layer.opaque = TRUE;
    }

    return self;
}

- (mw::OpenGLContextLock)lockContext {
    return mw::OpenGLContextLock(mw::OpenGLContextLock::unique_lock(mutex));
}

- (BOOL)prepareGL {
    glGenFramebuffers(1, &framebuffer);
    mw::gl::FramebufferBinding<GL_FRAMEBUFFER> framebufferBinding(framebuffer);

    glGenRenderbuffers(1, &renderbuffer);
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);

    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast<CAEAGLLayer *>(self.layer)];

    GLint backingWidth, backingHeight;
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
    glViewport(0, 0, backingWidth, backingHeight);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
    return (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
}

- (void)bindDrawable {
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}

- (void)display {
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}

- (void)dealloc {
    [_context release];
    [super dealloc];
}

@end

@interface MWKEAGLViewController : UIViewController
@end

@implementation MWKEAGLViewController

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (BOOL)shouldAutorotate {
    return NO;
}

@end

BEGIN_NAMESPACE_MW

IOSOpenGLContextManager::~IOSOpenGLContextManager() {
    // Calling releaseContexts here causes the application to crash at exit.  Since this class is
    // used as a singleton, it doesn't matter, anyway.
    //releaseContexts();
}

int IOSOpenGLContextManager::newFullscreenContext(int screen_number) {
    if (screen_number < 0 || screen_number >= getNumDisplays()) {
        throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                              (boost::format("Invalid screen number (%d)") % screen_number).str());
    }

    EAGLSharegroup *sharegroup = nil;
    if (contexts.count > 0) {
        sharegroup = static_cast<EAGLContext *>(contexts[0]).sharegroup;
    }

    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:sharegroup];
    if (!context) {
        throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create OpenGL ES context");
    }

    auto screen = UIScreen.screens[screen_number];
    __block bool success = false;

    dispatch_sync(dispatch_get_main_queue(), ^{
        if (UIWindow *window = [[UIWindow alloc] initWithFrame:screen.bounds]) {
            window.screen = screen;

            if (MWKEAGLViewController *viewController = [[MWKEAGLViewController alloc] init]) {
                window.rootViewController = viewController;

                if (MWKEAGLView *view = [[MWKEAGLView alloc] initWithFrame:window.bounds context:context]) {
                    viewController.view = view;
                    view.contentScaleFactor = screen.scale;  // Render at full resolution of display
                    [EAGLContext setCurrentContext:context];

                    if ([view prepareGL]) {
                        [window makeKeyAndVisible];

                        [contexts addObject:context];
                        [views addObject:view];
                        [windows addObject:window];

                        success = true;
                    }

                    [EAGLContext setCurrentContext:nil];
                    [view release];
                }

                [viewController release];
            }

            [window release];
        }
    });

    [context release];

    if (!success) {
        throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create fullscreen window");
    }

    return (contexts.count - 1);
}

int IOSOpenGLContextManager::newMirrorContext() {
    throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Mirror windows are not supported on this OS");
}

void IOSOpenGLContextManager::releaseContexts() {
    dispatch_sync(dispatch_get_main_queue(), ^{
        for (UIWindow *window in windows) {
            window.hidden = YES;
        }
        [windows removeAllObjects];
        [views removeAllObjects];
    });

    [contexts removeAllObjects];
}

int IOSOpenGLContextManager::getNumDisplays() const {
    // At present, we support only the main display
    return 1;
}

OpenGLContextLock IOSOpenGLContextManager::setCurrent(int context_id) {
    if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
        if ([EAGLContext setCurrentContext:view.context]) {
            auto lock = [view lockContext];
            [view bindDrawable];
            return lock;
        }
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Cannot set current OpenGL ES context");
    }
    return OpenGLContextLock();
}

void IOSOpenGLContextManager::clearCurrent() {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);  // Unbind the view's drawable object
    [EAGLContext setCurrentContext:nil];
}

void IOSOpenGLContextManager::bindDefaultFramebuffer(int context_id) {
    if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
        [view bindDrawable];
    }
}

void IOSOpenGLContextManager::flush(int context_id) {
    if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
        [view display];
    }
}

END_NAMESPACE_MW

<|endoftext|>


<commit_before>// @(#)root/tmva/pymva $Id$
// Author: Anirudh Dagar, 2020

#include <Python.h>
#include "TMVA/MethodPyTorch.h"

// #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
// #include <numpy/arrayobject.h>

#include "TMVA/Types.h"
#include "TMVA/Config.h"
#include "TMVA/ClassifierFactory.h"
#include "TMVA/Results.h"
#include "TMVA/TransformationHandler.h"
#include "TMVA/VariableTransformBase.h"
#include "TMVA/Tools.h"
#include "TMVA/Timer.h"

using namespace TMVA;

namespace TMVA {
namespace Internal {
class PyGILRAII {
   PyGILState_STATE m_GILState;

public:
   PyGILRAII() : m_GILState(PyGILState_Ensure()) {}
   ~PyGILRAII() { PyGILState_Release(m_GILState); }
};
} // namespace Internal
} // namespace TMVA

REGISTER_METHOD(PyTorch)

ClassImp(MethodPyTorch);

MethodPyTorch::MethodPyTorch(const TString &jobName, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption)
   : PyMethodBase(jobName, Types::kPyTorch, methodTitle, dsi, theOption) {
   fNumEpochs = 10;
   fBatchSize = 100;

   // TODO: Ignore if verbosity not required in pytorch models.
   fVerbose = 1;

   fContinueTraining = false;
   fSaveBestOnly = true;
   fTriesEarlyStopping = -1;
   fLearningRateSchedule = ""; // empty string deactivates learning rate scheduler
   fFilenameTrainedModel = ""; // empty string sets output model filename to default (in "weights/" directory.)
   fTensorBoard = "";          // empty string deactivates TensorBoard
}

MethodPyTorch::MethodPyTorch(DataSetInfo &theData, const TString &theWeightFile)
    : PyMethodBase(Types::kPyTorch, theData, theWeightFile) {
   fNumEpochs = 10;
   fBatchSize = 100;

   // TODO: Ignore if verbosity not required in pytorch models.
   fVerbose = 1;

   fContinueTraining = false;
   fSaveBestOnly = true;
   fTriesEarlyStopping = -1;
   fLearningRateSchedule = ""; // empty string deactivates learning rate scheduler
   fFilenameTrainedModel = ""; // empty string sets output model filename to default (in weights/)
   fTensorBoard = "";          // empty string deactivates TensorBoard
}

MethodPyTorch::~MethodPyTorch() {
}

Bool_t MethodPyTorch::HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t) {
   if (type == Types::kRegression) return kTRUE;
   if (type == Types::kClassification && numberClasses == 2) return kTRUE;
   if (type == Types::kMulticlass && numberClasses >= 2) return kTRUE;
   return kFALSE;
}

///////////////////////////////////////////////////////////////////////////////

void MethodPyTorch::DeclareOptions() {
   DeclareOptionRef(fFilenameModel, "FilenameModel", "Filename of the initial PyTorch model");
   DeclareOptionRef(fFilenameTrainedModel, "FilenameTrainedModel", "Filename of the trained output PyTorch model");
   DeclareOptionRef(fBatchSize, "BatchSize", "Training batch size");
   DeclareOptionRef(fNumEpochs, "NumEpochs", "Number of training epochs");

   // TODO: Check if verbosity is required in pytorch models.
   DeclareOptionRef(fVerbose, "Verbose", "PyTorch verbosity during training");

   DeclareOptionRef(fContinueTraining, "ContinueTraining", "Load weights from previous training");
   DeclareOptionRef(fSaveBestOnly, "SaveBestOnly", "Store only weights with smallest validation loss");
   DeclareOptionRef(fTriesEarlyStopping, "TriesEarlyStopping", "Number of epochs with no improvement in validation loss after "
                                          "which training will be stopped. The default or a negative number deactivates this option.");
   DeclareOptionRef(fLearningRateSchedule, "LearningRateSchedule", "Set new learning rate during training at specific epochs, e.g., \"50,0.01;70,0.005\" using torch.optim.lr_scheduler");
   DeclareOptionRef(fTensorBoard, "TensorBoard",
                    "Write a log during training to visualize and monitor the training performance with torch.utils.tensorboard");

   DeclareOptionRef(fNumValidationString = "20%", "ValidationSize", "Part of the training data to use for validation."
                    "Specify as 0.2 or 20% to use a fifth of the data set as validation set."
                    "Specify as 100 to use exactly 100 events. (Default: 20%)");

}

////////////////////////////////////////////////////////////////////////////////
/// Validation of the ValidationSize option. Allowed formats are 20%, 0.2 and
/// 100 etc.
///    - 20% and 0.2 selects 20% of the training set as validation data.
///    - 100 selects 100 events as the validation data.
///
/// @return number of samples in validation set
///
UInt_t TMVA::MethodPyTorch::GetNumValidationSamples()
{
   Int_t nValidationSamples = 0;
   UInt_t trainingSetSize = GetEventCollection(Types::kTraining).size();

   // Parsing + Validation
   // --------------------
   if (fNumValidationString.EndsWith("%")) {
      // Relative spec. format 20%
      TString intValStr = TString(fNumValidationString.Strip(TString::kTrailing, '%'));

      if (intValStr.IsFloat()) {
         Double_t valSizeAsDouble = fNumValidationString.Atof() / 100.0;
         nValidationSamples = GetEventCollection(Types::kTraining).size() * valSizeAsDouble;
      } else {
         Log() << kFATAL << "Cannot parse number \"" << fNumValidationString
               << "\". Expected string like \"20%\" or \"20.0%\"." << Endl;
      }
   } else if (fNumValidationString.IsFloat()) {
      Double_t valSizeAsDouble = fNumValidationString.Atof();

      if (valSizeAsDouble < 1.0) {
         // Relative spec. format 0.2
         nValidationSamples = GetEventCollection(Types::kTraining).size() * valSizeAsDouble;
      } else {
         // Absolute spec format 100 or 100.0
         nValidationSamples = valSizeAsDouble;
      }
   } else {
      Log() << kFATAL << "Cannot parse number \"" << fNumValidationString << "\". Expected string like \"0.2\" or \"100\"."
            << Endl;
   }

   // Value validation
   // ----------------
   if (nValidationSamples < 0) {
      Log() << kFATAL << "Validation size \"" << fNumValidationString << "\" is negative." << Endl;
   }

   if (nValidationSamples == 0) {
      Log() << kFATAL << "Validation size \"" << fNumValidationString << "\" is zero." << Endl;
   }

   if (nValidationSamples >= (Int_t)trainingSetSize) {
      Log() << kFATAL << "Validation size \"" << fNumValidationString
            << "\" is larger than or equal in size to training set (size=\"" << trainingSetSize << "\")." << Endl;
   }

   return nValidationSamples;
}<commit_msg>[PyMVA] Add MethodPyTorch::ProcessOptions<commit_after>// @(#)root/tmva/pymva $Id$
// Author: Anirudh Dagar, 2020

#include <Python.h>
#include "TMVA/MethodPyTorch.h"

// #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
// #include <numpy/arrayobject.h>

#include "TMVA/Types.h"
#include "TMVA/Config.h"
#include "TMVA/ClassifierFactory.h"
#include "TMVA/Results.h"
#include "TMVA/TransformationHandler.h"
#include "TMVA/VariableTransformBase.h"
#include "TMVA/Tools.h"
#include "TMVA/Timer.h"

using namespace TMVA;

namespace TMVA {
namespace Internal {
class PyGILRAII {
   PyGILState_STATE m_GILState;

public:
   PyGILRAII() : m_GILState(PyGILState_Ensure()) {}
   ~PyGILRAII() { PyGILState_Release(m_GILState); }
};
} // namespace Internal
} // namespace TMVA

REGISTER_METHOD(PyTorch)

ClassImp(MethodPyTorch);

MethodPyTorch::MethodPyTorch(const TString &jobName, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption)
   : PyMethodBase(jobName, Types::kPyTorch, methodTitle, dsi, theOption) {
   fNumEpochs = 10;
   fBatchSize = 100;

   // TODO: Ignore if verbosity not required in pytorch models.
   fVerbose = 1;

   fContinueTraining = false;
   fSaveBestOnly = true;
   fTriesEarlyStopping = -1;
   fLearningRateSchedule = ""; // empty string deactivates learning rate scheduler
   fFilenameTrainedModel = ""; // empty string sets output model filename to default (in "weights/" directory.)
   fTensorBoard = "";          // empty string deactivates TensorBoard
}

MethodPyTorch::MethodPyTorch(DataSetInfo &theData, const TString &theWeightFile)
    : PyMethodBase(Types::kPyTorch, theData, theWeightFile) {
   fNumEpochs = 10;
   fBatchSize = 100;

   // TODO: Ignore if verbosity not required in pytorch models.
   fVerbose = 1;

   fContinueTraining = false;
   fSaveBestOnly = true;
   fTriesEarlyStopping = -1;
   fLearningRateSchedule = ""; // empty string deactivates learning rate scheduler
   fFilenameTrainedModel = ""; // empty string sets output model filename to default (in weights/)
   fTensorBoard = "";          // empty string deactivates TensorBoard
}

MethodPyTorch::~MethodPyTorch() {
}

Bool_t MethodPyTorch::HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t) {
   if (type == Types::kRegression) return kTRUE;
   if (type == Types::kClassification && numberClasses == 2) return kTRUE;
   if (type == Types::kMulticlass && numberClasses >= 2) return kTRUE;
   return kFALSE;
}

///////////////////////////////////////////////////////////////////////////////

void MethodPyTorch::DeclareOptions() {
   DeclareOptionRef(fFilenameModel, "FilenameModel", "Filename of the initial PyTorch model");
   DeclareOptionRef(fFilenameTrainedModel, "FilenameTrainedModel", "Filename of the trained output PyTorch model");
   DeclareOptionRef(fBatchSize, "BatchSize", "Training batch size");
   DeclareOptionRef(fNumEpochs, "NumEpochs", "Number of training epochs");

   // TODO: Check if verbosity is required in pytorch models.
   DeclareOptionRef(fVerbose, "Verbose", "PyTorch verbosity during training");

   DeclareOptionRef(fContinueTraining, "ContinueTraining", "Load weights from previous training");
   DeclareOptionRef(fSaveBestOnly, "SaveBestOnly", "Store only weights with smallest validation loss");
   DeclareOptionRef(fTriesEarlyStopping, "TriesEarlyStopping", "Number of epochs with no improvement in validation loss after "
                                          "which training will be stopped. The default or a negative number deactivates this option.");
   DeclareOptionRef(fLearningRateSchedule, "LearningRateSchedule", "Set new learning rate during training at specific epochs, e.g., \"50,0.01;70,0.005\" using torch.optim.lr_scheduler");
   DeclareOptionRef(fTensorBoard, "TensorBoard",
                    "Write a log during training to visualize and monitor the training performance with torch.utils.tensorboard");

   DeclareOptionRef(fNumValidationString = "20%", "ValidationSize", "Part of the training data to use for validation."
                    "Specify as 0.2 or 20% to use a fifth of the data set as validation set."
                    "Specify as 100 to use exactly 100 events. (Default: 20%)");

}

////////////////////////////////////////////////////////////////////////////////
/// Validation of the ValidationSize option. Allowed formats are 20%, 0.2 and
/// 100 etc.
///    - 20% and 0.2 selects 20% of the training set as validation data.
///    - 100 selects 100 events as the validation data.
///
/// @return number of samples in validation set
///
UInt_t TMVA::MethodPyTorch::GetNumValidationSamples()
{
   Int_t nValidationSamples = 0;
   UInt_t trainingSetSize = GetEventCollection(Types::kTraining).size();

   // Parsing + Validation
   // --------------------
   if (fNumValidationString.EndsWith("%")) {
      // Relative spec. format 20%
      TString intValStr = TString(fNumValidationString.Strip(TString::kTrailing, '%'));

      if (intValStr.IsFloat()) {
         Double_t valSizeAsDouble = fNumValidationString.Atof() / 100.0;
         nValidationSamples = GetEventCollection(Types::kTraining).size() * valSizeAsDouble;
      } else {
         Log() << kFATAL << "Cannot parse number \"" << fNumValidationString
               << "\". Expected string like \"20%\" or \"20.0%\"." << Endl;
      }
   } else if (fNumValidationString.IsFloat()) {
      Double_t valSizeAsDouble = fNumValidationString.Atof();

      if (valSizeAsDouble < 1.0) {
         // Relative spec. format 0.2
         nValidationSamples = GetEventCollection(Types::kTraining).size() * valSizeAsDouble;
      } else {
         // Absolute spec format 100 or 100.0
         nValidationSamples = valSizeAsDouble;
      }
   } else {
      Log() << kFATAL << "Cannot parse number \"" << fNumValidationString << "\". Expected string like \"0.2\" or \"100\"."
            << Endl;
   }

   // Value validation
   // ----------------
   if (nValidationSamples < 0) {
      Log() << kFATAL << "Validation size \"" << fNumValidationString << "\" is negative." << Endl;
   }

   if (nValidationSamples == 0) {
      Log() << kFATAL << "Validation size \"" << fNumValidationString << "\" is zero." << Endl;
   }

   if (nValidationSamples >= (Int_t)trainingSetSize) {
      Log() << kFATAL << "Validation size \"" << fNumValidationString
            << "\" is larger than or equal in size to training set (size=\"" << trainingSetSize << "\")." << Endl;
   }

   return nValidationSamples;
}

void MethodPyTorch::ProcessOptions() {
   // Set default filename for trained model if option is not used
   if (fFilenameTrainedModel.IsNull()) {
      fFilenameTrainedModel = GetWeightFileDir() + "/TrainedModel_" + GetName() + ".pt";
   }

   //  -  set up number of threads for CPU if NumThreads option was specified
   //     `torch.set_num_threads` sets the number of threads that can be used to
   //     perform cpu operations like conv or mm (usually used by OpenMP or MKL).

   Log() << kINFO << "Using PyTorch - setting special configuration options "  << Endl;
   PyRunString("import torch");

   // check pytorch version
   PyRunString("torch_major_version = int(torch.__version__.split('.')[0])");
   PyObject *pyTorchVersion = PyDict_GetItemString(fLocalNS, "torch_major_version");
   int torchVersion = PyLong_AsLong(pyTorchVersion);
   Log() << kINFO << "Using PyTorch version " << torchVersion << Endl;

   // in case specify number of threads
   int num_threads = fNumThreads;
   if (num_threads > 0) {
      Log() << kINFO << "Setting the CPU number of threads =  "  << num_threads << Endl;

      PyRunString(TString::Format("torch.set_num_threads(%d)", num_threads));
      PyRunString(TString::Format("torch.set_num_interop_threads(%d)", num_threads));
   }

   // Setup model, either the initial model from `fFilenameModel` or
   // the trained model from `fFilenameTrainedModel`
   if (fContinueTraining) Log() << kINFO << "Continue training with trained model" << Endl;
   SetupTorchModel(fContinueTraining);
}
<|endoftext|>


<commit_before>#include "utils/test_main.hxx"

#include "executor/Timer.hxx"

using ::testing::ElementsAre;

class TimerTest : public ::testing::Test
{
protected:
    vector<Timer *> active_list(ActiveTimers *timers)
    {
        vector<Timer *> t;
        Timer *current_timer = static_cast<Timer *>(timers->activeTimers_.next);
        while (current_timer)
        {
            t.push_back(current_timer);
            current_timer = static_cast<Timer *>(current_timer->next);
        }
        return t;
    }
};

class CountingTimer : public Timer
{
public:
    CountingTimer(ActiveTimers *parent)
        : Timer(parent)
        , count_(0)
    {
    }

    ///@returns the number of times the timeout method was called.
    int count()
    {
        return count_;
    }

    long long timeout()
    {
        ++count_;
        return NONE;
    }

    bool is_active()
    {

        return isActive_;
    }

    bool is_expired()
    {

        return isExpired_;
    }

private:
    int count_;
};

class RestartingTimer : public CountingTimer
{
public:
    RestartingTimer(ActiveTimers *parent)
        : CountingTimer(parent)
        , stop_(false)
    {
    }

    long long timeout()
    {
        CountingTimer::timeout();
        return stop_ ? NONE : RESTART;
    }

    // Instructs the timer not to restart the period upon wakeup.
    void stop()
    {
        stop_ = true;
    }

private:
    // set to true to not restart the timer.
    bool stop_;
};

TEST(SemTest, TestExpire)
{
    OSSem sem;
    EXPECT_EQ(-1, sem.timedwait(MSEC_TO_NSEC(20)));
    EXPECT_EQ(ETIMEDOUT, errno);
}

TEST_F(TimerTest, TestExpire)
{
    ActiveTimers tim(&g_executor);
    CountingTimer t1(&tim);
    t1.start(MSEC_TO_NSEC(30));
    EXPECT_TRUE(t1.is_active());
    usleep(60000);
    EXPECT_EQ(0, tim.get_next_timeout());
    EXPECT_FALSE(t1.is_active());
    wait_for_main_executor();
}

TEST_F(TimerTest, Simple)
{
    CountingTimer t1(g_executor.active_timers());
    EXPECT_EQ(0, t1.count());
    usleep(20000);
    EXPECT_EQ(0, t1.count());
    EXPECT_FALSE(t1.is_active());
    t1.start(MSEC_TO_NSEC(30));
    EXPECT_TRUE(t1.is_active());
    EXPECT_LT(MSEC_TO_NSEC(20), g_executor.active_timers()->get_next_timeout());
    EXPECT_GT(MSEC_TO_NSEC(40), g_executor.active_timers()->get_next_timeout());
    EXPECT_EQ(0, t1.count());
    usleep(20000);
    wait_for_main_executor();
    EXPECT_EQ(0, t1.count());
    usleep(20000);
    EXPECT_EQ(1, t1.count());
    EXPECT_FALSE(t1.is_active());
    EXPECT_LT(SEC_TO_NSEC(1800),
              g_executor.active_timers()->get_next_timeout());
}

TEST_F(TimerTest, TwoTimers)
{
    CountingTimer t1(g_executor.active_timers());
    CountingTimer t2(g_executor.active_timers());
    EXPECT_EQ(0, t1.count());
    EXPECT_EQ(0, t2.count());
    t1.start(MSEC_TO_NSEC(10));
    EXPECT_THAT(active_list(g_executor.active_timers()), ElementsAre(&t1));
    t2.start(MSEC_TO_NSEC(20));
    EXPECT_THAT(active_list(g_executor.active_timers()), ElementsAre(&t1, &t2));
    EXPECT_TRUE(t1.is_active());
    EXPECT_TRUE(t2.is_active());
    usleep(15000);
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(0, t2.count());
    usleep(7000);
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(1, t2.count());

    // Let's restart one of the timers.
    t2.restart();
    usleep(15000);
    EXPECT_EQ(1, t2.count());
    usleep(7000);
    EXPECT_EQ(2, t2.count());
    wait_for_main_executor();
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(2, t2.count());
}

TEST_F(TimerTest, ExpireTogether)
{
    // In this test we create two timers that will expire roughly at the same
    // time, and a third expiring later. We block the main executor to pile up
    // the two timers. Then release it, which should trigger them both. The
    // third will show up later.
    CountingTimer t1(g_executor.active_timers());
    CountingTimer t2(g_executor.active_timers());
    CountingTimer t3(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(10));
    t2.start(MSEC_TO_NSEC(10) - 1);
    t3.start(MSEC_TO_NSEC(20));
    usleep(5000);
    BlockExecutor b;
    g_executor.add(&b);
    b.wait_for_blocked();

    EXPECT_EQ(0, t1.count());
    EXPECT_EQ(0, t2.count());
    EXPECT_EQ(0, t3.count());

    usleep(10000);

    EXPECT_EQ(0, t1.count());
    EXPECT_EQ(0, t2.count());
    EXPECT_EQ(0, t3.count());
    b.release_block();
    wait_for_main_executor();
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(1, t2.count());
    EXPECT_EQ(0, t3.count());
    usleep(10000);
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(1, t2.count());
    EXPECT_EQ(1, t3.count());
}

TEST_F(TimerTest, Wakeup)
{
    CountingTimer t1(g_executor.active_timers());
    CountingTimer t2(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(1000));
    t2.start(MSEC_TO_NSEC(30));
    usleep(10000);
    EXPECT_EQ(0, t1.count());
    t1.trigger();
    wait_for_main_executor();
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(0, t2.count());
    usleep(25000);
    EXPECT_EQ(1, t2.count());
}

TEST_F(TimerTest, Restart)
{
    RestartingTimer t1(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(10));
    usleep(5000);
    EXPECT_EQ(0, t1.count());
    usleep(10000);
    EXPECT_EQ(1, t1.count());
    usleep(20000);
    EXPECT_EQ(3, t1.count());
    EXPECT_TRUE(t1.is_active());
    t1.stop();
    t1.trigger();
    wait_for_main_executor();
    EXPECT_FALSE(t1.is_active());
}

TEST_F(TimerTest, NoRestartSkew)
{
    RestartingTimer t1(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(10));
    usleep(55000);
    EXPECT_EQ(5, t1.count());
    // We block the executor for 10 periods. We expect the triggers to have
    // piled up, so when we release the block all the ticks should happen
    // immediately.
    BlockExecutor b;
    g_executor.add(&b);
    b.wait_for_blocked();
    EXPECT_EQ(5, t1.count());
    usleep(100000);

    // All of this happens within a short time, increasing the cound form 5 to
    // 15.
    EXPECT_EQ(5, t1.count());
    b.release_block();
    wait_for_main_executor();
    EXPECT_EQ(15, t1.count());

    usleep(30000);
    EXPECT_EQ(18, t1.count());
    t1.stop();
    t1.trigger();
    wait_for_main_executor();
    EXPECT_FALSE(t1.is_active());
}
<commit_msg>Prolongs timeouts in timer test to reduce flakiness when CPU is loaded at the time of running.<commit_after>#include "utils/test_main.hxx"

#include "executor/Timer.hxx"

using ::testing::ElementsAre;

class TimerTest : public ::testing::Test
{
protected:
    vector<Timer *> active_list(ActiveTimers *timers)
    {
        vector<Timer *> t;
        Timer *current_timer = static_cast<Timer *>(timers->activeTimers_.next);
        while (current_timer)
        {
            t.push_back(current_timer);
            current_timer = static_cast<Timer *>(current_timer->next);
        }
        return t;
    }
};

class CountingTimer : public Timer
{
public:
    CountingTimer(ActiveTimers *parent)
        : Timer(parent)
        , count_(0)
    {
    }

    ///@returns the number of times the timeout method was called.
    int count()
    {
        return count_;
    }

    long long timeout()
    {
        ++count_;
        return NONE;
    }

    bool is_active()
    {

        return isActive_;
    }

    bool is_expired()
    {

        return isExpired_;
    }

private:
    int count_;
};

class RestartingTimer : public CountingTimer
{
public:
    RestartingTimer(ActiveTimers *parent)
        : CountingTimer(parent)
        , stop_(false)
    {
    }

    long long timeout()
    {
        CountingTimer::timeout();
        return stop_ ? NONE : RESTART;
    }

    // Instructs the timer not to restart the period upon wakeup.
    void stop()
    {
        stop_ = true;
    }

private:
    // set to true to not restart the timer.
    bool stop_;
};

TEST(SemTest, TestExpire)
{
    OSSem sem;
    EXPECT_EQ(-1, sem.timedwait(MSEC_TO_NSEC(20)));
    EXPECT_EQ(ETIMEDOUT, errno);
}

TEST_F(TimerTest, TestExpire)
{
    ActiveTimers tim(&g_executor);
    CountingTimer t1(&tim);
    t1.start(MSEC_TO_NSEC(30));
    EXPECT_TRUE(t1.is_active());
    usleep(60000);
    EXPECT_EQ(0, tim.get_next_timeout());
    EXPECT_FALSE(t1.is_active());
    wait_for_main_executor();
}

TEST_F(TimerTest, Simple)
{
    CountingTimer t1(g_executor.active_timers());
    EXPECT_EQ(0, t1.count());
    usleep(40000);
    EXPECT_EQ(0, t1.count());
    EXPECT_FALSE(t1.is_active());
    t1.start(MSEC_TO_NSEC(60));
    EXPECT_TRUE(t1.is_active());
    EXPECT_LT(MSEC_TO_NSEC(40), g_executor.active_timers()->get_next_timeout());
    EXPECT_GT(MSEC_TO_NSEC(80), g_executor.active_timers()->get_next_timeout());
    EXPECT_EQ(0, t1.count());
    usleep(40000);
    wait_for_main_executor();
    EXPECT_EQ(0, t1.count());
    usleep(40000);
    EXPECT_EQ(1, t1.count());
    EXPECT_FALSE(t1.is_active());
    EXPECT_LT(SEC_TO_NSEC(1800),
              g_executor.active_timers()->get_next_timeout());
}

TEST_F(TimerTest, TwoTimers)
{
    CountingTimer t1(g_executor.active_timers());
    CountingTimer t2(g_executor.active_timers());
    EXPECT_EQ(0, t1.count());
    EXPECT_EQ(0, t2.count());
    t1.start(MSEC_TO_NSEC(10));
    EXPECT_THAT(active_list(g_executor.active_timers()), ElementsAre(&t1));
    t2.start(MSEC_TO_NSEC(20));
    EXPECT_THAT(active_list(g_executor.active_timers()), ElementsAre(&t1, &t2));
    EXPECT_TRUE(t1.is_active());
    EXPECT_TRUE(t2.is_active());
    usleep(15000);
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(0, t2.count());
    usleep(7000);
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(1, t2.count());

    // Let's restart one of the timers.
    t2.restart();
    usleep(15000);
    EXPECT_EQ(1, t2.count());
    usleep(7000);
    EXPECT_EQ(2, t2.count());
    wait_for_main_executor();
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(2, t2.count());
}

TEST_F(TimerTest, ExpireTogether)
{
    // In this test we create two timers that will expire roughly at the same
    // time, and a third expiring later. We block the main executor to pile up
    // the two timers. Then release it, which should trigger them both. The
    // third will show up later.
    CountingTimer t1(g_executor.active_timers());
    CountingTimer t2(g_executor.active_timers());
    CountingTimer t3(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(10));
    t2.start(MSEC_TO_NSEC(10) - 1);
    t3.start(MSEC_TO_NSEC(20));
    usleep(5000);
    BlockExecutor b;
    g_executor.add(&b);
    b.wait_for_blocked();

    EXPECT_EQ(0, t1.count());
    EXPECT_EQ(0, t2.count());
    EXPECT_EQ(0, t3.count());

    usleep(10000);

    EXPECT_EQ(0, t1.count());
    EXPECT_EQ(0, t2.count());
    EXPECT_EQ(0, t3.count());
    b.release_block();
    wait_for_main_executor();
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(1, t2.count());
    EXPECT_EQ(0, t3.count());
    usleep(10000);
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(1, t2.count());
    EXPECT_EQ(1, t3.count());
}

TEST_F(TimerTest, Wakeup)
{
    CountingTimer t1(g_executor.active_timers());
    CountingTimer t2(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(1000));
    t2.start(MSEC_TO_NSEC(30));
    usleep(10000);
    EXPECT_EQ(0, t1.count());
    t1.trigger();
    wait_for_main_executor();
    EXPECT_EQ(1, t1.count());
    EXPECT_EQ(0, t2.count());
    usleep(25000);
    EXPECT_EQ(1, t2.count());
}

TEST_F(TimerTest, Restart)
{
    RestartingTimer t1(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(20));
    usleep(10000);
    EXPECT_EQ(0, t1.count());
    usleep(20000);
    EXPECT_EQ(1, t1.count());
    usleep(40000);
    EXPECT_EQ(3, t1.count());
    EXPECT_TRUE(t1.is_active());
    t1.stop();
    t1.trigger();
    wait_for_main_executor();
    EXPECT_FALSE(t1.is_active());
}

TEST_F(TimerTest, NoRestartSkew)
{
    RestartingTimer t1(g_executor.active_timers());
    t1.start(MSEC_TO_NSEC(10));
    usleep(55000);
    EXPECT_EQ(5, t1.count());
    // We block the executor for 10 periods. We expect the triggers to have
    // piled up, so when we release the block all the ticks should happen
    // immediately.
    BlockExecutor b;
    g_executor.add(&b);
    b.wait_for_blocked();
    EXPECT_EQ(5, t1.count());
    usleep(100000);

    // All of this happens within a short time, increasing the cound form 5 to
    // 15.
    EXPECT_EQ(5, t1.count());
    b.release_block();
    wait_for_main_executor();
    EXPECT_EQ(15, t1.count());

    usleep(30000);
    EXPECT_EQ(18, t1.count());
    t1.stop();
    t1.trigger();
    wait_for_main_executor();
    EXPECT_FALSE(t1.is_active());
}
<|endoftext|>


<commit_before><commit_msg>-Werror,-Wunused-const-variable<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ToolPanel.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2005-09-23 11:32:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#include "taskpane/ToolPanel.hxx"

#include "TaskPaneFocusManager.hxx"
#include "taskpane/TitleBar.hxx"
#include "taskpane/TitledControl.hxx"
#include "taskpane/ControlContainer.hxx"
#include "TaskPaneViewShell.hxx"
#include "taskpane/TaskPaneControlFactory.hxx"
#include "AccessibleTaskPane.hxx"

#include "strings.hrc"
#include "sdresid.hxx"

#ifndef _SV_DECOVIEW_HXX
#include <vcl/decoview.hxx>
#endif
#ifndef _SV_MENU_HXX
#include <vcl/menu.hxx>
#endif

namespace sd { namespace toolpanel {

/** Use WB_DIALOGCONTROL as argument for the Control constructor to
    let VCL handle focus traveling.  In addition the control
    descriptors have to use WB_TABSTOP.
*/
ToolPanel::ToolPanel (
    Window* pParentWindow,
    TaskPaneViewShell& rViewShell)
    : Control (pParentWindow, WB_DIALOGCONTROL),
      mrViewShell(rViewShell),
      TreeNode (NULL),
      mbRearrangeActive(false)
{
    SetBackground (Wallpaper ());
}

ToolPanel::~ToolPanel (void)
{
}

sal_uInt32 ToolPanel::AddControl (
    ::std::auto_ptr<ControlFactory> pControlFactory,
    const String& rTitle,
    ULONG nHelpId)
{
    TitledControl* pTitledControl = new TitledControl (
        this,
        pControlFactory,
        rTitle,
        TitleBar::TBT_CONTROL_TITLE);
    ::std::auto_ptr<TreeNode> pChild (pTitledControl);

    // Get the (grand) parent window which is focus-wise our parent.
    Window* pParent = GetParent();
    if (pParent != NULL)
        pParent = pParent->GetParent();

    FocusManager& rFocusManager (FocusManager::Instance());
    int nControlCount (mpControlContainer->GetControlCount());

    // Add a link up from every control to the parent.  A down link is added
    // only for the first control so that when entering the sub tool panel
    // the focus is set to the first control.
    if (pParent != NULL)
    {
        if (nControlCount == 1)
            rFocusManager.RegisterDownLink(pParent, pChild->GetWindow());
        rFocusManager.RegisterUpLink(pChild->GetWindow(), pParent);
    }

    // Replace the old links for cycling between first and last child by
    // current ones.
    if (nControlCount > 0)
    {
        ::Window* pFirst = mpControlContainer->GetControl(0)->GetWindow();
        ::Window* pLast = mpControlContainer->GetControl(nControlCount-1)->GetWindow();
        rFocusManager.RemoveLinks(pFirst,pLast);
        rFocusManager.RemoveLinks(pLast,pFirst);

        rFocusManager.RegisterLink(pFirst,pChild->GetWindow(), KEY_UP);
        rFocusManager.RegisterLink(pChild->GetWindow(),pFirst, KEY_DOWN);
    }

    pTitledControl->GetWindow()->SetHelpId(nHelpId);

    return mpControlContainer->AddControl (pChild);
}

void ToolPanel::ListHasChanged (void)
{
    mpControlContainer->ListHasChanged ();
    Rearrange ();
}

void ToolPanel::Resize (void)
{
    Control::Resize();
    Rearrange ();
}

void ToolPanel::RequestResize (void)
{
    Invalidate();
    Rearrange ();
}

/** Subtract the space for the title bars from the available space and
    give the remaining space to the active control.
*/
void ToolPanel::Rearrange (void)
{
    // Prevent recursive calls.
    if ( ! mbRearrangeActive && mpControlContainer->GetVisibleControlCount()>0)
    {
        mbRearrangeActive = true;

        SetBackground (Wallpaper ());

        // Make the area that is covered by the children a little bit
        // smaller so that a frame is visible arround them.
        Rectangle aAvailableArea (Point(0,0), GetOutputSizePixel());

        int nWidth = aAvailableArea.GetWidth();
        sal_uInt32 nControlCount (mpControlContainer->GetControlCount());
        sal_uInt32 nActiveControlIndex (
            mpControlContainer->GetActiveControlIndex());

        // Place title bars of controls above the active control and thereby
        // determine the top of the active control.
        sal_uInt32 nIndex;
        for (nIndex=mpControlContainer->GetFirstIndex();
             nIndex<nActiveControlIndex;
             nIndex=mpControlContainer->GetNextIndex(nIndex))
        {
            TreeNode* pChild = mpControlContainer->GetControl(nIndex);
            if (pChild != NULL)
            {
                sal_uInt32 nHeight = pChild->GetPreferredHeight (nWidth);
                pChild->GetWindow()->SetPosSizePixel (
                    aAvailableArea.TopLeft(),
                    Size(nWidth, nHeight));
                aAvailableArea.Top() += nHeight;
            }
        }

        // Place title bars of controls below the active control and thereby
        // determine the bottom of the active control.
        for (nIndex=mpControlContainer->GetLastIndex();
             nIndex<nControlCount && nIndex!=nActiveControlIndex;
             nIndex=mpControlContainer->GetPreviousIndex(nIndex))
        {
            TreeNode* pChild = mpControlContainer->GetControl(nIndex);
            if (pChild != NULL)
            {
                sal_uInt32 nHeight = pChild->GetPreferredHeight (nWidth);
                pChild->GetWindow()->SetPosSizePixel (
                    Point(aAvailableArea.Left(),
                        aAvailableArea.Bottom()-nHeight+1),
                        Size(nWidth, nHeight));
                aAvailableArea.Bottom() -= nHeight;
            }
        }

        // Finally place the active control.
        TreeNode* pChild = mpControlContainer->GetControl(nActiveControlIndex);
        if (pChild != NULL)
            pChild->GetWindow()->SetPosSizePixel (
                aAvailableArea.TopLeft(),
                aAvailableArea.GetSize());

        mbRearrangeActive = false;
    }
    else
        SetBackground (
            Application::GetSettings().GetStyleSettings().GetDialogColor());
}

Size ToolPanel::GetPreferredSize (void)
{
    return Size(300,300);
}

sal_Int32 ToolPanel::GetPreferredWidth (sal_Int32 nHeight)
{
    return 300;
}

sal_Int32 ToolPanel::GetPreferredHeight (sal_Int32 nWidth)
{
    return 300;
}

bool ToolPanel::IsResizable (void)
{
    return true;
}

::Window* ToolPanel::GetWindow (void)
{
    return this;
}

TaskPaneShellManager* ToolPanel::GetShellManager (void)
{
    return &mrViewShell.GetSubShellManager();
}

::com::sun::star::uno::Reference<
    ::com::sun::star::accessibility::XAccessible> ToolPanel::CreateAccessibleObject (
        const ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible>& rxParent)
{
    return new ::accessibility::AccessibleTaskPane (
        rxParent,
        String(SdResId(STR_RIGHT_PANE_TITLE)),
        String(SdResId(STR_RIGHT_PANE_TITLE)),
        *this);
}

} } // end of namespace ::sd::toolpanel
<commit_msg>INTEGRATION: CWS pchfix02 (1.9.272); FILE MERGED 2006/09/01 17:37:24 kaib 1.9.272.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ToolPanel.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 19:16:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "taskpane/ToolPanel.hxx"

#include "TaskPaneFocusManager.hxx"
#include "taskpane/TitleBar.hxx"
#include "taskpane/TitledControl.hxx"
#include "taskpane/ControlContainer.hxx"
#include "TaskPaneViewShell.hxx"
#include "taskpane/TaskPaneControlFactory.hxx"
#include "AccessibleTaskPane.hxx"

#include "strings.hrc"
#include "sdresid.hxx"

#ifndef _SV_DECOVIEW_HXX
#include <vcl/decoview.hxx>
#endif
#ifndef _SV_MENU_HXX
#include <vcl/menu.hxx>
#endif

namespace sd { namespace toolpanel {

/** Use WB_DIALOGCONTROL as argument for the Control constructor to
    let VCL handle focus traveling.  In addition the control
    descriptors have to use WB_TABSTOP.
*/
ToolPanel::ToolPanel (
    Window* pParentWindow,
    TaskPaneViewShell& rViewShell)
    : Control (pParentWindow, WB_DIALOGCONTROL),
      mrViewShell(rViewShell),
      TreeNode (NULL),
      mbRearrangeActive(false)
{
    SetBackground (Wallpaper ());
}

ToolPanel::~ToolPanel (void)
{
}

sal_uInt32 ToolPanel::AddControl (
    ::std::auto_ptr<ControlFactory> pControlFactory,
    const String& rTitle,
    ULONG nHelpId)
{
    TitledControl* pTitledControl = new TitledControl (
        this,
        pControlFactory,
        rTitle,
        TitleBar::TBT_CONTROL_TITLE);
    ::std::auto_ptr<TreeNode> pChild (pTitledControl);

    // Get the (grand) parent window which is focus-wise our parent.
    Window* pParent = GetParent();
    if (pParent != NULL)
        pParent = pParent->GetParent();

    FocusManager& rFocusManager (FocusManager::Instance());
    int nControlCount (mpControlContainer->GetControlCount());

    // Add a link up from every control to the parent.  A down link is added
    // only for the first control so that when entering the sub tool panel
    // the focus is set to the first control.
    if (pParent != NULL)
    {
        if (nControlCount == 1)
            rFocusManager.RegisterDownLink(pParent, pChild->GetWindow());
        rFocusManager.RegisterUpLink(pChild->GetWindow(), pParent);
    }

    // Replace the old links for cycling between first and last child by
    // current ones.
    if (nControlCount > 0)
    {
        ::Window* pFirst = mpControlContainer->GetControl(0)->GetWindow();
        ::Window* pLast = mpControlContainer->GetControl(nControlCount-1)->GetWindow();
        rFocusManager.RemoveLinks(pFirst,pLast);
        rFocusManager.RemoveLinks(pLast,pFirst);

        rFocusManager.RegisterLink(pFirst,pChild->GetWindow(), KEY_UP);
        rFocusManager.RegisterLink(pChild->GetWindow(),pFirst, KEY_DOWN);
    }

    pTitledControl->GetWindow()->SetHelpId(nHelpId);

    return mpControlContainer->AddControl (pChild);
}

void ToolPanel::ListHasChanged (void)
{
    mpControlContainer->ListHasChanged ();
    Rearrange ();
}

void ToolPanel::Resize (void)
{
    Control::Resize();
    Rearrange ();
}

void ToolPanel::RequestResize (void)
{
    Invalidate();
    Rearrange ();
}

/** Subtract the space for the title bars from the available space and
    give the remaining space to the active control.
*/
void ToolPanel::Rearrange (void)
{
    // Prevent recursive calls.
    if ( ! mbRearrangeActive && mpControlContainer->GetVisibleControlCount()>0)
    {
        mbRearrangeActive = true;

        SetBackground (Wallpaper ());

        // Make the area that is covered by the children a little bit
        // smaller so that a frame is visible arround them.
        Rectangle aAvailableArea (Point(0,0), GetOutputSizePixel());

        int nWidth = aAvailableArea.GetWidth();
        sal_uInt32 nControlCount (mpControlContainer->GetControlCount());
        sal_uInt32 nActiveControlIndex (
            mpControlContainer->GetActiveControlIndex());

        // Place title bars of controls above the active control and thereby
        // determine the top of the active control.
        sal_uInt32 nIndex;
        for (nIndex=mpControlContainer->GetFirstIndex();
             nIndex<nActiveControlIndex;
             nIndex=mpControlContainer->GetNextIndex(nIndex))
        {
            TreeNode* pChild = mpControlContainer->GetControl(nIndex);
            if (pChild != NULL)
            {
                sal_uInt32 nHeight = pChild->GetPreferredHeight (nWidth);
                pChild->GetWindow()->SetPosSizePixel (
                    aAvailableArea.TopLeft(),
                    Size(nWidth, nHeight));
                aAvailableArea.Top() += nHeight;
            }
        }

        // Place title bars of controls below the active control and thereby
        // determine the bottom of the active control.
        for (nIndex=mpControlContainer->GetLastIndex();
             nIndex<nControlCount && nIndex!=nActiveControlIndex;
             nIndex=mpControlContainer->GetPreviousIndex(nIndex))
        {
            TreeNode* pChild = mpControlContainer->GetControl(nIndex);
            if (pChild != NULL)
            {
                sal_uInt32 nHeight = pChild->GetPreferredHeight (nWidth);
                pChild->GetWindow()->SetPosSizePixel (
                    Point(aAvailableArea.Left(),
                        aAvailableArea.Bottom()-nHeight+1),
                        Size(nWidth, nHeight));
                aAvailableArea.Bottom() -= nHeight;
            }
        }

        // Finally place the active control.
        TreeNode* pChild = mpControlContainer->GetControl(nActiveControlIndex);
        if (pChild != NULL)
            pChild->GetWindow()->SetPosSizePixel (
                aAvailableArea.TopLeft(),
                aAvailableArea.GetSize());

        mbRearrangeActive = false;
    }
    else
        SetBackground (
            Application::GetSettings().GetStyleSettings().GetDialogColor());
}

Size ToolPanel::GetPreferredSize (void)
{
    return Size(300,300);
}

sal_Int32 ToolPanel::GetPreferredWidth (sal_Int32 nHeight)
{
    return 300;
}

sal_Int32 ToolPanel::GetPreferredHeight (sal_Int32 nWidth)
{
    return 300;
}

bool ToolPanel::IsResizable (void)
{
    return true;
}

::Window* ToolPanel::GetWindow (void)
{
    return this;
}

TaskPaneShellManager* ToolPanel::GetShellManager (void)
{
    return &mrViewShell.GetSubShellManager();
}

::com::sun::star::uno::Reference<
    ::com::sun::star::accessibility::XAccessible> ToolPanel::CreateAccessibleObject (
        const ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible>& rxParent)
{
    return new ::accessibility::AccessibleTaskPane (
        rxParent,
        String(SdResId(STR_RIGHT_PANE_TITLE)),
        String(SdResId(STR_RIGHT_PANE_TITLE)),
        *this);
}

} } // end of namespace ::sd::toolpanel
<|endoftext|>