<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 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) 1999, 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.6  2003/11/27 16:44:59  neilg
 * implement isSpecified; thanks to Pete Lloyd
 *
 * Revision 1.5  2003/11/27 06:10:32  neilg
 * PSVIAttribute implementation
 *
 * Revision 1.4  2003/11/25 16:14:28  neilg
 * move inlines into PSVIItem.hpp
 *
 * Revision 1.3  2003/11/21 22:34:45  neilg
 * More schema component model implementation, thanks to David Cargill.
 * In particular, this cleans up and completes the XSModel, XSNamespaceItem,
 * XSAttributeDeclaration and XSAttributeGroup implementations.
 *
 * Revision 1.2  2003/11/06 15:30:04  neilg
 * first part of PSVI/schema component model implementation, thanks to David Cargill.  This covers setting the PSVIHandler on parser objects, as well as implementing XSNotation, XSSimpleTypeDefinition, XSIDCDefinition, and most of XSWildcard, XSComplexTypeDefinition, XSElementDeclaration, XSAttributeDeclaration and XSAttributeUse.
 *
 * Revision 1.1  2003/09/16 14:33:36  neilg
 * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
 *
 */

#if !defined(PSVIITEM_HPP)
#define PSVIITEM_HPP

#include <xercesc/util/PlatformUtils.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/**
 * Represent the PSVI contributions for one element or one attribute information item.
 * This is *always* owned by the validator /parser object from which
 * it is obtained.  It is designed to be subclassed; subclasses will
 * specify under what conditions it may be relied upon to have meaningful contents.
 */

// forward declarations
class XSTypeDefinition;
class XSSimpleTypeDefinition;

class XMLPARSER_EXPORT PSVIItem : public XMemory
{
public:

    enum VALIDITY_STATE {
	    /** Validity value indicating that validation has either not
	    been performed or that a strict assessment of validity could
	    not be performed
	    */
	    VALIDITY_NOTKNOWN               = 0,

	    /** Validity value indicating that validation has been strictly
	     assessed and the element in question is invalid according to the
	     rules of schema validation.
	    */
	    VALIDITY_INVALID               = 1,

	    /** Validity value indicating that validation has been strictly
	     assessed and the element in question is valid according to the rules
	     of schema validation.
	     */
	    VALIDITY_VALID                 = 2
    };

    enum ASSESSMENT_TYPE {
	    /** Validation status indicating that schema validation has been
	     performed and the element in question has specifically been skipped.
	     */
	    VALIDATION_NONE                = 0,

	    /** Validation status indicating that schema validation has been
	    performed on the element in question under the rules of lax validation.
	    */
	    VALIDATION_PARTIAL             = 1,

	    /**  Validation status indicating that full schema validation has been
	    performed on the element.  */
	    VALIDATION_FULL                = 2
    };

    //  Constructors and Destructor
    // -----------------------------------------------------------------------
    /** @name Constructors */
    //@{

    /**
      * The default constructor
      *
      * @param  manager     The configurable memory manager
      */
    PSVIItem(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);

    //@};

    /** @name Destructor */
    //@{
    virtual ~PSVIItem();
    //@}

    //---------------------
    /** @name PSVIItem methods */

    //@{

    /**
     * [validation context]
     *
     * @return A string identifying the nearest ancestor element
     *          information item with a [schema information] property
     *         (or this element item itself if it has such a property)
     *          (form to be determined)
     * @see XML Schema Part 1: Structures [validation context]
     */
    const XMLCh *getValidationContext();

    /**
     * Determine the validity of the node with respect
     * to the validation being attempted
     *
     * @return return the [validity] property. Possible values are:
     *         VALIDITY_UNKNOWN, VALIDITY_INVALID, VALIDITY_VALID
     */
    VALIDITY_STATE getValidity() const;

    /**
     * Determines the extent to which the item has been validated
     *
     * @return return the [validation attempted] property. The possible values are
     *         VALIDATION_NONE, VALIDATION_ORDERED_PARTIAL and VALIDATION_FULL
     */
    ASSESSMENT_TYPE getValidationAttempted() const;

    /**
     * A list of error codes generated from validation attempts.
     * Need to find all the possible subclause reports that need reporting
     *
     * @return list of error codes
     */
    /***
    const XMLCh ** getErrorCodes();
    ****/

    /**
     * [schema normalized value]
     *
     * @see XML Schema Part 1: Structures [schema normalized value]
     * @return the normalized value of this item after validation
     */
    const XMLCh *getSchemaNormalizedValue();

    /**
     * An item isomorphic to the type definition used to validate this element.
     *
     * @return  a type declaration
     */
    virtual XSTypeDefinition *getTypeDefinition() = 0;

    /**
     * If and only if that type definition is a simple type definition
     * with {variety} union, or a complex type definition whose {content type}
     * is a simple thype definition with {variety} union, then an item isomorphic
     * to that member of the union's {member type definitions} which actually
     * validated the element item's normalized value.
     *
     * @return  a simple type declaration
     */
    virtual XSSimpleTypeDefinition *getMemberTypeDefinition() = 0;

    /**
     * [schema default]
     *
     * @return The canonical lexical representation of the declaration's {value constraint} value.
     * @see XML Schema Part 1: Structures [schema default]
     */
    const XMLCh *getSchemaDefault();

    /**
     * [schema specified]
     * @see XML Schema Part 1: Structures [schema specified]
     * @return true - value was specified in schema, false - value comes from the infoset
     */
    bool getIsSchemaSpecified() const;

    /**
     * Return the canonical representation of this value.
     * Note that, formally, this is not a PSVI property.
     * @return string representing the canonical representation, if this item
     * was validated by a simple type definition for which canonical
     * representations of values are defined.
     */
    const XMLCh *getCanonicalRepresentation();

    //@}

    //----------------------------------
    /** methods needed by implementation */

    //@{

    void setValidationAttempted(PSVIItem::ASSESSMENT_TYPE attemptType);
    void setValidity(PSVIItem::VALIDITY_STATE validity);

    /** reset the object
     * @param validationContext:  corresponds to schema validation context property
     * @param normalizedValue:  corresponds to schema normalized value property
     * @param validityState:  state of item's validity
     * @param assessmentType:  type of assessment carried out on item
     */
    void reset(
            const XMLCh* const validationContext
            , const XMLCh* const normalizedValue
            , const VALIDITY_STATE validityState
            , const ASSESSMENT_TYPE assessmentType
        );
    //@}
private:

    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    PSVIItem(const PSVIItem&);
    PSVIItem & operator=(const PSVIItem &);

protected:
    // -----------------------------------------------------------------------
    //  data members
    // -----------------------------------------------------------------------
    // fMemoryManager:
    //  used for any memory allocations
    // fValidationContext
    //  corresponds to the schema [validation context] property
    // fNormalizedValue
    //  The schema normalized value (when present)
    // fDefaultValue
    //  default value specified in the schema, if any
    // fCanonicalValue
    //  canonicalized version of normalizedValue
    // fValidityState
    //  Whether this item is valid or not
    // fAssessmentType
    //  The kind of assessment that produced the given validity outcome
    // fIsSpecified
    //  Whether this item exists because a default was specified in the schema
    // fType
    //  type responsible for validating this item
    // fMemberType
    //  If fType is a union type, the member type that validated this item
    MemoryManager* const        fMemoryManager;
    const XMLCh*                fValidationContext;
    const XMLCh*                fNormalizedValue;
    const XMLCh*                fDefaultValue;
    const XMLCh*                fCanonicalValue;
    VALIDITY_STATE              fValidityState;
    ASSESSMENT_TYPE             fAssessmentType;
    bool                        fIsSpecified;
    XSTypeDefinition *          fType;
    XSSimpleTypeDefinition*     fMemberType;
};

inline PSVIItem::~PSVIItem() {}

inline const XMLCh *PSVIItem::getValidationContext()
{
    return fValidationContext;
}

inline const XMLCh* PSVIItem::getSchemaNormalizedValue()
{
    return fNormalizedValue;
}

inline const XMLCh* PSVIItem::getSchemaDefault()
{
    return fDefaultValue;
}

inline const XMLCh* PSVIItem::getCanonicalRepresentation()
{
    return fCanonicalValue;
}

inline PSVIItem::VALIDITY_STATE PSVIItem::getValidity() const
{
    return fValidityState;
}
inline PSVIItem::ASSESSMENT_TYPE PSVIItem::getValidationAttempted() const
inline bool PSVIItem::getIsSchemaSpecified() const
{
    return fIsSpecified;
}

{
    return fAssessmentType;
}

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>fix compilation error<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 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) 1999, 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.7  2003/11/27 17:58:59  neilg
 * fix compilation error
 *
 * Revision 1.6  2003/11/27 16:44:59  neilg
 * implement isSpecified; thanks to Pete Lloyd
 *
 * Revision 1.5  2003/11/27 06:10:32  neilg
 * PSVIAttribute implementation
 *
 * Revision 1.4  2003/11/25 16:14:28  neilg
 * move inlines into PSVIItem.hpp
 *
 * Revision 1.3  2003/11/21 22:34:45  neilg
 * More schema component model implementation, thanks to David Cargill.
 * In particular, this cleans up and completes the XSModel, XSNamespaceItem,
 * XSAttributeDeclaration and XSAttributeGroup implementations.
 *
 * Revision 1.2  2003/11/06 15:30:04  neilg
 * first part of PSVI/schema component model implementation, thanks to David Cargill.  This covers setting the PSVIHandler on parser objects, as well as implementing XSNotation, XSSimpleTypeDefinition, XSIDCDefinition, and most of XSWildcard, XSComplexTypeDefinition, XSElementDeclaration, XSAttributeDeclaration and XSAttributeUse.
 *
 * Revision 1.1  2003/09/16 14:33:36  neilg
 * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
 *
 */

#if !defined(PSVIITEM_HPP)
#define PSVIITEM_HPP

#include <xercesc/util/PlatformUtils.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/**
 * Represent the PSVI contributions for one element or one attribute information item.
 * This is *always* owned by the validator /parser object from which
 * it is obtained.  It is designed to be subclassed; subclasses will
 * specify under what conditions it may be relied upon to have meaningful contents.
 */

