<commit_before>/** @file gsGeometry.h

    @brief Provides declaration of Geometry abstract interface.

    This file is part of the G+Smo library. 

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    Author(s): <NAME>
*/

#pragma once

#include <gsCore/gsFunction.h>
#include <gsCore/gsBoundary.h>


#define GISMO_BASIS_ACCESSORS \
    Basis & basis() { return static_cast<Basis&>(*this->m_basis); } \
    const Basis & basis() const { return static_cast<const Basis&>(*this->m_basis); }
    // bool isProjective() const{ return Basis::IsRational; }

namespace gismo
{

/** 
    \brief
    Abstract base class representing a geometry map.

    The combination of a basis with a coefficient matrix of the proper
    size describes a function. Such objects are called geometries.


    Note that geometries are, essentially, functions mapping from the
    parameter domain to the physical space,

    \f[ G \ :\ \mathbb R^d \to \mathbb R^n \f]

    so that 

    \f[ G(\hat x) = x \qquad \hat x \in \mathbb R^d, \ x \in \mathbb R^n \f]

    and therefore they derive from gsFunction. A gsGeometry can thus be
    used wherever a gsFunction is expected.
    
    All geometry classes derive from the abstract base class
    gsGeometry, see the \ref geometry.  In general, there is a
    statically known one-to-one mapping between basis types and their
    associated geometry types. For instance, when you ask a
    gsBSplineBasis to create a geometry using some given coefficient
    matrix, you will get back an instance of gsBSpline. In turn, the
    basis that the gsBSpline object stores internally is of type
    gsBSplineBasis.

    The parameter domain of the basis is also the parameter domain of
    the geometry map, and has a certain source dimension \em d (see
    gsGeometry::parDim()). Depending on the parameter domain
    dimension, derived geometries inherit gsCurve, gsSurface, gsVolume
    or gsBulk, for dimension 1,2,3 or 4, respectively.

    The dimension \em n of the resulting geometry,
    i.e., of the image of the geometry map, is defined by the
    size of the given coefficients, and may be larger than \em d
    (see gsGeometry::geoDim()). $\,$

    For instance, for a B-spline basis (<em>d = 1</em>), we could
    have coefficients of dimension <em>n = 1</em>, which results
    in a parametrization of a 1-D interval, or we could have
    coefficients of size <em>n = 3</em>, which results in a B-spline
    curve in 3-D space.

    The coefficients are stored as an <em>s x n</em> matrix,
    where \em s is the size of the basis, i.e., the number of
    its basis functions.
    Every row of the coefficient matrix is an *n*-dimensional control
    point, i.e., the vector-valued coefficient for the associated
    basis function.

    Evaluation at parameter values is done with
    \ref func_eval_members "the Evaluation member functions" derived 
    from gsFunction.

    \tparam T coefficient type

    \ingroup function
    \ingroup geometry
    \ingroup Core
*/
template<class T>
class gsGeometry : public gsFunction<T>
{

public: 
    /// Shared pointer for gsGeometry
    //typedef memory::shared_ptr<gsGeometry> Ptr;
    typedef memory::shared_ptr<gsGeometry> Ptr; //todo

    /// Unique pointer for gsGeometry
    //typedef memory::unique_ptr<gsGeometry> uPtr;
    typedef memory::unique_ptr<gsGeometry> uPtr; //todo

    typedef T Scalar_t;

    typedef memory::unique_ptr<gsGeometryEvaluator<T> > Evaluator;

public:

    /// @name Constructors
    /// @{
    
    /// @brief Default constructor.  Note: Derived constructors (except for
    /// the default) should assign \a m_basis to a valid pointer
    gsGeometry() :m_basis( NULL ), m_id(0)
    { }

    /// @brief Constructor by a basis and coefficient vector
    ///
    /// Coefficients are given by \em{give(coefs) and they are
    /// consumed, i.e. the \coefs variable will be empty after the call
    gsGeometry( const gsBasis<T> & basis, gsMatrix<Scalar_t> coefs) :
    m_basis( basis.clone() ), m_id(0)
    {
        m_coefs.swap(coefs);
        GISMO_ASSERT( basis.size() == m_coefs.rows(), 
                      "The coefficient matrix of the geometry (rows="<<m_coefs.rows()
                      <<") does not match the number of basis functions in its basis("
                      << basis.size() <<").");
    }

    /// @brief Copy Constructor
    gsGeometry(const gsGeometry & o) 
    : m_coefs(o.m_coefs), m_basis(o.m_basis != NULL ? o.basis().clone() : NULL), m_id(o.m_id)
    { }

    /// @}

    gsGeometry& operator=( const gsGeometry & o)
    {
        if ( this != &o )
        {
            m_coefs = o.m_coefs;
            delete m_basis;
            m_basis = o.basis().clone() ;
            m_id = o.m_id;
        }
        return *this;
    }
    
    virtual ~gsGeometry() 
    {
        delete m_basis;
    }

#if EIGEN_HAS_RVALUE_REFERENCES
    gsGeometry(gsGeometry&& other) 
    : m_coefs(std::move(other.m_coefs)), m_basis(other.m_basis)
    {
        other.m_basis = NULL;
    }
    gsGeometry & operator=(gsGeometry&& other)
    {
        m_coefs.swap(other.m_coefs); other.m_coefs.clear();
        delete m_basis; 
        m_basis = other.m_basis; other.m_basis = NULL;
        return *this;
    }
#endif

public:

