<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.9  2003/10/02 19:20:42  peiyongz
 * fWhiteSpace moved to DatatypeValidator
 *
 * Revision 1.8  2003/10/01 01:09:35  knoaman
 * Refactoring of some code to improve performance.
 *
 * Revision 1.7  2003/09/30 21:31:37  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.6  2003/09/29 21:47:35  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.5  2003/05/15 18:53:27  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.4  2002/12/18 14:17:55  gareth
 * Fix to bug #13438. When you eant a vector that calls delete[] on its members you should use RefArrayVectorOf.
 *
 * Revision 1.3  2002/11/04 14:53:28  tng
 * C++ Namespace Support.
 *
 * Revision 1.2  2002/09/24 19:44:40  tng
 * Performance: use XMLString::equals instead of XMLString::compareString
 *
 * Revision 1.1.1.1  2002/02/01 22:22:42  peiyongz
 * sane_include
 *
 * Revision 1.17  2001/10/09 20:54:35  peiyongz
 * init(): take 1 arg.
 *
 * Revision 1.16  2001/09/27 13:51:25  peiyongz
 * DTV Reorganization: ctor/init created to be used by derived class
 *
 * Revision 1.15  2001/09/25 15:58:14  peiyongz
 * Check baseValidator in assignAdditinoalFacet() and inheritAdditionalFacet()
 *
 * Revision 1.14  2001/09/24 15:31:13  peiyongz
 * DTV Reorganization: inherit from AbstractStringValidator
 *
 * Revision 1.12  2001/08/21 18:42:53  peiyongz
 * Bugzilla# 2816: cleanUp() declared with external linkage and called
 *                          before defined as inline
 *
 * Revision 1.11  2001/06/20 17:56:09  peiyongz
 * support for "fixed" option on constrainning facets
 *
 * Revision 1.10  2001/05/29 19:49:36  tng
 * Schema: Constraint Checking Fix in datatypeValidators.  By Pei Yong Zhang.
 *
 * Revision 1.9  2001/05/28 21:11:18  tng
 * Schema: Various DatatypeValidator fix.  By Pei Yong Zhang
 *
 * Revision 1.8  2001/05/23 16:05:11  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.7  2001/05/23 15:45:25  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.6  2001/05/18 13:36:48  tng
 * Schema: Catch RegularExpression exception and NumberFormatException
 *
 * Revision 1.5  2001/05/18 13:23:51  tng
 * Schema: Exception messages in DatatypeValidator.  By Pei Yong Zhang.
 *
 * Revision 1.4  2001/05/16 14:33:40  tng
 * Schema Constraint checking fix.
 *
 * Revision 1.3  2001/05/11 17:17:28  tng
 * Schema: DatatypeValidator fixes.  By Pei Yong Zhang.
 *
 * Revision 1.2  2001/05/11 13:27:29  tng
 * Copyright update.
 *
 * Revision 1.1  2001/05/09 18:43:42  tng
 * Add StringDatatypeValidator and BooleanDatatypeValidator.  By Pei Yong Zhang.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/datatype/StringDatatypeValidator.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>

XERCES_CPP_NAMESPACE_BEGIN

static const int BUF_LEN = 64;
static XMLCh value1[BUF_LEN+1];
static XMLCh value2[BUF_LEN+1];

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
StringDatatypeValidator::StringDatatypeValidator(MemoryManager* const manager)
:AbstractStringValidator(0, 0, 0, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , RefArrayVectorOf<XMLCh>*      const enums
                        , const int                           finalSet
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    init(enums);
}

StringDatatypeValidator::~StringDatatypeValidator()
{}

DatatypeValidator* StringDatatypeValidator::newInstance
(
      RefHashTableOf<KVStringPair>* const facets
    , RefArrayVectorOf<XMLCh>* const      enums
    , const int                           finalSet
    , MemoryManager* const                manager
)
{
    return (DatatypeValidator*) new (manager) StringDatatypeValidator(this, facets, enums, finalSet, manager);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , const int                           finalSet
                        , const ValidatorType                 type
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, type, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    // do not invoke init() here!!!
}

// ---------------------------------------------------------------------------
//  Utilities
// ---------------------------------------------------------------------------
void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
                                                  , const XMLCh* const value)
{
    if (XMLString::equals(key, SchemaSymbols::fgELT_WHITESPACE))
    {
        // whiteSpace = preserve | replace | collapse
        if (XMLString::equals(value, SchemaSymbols::fgWS_PRESERVE))
            setWhiteSpace(DatatypeValidator::PRESERVE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_REPLACE))
            setWhiteSpace(DatatypeValidator::REPLACE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_COLLAPSE))
            setWhiteSpace(DatatypeValidator::COLLAPSE);
        else
            ThrowXML1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value);
        //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'.");

        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
    else
    {
        ThrowXML1(InvalidDatatypeFacetException
                , XMLExcepts::FACET_Invalid_Tag
                , key);
    }
}

void StringDatatypeValidator::inheritAdditionalFacet()
{
    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    // inherit whitespace
    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
        ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0))
    {
        setWhiteSpace(getBaseValidator()->getWSFacet());
        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
}

void StringDatatypeValidator::checkAdditionalFacetConstraints() const
{

    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    short    thisWSFacet = getWSFacet();
    short    baseWSFacet = pBaseValidator->getWSFacet();

    // check 4.3.6.c1 error: whitespace
    if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) &&
        ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ))
    {
        if ((baseWSFacet == DatatypeValidator::COLLAPSE) &&
            ((thisWSFacet == DatatypeValidator::PRESERVE) ||
             (thisWSFacet == DatatypeValidator::REPLACE)))
             ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse);

        if ((baseWSFacet == DatatypeValidator::REPLACE) &&
            (thisWSFacet == DatatypeValidator::PRESERVE))
            ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace);

        if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
            ( thisWSFacet != baseWSFacet))
        {
            ThrowXML2(InvalidDatatypeFacetException
                        , XMLExcepts::FACET_whitespace_base_fixed
                        , getWSstring(thisWSFacet)
                        , getWSstring(baseWSFacet));
        }
    }

}

void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content) const
{
    //
    // check WhiteSpace
    //
    if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )
    {
        if ( getWSFacet() == DatatypeValidator::REPLACE )
        {
            if (!XMLString::isWSReplaced(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content);
        }
        else if ( getWSFacet() == DatatypeValidator::COLLAPSE )
        {
            if (!XMLString::isWSCollapsed(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content);
        }

    }
}

void StringDatatypeValidator::checkValueSpace(const XMLCh* const content)
{}

int StringDatatypeValidator::getLength(const XMLCh* const content) const
{
    return XMLString::stringLen(content);
}

/***
 * Support for Serialization/De-serialization
 ***/

IMPL_XSERIALIZABLE_TOCREATE(StringDatatypeValidator)

void StringDatatypeValidator::serialize(XSerializeEngine& serEng)
{
    AbstractStringValidator::serialize(serEng);
}

XERCES_CPP_NAMESPACE_END

/**
  * End of file StringDatatypeValidator.cpp
  */
<commit_msg>remove unused statics<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.10  2003/11/24 05:11:06  neilg
 * remove unused statics
 *
 * Revision 1.9  2003/10/02 19:20:42  peiyongz
 * fWhiteSpace moved to DatatypeValidator
 *
 * Revision 1.8  2003/10/01 01:09:35  knoaman
 * Refactoring of some code to improve performance.
 *
 * Revision 1.7  2003/09/30 21:31:37  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.6  2003/09/29 21:47:35  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.5  2003/05/15 18:53:27  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.4  2002/12/18 14:17:55  gareth
 * Fix to bug #13438. When you eant a vector that calls delete[] on its members you should use RefArrayVectorOf.
 *
 * Revision 1.3  2002/11/04 14:53:28  tng
 * C++ Namespace Support.
 *
 * Revision 1.2  2002/09/24 19:44:40  tng
 * Performance: use XMLString::equals instead of XMLString::compareString
 *
 * Revision 1.1.1.1  2002/02/01 22:22:42  peiyongz
 * sane_include
 *
 * Revision 1.17  2001/10/09 20:54:35  peiyongz
 * init(): take 1 arg.
 *
 * Revision 1.16  2001/09/27 13:51:25  peiyongz
 * DTV Reorganization: ctor/init created to be used by derived class
 *
 * Revision 1.15  2001/09/25 15:58:14  peiyongz
 * Check baseValidator in assignAdditinoalFacet() and inheritAdditionalFacet()
 *
 * Revision 1.14  2001/09/24 15:31:13  peiyongz
 * DTV Reorganization: inherit from AbstractStringValidator
 *
 * Revision 1.12  2001/08/21 18:42:53  peiyongz
 * Bugzilla# 2816: cleanUp() declared with external linkage and called
 *                          before defined as inline
 *
 * Revision 1.11  2001/06/20 17:56:09  peiyongz
 * support for "fixed" option on constrainning facets
 *
 * Revision 1.10  2001/05/29 19:49:36  tng
 * Schema: Constraint Checking Fix in datatypeValidators.  By Pei Yong Zhang.
 *
 * Revision 1.9  2001/05/28 21:11:18  tng
 * Schema: Various DatatypeValidator fix.  By Pei Yong Zhang
 *
 * Revision 1.8  2001/05/23 16:05:11  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.7  2001/05/23 15:45:25  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.6  2001/05/18 13:36:48  tng
 * Schema: Catch RegularExpression exception and NumberFormatException
 *
 * Revision 1.5  2001/05/18 13:23:51  tng
 * Schema: Exception messages in DatatypeValidator.  By Pei Yong Zhang.
 *
 * Revision 1.4  2001/05/16 14:33:40  tng
 * Schema Constraint checking fix.
 *
 * Revision 1.3  2001/05/11 17:17:28  tng
 * Schema: DatatypeValidator fixes.  By Pei Yong Zhang.
 *
 * Revision 1.2  2001/05/11 13:27:29  tng
 * Copyright update.
 *
 * Revision 1.1  2001/05/09 18:43:42  tng
 * Add StringDatatypeValidator and BooleanDatatypeValidator.  By Pei Yong Zhang.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/datatype/StringDatatypeValidator.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
StringDatatypeValidator::StringDatatypeValidator(MemoryManager* const manager)
:AbstractStringValidator(0, 0, 0, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , RefArrayVectorOf<XMLCh>*      const enums
                        , const int                           finalSet
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    init(enums);
}

StringDatatypeValidator::~StringDatatypeValidator()
{}

DatatypeValidator* StringDatatypeValidator::newInstance
(
      RefHashTableOf<KVStringPair>* const facets
    , RefArrayVectorOf<XMLCh>* const      enums
    , const int                           finalSet
    , MemoryManager* const                manager
)
{
    return (DatatypeValidator*) new (manager) StringDatatypeValidator(this, facets, enums, finalSet, manager);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , const int                           finalSet
                        , const ValidatorType                 type
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, type, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    // do not invoke init() here!!!
}

// ---------------------------------------------------------------------------
//  Utilities
// ---------------------------------------------------------------------------
void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
                                                  , const XMLCh* const value)
{
    if (XMLString::equals(key, SchemaSymbols::fgELT_WHITESPACE))
    {
        // whiteSpace = preserve | replace | collapse
        if (XMLString::equals(value, SchemaSymbols::fgWS_PRESERVE))
            setWhiteSpace(DatatypeValidator::PRESERVE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_REPLACE))
            setWhiteSpace(DatatypeValidator::REPLACE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_COLLAPSE))
            setWhiteSpace(DatatypeValidator::COLLAPSE);
        else
            ThrowXML1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value);
        //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'.");

        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
    else
    {
        ThrowXML1(InvalidDatatypeFacetException
                , XMLExcepts::FACET_Invalid_Tag
                , key);
    }
}