// forward declarations
class XSTypeDefinition;
class XSSimpleTypeDefinition;

class XMLPARSER_EXPORT PSVIItem : public XMemory
{
public:

    enum VALIDITY_STATE {
	    /** Validity value indicating that validation has either not
	    been performed or that a strict assessment of validity could
	    not be performed
	    */
	    VALIDITY_NOTKNOWN               = 0,

	    /** Validity value indicating that validation has been strictly
	     assessed and the element in question is invalid according to the
	     rules of schema validation.
	    */
	    VALIDITY_INVALID               = 1,

	    /** Validity value indicating that validation has been strictly
	     assessed and the element in question is valid according to the rules
	     of schema validation.
	     */
	    VALIDITY_VALID                 = 2
    };

    enum ASSESSMENT_TYPE {
	    /** Validation status indicating that schema validation has been
	     performed and the element in question has specifically been skipped.
	     */
	    VALIDATION_NONE                = 0,

	    /** Validation status indicating that schema validation has been
	    performed on the element in question under the rules of lax validation.
	    */
	    VALIDATION_PARTIAL             = 1,

	    /**  Validation status indicating that full schema validation has been
	    performed on the element.  */
	    VALIDATION_FULL                = 2
    };

    //  Constructors and Destructor
    // -----------------------------------------------------------------------
    /** @name Constructors */
    //@{

    /**
      * The default constructor
      *
      * @param  manager     The configurable memory manager
      */
    PSVIItem(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);

    //@};

    /** @name Destructor */
    //@{
    virtual ~PSVIItem();
    //@}

    //---------------------
    /** @name PSVIItem methods */

    //@{

    /**
     * [validation context]
     *
     * @return A string identifying the nearest ancestor element
     *          information item with a [schema information] property
     *         (or this element item itself if it has such a property)
     *          (form to be determined)
     * @see XML Schema Part 1: Structures [validation context]
     */
    const XMLCh *getValidationContext();

    /**
     * Determine the validity of the node with respect
     * to the validation being attempted
     *
     * @return return the [validity] property. Possible values are:
     *         VALIDITY_UNKNOWN, VALIDITY_INVALID, VALIDITY_VALID
     */
    VALIDITY_STATE getValidity() const;

    /**
     * Determines the extent to which the item has been validated
     *
     * @return return the [validation attempted] property. The possible values are
     *         VALIDATION_NONE, VALIDATION_ORDERED_PARTIAL and VALIDATION_FULL
     */
    ASSESSMENT_TYPE getValidationAttempted() const;

    /**
     * A list of error codes generated from validation attempts.
     * Need to find all the possible subclause reports that need reporting
     *
     * @return list of error codes
     */
    /***
    const XMLCh ** getErrorCodes();
    ****/

    /**
     * [schema normalized value]
     *
     * @see XML Schema Part 1: Structures [schema normalized value]
     * @return the normalized value of this item after validation
     */
    const XMLCh *getSchemaNormalizedValue();

    /**
     * An item isomorphic to the type definition used to validate this element.
     *
     * @return  a type declaration
     */
    virtual XSTypeDefinition *getTypeDefinition() = 0;

    /**
     * If and only if that type definition is a simple type definition
     * with {variety} union, or a complex type definition whose {content type}
     * is a simple thype definition with {variety} union, then an item isomorphic
     * to that member of the union's {member type definitions} which actually
     * validated the element item's normalized value.
     *
     * @return  a simple type declaration
     */
    virtual XSSimpleTypeDefinition *getMemberTypeDefinition() = 0;

    /**
     * [schema default]
     *
     * @return The canonical lexical representation of the declaration's {value constraint} value.
     * @see XML Schema Part 1: Structures [schema default]
     */
    const XMLCh *getSchemaDefault();

    /**
     * [schema specified]
     * @see XML Schema Part 1: Structures [schema specified]
     * @return true - value was specified in schema, false - value comes from the infoset
     */
    bool getIsSchemaSpecified() const;

    /**
     * Return the canonical representation of this value.
     * Note that, formally, this is not a PSVI property.
     * @return string representing the canonical representation, if this item
     * was validated by a simple type definition for which canonical
     * representations of values are defined.
     */
    const XMLCh *getCanonicalRepresentation();

    //@}

    //----------------------------------
    /** methods needed by implementation */

    //@{

    void setValidationAttempted(PSVIItem::ASSESSMENT_TYPE attemptType);
    void setValidity(PSVIItem::VALIDITY_STATE validity);

    /** reset the object
     * @param validationContext:  corresponds to schema validation context property
     * @param normalizedValue:  corresponds to schema normalized value property
     * @param validityState:  state of item's validity
     * @param assessmentType:  type of assessment carried out on item
     */
    void reset(
            const XMLCh* const validationContext
            , const XMLCh* const normalizedValue
            , const VALIDITY_STATE validityState
            , const ASSESSMENT_TYPE assessmentType
        );
    //@}
private:

    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    PSVIItem(const PSVIItem&);
    PSVIItem & operator=(const PSVIItem &);

protected:
    // -----------------------------------------------------------------------
    //  data members
    // -----------------------------------------------------------------------
    // fMemoryManager:
    //  used for any memory allocations
    // fValidationContext
    //  corresponds to the schema [validation context] property
    // fNormalizedValue
    //  The schema normalized value (when present)
    // fDefaultValue
    //  default value specified in the schema, if any
    // fCanonicalValue
    //  canonicalized version of normalizedValue
    // fValidityState
    //  Whether this item is valid or not
    // fAssessmentType
    //  The kind of assessment that produced the given validity outcome
    // fIsSpecified
    //  Whether this item exists because a default was specified in the schema
    // fType
    //  type responsible for validating this item
    // fMemberType
    //  If fType is a union type, the member type that validated this item
    MemoryManager* const        fMemoryManager;
    const XMLCh*                fValidationContext;
    const XMLCh*                fNormalizedValue;
    const XMLCh*                fDefaultValue;
    const XMLCh*                fCanonicalValue;
    VALIDITY_STATE              fValidityState;
    ASSESSMENT_TYPE             fAssessmentType;
    bool                        fIsSpecified;
    XSTypeDefinition *          fType;
    XSSimpleTypeDefinition*     fMemberType;
};

inline PSVIItem::~PSVIItem() {}

inline const XMLCh *PSVIItem::getValidationContext()
{
    return fValidationContext;
}

inline const XMLCh* PSVIItem::getSchemaNormalizedValue()
{
    return fNormalizedValue;
}

inline const XMLCh* PSVIItem::getSchemaDefault()
{
    return fDefaultValue;
}

inline const XMLCh* PSVIItem::getCanonicalRepresentation()
{
    return fCanonicalValue;
}

inline PSVIItem::VALIDITY_STATE PSVIItem::getValidity() const
{
    return fValidityState;
}

inline bool PSVIItem::getIsSchemaSpecified() const
{
    return fIsSpecified;
}

inline PSVIItem::ASSESSMENT_TYPE PSVIItem::getValidationAttempted() const
{
    return fAssessmentType;
}

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 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) 1999, 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  2004/05/04 19:02:40  cargilld
 * Enable IDs to work on all kinds of schema components
 *
 * Revision 1.8  2003/11/21 17:34:04  knoaman
 * PSVI update
 *
 * Revision 1.7  2003/11/15 21:18:39  neilg
 * fixes for compilation under gcc
 *
 * Revision 1.6  2003/11/14 22:47:53  neilg
 * fix bogus log message from previous commit...
 *
 * Revision 1.5  2003/11/14 22:33:30  neilg
 * Second phase of schema component model implementation.
 * Implement XSModel, XSNamespaceItem, and the plumbing necessary
 * to connect them to the other components.
 * Thanks to David Cargill.
 *
 * Revision 1.4  2003/10/15 16:02:49  peiyongz
 * Solve Linkage error on Solaris
 *
 * Revision 1.3  2003/10/10 18:37:51  neilg
 * update XSModel and XSObject interface so that IDs can be used to query components in XSModels, and so that those IDs can be recovered from components
 *
 * Revision 1.2  2003/09/17 17:45:37  neilg
 * remove spurious inlines; hopefully this will make Solaris/AIX compilers happy.
 *
 * Revision 1.1  2003/09/16 14:33:36  neilg
 * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
 *
 */

#include <xercesc/framework/psvi/XSObject.hpp>
#include <xercesc/framework/psvi/XSModel.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XSObject: Constructors and Destructor
// ---------------------------------------------------------------------------
XSObject::XSObject(XSConstants::COMPONENT_TYPE compType,
                   XSModel* const xsModel,
                   MemoryManager* const manager)
    : fComponentType(compType)
    , fXSModel(xsModel)
    , fMemoryManager(manager)
    , fId(0)
{
    if (xsModel)
    {
        xsModel->addComponentToIdVector(this, compType-1);
    }
}

XSObject::~XSObject()
{
}

// ---------------------------------------------------------------------------
//  XSObject: Virtual interface methods
// ---------------------------------------------------------------------------
const XMLCh *XSObject::getName()
{
    return 0;
}

const XMLCh *XSObject::getNamespace()
{
    return 0;
}

XSNamespaceItem *XSObject::getNamespaceItem()
{
    return 0;
}

unsigned int XSObject::getId() const
{
    return fId;
}

inline void XSObject::setId(unsigned int id)
{
    fId = id;
}

XERCES_CPP_NAMESPACE_END

<commit_msg>remove inline<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 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) 1999, 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  2004/05/05 14:50:41  peiyongz
 * remove inline
 *
 * Revision 1.9  2004/05/04 19:02:40  cargilld
 * Enable IDs to work on all kinds of schema components
 *
 * Revision 1.8  2003/11/21 17:34:04  knoaman
 * PSVI update
 *
 * Revision 1.7  2003/11/15 21:18:39  neilg
 * fixes for compilation under gcc
 *
 * Revision 1.6  2003/11/14 22:47:53  neilg
 * fix bogus log message from previous commit...
 *
 * Revision 1.5  2003/11/14 22:33:30  neilg
 * Second phase of schema component model implementation.
 * Implement XSModel, XSNamespaceItem, and the plumbing necessary
 * to connect them to the other components.
 * Thanks to David Cargill.
 *
 * Revision 1.4  2003/10/15 16:02:49  peiyongz
 * Solve Linkage error on Solaris
 *
 * Revision 1.3  2003/10/10 18:37:51  neilg
 * update XSModel and XSObject interface so that IDs can be used to query components in XSModels, and so that those IDs can be recovered from components
 *
 * Revision 1.2  2003/09/17 17:45:37  neilg
 * remove spurious inlines; hopefully this will make Solaris/AIX compilers happy.
 *
 * Revision 1.1  2003/09/16 14:33:36  neilg
 * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
 *
 */