    /**
        @name Evaluation functions

        re-implemented from gsFunction, see also \ref func_eval_members
        @{
    */<commit_msg>forgotten move<commit_after>/** @file gsGeometry.h

    @brief Provides declaration of Geometry abstract interface.

    This file is part of the G+Smo library. 

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    Author(s): <NAME>
*/

#pragma once

#include <gsCore/gsFunction.h>
#include <gsCore/gsBoundary.h>


#define GISMO_BASIS_ACCESSORS \
    Basis & basis() { return static_cast<Basis&>(*this->m_basis); } \
    const Basis & basis() const { return static_cast<const Basis&>(*this->m_basis); }
    // bool isProjective() const{ return Basis::IsRational; }

namespace gismo
{

/** 
    \brief
    Abstract base class representing a geometry map.

    The combination of a basis with a coefficient matrix of the proper
    size describes a function. Such objects are called geometries.


    Note that geometries are, essentially, functions mapping from the
    parameter domain to the physical space,

    \f[ G \ :\ \mathbb R^d \to \mathbb R^n \f]

    so that 

    \f[ G(\hat x) = x \qquad \hat x \in \mathbb R^d, \ x \in \mathbb R^n \f]

    and therefore they derive from gsFunction. A gsGeometry can thus be
    used wherever a gsFunction is expected.
    
    All geometry classes derive from the abstract base class
    gsGeometry, see the \ref geometry.  In general, there is a
    statically known one-to-one mapping between basis types and their
    associated geometry types. For instance, when you ask a
    gsBSplineBasis to create a geometry using some given coefficient
    matrix, you will get back an instance of gsBSpline. In turn, the
    basis that the gsBSpline object stores internally is of type
    gsBSplineBasis.

    The parameter domain of the basis is also the parameter domain of
    the geometry map, and has a certain source dimension \em d (see
    gsGeometry::parDim()). Depending on the parameter domain
    dimension, derived geometries inherit gsCurve, gsSurface, gsVolume
    or gsBulk, for dimension 1,2,3 or 4, respectively.

    The dimension \em n of the resulting geometry,
    i.e., of the image of the geometry map, is defined by the
    size of the given coefficients, and may be larger than \em d
    (see gsGeometry::geoDim()). $\,$

    For instance, for a B-spline basis (<em>d = 1</em>), we could
    have coefficients of dimension <em>n = 1</em>, which results
    in a parametrization of a 1-D interval, or we could have
    coefficients of size <em>n = 3</em>, which results in a B-spline
    curve in 3-D space.

    The coefficients are stored as an <em>s x n</em> matrix,
    where \em s is the size of the basis, i.e., the number of
    its basis functions.
    Every row of the coefficient matrix is an *n*-dimensional control
    point, i.e., the vector-valued coefficient for the associated
    basis function.

    Evaluation at parameter values is done with
    \ref func_eval_members "the Evaluation member functions" derived 
    from gsFunction.

    \tparam T coefficient type

    \ingroup function
    \ingroup geometry
    \ingroup Core
*/
template<class T>
class gsGeometry : public gsFunction<T>
{

public: 
    /// Shared pointer for gsGeometry
    //typedef memory::shared_ptr<gsGeometry> Ptr;
    typedef memory::shared_ptr<gsGeometry> Ptr; //todo

    /// Unique pointer for gsGeometry
    //typedef memory::unique_ptr<gsGeometry> uPtr;
    typedef memory::unique_ptr<gsGeometry> uPtr; //todo

    typedef T Scalar_t;

    typedef memory::unique_ptr<gsGeometryEvaluator<T> > Evaluator;

public:

    /// @name Constructors
    /// @{
    
    /// @brief Default constructor.  Note: Derived constructors (except for
    /// the default) should assign \a m_basis to a valid pointer
    gsGeometry() :m_basis( NULL ), m_id(0)
    { }

    /// @brief Constructor by a basis and coefficient vector
    ///
    /// Coefficients are given by \em{give(coefs) and they are
    /// consumed, i.e. the \coefs variable will be empty after the call
    gsGeometry( const gsBasis<T> & basis, gsMatrix<Scalar_t> coefs) :
    m_basis( basis.clone() ), m_id(0)
    {
        m_coefs.swap(coefs);
        GISMO_ASSERT( basis.size() == m_coefs.rows(), 
                      "The coefficient matrix of the geometry (rows="<<m_coefs.rows()
                      <<") does not match the number of basis functions in its basis("
                      << basis.size() <<").");
    }

    /// @brief Copy Constructor
    gsGeometry(const gsGeometry & o) 
    : m_coefs(o.m_coefs), m_basis(o.m_basis != NULL ? o.basis().clone() : NULL), m_id(o.m_id)
    { }

    /// @}

    gsGeometry& operator=( const gsGeometry & o)
    {
        if ( this != &o )
        {
            m_coefs = o.m_coefs;
            delete m_basis;
            m_basis = o.basis().clone() ;
            m_id = o.m_id;
        }
        return *this;
    }
    
    virtual ~gsGeometry() 
    {
        delete m_basis;
    }

#if EIGEN_HAS_RVALUE_REFERENCES
    gsGeometry(gsGeometry&& other) 
    : m_coefs(std::move(other.m_coefs)), m_basis(other.m_basis), 
      m_id(std::move(other.m_id))
    {
        other.m_basis = NULL;
    }
    gsGeometry & operator=(gsGeometry&& other)
    {
        m_coefs.swap(other.m_coefs); other.m_coefs.clear();
        delete m_basis; 
        m_basis = other.m_basis; other.m_basis = NULL;
        return *this;
    }
#endif

public:

    /**
        @name Evaluation functions

        re-implemented from gsFunction, see also \ref func_eval_members
        @{
    */
{'fraction_non_alphanumeric': 0.09635533267663651, 'fraction_numerical': 0.002686486970538193, 'mean_word_length': 2.569191434963247, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6402721', 'n_tokens_mistral': 3599, 'n_tokens_neox': 3351, 'n_words': 1232}