void StringDatatypeValidator::inheritAdditionalFacet()
{
    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    // inherit whitespace
    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
        ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0))
    {
        setWhiteSpace(getBaseValidator()->getWSFacet());
        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
}

void StringDatatypeValidator::checkAdditionalFacetConstraints() const
{

    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    short    thisWSFacet = getWSFacet();
    short    baseWSFacet = pBaseValidator->getWSFacet();

    // check 4.3.6.c1 error: whitespace
    if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) &&
        ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ))
    {
        if ((baseWSFacet == DatatypeValidator::COLLAPSE) &&
            ((thisWSFacet == DatatypeValidator::PRESERVE) ||
             (thisWSFacet == DatatypeValidator::REPLACE)))
             ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse);

        if ((baseWSFacet == DatatypeValidator::REPLACE) &&
            (thisWSFacet == DatatypeValidator::PRESERVE))
            ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace);

        if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
            ( thisWSFacet != baseWSFacet))
        {
            ThrowXML2(InvalidDatatypeFacetException
                        , XMLExcepts::FACET_whitespace_base_fixed
                        , getWSstring(thisWSFacet)
                        , getWSstring(baseWSFacet));
        }
    }

}

void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content) const
{
    //
    // check WhiteSpace
    //
    if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )
    {
        if ( getWSFacet() == DatatypeValidator::REPLACE )
        {
            if (!XMLString::isWSReplaced(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content);
        }
        else if ( getWSFacet() == DatatypeValidator::COLLAPSE )
        {
            if (!XMLString::isWSCollapsed(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content);
        }

    }
}

void StringDatatypeValidator::checkValueSpace(const XMLCh* const content)
{}

int StringDatatypeValidator::getLength(const XMLCh* const content) const
{
    return XMLString::stringLen(content);
}

/***
 * Support for Serialization/De-serialization
 ***/

IMPL_XSERIALIZABLE_TOCREATE(StringDatatypeValidator)

void StringDatatypeValidator::serialize(XSerializeEngine& serEng)
{
    AbstractStringValidator::serialize(serEng);
}

XERCES_CPP_NAMESPACE_END

/**
  * End of file StringDatatypeValidator.cpp
  */
<|endoftext|>


<commit_before>// (C) 2014 Arek Olek

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>

#include <omp.h>

#include "bfs.hpp"
#include "dfs.hpp"
#include "fifodfs.hpp"
#include "fivethree.hpp"
#include "lost.hpp"
#include "rdfs.hpp"
#include "random.hpp"
#include "ilst.hpp"
#include "greedy.hpp"

#include "test_suite.hpp"

#include "debug.hpp"
#include "graph.hpp"
#include "options.hpp"
#include "range.hpp"
#include "timing.hpp"

boost::adjacency_matrix<boost::undirectedS> typedef amatrix;
boost::adjacency_list<boost::hash_setS, boost::vecS, boost::undirectedS> typedef alist;

template<class Graph, class Tree>
std::function<Tree(Graph&)> make_construction(std::string name) {
  if (name == "bfs")
    return bfs_tree<Graph, Tree> ;
  if (name == "dfs")
    return dfs_tree<Graph, Tree> ;
  if (name == "rdfs")
    return rdfs_tree<Graph, Tree> ;
  if (name == "rdfs50")
    return rdfs_best_tree<Graph, Tree> ;
  if (name == "fifo")
    return fifo_dfs_tree<Graph, Tree> ;
  if (name == "random")
    return random_tree<Graph, Tree> ;
  if (name == "wilson")
    return wilson_tree<Graph, Tree> ;
  if (name == "greedy")
    return greedy_tree<Graph, Tree> ;
  if (name == "ilst")
    return ilst<Graph, Tree> ;
  if (name == "5/3")
    return five_three_tree<Graph, Tree> ;
  throw std::invalid_argument("Unknown construction method: " + name);
}

template <class Graph, class Tree, class Suite, class Strings>
void run(Suite& suite, Strings const & constructions, Strings const & improvements) {
  #pragma omp parallel
  {
    auto id = omp_get_thread_num();
    std::stringstream buffer;
    std::string steps;
    double elapsed_c, elapsed_i;
    timing timer;
    #pragma omp for schedule(dynamic) nowait
    for(uint i = 0; i < suite.size(); ++i) {
      auto G = suite.get(i);
      if(!is_connected(G)) continue;

      for(auto cname : constructions) {
        auto construct = make_construction<Graph, Tree>(cname);
        timer.start();
        auto T = construct(G);
        elapsed_c = timer.stop();

        assert(num_edges(T) == num_vertices(T)-1);

        for(auto iname : improvements) {
          auto improve = make_improvement<Graph, Tree>(iname);
          timer.start();
          steps = improve(G, T);
          elapsed_i = timer.stop();

          // run type parameter vertices edges upper construction improvement internal time steps
          buffer
            << i << '\t'
            << id << '\t'
            << suite.type() << '\t'
            << suite.parameter() << '\t'
            << num_vertices(G) << '\t'
            << num_edges(G) << '\t'
            << upper_bound(G) << '\t'
            << cname << '\t'
            << iname << '\t'
            << num_internal(T) << '\t'
            << elapsed_c << '\t'
            << elapsed_i << '\t'
            << steps << '\t'
            << std::endl;
            ;
          //show("graph" + std::to_string(i) + ".dot", G, T);

          elapsed_c += elapsed_i;
        }
      }
    }
    #pragma omp critical
    std::cout << buffer.str();
  }
}

template <class Graph, class Tree, class Sizes, class Params, class Strings>
void run(std::string t, unsigned z, Sizes sizes, Params params,
         Strings const & constructions, Strings const & improvements) {
  if (t.find(".xml") != std::string::npos) {
    real_suite<Graph> suite(t, z);
    run<Graph, Tree>(suite, constructions, improvements);
  } else if (t.find('.') != std::string::npos) {
    file_suite<Graph> suite(t);
    run<Graph, Tree>(suite, constructions, improvements);
  } else {
    for (auto n : sizes) {
      for (auto p : params) {
        test_suite<Graph> suite(t, z, n, p);
        run<Graph, Tree>(suite, constructions, improvements);
      }
    }
  }
}

int main(int argc, char** argv){
  using std::string;
  using std::vector;

  std::ios_base::sync_with_stdio(0);

  options opt(argc, argv);
  auto z = opt.get<int>("-z", 100);
  auto sizes = opt.getList<int>("-n", {100});
  auto tests = opt.getList<string>("-t", {"gnp+path"/*, "rgg"*/});
  auto parameters = opt.getList<float>("-p", {
      0.0001f//, 0.0005f, 0.001f, 0.003f, 0.005f, 0.008f, 0.01f, 0.03f, 0.05f, 0.08f, 0.1f, 0.2f, 0.25f, 0.3f, 0.35f,
      //0.4, 0.45, 0.5, 0.55, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99
  });
  auto constructions = opt.getList<string>("-c", {"bfs", "dfs", "rdfs", "fifo", "rdfs50", "ilst", "random"});
  auto improvements = opt.getList<string>("-i", {"none"/*, "prieto", "lost-light", "lost"*/});

  //~ vector<float> ps {0.0002, 0.0105, 0.021, 0.0312, 0.0415, 0.0518, 0.062, 0.0725, 0.0827};

  //std::cout << "run,type,parameter,vertices,edges,upper,construction,improvement,internal,time,steps" << std::endl;
  for(auto t : tests)
    run<alist, alist>(t, z, sizes, parameters, constructions, improvements);

  return 0;
}
<commit_msg>write results asap<commit_after>// (C) 2014 Arek Olek

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>

#include <omp.h>

#include "bfs.hpp"
#include "dfs.hpp"
#include "fifodfs.hpp"
#include "fivethree.hpp"
#include "lost.hpp"
#include "rdfs.hpp"
#include "random.hpp"
#include "ilst.hpp"
#include "greedy.hpp"

#include "test_suite.hpp"

#include "debug.hpp"
#include "graph.hpp"
#include "options.hpp"
#include "range.hpp"
#include "timing.hpp"

boost::adjacency_matrix<boost::undirectedS> typedef amatrix;
boost::adjacency_list<boost::hash_setS, boost::vecS, boost::undirectedS> typedef alist;

template<class Graph, class Tree>
std::function<Tree(Graph&)> make_construction(std::string name) {
  if (name == "bfs")
    return bfs_tree<Graph, Tree> ;
  if (name == "dfs")
    return dfs_tree<Graph, Tree> ;
  if (name == "rdfs")
    return rdfs_tree<Graph, Tree> ;
  if (name == "rdfs50")
    return rdfs_best_tree<Graph, Tree> ;
  if (name == "fifo")
    return fifo_dfs_tree<Graph, Tree> ;
  if (name == "random")
    return random_tree<Graph, Tree> ;
  if (name == "wilson")
    return wilson_tree<Graph, Tree> ;
  if (name == "greedy")
    return greedy_tree<Graph, Tree> ;
  if (name == "ilst")
    return ilst<Graph, Tree> ;
  if (name == "5/3")
    return five_three_tree<Graph, Tree> ;
  throw std::invalid_argument("Unknown construction method: " + name);
}

template <class Graph, class Tree, class Suite, class Strings>
void run(Suite& suite, Strings const & constructions, Strings const & improvements) {
  #pragma omp parallel
  {
    auto id = omp_get_thread_num();
    std::string steps;
    double elapsed_c, elapsed_i;
    timing timer;
    #pragma omp for schedule(dynamic) nowait
    for(uint i = 0; i < suite.size(); ++i) {
      std::stringstream buffer;
      auto G = suite.get(i);
      if(!is_connected(G)) continue;

      for(auto cname : constructions) {
        auto construct = make_construction<Graph, Tree>(cname);
        timer.start();
        auto T = construct(G);
        elapsed_c = timer.stop();

        assert(num_edges(T) == num_vertices(T)-1);

        for(auto iname : improvements) {
          auto improve = make_improvement<Graph, Tree>(iname);
          timer.start();
          steps = improve(G, T);
          elapsed_i = timer.stop();

          // run type parameter vertices edges upper construction improvement internal time steps
          buffer
            << i << '\t'
            << id << '\t'
            << suite.type() << '\t'
            << suite.parameter() << '\t'
            << num_vertices(G) << '\t'
            << num_edges(G) << '\t'
            << upper_bound(G) << '\t'
            << cname << '\t'
            << iname << '\t'
            << num_internal(T) << '\t'
            << elapsed_c << '\t'
            << elapsed_i << '\t'
            << steps << '\t'
            << std::endl;
            ;
          //show("graph" + std::to_string(i) + ".dot", G, T);

          elapsed_c += elapsed_i;
        }
      }
      #pragma omp critical
      std::cout << buffer.str() << std::flush;
    }
  }
}

template <class Graph, class Tree, class Sizes, class Params, class Strings>
void run(std::string t, unsigned z, Sizes sizes, Params params,
         Strings const & constructions, Strings const & improvements) {
  if (t.find(".xml") != std::string::npos) {
    real_suite<Graph> suite(t, z);
    run<Graph, Tree>(suite, constructions, improvements);
  } else if (t.find('.') != std::string::npos) {
    file_suite<Graph> suite(t);
    run<Graph, Tree>(suite, constructions, improvements);
  } else {
    for (auto n : sizes) {
      for (auto p : params) {
        test_suite<Graph> suite(t, z, n, p);
        run<Graph, Tree>(suite, constructions, improvements);
      }
    }
  }
}

int main(int argc, char** argv){
  using std::string;
  using std::vector;

  std::ios_base::sync_with_stdio(0);

  options opt(argc, argv);
  auto z = opt.get<int>("-z", 100);
  auto sizes = opt.getList<int>("-n", {100});
  auto tests = opt.getList<string>("-t", {"gnp+path"/*, "rgg"*/});
  auto parameters = opt.getList<float>("-p", {
      0.0001f//, 0.0005f, 0.001f, 0.003f, 0.005f, 0.008f, 0.01f, 0.03f, 0.05f, 0.08f, 0.1f, 0.2f, 0.25f, 0.3f, 0.35f,
      //0.4, 0.45, 0.5, 0.55, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99
  });
  auto constructions = opt.getList<string>("-c", {"bfs", "dfs", "rdfs", "fifo", "rdfs50", "ilst", "random"});
  auto improvements = opt.getList<string>("-i", {"none"/*, "prieto", "lost-light", "lost"*/});

  //~ vector<float> ps {0.0002, 0.0105, 0.021, 0.0312, 0.0415, 0.0518, 0.062, 0.0725, 0.0827};

  //std::cout << "run,type,parameter,vertices,edges,upper,construction,improvement,internal,time,steps" << std::endl;
  for(auto t : tests)
    run<alist, alist>(t, z, sizes, parameters, constructions, improvements);

  return 0;
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <algorithm>

#include "mlir-hlo/Analysis/userange_analysis.h"
#include "mlir-hlo/Transforms/PassDetail.h"
#include "mlir-hlo/Transforms/passes.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/Operation.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/BufferUtils.h"

namespace mlir {

namespace {

/// Reuses already allocated buffer to save allocation operations.
class BufferReuse : BufferPlacementTransformationBase {
  using ValueSetMap = llvm::MapVector<Value, DenseSet<Value>>;
  using ValueVectorMap = llvm::MapVector<Value, SmallVector<Value, 4>>;

 public:
  explicit BufferReuse(Operation *op)
      : BufferPlacementTransformationBase(op),
        dominators(op),
        postDominators(op),
        userange(op, allocs, aliases) {}

  /// Reuses already allocated buffers to save allocation operations.
  void reuse(Operation *operation) {
    // Create a list of values that can potentially be replaced for each value
    // in the useRangeMap. The potentialReuseMap maps each value to the
    // respective list.
    ValueVectorMap potentialReuseMap;
    for (BufferPlacementAllocs::AllocEntry entry : allocs) {
      Value itemA = std::get<0>(entry);
      SmallVector<Value, 4> potReuseVector;
      for (BufferPlacementAllocs::AllocEntry entry : allocs) {
        Value itemB = std::get<0>(entry);
        // Do not compare an item to itself and make sure that the value of item
        // B is not a BlockArgument. BlockArguments cannot be reused. Also
        // perform a reuse compatibility check.
        if (itemA == itemB || !checkReuseCompatibility(itemA, itemB)) continue;

        // Check if itemA interferes with itemB. If this is the case no reuse is
        // possible.
        if (userange.rangesInterfere(itemA, itemB)) continue;

        // The defining block of itemA has to dominate all uses of itemB.
        if (!dominatesAllUses(itemA.getParentBlock(), itemB)) continue;

        // Insert itemB into the right place of the potReuseVector. The order of
        // the vector is defined via the program order of the first use of each
        // item.
        auto insertionPoint = potReuseVector.begin();
        while (insertionPoint != potReuseVector.end()) {
          if (userange.getFirstUseIndex(itemB) <
              userange.getFirstUseIndex(*insertionPoint))
            break;
          ++insertionPoint;
        }
        potReuseVector.insert(insertionPoint, itemB);
      }

      potentialReuseMap.insert({itemA, potReuseVector});
    }

    // Replace all uses of the value that is replaced and
    // delete the DefiningOp.
    for (auto &reuse : computeActualReuse(potentialReuseMap)) {
      for (Value reuseValue : reuse.second) {
        reuseValue.replaceAllUsesWith(reuse.first);
        reuseValue.getDefiningOp()->erase();
      }
    }
  }

 private:
  /// Check if all uses of item are dominated by the given block.
  bool dominatesAllUses(Block *block, Value item) {
    for (OpOperand &operand : item.getUses()) {
      if (!dominators.dominates(block, operand.getOwner()->getBlock()))
        return false;
    }
    return true;
  }

  /// Checks if there is a transitive interference between potReuseValue and the
  /// value that may replace it, we call this value V. potReuses is the vector
  /// of all values that can potentially be replaced by V. If potReuseValue
  /// already replaces any other value that is not part of the potReuses vector
  /// it cannot be replaced by V anymore.
  bool transitiveInterference(Value potReuseValue,
                              SmallVector<Value, 4> &potReuses,
                              ValueSetMap &actualReuseMap) {
    auto actualReuser = actualReuseMap.find(potReuseValue);
    return actualReuser != actualReuseMap.end() &&
           llvm::any_of(actualReuser->second, [&](Value vReuse) {
             return std::find(potReuses.begin(), potReuses.end(), vReuse) ==
                    potReuses.end();
           });
  }

  /// Checks if the types of the given values are compatible for a
  /// replacement.
  bool checkReuseCompatibility(Value a, Value b) {
    auto shapedA = a.getType().cast<ShapedType>();
    auto shapedB = b.getType().cast<ShapedType>();

    // If both types are shaped we can check for equality.
    if (shapedA.hasStaticShape() && shapedB.hasStaticShape())
      return a.getType() == b.getType();
    // If only one of the types is shaped we cannot detect compatibility since
    // we do not know how the allocation operation behaves on its operands.
    if (shapedA.hasStaticShape() != shapedB.hasStaticShape()) return false;

    // Compare the element Types of both shapes.
    if (shapedA.getElementType() != shapedB.getElementType()) return false;

    // If the shapes have different ranks, we cannot reuse them.
    if (shapedA.getRank() != shapedB.getRank()) return false;

    // Compare each dimension. If the dimensions are not equal no reuse is
    // possible.
    for (unsigned idx = 0, e = shapedA.getRank(); idx < e; ++idx) {
      if (shapedA.getDimSize(idx) != shapedB.getDimSize(idx)) return false;
    }

    // We need the actual alloc operation of both types. For aliases we need
    // to check for the defining OP of the alias' origin.
    Operation *defOpA = a.getDefiningOp();
    Operation *defOpB = b.getDefiningOp();

    // If the alloc method or the number of operands is not the same the types
    // might not be compatible.
    if (defOpA->getName() != defOpB->getName() ||
        defOpA->getNumOperands() != defOpB->getNumOperands())
      return false;

    // If all operands are equal the types are compatible.
    auto operandsA = defOpA->getOperands();
    auto operandsB = defOpB->getOperands();
    return std::equal(operandsA.begin(), operandsA.end(), operandsB.begin(),
                      operandsB.end());
  }

  /// A Fixpoint iteration over the potential reuses to compute the actual
  /// reuses.
  ValueSetMap computeActualReuse(ValueVectorMap &potentialReuseMap) {
    // The replacedSet contains all values that are going to be replaced.
    DenseSet<Value> replacedSet;

    // The currentReuserSet contains all values that are replacing another
    // value in the current iteration. Note: This is necessary because the
    // replacing property is not transitive.
    DenseSet<Value> currentReuserSet;

    /// Maps a value to the set of values that it replaces.
    ValueSetMap actualReuseMap;

    for (;;) {
      // Clear the currentReuserSet for this iteration.
      currentReuserSet.clear();
      // Step 1 of the fixpoint iteration: Choose a value to be replaced for
      // each value in the potentialReuseMap.
      choosePotentialReuses(replacedSet, currentReuserSet, potentialReuseMap,
                            actualReuseMap);

      // If the currentReuseSet is empty we can terminate the fixpoint
      // iteration.
      if (currentReuserSet.empty()) break;

      // Step 2 of the fixpoint iteration: Update the potentialReuseVectors for
      // each value in the potentialReuseMap. Due to the chosen replacements in
      // step 1 some values might not be replaceable anymore. Also remove all
      // replaced values from the potentialReuseMap.
      updatePotentialReuses(replacedSet, potentialReuseMap, actualReuseMap);
    }
    return actualReuseMap;
  }

  /// For each value in the potentialReuseMap, check if another value tries to
  /// reuse it or if it is already replaced by another value. If neither is the
  /// case add the value and its reuses (if any) to the actualReuseMap.
  void choosePotentialReuses(DenseSet<Value> &replacedSet,
                             DenseSet<Value> &currentReuserSet,
                             ValueVectorMap &potentialReuseMap,
                             ValueSetMap &actualReuseMap) {
    for (auto &potReuser : potentialReuseMap) {
      Value item = potReuser.first;
      SmallVector<Value, 4> &potReuses = potReuser.second;

      // If the current value is replaced already we have to skip it.
      if (replacedSet.contains(item)) continue;

      // Find a value that can be reused. If the value is already in the
      // currentReuserSet then we have to break. Due to the order of the
      // values we must not skip it, because it can potentially be replaced in
      // the next iteration. However, we may skip the value if it is replaced
      // by another value.
      for (Value v : potReuses) {
        if (currentReuserSet.contains(v)) break;
        if (replacedSet.contains(v)) continue;

        // Update the actualReuseMap.
        actualReuseMap[item].insert(v);

        // Check if the replaced value already replaces other values and also
        // add them to the reused set.
        auto alreadyReplaced = actualReuseMap.find(v);
        if (alreadyReplaced != actualReuseMap.end()) {
          actualReuseMap[item].insert(alreadyReplaced->second.begin(),
                                      alreadyReplaced->second.end());
          actualReuseMap.erase(v);
        }

        // Merge the userange of v into the userange of item.
        userange.unionRanges(item, v);

        currentReuserSet.insert(item);
        replacedSet.insert(v);
        break;
      }
    }
  }

  /// Update the potentialReuseVectors for each value in the potentialReuseMap.
  void updatePotentialReuses(DenseSet<Value> &replacedSet,
                             ValueVectorMap &potentialReuseMap,
                             ValueSetMap &actualReuseMap) {
    for (auto itReuseMap = potentialReuseMap.begin();
         itReuseMap != potentialReuseMap.end();) {
      Value item = itReuseMap->first;
      SmallVector<Value, 4> &potReuses = itReuseMap->second;

      // If the item is already reused, we can remove it from the
      // potentialReuseMap.
      if (replacedSet.contains(item)) {
        potentialReuseMap.erase(itReuseMap);
        continue;
      }

      // Remove all potential reuses that cannot be reused for this value.
      potReuses.erase(
          std::remove_if(potReuses.begin(), potReuses.end(),
                         [&](Value potReuseValue) {
                           return replacedSet.contains(potReuseValue) ||
                                  transitiveInterference(potReuseValue,
                                                         potReuses,
                                                         actualReuseMap) ||
                                  userange.rangesInterfere(item, potReuseValue);
                         }),
          potReuses.end());
      ++itReuseMap;
    }
  }

  /// The current dominance info.
  DominanceInfo dominators;

  /// The current postdominance info.
  PostDominanceInfo postDominators;

  /// The current userange info.
  UserangeAnalysis userange;
};

/// The buffer reuse pass that uses already allocated buffers if all critera
/// are met.
struct BufferReusePass : BufferReuseBase<BufferReusePass> {
  void runOnFunction() override {
    // Reuse allocated buffer instead of new allocation.
    Operation *funcOp = getFunction();
    BufferReuse optimizer(funcOp);
    optimizer.reuse(funcOp);
  }
};

}  // end namespace

std::unique_ptr<FunctionPass> createBufferReusePass() {
  return std::make_unique<BufferReusePass>();
}

}  // end namespace mlir
<commit_msg>Apply clang-tidy fixes for llvm-qualified-auto in buffer_reuse.cc (NFC)<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <algorithm>

#include "mlir-hlo/Analysis/userange_analysis.h"
#include "mlir-hlo/Transforms/PassDetail.h"
#include "mlir-hlo/Transforms/passes.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/Operation.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/BufferUtils.h"

namespace mlir {

namespace {

/// Reuses already allocated buffer to save allocation operations.
class BufferReuse : BufferPlacementTransformationBase {
  using ValueSetMap = llvm::MapVector<Value, DenseSet<Value>>;
  using ValueVectorMap = llvm::MapVector<Value, SmallVector<Value, 4>>;

 public:
  explicit BufferReuse(Operation *op)
      : BufferPlacementTransformationBase(op),
        dominators(op),
        postDominators(op),
        userange(op, allocs, aliases) {}

  /// Reuses already allocated buffers to save allocation operations.
  void reuse(Operation *operation) {
    // Create a list of values that can potentially be replaced for each value
    // in the useRangeMap. The potentialReuseMap maps each value to the
    // respective list.
    ValueVectorMap potentialReuseMap;
    for (BufferPlacementAllocs::AllocEntry entry : allocs) {
      Value itemA = std::get<0>(entry);
      SmallVector<Value, 4> potReuseVector;
      for (BufferPlacementAllocs::AllocEntry entry : allocs) {
        Value itemB = std::get<0>(entry);
        // Do not compare an item to itself and make sure that the value of item
        // B is not a BlockArgument. BlockArguments cannot be reused. Also
        // perform a reuse compatibility check.
        if (itemA == itemB || !checkReuseCompatibility(itemA, itemB)) continue;

        // Check if itemA interferes with itemB. If this is the case no reuse is
        // possible.
        if (userange.rangesInterfere(itemA, itemB)) continue;

        // The defining block of itemA has to dominate all uses of itemB.
        if (!dominatesAllUses(itemA.getParentBlock(), itemB)) continue;

        // Insert itemB into the right place of the potReuseVector. The order of
        // the vector is defined via the program order of the first use of each
        // item.
        auto *insertionPoint = potReuseVector.begin();
        while (insertionPoint != potReuseVector.end()) {
          if (userange.getFirstUseIndex(itemB) <
              userange.getFirstUseIndex(*insertionPoint))
            break;
          ++insertionPoint;
        }
        potReuseVector.insert(insertionPoint, itemB);
      }

      potentialReuseMap.insert({itemA, potReuseVector});
    }

    // Replace all uses of the value that is replaced and
    // delete the DefiningOp.
    for (auto &reuse : computeActualReuse(potentialReuseMap)) {
      for (Value reuseValue : reuse.second) {
        reuseValue.replaceAllUsesWith(reuse.first);
        reuseValue.getDefiningOp()->erase();
      }
    }
  }

 private:
  /// Check if all uses of item are dominated by the given block.
  bool dominatesAllUses(Block *block, Value item) {
    for (OpOperand &operand : item.getUses()) {
      if (!dominators.dominates(block, operand.getOwner()->getBlock()))
        return false;
    }
    return true;
  }

  /// Checks if there is a transitive interference between potReuseValue and the
  /// value that may replace it, we call this value V. potReuses is the vector
  /// of all values that can potentially be replaced by V. If potReuseValue
  /// already replaces any other value that is not part of the potReuses vector
  /// it cannot be replaced by V anymore.
  bool transitiveInterference(Value potReuseValue,
                              SmallVector<Value, 4> &potReuses,
                              ValueSetMap &actualReuseMap) {
    auto actualReuser = actualReuseMap.find(potReuseValue);
    return actualReuser != actualReuseMap.end() &&
           llvm::any_of(actualReuser->second, [&](Value vReuse) {
             return std::find(potReuses.begin(), potReuses.end(), vReuse) ==
                    potReuses.end();
           });
  }

  /// Checks if the types of the given values are compatible for a
  /// replacement.
  bool checkReuseCompatibility(Value a, Value b) {
    auto shapedA = a.getType().cast<ShapedType>();
    auto shapedB = b.getType().cast<ShapedType>();

    // If both types are shaped we can check for equality.
    if (shapedA.hasStaticShape() && shapedB.hasStaticShape())
      return a.getType() == b.getType();
    // If only one of the types is shaped we cannot detect compatibility since
    // we do not know how the allocation operation behaves on its operands.
    if (shapedA.hasStaticShape() != shapedB.hasStaticShape()) return false;

    // Compare the element Types of both shapes.
    if (shapedA.getElementType() != shapedB.getElementType()) return false;

    // If the shapes have different ranks, we cannot reuse them.
    if (shapedA.getRank() != shapedB.getRank()) return false;

    // Compare each dimension. If the dimensions are not equal no reuse is
    // possible.
    for (unsigned idx = 0, e = shapedA.getRank(); idx < e; ++idx) {
      if (shapedA.getDimSize(idx) != shapedB.getDimSize(idx)) return false;
    }

    // We need the actual alloc operation of both types. For aliases we need
    // to check for the defining OP of the alias' origin.
    Operation *defOpA = a.getDefiningOp();
    Operation *defOpB = b.getDefiningOp();

    // If the alloc method or the number of operands is not the same the types
    // might not be compatible.
    if (defOpA->getName() != defOpB->getName() ||
        defOpA->getNumOperands() != defOpB->getNumOperands())
      return false;

    // If all operands are equal the types are compatible.
    auto operandsA = defOpA->getOperands();
    auto operandsB = defOpB->getOperands();
    return std::equal(operandsA.begin(), operandsA.end(), operandsB.begin(),
                      operandsB.end());
  }

  /// A Fixpoint iteration over the potential reuses to compute the actual
  /// reuses.
  ValueSetMap computeActualReuse(ValueVectorMap &potentialReuseMap) {
    // The replacedSet contains all values that are going to be replaced.
    DenseSet<Value> replacedSet;

    // The currentReuserSet contains all values that are replacing another
    // value in the current iteration. Note: This is necessary because the
    // replacing property is not transitive.
    DenseSet<Value> currentReuserSet;

    /// Maps a value to the set of values that it replaces.
    ValueSetMap actualReuseMap;

    for (;;) {
      // Clear the currentReuserSet for this iteration.
      currentReuserSet.clear();
      // Step 1 of the fixpoint iteration: Choose a value to be replaced for
      // each value in the potentialReuseMap.
      choosePotentialReuses(replacedSet, currentReuserSet, potentialReuseMap,
                            actualReuseMap);

      // If the currentReuseSet is empty we can terminate the fixpoint
      // iteration.
      if (currentReuserSet.empty()) break;

      // Step 2 of the fixpoint iteration: Update the potentialReuseVectors for
      // each value in the potentialReuseMap. Due to the chosen replacements in
      // step 1 some values might not be replaceable anymore. Also remove all
      // replaced values from the potentialReuseMap.
      updatePotentialReuses(replacedSet, potentialReuseMap, actualReuseMap);
    }
    return actualReuseMap;
  }

  /// For each value in the potentialReuseMap, check if another value tries to
  /// reuse it or if it is already replaced by another value. If neither is the
  /// case add the value and its reuses (if any) to the actualReuseMap.
  void choosePotentialReuses(DenseSet<Value> &replacedSet,
                             DenseSet<Value> &currentReuserSet,
                             ValueVectorMap &potentialReuseMap,
                             ValueSetMap &actualReuseMap) {
    for (auto &potReuser : potentialReuseMap) {
      Value item = potReuser.first;
      SmallVector<Value, 4> &potReuses = potReuser.second;

      // If the current value is replaced already we have to skip it.
      if (replacedSet.contains(item)) continue;

      // Find a value that can be reused. If the value is already in the
      // currentReuserSet then we have to break. Due to the order of the
      // values we must not skip it, because it can potentially be replaced in
      // the next iteration. However, we may skip the value if it is replaced
      // by another value.
      for (Value v : potReuses) {
        if (currentReuserSet.contains(v)) break;
        if (replacedSet.contains(v)) continue;

        // Update the actualReuseMap.
        actualReuseMap[item].insert(v);

        // Check if the replaced value already replaces other values and also
        // add them to the reused set.
        auto alreadyReplaced = actualReuseMap.find(v);
        if (alreadyReplaced != actualReuseMap.end()) {
          actualReuseMap[item].insert(alreadyReplaced->second.begin(),
                                      alreadyReplaced->second.end());
          actualReuseMap.erase(v);
        }

        // Merge the userange of v into the userange of item.
        userange.unionRanges(item, v);

        currentReuserSet.insert(item);
        replacedSet.insert(v);
        break;
      }
    }
  }

  /// Update the potentialReuseVectors for each value in the potentialReuseMap.
  void updatePotentialReuses(DenseSet<Value> &replacedSet,
                             ValueVectorMap &potentialReuseMap,
                             ValueSetMap &actualReuseMap) {
    for (auto itReuseMap = potentialReuseMap.begin();
         itReuseMap != potentialReuseMap.end();) {
      Value item = itReuseMap->first;
      SmallVector<Value, 4> &potReuses = itReuseMap->second;

      // If the item is already reused, we can remove it from the
      // potentialReuseMap.
      if (replacedSet.contains(item)) {
        potentialReuseMap.erase(itReuseMap);
        continue;
      }

      // Remove all potential reuses that cannot be reused for this value.
      potReuses.erase(
          std::remove_if(potReuses.begin(), potReuses.end(),
                         [&](Value potReuseValue) {
                           return replacedSet.contains(potReuseValue) ||
                                  transitiveInterference(potReuseValue,
                                                         potReuses,
                                                         actualReuseMap) ||
                                  userange.rangesInterfere(item, potReuseValue);
                         }),
          potReuses.end());
      ++itReuseMap;
    }
  }

  /// The current dominance info.
  DominanceInfo dominators;

  /// The current postdominance info.
  PostDominanceInfo postDominators;

  /// The current userange info.
  UserangeAnalysis userange;
};

/// The buffer reuse pass that uses already allocated buffers if all critera
/// are met.
struct BufferReusePass : BufferReuseBase<BufferReusePass> {
  void runOnFunction() override {
    // Reuse allocated buffer instead of new allocation.
    Operation *funcOp = getFunction();
    BufferReuse optimizer(funcOp);
    optimizer.reuse(funcOp);
  }
};

}  // end namespace

std::unique_ptr<FunctionPass> createBufferReusePass() {
  return std::make_unique<BufferReusePass>();
}

}  // end namespace mlir
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s

// Various tests related to partial ordering of variadic templates.
template<typename ...Types> struct tuple;

template<typename Tuple>
struct X1 {
  static const unsigned value = 0;
};

template<typename Head, typename ...Tail>
struct X1<tuple<Head, Tail...> > {
  static const unsigned value = 1;
};

template<typename Head, typename ...Tail>
struct X1<tuple<Head, Tail&...> > {
  static const unsigned value = 2;
};

template<typename Head, typename ...Tail>
struct X1<tuple<Head&, Tail&...> > {
  static const unsigned value = 3;
};

int check0[X1<tuple<>>::value == 0? 1 : -1];
int check1[X1<tuple<int>>::value == 2? 1 : -1];
int check2[X1<tuple<int, int>>::value == 1? 1 : -1];
int check3[X1<tuple<int, int&>>::value == 2? 1 : -1];
int check4[X1<tuple<int&, int&>>::value == 3? 1 : -1];
<commit_msg>Add some more partial-ordering tests, including one that changes with the proposed resolution to core isue 692. I'm not certain which way we'll go on this one.<commit_after>// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s

// Various tests related to partial ordering of variadic templates.
template<typename ...Types> struct tuple;

template<typename Tuple>
struct X1 {
  static const unsigned value = 0;
};

template<typename Head, typename ...Tail>
struct X1<tuple<Head, Tail...> > {
  static const unsigned value = 1;
};

template<typename Head, typename ...Tail>
struct X1<tuple<Head, Tail&...> > {
  static const unsigned value = 2;
};

template<typename Head, typename ...Tail>
struct X1<tuple<Head&, Tail&...> > {
  static const unsigned value = 3;
};

int check0[X1<tuple<>>::value == 0? 1 : -1];
int check1[X1<tuple<int>>::value == 2? 1 : -1];
int check2[X1<tuple<int, int>>::value == 1? 1 : -1];
int check3[X1<tuple<int, int&>>::value == 2? 1 : -1];
int check4[X1<tuple<int&, int&>>::value == 3? 1 : -1];

// Partial ordering of function templates.
template<typename T1, typename T2, typename ...Rest>
int &f0(T1, T2, Rest...); // expected-note{{candidate function [with T1 = int, T2 = double, Rest = <>]}}

template<typename T1, typename T2>
float &f0(T1, T2); // expected-note{{candidate function [with T1 = int, T2 = double]}}

// FIXME: this is currently ambiguous, based on the proposed resolution
// to core issue 692.
void test_f0() {
  int &ir1 = f0(1, 2.0, 'a');
  float &fr1 = f0(1, 2.0); // expected-error{{call to 'f0' is ambiguous}}
}

template<typename T1, typename T2, typename ...Rest>
int &f1(T1, T2, Rest...);

template<typename T1, typename T2>
float &f1(T1, T2, ...);

void test_f1() {
  int &ir1 = f1(1, 2.0, 'a');
}

template<typename T1, typename T2, typename ...Rest>
int &f2(T1, T2, Rest...);

float &f2(...);

void test_f2() {
  int &ir1 = f2(1, 2.0, 'a');
}
<|endoftext|>


<commit_before>#ifndef UTIL_POINT_H__
#define UTIL_POINT_H__

#include <sstream>
#include <iostream>

namespace util {

template <typename T>
struct point {

	point() {};

	template <typename S>
	point(const S& x_, const S& y_) :
		x(x_),
		y(y_) {}

	template <typename S>
	point(const point<S>& other) :
		x(other.x),
		y(other.y) {}

	T x;
	T y;

	template <typename S>
	point<T>& operator+=(const point<S>& other) {

		x += other.x;
		y += other.y;

		return *this;
	}

	template <typename S>
	point<T>& operator-=(const point<S>& other) {

		x -= other.x;
		y -= other.y;

		return *this;
	}

	point<T> operator-() const {

		return point<T>(-x, -y);
	}

	template <typename S>
	point<T>& operator*=(const S& s) {

		x *= s;
		y *= s;

		return *this;
	}

	template <typename S>
	point<T>& operator/=(const S& s) {

		x /= s;
		y /= s;

		return *this;
	}

	template <typename S>
	point<T>& operator*=(const point<S>& p) {

		x *= p.x;
		y *= p.y;

		return *this;
	}

	template <typename S>
	point<T>& operator/=(const point<S>& p) {

		x /= p.x;
		y /= p.y;

		return *this;
	}

	bool operator==(const point<T>& other) const {

		return x == other.x && y == other.y;
	}

	bool operator!=(const point<T>& other) const {

		return !(*this == other);
	}
};

} // namespace util

template <typename T, typename S>
util::point<T> operator+(const util::point<T>& p, const util::point<S>& o) {

	util::point<T> result(p);

	return result += o;
}

template <typename T, typename S>
util::point<T> operator-(const util::point<T>& p, const util::point<S>& o) {

	util::point<T> result(p);

	return result -= o;
}

template <typename T, typename S>
util::point<T> operator*(const util::point<T>& p, const S& s) {

	util::point<T> result(p);

	return result *= s;
}

template <typename T>
util::point<T> operator*(const T& s, const util::point<T>& p) {

	util::point<T> result(p);

	return result *= s;
}

template <typename T, typename S>
util::point<T> operator/(const util::point<T>& p, const S& s) {

	util::point<T> result(p);

	return result /= s;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const util::point<T>& point) {

	os << "(" << point.x << ", " << point.y << ")";

	return os;
}

#endif // UTIL_POINT_H__

<commit_msg>moved operator<< for point to namespace util (clang wants it this way)<commit_after>#ifndef UTIL_POINT_H__
#define UTIL_POINT_H__

#include <sstream>
#include <iostream>

namespace util {

template <typename T>
struct point {

	point() {};

	template <typename S>
	point(const S& x_, const S& y_) :
		x(x_),
		y(y_) {}

	template <typename S>
	point(const point<S>& other) :
		x(other.x),
		y(other.y) {}

	T x;
	T y;

	template <typename S>
	point<T>& operator+=(const point<S>& other) {

		x += other.x;
		y += other.y;

		return *this;
	}

	template <typename S>
	point<T>& operator-=(const point<S>& other) {

		x -= other.x;
		y -= other.y;

		return *this;
	}

	point<T> operator-() const {

		return point<T>(-x, -y);
	}

	template <typename S>
	point<T>& operator*=(const S& s) {

		x *= s;
		y *= s;

		return *this;
	}

	template <typename S>
	point<T>& operator/=(const S& s) {

		x /= s;
		y /= s;

		return *this;
	}

	template <typename S>
	point<T>& operator*=(const point<S>& p) {

		x *= p.x;
		y *= p.y;

		return *this;
	}

	template <typename S>
	point<T>& operator/=(const point<S>& p) {

		x /= p.x;
		y /= p.y;

		return *this;
	}

	bool operator==(const point<T>& other) const {

		return x == other.x && y == other.y;
	}

	bool operator!=(const point<T>& other) const {

		return !(*this == other);
	}
};

} // namespace util

template <typename T, typename S>
util::point<T> operator+(const util::point<T>& p, const util::point<S>& o) {

	util::point<T> result(p);

	return result += o;
}

template <typename T, typename S>
util::point<T> operator-(const util::point<T>& p, const util::point<S>& o) {

	util::point<T> result(p);

	return result -= o;
}

template <typename T, typename S>
util::point<T> operator*(const util::point<T>& p, const S& s) {

	util::point<T> result(p);

	return result *= s;
}

template <typename T>
util::point<T> operator*(const T& s, const util::point<T>& p) {

	util::point<T> result(p);

	return result *= s;
}

template <typename T, typename S>
util::point<T> operator/(const util::point<T>& p, const S& s) {

	util::point<T> result(p);

	return result /= s;
}

namespace util {

template <typename T>
std::ostream& operator<<(std::ostream& os, const util::point<T>& point) {

	os << "(" << point.x << ", " << point.y << ")";

	return os;
}

} // namespace util

#endif // UTIL_POINT_H__

<|endoftext|>


<commit_before>#include "power.hpp"
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <limits>
#include <cassert>
//For the normalized power spectrum
#include <gsl/gsl_integration.h>

PowerSpec_Tabulated::PowerSpec_Tabulated(const char * FileWithTransfer, const char * FileWithInputSpectrum, double Omega, double OmegaLambda, double OmegaBaryon, double OmegaNu,
                        double InputSpectrum_UnitLength_in_cm, double UnitLength_in_cm, bool no_gas, bool neutrinos_ks)
{
  //Set up conversion factor between internal units and CAMB units
  scale = (InputSpectrum_UnitLength_in_cm / UnitLength_in_cm);
  std::vector<double> kmatter;
  std::vector<double> pmatter;

  std::fstream matpow;
  matpow.open(FileWithInputSpectrum, std::fstream::in);
  if ( ! matpow.is_open() ) {
      std::cerr<<"Can't open matter power spectrum in file: "<< FileWithInputSpectrum<<std::endl;
      exit(17);
  }

  /* define matter array */
  while ( matpow.good() ) {
    double ktmp,ptmp;
    matpow >> ktmp;
    matpow >> ptmp;
    if (!matpow.good() )
        break;
    kmatter.push_back(ktmp);
    pmatter.push_back(ptmp);
  }
  std::cerr<<"Found "<<pmatter.size()<<" rows in input spectrum table\n"<<std::endl;
  matpow.close();

  std::fstream transfer;
  transfer.open(FileWithTransfer, std::fstream::in);
  if ( ! transfer.is_open() ) {
      std::cerr<<"Can't open transfer function in file: "<< FileWithTransfer<<std::endl;
      exit(17);
  }

  //Temporary arrays which can be resized so we don't have to read the file twice
  std::vector<double> ktransfer_vector;
  std::vector<double> transfer_vector[N_TYPES];

  while ( transfer.good() ) {
      double T_b, dummy, T_nu, T_nu2,T_tot, T_cdm;
      double k;
      double delta_cdm, delta_nu, delta_nu_2nd,delta_tot, delta_b;
      //Read the row.
      transfer >> k;
      transfer >> T_cdm;
      transfer >> T_b;
      //radiation
      transfer >> dummy;
      transfer >> T_nu2;
      transfer >> T_nu;
      transfer >> T_tot;
      //Ignore the rest of the line
      transfer.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
      if ( ! transfer.good() )
          break;
      /* The dark matter may incorporate other particle types as well, eg,
       * fake neutrinos, or baryons.
       * NOTE that CAMB defines T_tot = (T_CDM M_CDM + T_b M_b +T_nu M_nu) / (M_CDM + M_b +M_nu)
       * HOWEVER, when relativistic (ie, in the early universe), neutrinos will redshift
       * like radiation. The CAMB transfer function takes this into account when calculating T_tot,
       * so instead of summing the transfer functions, use the total transfer function and
       * optionally subtract the baryons.
       * We want to incorporate neutrinos into the dark matter if we are changing the transfer function,
       * but not if we are using the full kspace method. */
      if(neutrinos_ks){
            T_cdm = T_tot;
            /*If we have separate gas particles, subtract
             * the baryon transfer function */
            if(!no_gas){
                T_cdm = (Omega*T_tot - T_b*OmegaBaryon)/(Omega-OmegaBaryon);
            }
      }
      /*Add baryons to the CDM if there are no gas particles*/
      else if(no_gas){
//                 T_cdm = (Omega*T_tot - T_nu*OmegaDM_2ndSpecies)/(Omega-OmegaDM_2ndSpecies);
            T_cdm = (T_cdm*(Omega-OmegaNu - OmegaBaryon) + T_b*OmegaBaryon)/(Omega-OmegaNu);
      }
      /*This should be equivalent to the above in almost all cases,
       * but perhaps we want to see the effect of changing only the ICs in CAMB for the neutrinos.*/
      if(no_gas && OmegaNu == 0){
              T_cdm = T_tot;
      }
      /* obtain P(k) from transfer function ratios like suggested by JL*/
      /*NOTE for this to work CAMB's transfer_k_interp_matterpower must be off!!*/
      size_t cursize = ktransfer_vector.size();
      delta_b   = k * k * k * pow(T_b/T_tot,2) * pmatter[cursize]/(2*M_PI*M_PI);
      delta_cdm = k * k * k * pow(T_cdm/T_tot,2)* pmatter[cursize]/(2*M_PI*M_PI);
      delta_nu = k * k * k * pow(T_nu/T_tot,2) * pmatter[cursize]/(2*M_PI*M_PI);
      delta_nu_2nd = k * k * k * pow(T_nu2/T_tot,2) * pmatter[cursize]/(2*M_PI*M_PI);
      delta_tot = k * k * k * pmatter[cursize]/(2*M_PI*M_PI);
      //Assign row to structures
      ktransfer_vector.push_back(k);
      transfer_vector[0].push_back(delta_b);
      transfer_vector[1].push_back(delta_cdm);
      transfer_vector[2].push_back(delta_nu);
      transfer_vector[3].push_back(delta_nu_2nd);
      transfer_vector[4].push_back(delta_tot);

  }
  transfer.close();

  //Do some basic checks on the read input files.
  if (ktransfer_vector.size() != pmatter.size() ) {
      std::cerr << "Transfer function was "<<ktransfer_vector.size()<<" lines long, but input power spectrum was "<<pmatter.size()<<std::endl;
      exit(47);
  }
  //Allocate arrays for the gsl interpolation (which must be raw arrays, unfortunately)
  //Then allocate the interpolation objects
  ktransfer_table = new double[ktransfer_vector.size()];
  //Copy over the k values
  for (size_t i=0; i<ktransfer_vector.size(); i++) {
        ktransfer_table[i] = log10(ktransfer_vector[i]);
        if(fabs(kmatter[i]- ktransfer_vector[i]) > 0.01 * kmatter[i]) {
              fprintf(stderr, "Error: Input spectrum row %ld has k=%g, transfer has k=%g.\n",i,kmatter[i],ktransfer_vector[i]);
              std::cerr<<"Remember you need transfer_k_interp_matterpower = F in CAMB"<<std::endl;
              exit(47);
        }
        if(i >0 && ktransfer_table[i] <= ktransfer_table[i-1]) {
              std::cerr<<"Transfer table is not increasing in k: i = "<<i<<", k = "<<ktransfer_table[i]<<" <= "<<ktransfer_table[i-1]<<std::endl;
              exit(48);
        }
  }
  for(int type=0; type < N_TYPES; type++){
      //Check everything is the same size
      assert( ktransfer_vector.size() == transfer_vector[type].size());
      transfer_table[type] = new double[transfer_vector[type].size()];
      //Copy data from the temporary vectors to the statically sized C-arrays
      for (size_t i=0; i<transfer_vector[type].size(); i++) {
          //Make sure we do not take log(0)
          transfer_table[type][i] = log10(std::max(transfer_vector[type][i],1e-90));
      }
      //Set up the interpolation structures
      trans_interp[type] = gsl_interp_alloc(gsl_interp_cspline,transfer_vector[type].size());
      trans_interp_accel[type] = gsl_interp_accel_alloc();
      //Initialise the interpolator; same k values for each one, different T values.
      //Size asserted to be the same.
      gsl_interp_init(trans_interp[type],ktransfer_table, transfer_table[type],transfer_vector[type].size());
  }
  //Store the size of the arrays
  NPowerTable = ktransfer_vector.size();
}

double PowerSpec_Tabulated::power(double k, int Type)
{
  double kold = k;

  k *= scale;	/* convert to h/Mpc */

  double logk = log10(k);

  if(logk < ktransfer_table[0] || logk > ktransfer_table[NPowerTable - 1])
    return 0;

  //Clamp the requested type.
  if (Type > N_TYPES-1 || Type < 0)
      Type = N_TYPES-1;

  double logD = gsl_interp_eval(trans_interp[Type], ktransfer_table, transfer_table[Type], logk, trans_interp_accel[Type]);

  double Delta2 = pow(10.0, logD);

  double P = Delta2 / (4 * M_PI * kold * kold * kold);
  //  printf(" k,P,u,logD,dlogk,binlow,binhigh,PowerTable[binlow].logD,PowerTable[binhigh].logD %g %g %g %g %g %g %d %d %g %g\n",k,P,u,logD,Delta2,dlogk,binlow,binhigh,PowerTable[binlow].logD,PowerTable[binhigh].logD);
  return P;
}

//Definitions for the normalized power spectrum
//These mostly compute sigma_8 via the GSL
NormalizedPowerSpec::NormalizedPowerSpec(PowerSpec * PSpec, double Sigma8, double PrimordialIndex, double Dplus, double UnitLength_in_cm): PSpec(PSpec), PrimordialIndex(PrimordialIndex), Dplus(Dplus)
{
        R8 = 8 * (3.085678e24 / UnitLength_in_cm);	/* 8 Mpc/h */
        //Uses R8
        Norm = Sigma8 * Sigma8 / TopHatSigma2();
        printf("Normalization adjusted to  Sigma8=%g   (Normfac=%g)\n\n", Sigma8, Norm);
//         Cosmology cosmo(HubbleParam, Omega, OmegaLambda, MNu, InvertedHierarchy);
//         Dplus = cosmo.GrowthFactor(InitTime, 1.0);
        printf("Dplus initial redshift =%g  \n\n", Dplus);
}

double sigma2_int(double k, void * params)
{
  NormalizedPowerSpec * PSpec = (NormalizedPowerSpec *) params;
  double r = PSpec->R8;
  double kr, kr2, w, x;
  kr = r * k;
  kr2 = kr * kr;

  /*Series expansion; actually good until kr~1*/
  if(kr < 1e-2)
      w = 1./3. - kr2/30. +kr2*kr2/840.;
  else
      w = 3 * (sin(kr) / kr - cos(kr)) / kr2;
  x = 4 * M_PI * k * k * w * w * PSpec->power(k,100);
  return x;
}

double NormalizedPowerSpec::TopHatSigma2()
{
  gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
  double result,abserr;
  gsl_function F;
  F.function = &sigma2_int;
  F.params = this;

  /* note: 500/R is here chosen as integration boundary (infinity) */
  gsl_integration_qags (&F, 0, 500./this->R8, 0, 1e-4,1000,w,&result, &abserr);
//   printf("gsl_integration_qng in TopHatSigma2. Result %g, error: %g, intervals: %lu\n",result, abserr,w->size);
  gsl_integration_workspace_free (w);
  return result;
}

<commit_msg>Remove not needed multiply and divide by k to change units.<commit_after>#include "power.hpp"
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <limits>
#include <cassert>
//For the normalized power spectrum
#include <gsl/gsl_integration.h>

PowerSpec_Tabulated::PowerSpec_Tabulated(const char * FileWithTransfer, const char * FileWithInputSpectrum, double Omega, double OmegaLambda, double OmegaBaryon, double OmegaNu,
                        double InputSpectrum_UnitLength_in_cm, double UnitLength_in_cm, bool no_gas, bool neutrinos_ks)
{
  //Set up conversion factor between internal units and CAMB units
  scale = (InputSpectrum_UnitLength_in_cm / UnitLength_in_cm);
  std::vector<double> kmatter;
  std::vector<double> pmatter;

  std::fstream matpow;
  matpow.open(FileWithInputSpectrum, std::fstream::in);
  if ( ! matpow.is_open() ) {
      std::cerr<<"Can't open matter power spectrum in file: "<< FileWithInputSpectrum<<std::endl;
      exit(17);
  }

  /* define matter array */
  while ( matpow.good() ) {
    double ktmp,ptmp;
    matpow >> ktmp;
    matpow >> ptmp;
    if (!matpow.good() )
        break;
    kmatter.push_back(ktmp);
    pmatter.push_back(ptmp);
  }
  std::cerr<<"Found "<<pmatter.size()<<" rows in input spectrum table\n"<<std::endl;
  matpow.close();

  std::fstream transfer;
  transfer.open(FileWithTransfer, std::fstream::in);
  if ( ! transfer.is_open() ) {
      std::cerr<<"Can't open transfer function in file: "<< FileWithTransfer<<std::endl;
      exit(17);
  }

  //Temporary arrays which can be resized so we don't have to read the file twice
  std::vector<double> ktransfer_vector;
  std::vector<double> transfer_vector[N_TYPES];

  while ( transfer.good() ) {
      double T_b, dummy, T_nu, T_nu2,T_tot, T_cdm;
      double k;
      double delta_cdm, delta_nu, delta_nu_2nd,delta_tot, delta_b;
      //Read the row.
      transfer >> k;
      transfer >> T_cdm;
      transfer >> T_b;
      //radiation
      transfer >> dummy;
      transfer >> T_nu2;
      transfer >> T_nu;
      transfer >> T_tot;
      //Ignore the rest of the line
      transfer.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
      if ( ! transfer.good() )
          break;
      /* The dark matter may incorporate other particle types as well, eg,
       * fake neutrinos, or baryons.
       * NOTE that CAMB defines T_tot = (T_CDM M_CDM + T_b M_b +T_nu M_nu) / (M_CDM + M_b +M_nu)
       * HOWEVER, when relativistic (ie, in the early universe), neutrinos will redshift
       * like radiation. The CAMB transfer function takes this into account when calculating T_tot,
       * so instead of summing the transfer functions, use the total transfer function and
       * optionally subtract the baryons.
       * We want to incorporate neutrinos into the dark matter if we are changing the transfer function,
       * but not if we are using the full kspace method. */
      if(neutrinos_ks){
            T_cdm = T_tot;
            /*If we have separate gas particles, subtract
             * the baryon transfer function */
            if(!no_gas){
                T_cdm = (Omega*T_tot - T_b*OmegaBaryon)/(Omega-OmegaBaryon);
            }
      }
      /*Add baryons to the CDM if there are no gas particles*/
      else if(no_gas){
//                 T_cdm = (Omega*T_tot - T_nu*OmegaDM_2ndSpecies)/(Omega-OmegaDM_2ndSpecies);
            T_cdm = (T_cdm*(Omega-OmegaNu - OmegaBaryon) + T_b*OmegaBaryon)/(Omega-OmegaNu);
      }
      /*This should be equivalent to the above in almost all cases,
       * but perhaps we want to see the effect of changing only the ICs in CAMB for the neutrinos.*/
      if(no_gas && OmegaNu == 0){
              T_cdm = T_tot;
      }
      /* obtain P(k) from transfer function ratios like suggested by JL*/
      /*NOTE for this to work CAMB's transfer_k_interp_matterpower must be off!!*/
      size_t cursize = ktransfer_vector.size();
      delta_b   = pow(T_b/T_tot,2) * pmatter[cursize]/(2*M_PI*M_PI);
      delta_cdm = pow(T_cdm/T_tot,2)* pmatter[cursize]/(2*M_PI*M_PI);
      delta_nu = pow(T_nu/T_tot,2) * pmatter[cursize]/(2*M_PI*M_PI);
      delta_nu_2nd = pow(T_nu2/T_tot,2) * pmatter[cursize]/(2*M_PI*M_PI);
      delta_tot = pmatter[cursize]/(2*M_PI*M_PI);
      //Assign row to structures
      ktransfer_vector.push_back(k);
      transfer_vector[0].push_back(delta_b);
      transfer_vector[1].push_back(delta_cdm);
      transfer_vector[2].push_back(delta_nu);
      transfer_vector[3].push_back(delta_nu_2nd);
      transfer_vector[4].push_back(delta_tot);

  }
  transfer.close();

  //Do some basic checks on the read input files.
  if (ktransfer_vector.size() != pmatter.size() ) {
      std::cerr << "Transfer function was "<<ktransfer_vector.size()<<" lines long, but input power spectrum was "<<pmatter.size()<<std::endl;
      exit(47);
  }
  //Allocate arrays for the gsl interpolation (which must be raw arrays, unfortunately)
  //Then allocate the interpolation objects
  ktransfer_table = new double[ktransfer_vector.size()];
  //Copy over the k values
  for (size_t i=0; i<ktransfer_vector.size(); i++) {
        ktransfer_table[i] = log10(ktransfer_vector[i]);
        if(fabs(kmatter[i]- ktransfer_vector[i]) > 0.01 * kmatter[i]) {
              fprintf(stderr, "Error: Input spectrum row %ld has k=%g, transfer has k=%g.\n",i,kmatter[i],ktransfer_vector[i]);
              std::cerr<<"Remember you need transfer_k_interp_matterpower = F in CAMB"<<std::endl;
              exit(47);
        }
        if(i >0 && ktransfer_table[i] <= ktransfer_table[i-1]) {
              std::cerr<<"Transfer table is not increasing in k: i = "<<i<<", k = "<<ktransfer_table[i]<<" <= "<<ktransfer_table[i-1]<<std::endl;
              exit(48);
        }
  }
  for(int type=0; type < N_TYPES; type++){
      //Check everything is the same size
      assert( ktransfer_vector.size() == transfer_vector[type].size());
      transfer_table[type] = new double[transfer_vector[type].size()];
      //Copy data from the temporary vectors to the statically sized C-arrays
      for (size_t i=0; i<transfer_vector[type].size(); i++) {
          //Make sure we do not take log(0)
          transfer_table[type][i] = log10(std::max(transfer_vector[type][i],1e-90));
      }
      //Set up the interpolation structures
      trans_interp[type] = gsl_interp_alloc(gsl_interp_cspline,transfer_vector[type].size());
      trans_interp_accel[type] = gsl_interp_accel_alloc();
      //Initialise the interpolator; same k values for each one, different T values.
      //Size asserted to be the same.
      gsl_interp_init(trans_interp[type],ktransfer_table, transfer_table[type],transfer_vector[type].size());
  }
  //Store the size of the arrays
  NPowerTable = ktransfer_vector.size();
}

double PowerSpec_Tabulated::power(double k, int Type)
{

  double logk = log10(k*scale);

  if(logk < ktransfer_table[0] || logk > ktransfer_table[NPowerTable - 1])
    return 0;

  //Clamp the requested type.
  if (Type > N_TYPES-1 || Type < 0)
      Type = N_TYPES-1;

  double logD = gsl_interp_eval(trans_interp[Type], ktransfer_table, transfer_table[Type], logk, trans_interp_accel[Type]);

  double Delta2 = pow(10.0, logD);

  double P = Delta2 * scale * scale * scale / (4 * M_PI );
  //  printf(" k,P,u,logD,dlogk,binlow,binhigh,PowerTable[binlow].logD,PowerTable[binhigh].logD %g %g %g %g %g %g %d %d %g %g\n",k,P,u,logD,Delta2,dlogk,binlow,binhigh,PowerTable[binlow].logD,PowerTable[binhigh].logD);
  return P;
}

//Definitions for the normalized power spectrum
//These mostly compute sigma_8 via the GSL
NormalizedPowerSpec::NormalizedPowerSpec(PowerSpec * PSpec, double Sigma8, double PrimordialIndex, double Dplus, double UnitLength_in_cm): PSpec(PSpec), PrimordialIndex(PrimordialIndex), Dplus(Dplus)
{
        R8 = 8 * (3.085678e24 / UnitLength_in_cm);	/* 8 Mpc/h */
        //Uses R8
        Norm = Sigma8 * Sigma8 / TopHatSigma2();
        printf("Normalization adjusted to  Sigma8=%g   (Normfac=%g)\n\n", Sigma8, Norm);
//         Cosmology cosmo(HubbleParam, Omega, OmegaLambda, MNu, InvertedHierarchy);
//         Dplus = cosmo.GrowthFactor(InitTime, 1.0);
        printf("Dplus initial redshift =%g  \n\n", Dplus);
}

double sigma2_int(double k, void * params)
{
  NormalizedPowerSpec * PSpec = (NormalizedPowerSpec *) params;
  double r = PSpec->R8;
  double kr, kr2, w, x;
  kr = r * k;
  kr2 = kr * kr;

  /*Series expansion; actually good until kr~1*/
  if(kr < 1e-2)
      w = 1./3. - kr2/30. +kr2*kr2/840.;
  else
      w = 3 * (sin(kr) / kr - cos(kr)) / kr2;
  x = 4 * M_PI * k * k * w * w * PSpec->power(k,100);
  return x;
}

double NormalizedPowerSpec::TopHatSigma2()
{
  gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
  double result,abserr;
  gsl_function F;
  F.function = &sigma2_int;
  F.params = this;

  /* note: 500/R is here chosen as integration boundary (infinity) */
  gsl_integration_qags (&F, 0, 500./this->R8, 0, 1e-4,1000,w,&result, &abserr);
//   printf("gsl_integration_qng in TopHatSigma2. Result %g, error: %g, intervals: %lu\n",result, abserr,w->size);
  gsl_integration_workspace_free (w);
  return result;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "prefdb.h"
#include "main.h"
#include "win.h"
#include <glibmm/i18n.h>

#include <fstream>
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

const ButtonInfo default_button(Button2);
const int default_pressure_threshold = 192;

PrefDB::PrefDB() :
	TimeoutWatcher(5000),
	good_state(true),
	button(default_button),
	trace(TraceDefault),
	advanced_ignore(false),
	ignore_grab(false),
	timing_workaround(false),
	pressure_abort(false),
	pressure_threshold(default_pressure_threshold),
	proximity(false),
	feedback(true),
	left_handed(false),
	init_timeout(250),
	final_timeout(250),
	timeout_profile(TimeoutDefault),
	timeout_gestures(false),
	tray_icon(true),
	color(Gdk::Color("#980101")),
	trace_width(5),
	advanced_popups(true),
	scroll_invert(true),
	scroll_speed(2.0),
	tray_feedback(false),
	show_osd(true)
{}

template<class Archive> void PrefDB::serialize(Archive & ar, const unsigned int version) {
	if (version < 11) {
		std::set<std::string> old;
		ar & old;
		for (std::set<std::string>::iterator i = old.begin(); i != old.end(); i++)
			exceptions.unsafe_ref()[*i] = RButtonInfo();
	} else ar & exceptions.unsafe_ref();
	if (version < 14) {
		double p = 0.5;
		ar & p;
	}
	ar & button.unsafe_ref();
	if (version < 2) {
		bool help;
		ar & help;
	}
	ar & trace.unsafe_ref();
	if (trace.get() == TraceShape)
		trace.unsafe_ref() = TraceDefault;
	if (version < 3) {
		int delay;
		ar & delay;
	}
	if (version == 1) {
		ButtonInfo foo;
		ar & foo;
		ar & foo;
		return;
	}
	if (version < 2) return;
	if (version != 6)
		ar & advanced_ignore.unsafe_ref();
	int radius = 16;
	ar & radius;
	if (version < 4) return;
	ar & ignore_grab.unsafe_ref();
	ar & timing_workaround.unsafe_ref();
	bool show_clicks = false;
	ar & show_clicks;
	ar & pressure_abort.unsafe_ref();
	ar & pressure_threshold.unsafe_ref();
	ar & proximity.unsafe_ref();
	if (version < 5) return;
	ar & feedback.unsafe_ref();
	ar & left_handed.unsafe_ref();
	ar & init_timeout.unsafe_ref();
	ar & final_timeout.unsafe_ref();
	if (version < 8) return;
	ar & timeout_profile.unsafe_ref();
	if (version < 9) return;
	ar & timeout_gestures.unsafe_ref();
	ar & tray_icon.unsafe_ref();
	if (version < 10) return;
	ar & excluded_devices.unsafe_ref();
	if (version < 12) {
		unsigned long c = 0;
		ar & c;
		color.unsafe_ref().color.set_rgb(257*(c >> 16), 257*((c >> 8) % 256), 257*(c % 256));
		return;
	} else {
		ar & color.unsafe_ref();
	}
	ar & trace_width.unsafe_ref();
	if (version < 13) return;
	ar & extra_buttons.unsafe_ref();
	ar & advanced_popups.unsafe_ref();
	ar & scroll_invert.unsafe_ref();
	ar & scroll_speed.unsafe_ref();
	ar & tray_feedback.unsafe_ref();
	ar & show_osd.unsafe_ref();
}

void PrefDB::timeout() {
	std::string filename = config_dir+"preferences"+versions[0];
	std::string tmp = filename + ".tmp";
	try {
		std::ofstream ofs(tmp.c_str());
		boost::archive::text_oarchive oa(ofs);
		const PrefDB *me = this;
		oa << *me;
		ofs.close();
		if (rename(tmp.c_str(), filename.c_str()))
			throw std::runtime_error("rename() failed");
		if (verbosity >= 2)
			printf("Saved preferences.\n");
	} catch (std::exception &e) {
		printf(_("Error: Couldn't save preferences: %s.\n"), e.what());
		if (!good_state)
			return;
		good_state = false;
		error_dialog(Glib::ustring::compose(_( "Couldn't save %1.  Your changes will be lost.  "
				"Make sure that \"%2\" is a directory and that you have write access to it.  "
				"You can change the configuration directory "
				"using the -c or --config-dir command line options."), _("preferences"), config_dir));
	}
}

bool ButtonInfo::overlap(const ButtonInfo &bi) const {
	if (button != bi.button)
		return false;
	if (state == AnyModifier || bi.state == AnyModifier)
		return true;
	return !((state ^ bi.state) & ~LockMask & ~Mod2Mask);
}

class TimeoutProfile : private Base {
	Out<TimeoutType> ∈
public:
	virtual void notify() {
		switch (in.get()) {
			case TimeoutOff:
				prefs.init_timeout.set(0);
				prefs.final_timeout.set(0);
				break;
			case TimeoutConservative:
				prefs.init_timeout.set(750);
				prefs.final_timeout.set(750);
				break;
			case TimeoutDefault:
				prefs.init_timeout.set(250);
				prefs.final_timeout.set(250);
				break;
			case TimeoutMedium:
				prefs.init_timeout.set(100);
				prefs.final_timeout.set(100);
				break;
			case TimeoutAggressive:
				prefs.init_timeout.set(50);
				prefs.final_timeout.set(75);
				break;
			case TimeoutFlick:
				prefs.init_timeout.set(30);
				prefs.final_timeout.set(50);
				break;
			case TimeoutCustom:
				break;
		}
	}
	TimeoutProfile(Out<TimeoutType> &in_) : in(in_) {
		in.connect(this);
		notify();
	}
};

void PrefDB::init() {
	std::string filename = config_dir+"preferences";
	for (const char **v = versions; *v; v++) {
		if (is_file(filename + *v)) {
			filename += *v;
			try {
				std::ifstream ifs(filename.c_str(), std::ios::binary);
				if (!ifs.fail()) {
					boost::archive::text_iarchive ia(ifs);
					ia >> *this;
					if (verbosity >= 2)
						std::cout << "Loaded preferences." << std::endl;
				}
			} catch (...) {
				printf(_("Error: Couldn't read preferences.\n"));
			}
			break;
		}
	}
	std::map<std::string, RButtonInfo>::iterator i = exceptions.unsafe_ref().find("(window manager frame)");
	if (i != exceptions.unsafe_ref().end()) {
		RButtonInfo bi = i->second;
		exceptions.unsafe_ref().erase(i);
		exceptions.unsafe_ref()[""] = bi;
	}
	new TimeoutProfile(timeout_profile);
	watch(init_timeout);
	watch(final_timeout);
}

PrefDB prefs;
<commit_msg>Set default width to 3<commit_after>/*
 * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "prefdb.h"
#include "main.h"
#include "win.h"
#include <glibmm/i18n.h>

#include <fstream>
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

const ButtonInfo default_button(Button2);
const int default_pressure_threshold = 192;

PrefDB::PrefDB() :
	TimeoutWatcher(5000),
	good_state(true),
	button(default_button),
	trace(TraceDefault),
	advanced_ignore(false),
	ignore_grab(false),
	timing_workaround(false),
	pressure_abort(false),
	pressure_threshold(default_pressure_threshold),
	proximity(false),
	feedback(true),
	left_handed(false),
	init_timeout(250),
	final_timeout(250),
	timeout_profile(TimeoutDefault),
	timeout_gestures(false),
	tray_icon(true),
	color(Gdk::Color("#980101")),
	trace_width(3),
	advanced_popups(true),
	scroll_invert(true),
	scroll_speed(2.0),
	tray_feedback(false),
	show_osd(true)
{}

template<class Archive> void PrefDB::serialize(Archive & ar, const unsigned int version) {
	if (version < 11) {
		std::set<std::string> old;
		ar & old;
		for (std::set<std::string>::iterator i = old.begin(); i != old.end(); i++)
			exceptions.unsafe_ref()[*i] = RButtonInfo();
	} else ar & exceptions.unsafe_ref();
	if (version < 14) {
		double p = 0.5;
		ar & p;
	}
	ar & button.unsafe_ref();
	if (version < 2) {
		bool help;
		ar & help;
	}
	ar & trace.unsafe_ref();
	if (trace.get() == TraceShape)
		trace.unsafe_ref() = TraceDefault;
	if (version < 3) {
		int delay;
		ar & delay;
	}
	if (version == 1) {
		ButtonInfo foo;
		ar & foo;
		ar & foo;
		return;
	}
	if (version < 2) return;
	if (version != 6)
		ar & advanced_ignore.unsafe_ref();
	int radius = 16;
	ar & radius;
	if (version < 4) return;
	ar & ignore_grab.unsafe_ref();
	ar & timing_workaround.unsafe_ref();
	bool show_clicks = false;
	ar & show_clicks;
	ar & pressure_abort.unsafe_ref();
	ar & pressure_threshold.unsafe_ref();
	ar & proximity.unsafe_ref();
	if (version < 5) return;
	ar & feedback.unsafe_ref();
	ar & left_handed.unsafe_ref();
	ar & init_timeout.unsafe_ref();
	ar & final_timeout.unsafe_ref();
	if (version < 8) return;
	ar & timeout_profile.unsafe_ref();
	if (version < 9) return;
	ar & timeout_gestures.unsafe_ref();
	ar & tray_icon.unsafe_ref();
	if (version < 10) return;
	ar & excluded_devices.unsafe_ref();
	if (version < 12) {
		unsigned long c = 0;
		ar & c;
		color.unsafe_ref().color.set_rgb(257*(c >> 16), 257*((c >> 8) % 256), 257*(c % 256));
		return;
	} else {
		ar & color.unsafe_ref();
	}
	ar & trace_width.unsafe_ref();
	if (version < 13) return;
	ar & extra_buttons.unsafe_ref();
	ar & advanced_popups.unsafe_ref();
	ar & scroll_invert.unsafe_ref();
	ar & scroll_speed.unsafe_ref();
	ar & tray_feedback.unsafe_ref();
	ar & show_osd.unsafe_ref();
}

void PrefDB::timeout() {
	std::string filename = config_dir+"preferences"+versions[0];
	std::string tmp = filename + ".tmp";
	try {
		std::ofstream ofs(tmp.c_str());
		boost::archive::text_oarchive oa(ofs);
		const PrefDB *me = this;
		oa << *me;
		ofs.close();
		if (rename(tmp.c_str(), filename.c_str()))
			throw std::runtime_error("rename() failed");
		if (verbosity >= 2)
			printf("Saved preferences.\n");
	} catch (std::exception &e) {
		printf(_("Error: Couldn't save preferences: %s.\n"), e.what());
		if (!good_state)
			return;
		good_state = false;
		error_dialog(Glib::ustring::compose(_( "Couldn't save %1.  Your changes will be lost.  "
				"Make sure that \"%2\" is a directory and that you have write access to it.  "
				"You can change the configuration directory "
				"using the -c or --config-dir command line options."), _("preferences"), config_dir));
	}
}

bool ButtonInfo::overlap(const ButtonInfo &bi) const {
	if (button != bi.button)
		return false;
	if (state == AnyModifier || bi.state == AnyModifier)
		return true;
	return !((state ^ bi.state) & ~LockMask & ~Mod2Mask);
}

class TimeoutProfile : private Base {
	Out<TimeoutType> ∈
public:
	virtual void notify() {
		switch (in.get()) {
			case TimeoutOff:
				prefs.init_timeout.set(0);
				prefs.final_timeout.set(0);
				break;
			case TimeoutConservative:
				prefs.init_timeout.set(750);
				prefs.final_timeout.set(750);
				break;
			case TimeoutDefault:
				prefs.init_timeout.set(250);
				prefs.final_timeout.set(250);
				break;
			case TimeoutMedium:
				prefs.init_timeout.set(100);
				prefs.final_timeout.set(100);
				break;
			case TimeoutAggressive:
				prefs.init_timeout.set(50);
				prefs.final_timeout.set(75);
				break;
			case TimeoutFlick:
				prefs.init_timeout.set(30);
				prefs.final_timeout.set(50);
				break;
			case TimeoutCustom:
				break;
		}
	}
	TimeoutProfile(Out<TimeoutType> &in_) : in(in_) {
		in.connect(this);
		notify();
	}
};

void PrefDB::init() {
	std::string filename = config_dir+"preferences";
	for (const char **v = versions; *v; v++) {
		if (is_file(filename + *v)) {
			filename += *v;
			try {
				std::ifstream ifs(filename.c_str(), std::ios::binary);
				if (!ifs.fail()) {
					boost::archive::text_iarchive ia(ifs);
					ia >> *this;
					if (verbosity >= 2)
						std::cout << "Loaded preferences." << std::endl;
				}
			} catch (...) {
				printf(_("Error: Couldn't read preferences.\n"));
			}
			break;
		}
	}
	std::map<std::string, RButtonInfo>::iterator i = exceptions.unsafe_ref().find("(window manager frame)");
	if (i != exceptions.unsafe_ref().end()) {
		RButtonInfo bi = i->second;
		exceptions.unsafe_ref().erase(i);
		exceptions.unsafe_ref()[""] = bi;
	}
	new TimeoutProfile(timeout_profile);
	watch(init_timeout);
	watch(final_timeout);
}

PrefDB prefs;
<|endoftext|>


<commit_before>/*
 * Persistence.hpp
 *
 *  Created on: 16.05.2017
 *      Author: Alexander
 */

#ifndef PERSISTENCE_BASE_PERSISTENCE_HPP_
#define PERSISTENCE_BASE_PERSISTENCE_HPP_

#include <map>
#include <memory>
#include <string>

namespace ecore
{
	class EObject;
	class EPackage;
}
namespace persistence
{
	namespace base
	{
		class Persistence
		{
			public:
				Persistence();
				virtual ~Persistence();

				virtual std::shared_ptr<ecore::EObject> load(const std::string &filename) = 0;
				virtual bool save(const std::string &filename, std::shared_ptr<ecore::EObject> model, std::shared_ptr<ecore::EPackage> metaMetaPackage, bool xsiMode = true) = 0;
				virtual std::map<std::string, std::shared_ptr<ecore::EObject>> getObjectReferenceMap();

			protected:
				bool isValidFile(const std::string &filename);
				std::map<std::string, std::shared_ptr<ecore::EObject>> m_refToObject_map;

		};
	} /* namespace base */
} /* namespace persistence */

#endif /* PERSISTENCE_HPP_ */
<commit_msg>make isValidFile abstract<commit_after>/*
 * Persistence.hpp
 *
 *  Created on: 16.05.2017
 *      Author: Alexander
 */

#ifndef PERSISTENCE_BASE_PERSISTENCE_HPP_
#define PERSISTENCE_BASE_PERSISTENCE_HPP_

#include <map>
#include <memory>
#include <string>

namespace ecore
{
	class EObject;
	class EPackage;
}
namespace persistence
{
	namespace base
	{
		class Persistence
		{
			public:
				Persistence();
				virtual ~Persistence();

				virtual std::shared_ptr<ecore::EObject> load(const std::string &filename) = 0;
				virtual bool save(const std::string &filename, std::shared_ptr<ecore::EObject> model, std::shared_ptr<ecore::EPackage> metaMetaPackage, bool xsiMode = true) = 0;
				virtual std::map<std::string, std::shared_ptr<ecore::EObject>> getObjectReferenceMap();

			protected:
				virtual bool isValidFile(const std::string &filename) =0;
				std::map<std::string, std::shared_ptr<ecore::EObject>> m_refToObject_map;

		};
	} /* namespace base */
} /* namespace persistence */

#endif /* PERSISTENCE_HPP_ */
<|endoftext|>