#include <xercesc/framework/psvi/XSObject.hpp>
#include <xercesc/framework/psvi/XSModel.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XSObject: Constructors and Destructor
// ---------------------------------------------------------------------------
XSObject::XSObject(XSConstants::COMPONENT_TYPE compType,
                   XSModel* const xsModel,
                   MemoryManager* const manager)
    : fComponentType(compType)
    , fXSModel(xsModel)
    , fMemoryManager(manager)
    , fId(0)
{
    if (xsModel)
    {
        xsModel->addComponentToIdVector(this, compType-1);
    }
}

XSObject::~XSObject()
{
}

// ---------------------------------------------------------------------------
//  XSObject: Virtual interface methods
// ---------------------------------------------------------------------------
const XMLCh *XSObject::getName()
{
    return 0;
}

const XMLCh *XSObject::getNamespace()
{
    return 0;
}

XSNamespaceItem *XSObject::getNamespaceItem()
{
    return 0;
}

unsigned int XSObject::getId() const
{
    return fId;
}

void XSObject::setId(unsigned int id)
{
    fId = id;
}

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_MAT_FUN_COV_EXP_QUAD_HPP
#define STAN_MATH_PRIM_MAT_FUN_COV_EXP_QUAD_HPP

#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/err/check_size_match.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/prim/mat/fun/squared_distance.hpp>
#include <stan/math/prim/scal/err/check_not_nan.hpp>
#include <stan/math/prim/scal/err/check_positive.hpp>
#include <stan/math/prim/scal/fun/square.hpp>
#include <stan/math/prim/scal/fun/exp.hpp>
#include <stan/math/prim/mat/fun/cumulative_sum.hpp>
#include <stan/math/prim/mat/fun/multiply.hpp>
#include <vector>
#include <cmath>

namespace stan {
  namespace math {

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x type of std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of length scale
     *
     * @param x std::vector of elements that can be used in square distance.
     *    This function assumes each element of x is the same size.
     * @param sigma standard deviation
     * @param l length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template <typename T_x, typename T_sigma, typename T_l>
    inline
    typename Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
                           Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x>& x, const T_sigma& sigma,
                 const T_l& length_scale) {
      using std::exp;
      check_positive("cov_exp_quad", "marginal variance", sigma);
      check_positive("cov_exp_quad", "length-scale", length_scale);
      for (size_t n = 0; n < x.size(); ++n)
	check_not_nan("cov_exp_quad", "x", x[n]);

      Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
		    Eigen::Dynamic, Eigen::Dynamic>
	cov(x.size(), x.size());

      int x_size = x.size();
      if (x_size == 0)
	return cov;

      T_sigma sigma_sq = square(sigma);
      T_l neg_half_inv_l_sq = -0.5 / square(length_scale);

      for (int j = 0; j < (x_size - 1); ++j) {
	cov(j, j) = sigma_sq;
	for (int i = j + 1; i < x_size; ++i) {
	  cov(i, j)
	    = sigma_sq * exp(squared_distance(x[i], x[j]) * neg_half_inv_l_sq);
	  cov(j, i) = cov(i, j);
	}
      }
      cov(x_size - 1, x_size - 1) = sigma_sq;
      return cov;
    }

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x type of std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of std::vector of length scale
     *
     * @param x std::vector of elements that can be used in square distance.
     *    This function assumes each element of x is the same size.
     * @param sigma standard deviation
     * @param l std::vector length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template<typename T_x, typename T_sigma, typename T_l>
    inline typename
    Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
                  Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x>& x,
                 const T_sigma& sigma,
		 const std::vector<T_l>& length_scale) {
      using std::exp;

      check_positive("cov_exp_quad", "marginal variance", sigma);
      for (size_t n = 0; n < x.size(); ++n) {
        check_not_nan("cov_exp_quad", "x", x[n]);
      }
      for(size_t n = 0; n < length_scale.size(); ++n) {
	check_positive("cov_exp_quad", "length-scale",
		       length_scale[n]);
	check_not_nan("cov_exp_quad", "length-scale",
		      length_scale[n]);
      }

      Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
                    Eigen::Dynamic, Eigen::Dynamic>
        cov(x.size(), x.size());

      int x_size = x.size();
      int l_size = length_scale.size();
      if (x_size == 0)
        return cov;

      T_sigma sigma_sq = square(sigma);
      T_l temp_exp;

      for (int j = 0; j < (x_size - 1); ++j) {
        cov(j, j) = sigma_sq;
        for (int i = j + 1; i < x_size; ++i) {
	  temp_exp = 0;
	  for(int k = 0; k < l_size; ++k) {
	    temp_exp += squared_distance(x[i], x[j])
	      / square(length_scale[k]);
	  }
	  cov(i, j) = sigma_sq * exp(-0.5 * temp_exp);
	  cov(j, i) = cov(i, j);
	}
      }
      cov(x_size - 1, x_size - 1) = sigma_sq;
      return cov;
    }

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x1 type of first std::vector of elements
     * @tparam T_x2 type of second std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of of length scale
     *
     * @param x1 std::vector of elements that can be used in square distance
     * @param x2 std::vector of elements that can be used in square distance
     * @param sigma standard deviation
     * @param l length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template<typename T_x1, typename T_x2, typename T_sigma, typename T_l>
    inline typename
    Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                  Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x1>& x1,
                 const std::vector<T_x2>& x2,
                 const T_sigma& sigma,
                 const T_l& length_scale) {
      using std::exp;
      check_positive("cov_exp_quad", "marginal variance", sigma);
      check_positive("cov_exp_quad", "length-scale", length_scale);
      for (size_t n = 0; n < x1.size(); ++n)
        check_not_nan("cov_exp_quad", "x1", x1[n]);
      for (size_t n = 0; n < x2.size(); ++n)
        check_not_nan("cov_exp_quad", "x2", x2[n]);

      Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                    Eigen::Dynamic, Eigen::Dynamic>
        cov(x1.size(), x2.size());
      if (x1.size() == 0 || x2.size() == 0)
        return cov;

      T_sigma sigma_sq = square(sigma);
      T_l neg_half_inv_l_sq = -0.5 / square(length_scale);

      for (size_t i = 0; i < x1.size(); ++i) {
        for (size_t j = 0; j < x2.size(); ++j) {
          cov(i, j) = sigma_sq * exp(squared_distance(x1[i], x2[j])
                                     * neg_half_inv_l_sq);
        }
      }
      return cov;
    }

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x1 type of first std::vector of elements
     * @tparam T_x2 type of second std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of length scale
     *
     * @param x1 std::vector of elements that can be used in square distance
     * @param x2 std::vector of elements that can be used in square distance
     * @param sigma standard deviation
     * @param l std::vector of length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template<typename T_x1, typename T_x2, typename T_sigma, typename T_l>
    inline typename
    Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                  Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x1>& x1,
                 const std::vector<T_x2>& x2,
                 const T_sigma& sigma,
                 const std::vector<T_l>& length_scale) {
      using std::exp;
      check_positive("cov_exp_quad", "marginal variance", sigma);
      for (size_t n = 0; n < x1.size(); ++n)
        check_not_nan("cov_exp_quad", "x1", x1[n]);
      for (size_t n = 0; n < x2.size(); ++n)
        check_not_nan("cov_exp_quad", "x2", x2[n]);
      for (size_t n = 0; n < length_scale.size(); ++n)
	check_positive("cov_exp_quad", "length-scale",
		       length_scale[n]);
      for (size_t n = 0; n < length_scale.size(); ++n)
	check_not_nan("cov_exp_quad", "length-scale",
		      length_scale[n]);

      Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                    Eigen::Dynamic, Eigen::Dynamic>
        cov(x1.size(), x2.size());
      if (x1.size() == 0 || x2.size() == 0)
        return cov;

      T_sigma sigma_sq = square(sigma);
      T_l temp_exp;

      for (size_t i = 0; i < x1.size(); ++i) {
        for (size_t j = 0; j < x2.size(); ++j) {
	  temp_exp = 0;
	  for(size_t k = 0; k < length_scale.size(); ++k) {
	    temp_exp += squared_distance(x1[i], x2[j])
	      / square(length_scale[k]);
	  }
	  cov(i, j) = sigma_sq * exp(-0.5 * temp_exp);
	}
      }
      return cov;
    }

  }
}
#endif
<commit_msg>remove unused includes<commit_after>#ifndef STAN_MATH_PRIM_MAT_FUN_COV_EXP_QUAD_HPP
#define STAN_MATH_PRIM_MAT_FUN_COV_EXP_QUAD_HPP

#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/err/check_size_match.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/prim/mat/fun/squared_distance.hpp>
#include <stan/math/prim/scal/err/check_not_nan.hpp>
#include <stan/math/prim/scal/err/check_positive.hpp>
#include <stan/math/prim/scal/fun/square.hpp>
#include <stan/math/prim/scal/fun/exp.hpp>
#include <vector>
#include <cmath>

namespace stan {
  namespace math {

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x type of std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of length scale
     *
     * @param x std::vector of elements that can be used in square distance.
     *    This function assumes each element of x is the same size.
     * @param sigma standard deviation
     * @param l length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template <typename T_x, typename T_sigma, typename T_l>
    inline
    typename Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
                           Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x>& x, const T_sigma& sigma,
                 const T_l& length_scale) {
      using std::exp;
      check_positive("cov_exp_quad", "marginal variance", sigma);
      check_positive("cov_exp_quad", "length-scale", length_scale);
      for (size_t n = 0; n < x.size(); ++n)
	check_not_nan("cov_exp_quad", "x", x[n]);

      Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
		    Eigen::Dynamic, Eigen::Dynamic>
	cov(x.size(), x.size());

      int x_size = x.size();
      if (x_size == 0)
	return cov;

      T_sigma sigma_sq = square(sigma);
      T_l neg_half_inv_l_sq = -0.5 / square(length_scale);

      for (int j = 0; j < (x_size - 1); ++j) {
	cov(j, j) = sigma_sq;
	for (int i = j + 1; i < x_size; ++i) {
	  cov(i, j)
	    = sigma_sq * exp(squared_distance(x[i], x[j]) * neg_half_inv_l_sq);
	  cov(j, i) = cov(i, j);
	}
      }
      cov(x_size - 1, x_size - 1) = sigma_sq;
      return cov;
    }

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x type of std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of std::vector of length scale
     *
     * @param x std::vector of elements that can be used in square distance.
     *    This function assumes each element of x is the same size.
     * @param sigma standard deviation
     * @param l std::vector length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template<typename T_x, typename T_sigma, typename T_l>
    inline typename
    Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
                  Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x>& x,
                 const T_sigma& sigma,
		 const std::vector<T_l>& length_scale) {
      using std::exp;

      check_positive("cov_exp_quad", "marginal variance", sigma);
      for (size_t n = 0; n < x.size(); ++n) {
        check_not_nan("cov_exp_quad", "x", x[n]);
      }
      for(size_t n = 0; n < length_scale.size(); ++n) {
	check_positive("cov_exp_quad", "length-scale",
		       length_scale[n]);
	check_not_nan("cov_exp_quad", "length-scale",
		      length_scale[n]);
      }

      Eigen::Matrix<typename stan::return_type<T_x, T_sigma, T_l>::type,
                    Eigen::Dynamic, Eigen::Dynamic>
        cov(x.size(), x.size());

      int x_size = x.size();
      int l_size = length_scale.size();
      if (x_size == 0)
        return cov;

      T_sigma sigma_sq = square(sigma);
      T_l temp_exp;

      for (int j = 0; j < (x_size - 1); ++j) {
        cov(j, j) = sigma_sq;
        for (int i = j + 1; i < x_size; ++i) {
	  temp_exp = 0;
	  for(int k = 0; k < l_size; ++k) {
	    temp_exp += squared_distance(x[i], x[j])
	      / square(length_scale[k]);
	  }
	  cov(i, j) = sigma_sq * exp(-0.5 * temp_exp);
	  cov(j, i) = cov(i, j);
	}
      }
      cov(x_size - 1, x_size - 1) = sigma_sq;
      return cov;
    }

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x1 type of first std::vector of elements
     * @tparam T_x2 type of second std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of of length scale
     *
     * @param x1 std::vector of elements that can be used in square distance
     * @param x2 std::vector of elements that can be used in square distance
     * @param sigma standard deviation
     * @param l length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template<typename T_x1, typename T_x2, typename T_sigma, typename T_l>
    inline typename
    Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                  Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x1>& x1,
                 const std::vector<T_x2>& x2,
                 const T_sigma& sigma,
                 const T_l& length_scale) {
      using std::exp;
      check_positive("cov_exp_quad", "marginal variance", sigma);
      check_positive("cov_exp_quad", "length-scale", length_scale);
      for (size_t n = 0; n < x1.size(); ++n)
        check_not_nan("cov_exp_quad", "x1", x1[n]);
      for (size_t n = 0; n < x2.size(); ++n)
        check_not_nan("cov_exp_quad", "x2", x2[n]);

      Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                    Eigen::Dynamic, Eigen::Dynamic>
        cov(x1.size(), x2.size());
      if (x1.size() == 0 || x2.size() == 0)
        return cov;

      T_sigma sigma_sq = square(sigma);
      T_l neg_half_inv_l_sq = -0.5 / square(length_scale);

      for (size_t i = 0; i < x1.size(); ++i) {
        for (size_t j = 0; j < x2.size(); ++j) {
          cov(i, j) = sigma_sq * exp(squared_distance(x1[i], x2[j])
                                     * neg_half_inv_l_sq);
        }
      }
      return cov;
    }

    /**
     * Returns a squared exponential kernel.
     *
     * @tparam T_x1 type of first std::vector of elements
     * @tparam T_x2 type of second std::vector of elements
     * @tparam T_sigma type of sigma
     * @tparam T_l type of length scale
     *
     * @param x1 std::vector of elements that can be used in square distance
     * @param x2 std::vector of elements that can be used in square distance
     * @param sigma standard deviation
     * @param l std::vector of length scale
     * @return squared distance
     * @throw std::domain_error if sigma <= 0, l <= 0, or
     *   x is nan or infinite
     */
    template<typename T_x1, typename T_x2, typename T_sigma, typename T_l>
    inline typename
    Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                  Eigen::Dynamic, Eigen::Dynamic>
    cov_exp_quad(const std::vector<T_x1>& x1,
                 const std::vector<T_x2>& x2,
                 const T_sigma& sigma,
                 const std::vector<T_l>& length_scale) {
      using std::exp;
      check_positive("cov_exp_quad", "marginal variance", sigma);
      for (size_t n = 0; n < x1.size(); ++n)
        check_not_nan("cov_exp_quad", "x1", x1[n]);
      for (size_t n = 0; n < x2.size(); ++n)
        check_not_nan("cov_exp_quad", "x2", x2[n]);
      for (size_t n = 0; n < length_scale.size(); ++n)
	check_positive("cov_exp_quad", "length-scale",
		       length_scale[n]);
      for (size_t n = 0; n < length_scale.size(); ++n)
	check_not_nan("cov_exp_quad", "length-scale",
		      length_scale[n]);

      Eigen::Matrix<typename stan::return_type<T_x1, T_x2, T_sigma, T_l>::type,
                    Eigen::Dynamic, Eigen::Dynamic>
        cov(x1.size(), x2.size());
      if (x1.size() == 0 || x2.size() == 0)
        return cov;

      T_sigma sigma_sq = square(sigma);
      T_l temp_exp;

      for (size_t i = 0; i < x1.size(); ++i) {
        for (size_t j = 0; j < x2.size(); ++j) {
	  temp_exp = 0;
	  for(size_t k = 0; k < length_scale.size(); ++k) {
	    temp_exp += squared_distance(x1[i], x2[j])
	      / square(length_scale[k]);
	  }
	  cov(i, j) = sigma_sq * exp(-0.5 * temp_exp);
	}
      }
      return cov;
    }
  }
}
#endif
<|endoftext|>


<commit_before>/*
MIT License

Copyright (c) 2017 Marc Haisenko

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "MHGroveBLE.h"

/*
Some notes about the Seeed Grove BLE:

The commands and responses are sent and received WITHOUT any delimiters like
"\r\n". After sending the command, you just wait for the response. You know the
reponse is complete if you don't receive any more stuff so you have to wait for
a timeout.

How utterly stupid! But that's the way it is.
*/

static const unsigned long kDefaultTimeout = 500;
static const unsigned long kRetryTimeout = 500;
static const unsigned long kWaitForDeviceTimeout = 5000;
static const unsigned long kConnectedReadTimeout = 50;

/** Internal state. */
enum class MHGroveBLE::InternalState {
  /** Initial state. */
  startup,
  /** Send "AT" periodically and wait until the device responds. */
  waitForDeviceAfterStartup,
  /** Set the Bluetooth name. */
  setName,
  /** Set the device role. */
  setRole,
  /** Set that we want to be notified about connections. */
  setNotification,
  /** Reset after setting the device up. */
  reset,
  /** Send "AT" periodically and wait until the device responds. */
  waitForDeviceAfterReset,
  /** Initialization is done, inform the handler. */
  initializationComplete,

  /** Waiting for a connection. */
  waitingForConnection,
  /** A peer has connected. */
  connected,

  /** An unrecoverable error occurred, operation is halted. */
  panicked
};

/** Return value for `receiveResponse`. */
enum class MHGroveBLE::ResponseState {
  /** Still receiving data. */
  receiving,
  /** Nothing received so far, need to resend the command. */
  needRetry,
  /** The timeout has been reached, no data received. */
  timedOut,
  /** The retry or timeout time has been reached, we have data in `rxBuffer`. */
  success
};

/** Internal helper: calculate whether a timeout occurred.

 Handles `millies()` overflow.
 */
static bool isTimeout(unsigned long now, unsigned long referenceTime, unsigned long duration)
{
  return (now - referenceTime) >= duration;
}

MHGroveBLE::MHGroveBLE(
  Stream & device,
  const char * name,
  unsigned int rxBufferSize
) :
  device(device),
  name(name),
  rxBufferSize(rxBufferSize),
  internalState(InternalState::startup)
{
  rxBuffer.reserve(rxBufferSize);
}

void MHGroveBLE::runOnce()
{
  switch (internalState) {
    case InternalState::startup:
      transitionToState(InternalState::waitForDeviceAfterStartup);
      break;

    case InternalState::waitForDeviceAfterStartup:
    case InternalState::waitForDeviceAfterReset:
      handleWaitForDevice();
      break;

    case InternalState::setName:
    case InternalState::setRole:
    case InternalState::setNotification:
      handleGenericCommand();
      break;

    case InternalState::reset:
      handleReset();
      break;

    case InternalState::initializationComplete:
      // It should not be possible to end up here since we immediately
      // transition to the `waitingForConnection` state.
      break;

    case InternalState::waitingForConnection:
      handleWaitForConnect();
      break;

    case InternalState::connected:
      handleConnected();
      break;

    case InternalState::panicked:
      // Once we've panicked we won't do anything again.
      break;
  }
}

MHGroveBLE::State MHGroveBLE::getState() {
  switch (internalState) {
    case InternalState::panicked:   return State::panicked;
    case InternalState::waitingForConnection: return State::waitingForConnection;
    case InternalState::connected:  return State::connected;
    default:                        return State::initializing;
  }
}

void MHGroveBLE::setOnReady(void (*onFunc)())
{
  onReady = onFunc;
}

void MHGroveBLE::setOnPanic(void (*onFunc)())
{
  onPanic = onFunc;
}

void MHGroveBLE::setOnConnect(void (*onFunc)())
{
  onConnect = onFunc;
}

void MHGroveBLE::setOnDisconnect(void (*onFunc)())
{
  onDisconnect = onFunc;
}

void MHGroveBLE::setOnDataReceived(void (*onFunc)(const String &))
{
  onDataReceived = onFunc;

}

void MHGroveBLE::setDebug(void (*debugFunc)(const char *))
{
  debug = debugFunc;
}

bool MHGroveBLE::send(const String & data)
{
  if (internalState != InternalState::connected) {
    return false;
  }

  device.print(data);
  return true;
}

/*******************************************************************************
 * Private section
 ******************************************************************************/

void MHGroveBLE::sendCommand(const String & command)
{
  if (debug) {
    String text = F("Sending command: ");
    text += command;
    debug(text.c_str());
  }

  device.print(command);

  // Clear the receive buffer after sending a command.
  rxBuffer = "";
}

MHGroveBLE::ResponseState MHGroveBLE::receiveResponse()
{
  unsigned long now = millis();
  bool timeoutReached = isTimeout(now, timeoutReferenceTime, timeoutDuration);
  bool retryReached =
    retryDuration > 0
    ? isTimeout(now, retryReferenceTime, retryDuration)
    : false;

  readIntoBuffer();

  if (retryReached || timeoutReached) {
    if (rxBuffer.length() > 0) {
      // We reached a timeout and have data! We're done.
      if (debug) {
        String text = F("Received response: ");
        text += rxBuffer;
        debug(text.c_str());
      }
      return ResponseState::success;

    } else if (timeoutReached) {
      // The hard timeout has been reached.
      return ResponseState::timedOut;

    } else {
      // The retry timeout (soft timeout) has been reached. Reset the reference
      // time to start the next retry phase.
      retryReferenceTime = now;
      return ResponseState::needRetry;
    }

  } else {
    // No timeout reached yet, keep on reading.
    return ResponseState::receiving;
  }
}

void MHGroveBLE::transitionToState(MHGroveBLE::InternalState nextState)
{
  unsigned long now = millis();

  if (debug) {
    String text = F("Transitioning to state: ");
    text += (int)nextState;
    debug(text.c_str());
  }

  switch (nextState) {
    case InternalState::startup: break;

    case InternalState::waitForDeviceAfterStartup:
      sendCommand(F("AT"));
      retryReferenceTime = now;
      retryDuration = kRetryTimeout;
      timeoutReferenceTime = now;
      timeoutDuration = kWaitForDeviceTimeout;
      break;

    case InternalState::setName: {
      String command = F("AT+NAME");
      command += name;
      sendCommand(command);
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kDefaultTimeout;
      genericNextInternalState = InternalState::setRole;
      break;
    }

    case InternalState::setRole:
      sendCommand(F("AT+ROLE0"));
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kDefaultTimeout;
      genericNextInternalState = InternalState::setNotification;
      break;

    case InternalState::setNotification:
      sendCommand(F("AT+NOTI1"));
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kDefaultTimeout;
      genericNextInternalState = InternalState::reset;
      break;

    case InternalState::reset:
      sendCommand(F("AT+RESET"));
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kDefaultTimeout;
      break;

    case InternalState::waitForDeviceAfterReset:
      sendCommand(F("AT"));
      retryReferenceTime = now;
      retryDuration = kRetryTimeout;
      timeoutReferenceTime = now;
      timeoutDuration = kWaitForDeviceTimeout;
      break;

    case InternalState::initializationComplete:
      if (onReady) {
        onReady();
      }
      break;

    case InternalState::waitingForConnection:
      if (internalState == InternalState::connected && onDisconnect) {
        onDisconnect();
      }
      rxBuffer = "";
      // No timeout handling in this state.
      break;

    case InternalState::connected:
      if (onConnect) {
        onConnect();
      }
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = 0;
      timeoutDuration = 0;
      break;

    case InternalState::panicked:
      if (debug) {
        debug("Panic!");
      }
      if (onPanic) {
        onPanic();
      }
      break;
  }

  internalState = nextState;

  if (nextState == InternalState::initializationComplete) {
    // When we've reached the `initializationComplete` state, we want to inform
    // the handler (done above) and then continue to the `waitingForConnection`
    // state right away.
    transitionToState(InternalState::waitingForConnection);
  }
}

bool MHGroveBLE::readIntoBuffer()
{
  bool didReceive = false;

  while (device.available() > 0) {
    int value = device.read();
    if (value < 0) {
      // Shouldn't happen? We asked whether there's stuff available!
      break;
    }

    if (rxBuffer.length() == rxBufferSize) {
      // We don't want to grow the receive buffer. Discard old data.
      rxBuffer.remove(0, 1);
    }

    rxBuffer += (char)value;
    didReceive = true;
  }

  return didReceive;
}

void MHGroveBLE::handleWaitForDevice()
{
  switch (receiveResponse()) {
    case ResponseState::receiving:
      break;

    case ResponseState::needRetry:
      sendCommand(F("AT"));
      break;

    case ResponseState::timedOut:
      panic();
      break;

    case ResponseState::success:
      switch (internalState) {
        case InternalState::waitForDeviceAfterStartup:
          transitionToState(InternalState::setName);
          break;

        case InternalState::waitForDeviceAfterReset:
          transitionToState(InternalState::initializationComplete);
          break;

        default:
          // Bug! Must not happen.
          panic();
      }
      break;
  }
}

void MHGroveBLE::handleGenericCommand()
{
  switch (receiveResponse()) {
    case ResponseState::receiving:
      break;

    case ResponseState::needRetry: // Bug, must not happen
    case ResponseState::timedOut:
      panic();
      break;

    case ResponseState::success:
      transitionToState(genericNextInternalState);
      break;
  }
}

void MHGroveBLE::handleReset()
{
  switch (receiveResponse()) {
    case ResponseState::receiving:
      break;

    case ResponseState::needRetry: // Bug, must not happen
      panic();
      break;

    case ResponseState::timedOut:
      // Try waiting for the device.
      // Fall-through
    case ResponseState::success:
      transitionToState(InternalState::waitForDeviceAfterReset);
      break;
  }
}

void MHGroveBLE::handleWaitForConnect()
{
  if (!readIntoBuffer()) {
    return;
  }

  if (rxBuffer.indexOf(F("OK+CONN")) != -1) {
    rxBuffer = "";
    // Once we've received this string immediately transition to the "connected"
    // state. There's no point in waiting for a timeout like when we're waiting
    // for AT command responses.
    // The point of doing this with `indexOf` is to recover if we have received
    // garbage before.
    transitionToState(InternalState::connected);
  }
}

void MHGroveBLE::handleConnected()
{
  unsigned long now = millis();
  bool connectionClosed = false;
  bool dataWasRead = readIntoBuffer();
  bool timeoutReached =
    timeoutDuration > 0
    ? isTimeout(now, timeoutReferenceTime, timeoutDuration)
    : false;

  if (!dataWasRead && !timeoutReached) {
    // Nothing happened, no need to react yet.
    return;
  }

  if (dataWasRead) {
    // Every time we read data we need to reset our timeout to avoid
    // timing out in the middle of a stream.
    timeoutReferenceTime = now;
    timeoutDuration = kConnectedReadTimeout;
  }

  // Pass the data to the handler if either the timeout occurred or if the
  // receive buffer is full. The later is necessary to not lose any data.
  if (timeoutReached || rxBuffer.length() == rxBufferSize) {
    // The Grove BLE sends "OK+LOST" when the connection is closed.
    // Unfortunately, an app is also able to send this string and we don't know
    // whether the Grove BLE or the app has sent it.
    // This is why `handleWaitForConnect` also needs to be able to handle
    // garbage: it's possible that an app sends "OK+LOST" and once the
    // connection is really closed, another "OK+LOST" is sent by Grove BLE
    // before the "OK+CONN" for a new connection arrives.
    int index = rxBuffer.lastIndexOf(F("OK+LOST"));
    // Check whether it's the last thing in the buffer to avoid reacting on the
    // string being part of some other text.
    if (index >= 0 && ((unsigned)index+7 == rxBuffer.length())) {
      connectionClosed = true;
      // Remove the sentinel.
      rxBuffer.remove(index);
    }

    // Pass the data to the handler...
    if (onDataReceived && rxBuffer.length() > 0) {
      onDataReceived(rxBuffer);
    }
    // ... and clear it.
    rxBuffer = "";
    timeoutReferenceTime = 0;
    timeoutDuration = 0;
  }

  if (connectionClosed) {
    transitionToState(InternalState::waitingForConnection);
  }
}

void MHGroveBLE::panic()
{
  transitionToState(InternalState::panicked);
}
<commit_msg>Reset the Grove BLE to factory default on startup, temporarily increase command timeout to 1 second<commit_after>/*
MIT License

Copyright (c) 2017 Marc Haisenko

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "MHGroveBLE.h"

/*
Some notes about the Seeed Grove BLE:

The commands and responses are sent and received WITHOUT any delimiters like
"\r\n". After sending the command, you just wait for the response. You know the
reponse is complete if you don't receive any more stuff so you have to wait for
a timeout.

How utterly stupid! But that's the way it is.
*/

static const unsigned long kGenericCommandTimeout = 1000;
static const unsigned long kRetryTimeout = 500;
static const unsigned long kWaitForDeviceTimeout = 5000;
static const unsigned long kConnectedReadTimeout = 50;

/** Internal state. */
enum class MHGroveBLE::InternalState {
  /** Initial state. */
  startup,
  /** Send "AT" periodically and wait until the device responds. */
  waitForDeviceAfterStartup,
  /** Reset all settings to their factory defaults. */
  renew,
  /** Set the Bluetooth name. */
  setName,
  /** Set that we want to be notified about connections. */
  setNotification,
  /** Reset after setting the device up. */
  reset,
  /** Send "AT" periodically and wait until the device responds. */
  waitForDeviceAfterReset,
  /** Initialization is done, inform the handler. */
  initializationComplete,

  /** Waiting for a connection. */
  waitingForConnection,
  /** A peer has connected. */
  connected,

  /** An unrecoverable error occurred, operation is halted. */
  panicked
};

/** Return value for `receiveResponse`. */
enum class MHGroveBLE::ResponseState {
  /** Still receiving data. */
  receiving,
  /** Nothing received so far, need to resend the command. */
  needRetry,
  /** The timeout has been reached, no data received. */
  timedOut,
  /** The retry or timeout time has been reached, we have data in `rxBuffer`. */
  success
};

/** Internal helper: calculate whether a timeout occurred.

 Handles `millies()` overflow.
 */
static bool isTimeout(unsigned long now, unsigned long referenceTime, unsigned long duration)
{
  return (now - referenceTime) >= duration;
}

MHGroveBLE::MHGroveBLE(
  Stream & device,
  const char * name,
  unsigned int rxBufferSize
) :
  device(device),
  name(name),
  rxBufferSize(rxBufferSize),
  internalState(InternalState::startup)
{
  rxBuffer.reserve(rxBufferSize);
}

void MHGroveBLE::runOnce()
{
  switch (internalState) {
    case InternalState::startup:
      transitionToState(InternalState::waitForDeviceAfterStartup);
      break;

    case InternalState::waitForDeviceAfterStartup:
    case InternalState::waitForDeviceAfterReset:
      handleWaitForDevice();
      break;

    case InternalState::renew:
    case InternalState::setName:
    case InternalState::setNotification:
      handleGenericCommand();
      break;

    case InternalState::reset:
      handleReset();
      break;

    case InternalState::initializationComplete:
      // It should not be possible to end up here since we immediately
      // transition to the `waitingForConnection` state.
      break;

    case InternalState::waitingForConnection:
      handleWaitForConnect();
      break;

    case InternalState::connected:
      handleConnected();
      break;

    case InternalState::panicked:
      // Once we've panicked we won't do anything again.
      break;
  }
}

MHGroveBLE::State MHGroveBLE::getState() {
  switch (internalState) {
    case InternalState::panicked:   return State::panicked;
    case InternalState::waitingForConnection: return State::waitingForConnection;
    case InternalState::connected:  return State::connected;
    default:                        return State::initializing;
  }
}

void MHGroveBLE::setOnReady(void (*onFunc)())
{
  onReady = onFunc;
}

void MHGroveBLE::setOnPanic(void (*onFunc)())
{
  onPanic = onFunc;
}

void MHGroveBLE::setOnConnect(void (*onFunc)())
{
  onConnect = onFunc;
}

void MHGroveBLE::setOnDisconnect(void (*onFunc)())
{
  onDisconnect = onFunc;
}

void MHGroveBLE::setOnDataReceived(void (*onFunc)(const String &))
{
  onDataReceived = onFunc;

}

void MHGroveBLE::setDebug(void (*debugFunc)(const char *))
{
  debug = debugFunc;
}

bool MHGroveBLE::send(const String & data)
{
  if (internalState != InternalState::connected) {
    return false;
  }

  device.print(data);
  return true;
}

/*******************************************************************************
 * Private section
 ******************************************************************************/

void MHGroveBLE::sendCommand(const String & command)
{
  if (debug) {
    String text = F("Sending command: ");
    text += command;
    debug(text.c_str());
  }

  device.print(command);

  // Clear the receive buffer after sending a command.
  rxBuffer = "";
}

MHGroveBLE::ResponseState MHGroveBLE::receiveResponse()
{
  unsigned long now = millis();
  bool timeoutReached = isTimeout(now, timeoutReferenceTime, timeoutDuration);
  bool retryReached =
    retryDuration > 0
    ? isTimeout(now, retryReferenceTime, retryDuration)
    : false;

  readIntoBuffer();

  if (retryReached || timeoutReached) {
    if (rxBuffer.length() > 0) {
      // We reached a timeout and have data! We're done.
      if (debug) {
        String text = F("Received response: ");
        text += rxBuffer;
        debug(text.c_str());
      }
      return ResponseState::success;

    } else if (timeoutReached) {
      // The hard timeout has been reached.
      return ResponseState::timedOut;

    } else {
      // The retry timeout (soft timeout) has been reached. Reset the reference
      // time to start the next retry phase.
      retryReferenceTime = now;
      return ResponseState::needRetry;
    }

  } else {
    // No timeout reached yet, keep on reading.
    return ResponseState::receiving;
  }
}

void MHGroveBLE::transitionToState(MHGroveBLE::InternalState nextState)
{
  unsigned long now = millis();

  if (debug) {
    String text = F("Transitioning to state: ");
    text += (int)nextState;
    debug(text.c_str());
  }

  switch (nextState) {
    case InternalState::startup: break;

    case InternalState::waitForDeviceAfterStartup:
      sendCommand(F("AT"));
      retryReferenceTime = now;
      retryDuration = kRetryTimeout;
      timeoutReferenceTime = now;
      timeoutDuration = kWaitForDeviceTimeout;
      break;

    case InternalState::renew:
      sendCommand(F("AT+RENEW"));
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kGenericCommandTimeout;
      genericNextInternalState = InternalState::setName;
      break;

    case InternalState::setName: {
      String command = F("AT+NAME");
      command += name;
      sendCommand(command);
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kGenericCommandTimeout;
      genericNextInternalState = InternalState::setNotification;
      break;
    }

    case InternalState::setNotification:
      sendCommand(F("AT+NOTI1"));
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kGenericCommandTimeout;
      genericNextInternalState = InternalState::reset;
      break;

    case InternalState::reset:
      sendCommand(F("AT+RESET"));
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = now;
      timeoutDuration = kGenericCommandTimeout;
      break;

    case InternalState::waitForDeviceAfterReset:
      sendCommand(F("AT"));
      retryReferenceTime = now;
      retryDuration = kRetryTimeout;
      timeoutReferenceTime = now;
      timeoutDuration = kWaitForDeviceTimeout;
      break;

    case InternalState::initializationComplete:
      if (onReady) {
        onReady();
      }
      break;

    case InternalState::waitingForConnection:
      if (internalState == InternalState::connected && onDisconnect) {
        onDisconnect();
      }
      rxBuffer = "";
      // No timeout handling in this state.
      break;

    case InternalState::connected:
      if (onConnect) {
        onConnect();
      }
      retryReferenceTime = 0;
      retryDuration = 0;
      timeoutReferenceTime = 0;
      timeoutDuration = 0;
      break;

    case InternalState::panicked:
      if (debug) {
        debug("Panic!");
      }
      if (onPanic) {
        onPanic();
      }
      break;
  }

  internalState = nextState;

  if (nextState == InternalState::initializationComplete) {
    // When we've reached the `initializationComplete` state, we want to inform
    // the handler (done above) and then continue to the `waitingForConnection`
    // state right away.
    transitionToState(InternalState::waitingForConnection);
  }
}

bool MHGroveBLE::readIntoBuffer()
{
  bool didReceive = false;

  while (device.available() > 0) {
    int value = device.read();
    if (value < 0) {
      // Shouldn't happen? We asked whether there's stuff available!
      break;
    }

    if (rxBuffer.length() == rxBufferSize) {
      // We don't want to grow the receive buffer. Discard old data.
      rxBuffer.remove(0, 1);
    }

    rxBuffer += (char)value;
    didReceive = true;
  }

  return didReceive;
}

void MHGroveBLE::handleWaitForDevice()
{
  switch (receiveResponse()) {
    case ResponseState::receiving:
      break;

    case ResponseState::needRetry:
      sendCommand(F("AT"));
      break;

    case ResponseState::timedOut:
      panic();
      break;

    case ResponseState::success:
      switch (internalState) {
        case InternalState::waitForDeviceAfterStartup:
          transitionToState(InternalState::renew);
          break;

        case InternalState::waitForDeviceAfterReset:
          transitionToState(InternalState::initializationComplete);
          break;

        default:
          // Bug! Must not happen.
          panic();
      }
      break;
  }
}

void MHGroveBLE::handleGenericCommand()
{
  switch (receiveResponse()) {
    case ResponseState::receiving:
      break;

    case ResponseState::needRetry: // Bug, must not happen
    case ResponseState::timedOut:
      panic();
      break;

    case ResponseState::success:
      transitionToState(genericNextInternalState);
      break;
  }
}

void MHGroveBLE::handleReset()
{
  switch (receiveResponse()) {
    case ResponseState::receiving:
      break;

    case ResponseState::needRetry: // Bug, must not happen
      panic();
      break;

    case ResponseState::timedOut:
      // Try waiting for the device.
      // Fall-through
    case ResponseState::success:
      transitionToState(InternalState::waitForDeviceAfterReset);
      break;
  }
}

void MHGroveBLE::handleWaitForConnect()
{
  if (!readIntoBuffer()) {
    return;
  }

  if (rxBuffer.indexOf(F("OK+CONN")) != -1) {
    rxBuffer = "";
    // Once we've received this string immediately transition to the "connected"
    // state. There's no point in waiting for a timeout like when we're waiting
    // for AT command responses.
    // The point of doing this with `indexOf` is to recover if we have received
    // garbage before.
    transitionToState(InternalState::connected);
  }
}

void MHGroveBLE::handleConnected()
{
  unsigned long now = millis();
  bool connectionClosed = false;
  bool dataWasRead = readIntoBuffer();
  bool timeoutReached =
    timeoutDuration > 0
    ? isTimeout(now, timeoutReferenceTime, timeoutDuration)
    : false;

  if (!dataWasRead && !timeoutReached) {
    // Nothing happened, no need to react yet.
    return;
  }

  if (dataWasRead) {
    // Every time we read data we need to reset our timeout to avoid
    // timing out in the middle of a stream.
    timeoutReferenceTime = now;
    timeoutDuration = kConnectedReadTimeout;
  }

  // Pass the data to the handler if either the timeout occurred or if the
  // receive buffer is full. The later is necessary to not lose any data.
  if (timeoutReached || rxBuffer.length() == rxBufferSize) {
    // The Grove BLE sends "OK+LOST" when the connection is closed.
    // Unfortunately, an app is also able to send this string and we don't know
    // whether the Grove BLE or the app has sent it.
    // This is why `handleWaitForConnect` also needs to be able to handle
    // garbage: it's possible that an app sends "OK+LOST" and once the
    // connection is really closed, another "OK+LOST" is sent by Grove BLE
    // before the "OK+CONN" for a new connection arrives.
    int index = rxBuffer.lastIndexOf(F("OK+LOST"));
    // Check whether it's the last thing in the buffer to avoid reacting on the
    // string being part of some other text.
    if (index >= 0 && ((unsigned)index+7 == rxBuffer.length())) {
      connectionClosed = true;
      // Remove the sentinel.
      rxBuffer.remove(index);
    }

    // Pass the data to the handler...
    if (onDataReceived && rxBuffer.length() > 0) {
      onDataReceived(rxBuffer);
    }
    // ... and clear it.
    rxBuffer = "";
    timeoutReferenceTime = 0;
    timeoutDuration = 0;
  }

  if (connectionClosed) {
    transitionToState(InternalState::waitingForConnection);
  }
}

void MHGroveBLE::panic()
{
  transitionToState(InternalState::panicked);
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>
#include <math.h>
#include <Windows.h>
#include "CL/cl.h"

///	For SSE information go to the Intel Intrinsics Guide
///	mm_add_ps  for adding vector float components ... etc ...
///
///

using namespace std;

struct vec4
{
	float	x, y, z, w;
};

const int	iVEC_COUNT = 37000000;
vec4*	vectors;
LARGE_INTEGER timerfreq;
LARGE_INTEGER timerstart;
LARGE_INTEGER timerend;
double timerdiff;

void CPUNormalise()
{
	//	normalise the vectors
	for (unsigned int i = 0; i < iVEC_COUNT; ++i)
	{
		float	d = (vectors[i].x * vectors[i].x +
			vectors[i].y * vectors[i].y +
			vectors[i].z * vectors[i].z +
			vectors[i].w * vectors[i].w);
		float	f1OnLength = 1.0f / sqrtf(d);

		vectors[i].x *= f1OnLength;
		vectors[i].y *= f1OnLength;
		vectors[i].z *= f1OnLength;
		vectors[i].w *= f1OnLength;
	}
}

//	normally these would be stored in the class rather than global
cl_platform_id	m_platform;
cl_device_id	m_device;
cl_int	result;
cl_context m_context;
cl_program m_program;
cl_kernel m_kernel;
cl_mem m_buffer;
cl_command_queue m_queue;
cl_event eventID;

bool LoadOpenCLSource(char* a_szFileName, cl_program* a_ProgramID)
{
	FILE* file = fopen("OpenCL_Normalise.cl", "r");
	if (file == nullptr)
	{
		cout << "Failed to open file!\n";
		return false;
	}
	else
	{
		cout << "Successfully opened OpenCl file.\n";
	}
	// read the program source
	fseek(file, 0, SEEK_END);
	unsigned int kernelSize = ftell(file);
	fseek(file, 0, SEEK_SET);
	char* kernelSource = new char[kernelSize + 1];
	memset(kernelSource, 0, kernelSize + 1);
	fread(kernelSource, sizeof(char), kernelSize, file);
	fclose(file);

	// build program from our source using the device context
	m_program = clCreateProgramWithSource(m_context, 1, (const char**)&kernelSource, &kernelSize, &result);
	if (result != CL_SUCCESS)
		printf("clCreateProgramWithSource failed: %i\n", result);
	result = clBuildProgram(m_program, 1, &m_device, nullptr, nullptr, nullptr);
	if (result != CL_SUCCESS)
		printf("clBuildProgram failed: %i\n", result);

	// extract the kernel
	m_kernel = clCreateKernel(m_program, "normalize_vec4", &result);
	if (result != CL_SUCCESS)
		printf("clCreateKernel failed: %i\n", result);

	return true;
}

void SetupOpenCLNormalise()
{
	// get the first platform
	cl_int result = clGetPlatformIDs(1, &m_platform, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetPlatformIDs failed: %i\n", result);
	// get the first device on the platform (default is GPU)
	result = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_DEFAULT, 1, &m_device, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetDeviceIDs failed: %i\n", result);
	// create a context for a device on the specified platform
	cl_context_properties contextProperties[] =
		{ CL_CONTEXT_PLATFORM, (cl_context_properties)m_platform, 0 };
	m_context = clCreateContext(contextProperties, 1, &m_device, nullptr, nullptr, &result);
	if (result != CL_SUCCESS)
		printf("clCreateContext failed: %i\n", result);
	// create a command queue to process commands
	m_queue = clCreateCommandQueue(m_context, m_device, CL_QUEUE_PROFILING_ENABLE, &result);
	if (result != CL_SUCCESS)
		printf("clCreateCommandQueue failed: %i\n", result);

	if (!LoadOpenCLSource("./src/OpenCL_Normalise.cl", &m_program))
	{
		cout << "Failed to load OpenCL souce!\n";
		return;
	}
}

void OpenCLNormalise()
{
	// create cl buffer for our data and copy it off the host (CPU)
	m_buffer = clCreateBuffer(m_context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(vec4)* iVEC_COUNT, vectors, &result);
	if (result != CL_SUCCESS)
		printf("clCreateBuffer failed: %i\n", result);

	// set the buffer as the first argument for our kernel
	result = clSetKernelArg(m_kernel, 0, sizeof(cl_mem), &m_buffer);
	if (result != CL_SUCCESS)
		printf("clSetKernelArg failed: %i\n", result);

	// process the kernel and give it an event ID
	eventID = 0;
	// we'll give it a size equal to the number of vec4's to process
	size_t globalWorkSize[] = { iVEC_COUNT };
	//	for multi-dimensional data sets use this format:
	//		size_t globalWorkSize[] = { iX_VEC_COUNT, iY_VEC_COUNT, iZ_VEC_COUNT };

	QueryPerformanceCounter(&timerstart);
	//	kick off the processing
	result = clEnqueueNDRangeKernel(m_queue, m_kernel, 1, nullptr, globalWorkSize, nullptr, 0, nullptr, &eventID);
	if (result != CL_SUCCESS)
		printf("clEnqueueNDRangeKernel failed: %i\n", result);

	// read back the processed data but wait for an event to complete
	result = clEnqueueReadBuffer(m_queue, m_buffer, CL_TRUE, 0, sizeof(vec4)* iVEC_COUNT, vectors, 1, &eventID, nullptr);
	if (result != CL_SUCCESS)
		printf("clEnqueueReadBuffer failed: %i\n", result);

	QueryPerformanceCounter(&timerend);
	timerdiff = (double)(timerend.QuadPart - timerstart.QuadPart) / (double)timerfreq.QuadPart;
	std::cout << "OpenCL Normalise Timer: " << timerdiff * 1000.0f << "ms.  " << iVEC_COUNT << " vectors.\n";

	// finish all opencl commands
	clFlush(m_queue);
	clFinish(m_queue);

	// how long did each event take?
	// get start / end profile data for the event
	cl_ulong clstartTime = 0;
	result = clGetEventProfilingInfo(eventID, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &clstartTime, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetEventProfilingInfo failed: %i\n", result);
	cl_ulong clendTime = 0;
	result = clGetEventProfilingInfo(eventID, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &clendTime, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetEventProfilingInfo failed: %i\n", result);
	// return time is in nanoseconds, so convert to milliseconds
	double clTime = (clendTime - clstartTime) * 1.0e-6;
	printf("GPU duration: %fms.\n", clTime);

}

void CleanUpOpenCL()
{
	clReleaseMemObject(m_buffer);
	clReleaseKernel(m_kernel);
	clReleaseProgram(m_program);
	clReleaseCommandQueue(m_queue);
	clReleaseContext(m_context);
}

int	main()
{

	//	allocating the vectors
	vectors = new vec4[iVEC_COUNT];

	//	initialising the vectors
	for (unsigned int i = 0; i < iVEC_COUNT; ++i)
	{
		vectors[i].x = vectors[i].y = vectors[i].z = vectors[i].w = 1.0f;
	}

	//	now set up the timer ...
	QueryPerformanceFrequency(&timerfreq);

	QueryPerformanceCounter(&timerstart);

	CPUNormalise();

	QueryPerformanceCounter(&timerend);

	timerdiff = (double)(timerend.QuadPart - timerstart.QuadPart) / (double)timerfreq.QuadPart;

	std::cout << "CPU Normalise Timer: " << timerdiff * 1000.0f << "ms.  " << iVEC_COUNT << " vectors.\n";

	//	now do it on the GPU!!!
	//	re-initialising the vectors
	for (unsigned int i = 0; i < iVEC_COUNT; ++i)
	{
		vectors[i].x = vectors[i].y = vectors[i].z = vectors[i].w = 1.0f;
	}
	SetupOpenCLNormalise();

	OpenCLNormalise();

	CleanUpOpenCL();
	delete[] vectors;
	system("pause");
}
<commit_msg>Adding GPU speedup factor reporting.<commit_after>#include <cstdlib>
#include <iostream>
#include <math.h>
#include <Windows.h>
#include "CL/cl.h"

///	For SSE information go to the Intel Intrinsics Guide
///	mm_add_ps  for adding vector float components ... etc ...
///
///

using namespace std;

struct vec4
{
	float	x, y, z, w;
};

const int	iVEC_COUNT = 37000000;
vec4*	vectors;
LARGE_INTEGER timerfreq;
LARGE_INTEGER timerstart;
LARGE_INTEGER timerend;
double timerdiff;
double clTime;

void CPUNormalise()
{
	//	normalise the vectors
	for (unsigned int i = 0; i < iVEC_COUNT; ++i)
	{
		float	d = (vectors[i].x * vectors[i].x +
			vectors[i].y * vectors[i].y +
			vectors[i].z * vectors[i].z +
			vectors[i].w * vectors[i].w);
		float	f1OnLength = 1.0f / sqrtf(d);

		vectors[i].x *= f1OnLength;
		vectors[i].y *= f1OnLength;
		vectors[i].z *= f1OnLength;
		vectors[i].w *= f1OnLength;
	}
}

//	normally these would be stored in the class rather than global
cl_platform_id	m_platform;
cl_device_id	m_device;
cl_int	result;
cl_context m_context;
cl_program m_program;
cl_kernel m_kernel;
cl_mem m_buffer;
cl_command_queue m_queue;
cl_event eventID;

bool LoadOpenCLSource(char* a_szFileName, cl_program* a_ProgramID)
{
	FILE* file = fopen("OpenCL_Normalise.cl", "r");
	if (file == nullptr)
	{
		cout << "Failed to open file!\n";
		return false;
	}
	else
	{
		cout << "Successfully opened OpenCl file.\n";
	}
	// read the program source
	fseek(file, 0, SEEK_END);
	unsigned int kernelSize = ftell(file);
	fseek(file, 0, SEEK_SET);
	char* kernelSource = new char[kernelSize + 1];
	memset(kernelSource, 0, kernelSize + 1);
	fread(kernelSource, sizeof(char), kernelSize, file);
	fclose(file);

	// build program from our source using the device context
	m_program = clCreateProgramWithSource(m_context, 1, (const char**)&kernelSource, &kernelSize, &result);
	if (result != CL_SUCCESS)
		printf("clCreateProgramWithSource failed: %i\n", result);
	result = clBuildProgram(m_program, 1, &m_device, nullptr, nullptr, nullptr);
	if (result != CL_SUCCESS)
		printf("clBuildProgram failed: %i\n", result);

	// extract the kernel
	m_kernel = clCreateKernel(m_program, "normalize_vec4", &result);
	if (result != CL_SUCCESS)
		printf("clCreateKernel failed: %i\n", result);

	return true;
}

void SetupOpenCLNormalise()
{
	// get the first platform
	cl_int result = clGetPlatformIDs(1, &m_platform, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetPlatformIDs failed: %i\n", result);
	// get the first device on the platform (default is GPU)
	result = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_DEFAULT, 1, &m_device, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetDeviceIDs failed: %i\n", result);
	// create a context for a device on the specified platform
	cl_context_properties contextProperties[] =
		{ CL_CONTEXT_PLATFORM, (cl_context_properties)m_platform, 0 };
	m_context = clCreateContext(contextProperties, 1, &m_device, nullptr, nullptr, &result);
	if (result != CL_SUCCESS)
		printf("clCreateContext failed: %i\n", result);
	// create a command queue to process commands
	m_queue = clCreateCommandQueue(m_context, m_device, CL_QUEUE_PROFILING_ENABLE, &result);
	if (result != CL_SUCCESS)
		printf("clCreateCommandQueue failed: %i\n", result);

	if (!LoadOpenCLSource("./src/OpenCL_Normalise.cl", &m_program))
	{
		cout << "Failed to load OpenCL souce!\n";
		return;
	}
}

void OpenCLNormalise()
{
	// create cl buffer for our data and copy it off the host (CPU)
	m_buffer = clCreateBuffer(m_context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(vec4)* iVEC_COUNT, vectors, &result);
	if (result != CL_SUCCESS)
		printf("clCreateBuffer failed: %i\n", result);

	// set the buffer as the first argument for our kernel
	result = clSetKernelArg(m_kernel, 0, sizeof(cl_mem), &m_buffer);
	if (result != CL_SUCCESS)
		printf("clSetKernelArg failed: %i\n", result);

	// process the kernel and give it an event ID
	eventID = 0;
	// we'll give it a size equal to the number of vec4's to process
	size_t globalWorkSize[] = { iVEC_COUNT };
	//	for multi-dimensional data sets use this format:
	//		size_t globalWorkSize[] = { iX_VEC_COUNT, iY_VEC_COUNT, iZ_VEC_COUNT };

	//	kick off the processing
	result = clEnqueueNDRangeKernel(m_queue, m_kernel, 1, nullptr, globalWorkSize, nullptr, 0, nullptr, &eventID);
	if (result != CL_SUCCESS)
		printf("clEnqueueNDRangeKernel failed: %i\n", result);

	// read back the processed data but wait for an event to complete
	result = clEnqueueReadBuffer(m_queue, m_buffer, CL_TRUE, 0, sizeof(vec4)* iVEC_COUNT, vectors, 1, &eventID, nullptr);
	if (result != CL_SUCCESS)
		printf("clEnqueueReadBuffer failed: %i\n", result);

	// finish all opencl commands
	clFlush(m_queue);
	clFinish(m_queue);

	// how long did each event take?
	// get start / end profile data for the event
	cl_ulong clstartTime = 0;
	result = clGetEventProfilingInfo(eventID, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &clstartTime, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetEventProfilingInfo failed: %i\n", result);
	cl_ulong clendTime = 0;
	result = clGetEventProfilingInfo(eventID, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &clendTime, nullptr);
	if (result != CL_SUCCESS)
		printf("clGetEventProfilingInfo failed: %i\n", result);
	// return time is in nanoseconds, so convert to milliseconds
	clTime = (clendTime - clstartTime) * 1.0e-6;
	printf("GPU duration: %fms.\n", clTime);

}

void CleanUpOpenCL()
{
	clReleaseMemObject(m_buffer);
	clReleaseKernel(m_kernel);
	clReleaseProgram(m_program);
	clReleaseCommandQueue(m_queue);
	clReleaseContext(m_context);
}

int	main()
{

	//	allocating the vectors
	vectors = new vec4[iVEC_COUNT];

	//	initialising the vectors
	for (unsigned int i = 0; i < iVEC_COUNT; ++i)
	{
		vectors[i].x = vectors[i].y = vectors[i].z = vectors[i].w = 1.0f;
	}

	//	now set up the timer ...
	QueryPerformanceFrequency(&timerfreq);

	QueryPerformanceCounter(&timerstart);

	CPUNormalise();

	QueryPerformanceCounter(&timerend);

	timerdiff = (double)(timerend.QuadPart - timerstart.QuadPart) / (double)timerfreq.QuadPart;

	std::cout << "CPU Normalise Timer: " << timerdiff * 1000.0f << "ms.  " << iVEC_COUNT << " vectors.\n";

	//	now do it on the GPU!!!
	//	re-initialising the vectors
	for (unsigned int i = 0; i < iVEC_COUNT; ++i)
	{
		vectors[i].x = vectors[i].y = vectors[i].z = vectors[i].w = 1.0f;
	}
	SetupOpenCLNormalise();

	OpenCLNormalise();

	cout << "GPU normalise is " << timerdiff / (clTime * 1.0e-3) << " times faster than the CPU normalise!\n";

	CleanUpOpenCL();
	delete[] vectors;
	system("pause");
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: ferr.cc,v 1.11 2008/05/10 13:34:01 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
//   Copyright (c) 2003 Stanislav Shwartsman
//          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
/////////////////////////////////////////////////////////////////////////

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu/cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR

#if BX_SUPPORT_FPU

#include "softfloat-specialize.h"

void BX_CPU_C::FPU_stack_overflow(void)
{
  /* The masked response */
  if (BX_CPU_THIS_PTR the_i387.is_IA_masked())
  {
    BX_CPU_THIS_PTR the_i387.FPU_push();
    BX_WRITE_FPU_REG(floatx80_default_nan, 0);
  }
  FPU_exception(FPU_EX_Stack_Overflow);
}

void BX_CPU_C::FPU_stack_underflow(int stnr, int pop_stack)
{
  /* The masked response */
  if (BX_CPU_THIS_PTR the_i387.is_IA_masked())
  {
    BX_WRITE_FPU_REG(floatx80_default_nan, stnr);
    if (pop_stack)
        BX_CPU_THIS_PTR the_i387.FPU_pop();
  }
  FPU_exception(FPU_EX_Stack_Underflow);
}

/* Returns 1 if unmasked exception occured */
bx_bool BX_CPU_C::FPU_exception(int exception)
{
  int unmasked = 0;

  /* Extract only the bits which we use to set the status word */
  exception &= (FPU_SW_Exceptions_Mask);

  /* Set the corresponding exception bits */
  FPU_PARTIAL_STATUS |= exception;

  /* Set summary bits iff exception isn't masked */
  if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask)
  {
    FPU_PARTIAL_STATUS |= (FPU_SW_Summary | FPU_SW_Backward);
    unmasked = 1;
  }

  if (exception & (FPU_SW_Stack_Fault | FPU_EX_Precision))
  {
    if (! (exception & FPU_SW_C1)) {
      /* This bit distinguishes over- from underflow for a stack fault,
           and roundup from round-down for precision loss. */
      FPU_PARTIAL_STATUS &= ~FPU_SW_C1;
    }
  }

  return unmasked;
}

#endif
<commit_msg>- Fixed x87 Inexact Result (#P) unmasked responce<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: ferr.cc,v 1.12 2008/09/02 05:36:15 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
//   Copyright (c) 2003 Stanislav Shwartsman
//          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
/////////////////////////////////////////////////////////////////////////

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu/cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR

#if BX_SUPPORT_FPU

#include "softfloat-specialize.h"

void BX_CPU_C::FPU_stack_overflow(void)
{
  /* The masked response */
  if (BX_CPU_THIS_PTR the_i387.is_IA_masked())
  {
    BX_CPU_THIS_PTR the_i387.FPU_push();
    BX_WRITE_FPU_REG(floatx80_default_nan, 0);
  }
  FPU_exception(FPU_EX_Stack_Overflow);
}

void BX_CPU_C::FPU_stack_underflow(int stnr, int pop_stack)
{
  /* The masked response */
  if (BX_CPU_THIS_PTR the_i387.is_IA_masked())
  {
    BX_WRITE_FPU_REG(floatx80_default_nan, stnr);
    if (pop_stack)
        BX_CPU_THIS_PTR the_i387.FPU_pop();
  }
  FPU_exception(FPU_EX_Stack_Underflow);
}

/* Returns unmasked exceptions if occured */
unsigned BX_CPU_C::FPU_exception(int exception)
{
  /* Extract only the bits which we use to set the status word */
  exception &= (FPU_SW_Exceptions_Mask);

  /* Set the corresponding exception bits */
  FPU_PARTIAL_STATUS |= exception;

  unsigned unmasked = FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask;

  /* Set summary bits iff exception isn't masked */
  if (unmasked)
    FPU_PARTIAL_STATUS |= (FPU_SW_Summary | FPU_SW_Backward);

  if (exception & (FPU_SW_Stack_Fault | FPU_EX_Precision))
  {
    if (! (exception & FPU_SW_C1)) {
      /* This bit distinguishes over- from underflow for a stack fault,
           and roundup from round-down for precision loss. */
      FPU_PARTIAL_STATUS &= ~FPU_SW_C1;
    }
  }

  // if #P unmasked exception occured the result still has to be
  // written to the destination.
  unmasked &= ~FPU_CW_Precision;

  return unmasked;
}

#endif
<|endoftext|>