<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef RPTUI_GROUPS_SORTING_HXX
#define RPTUI_GROUPS_SORTING_HXX

#include <vcl/floatwin.hxx>
#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#include <vcl/lstbox.hxx>
#include <vcl/edit.hxx>
#include <vcl/field.hxx>
#include <vcl/imagebtn.hxx>
#include <vcl/toolbox.hxx>
#include <com/sun/star/report/XGroups.hpp>
#include <com/sun/star/report/XGroup.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include "GroupProperties.hxx"
#include <comphelper/propmultiplex.hxx>
#include "cppuhelper/basemutex.hxx"
#include <svtools/svmedit.hxx>
#include <rtl/ref.hxx>

#include <vector>

#include <dbaccess/ToolBoxHelper.hxx>

#include <vcl/ImageListProvider.hxx>

namespace comphelper
{
    class OPropertyChangeMultiplexer;
}
namespace rptui
{
class OFieldExpressionControl;
class OReportController;
/*************************************************************************
|*
|* Groups and Sorting dialog
|*
\************************************************************************/

class OGroupsSortingDialog :    public FloatingWindow
                            ,   public ::cppu::BaseMutex
                                ,   public ::comphelper::OPropertyChangeListener
                           ,public dbaui::OToolBoxHelper
                           ,public vcl::IImageListProvider
{
    friend class OFieldExpressionControl;

    FixedLine                               m_aFL2;
    FixedText                               m_aMove;
//BTN   ImageButton                             m_aPB_Up;
//BTN   ImageButton                             m_aPB_Down;
//BTN   ImageButton                             m_aPB_Delete;
    ToolBox                                 m_aToolBox;

    FixedLine                               m_aFL3;
    FixedText                               m_aOrder;
    ListBox                                 m_aOrderLst;
    FixedText                               m_aHeader;
    ListBox                                 m_aHeaderLst;
    FixedText                               m_aFooter;
    ListBox                                 m_aFooterLst;
    FixedText                               m_aGroupOn;
    ListBox                                 m_aGroupOnLst;
    FixedText                               m_aGroupInterval;
    NumericField                            m_aGroupIntervalEd;
    FixedText                               m_aKeepTogether;
    ListBox                                 m_aKeepTogetherLst;
    FixedLine                               m_aFL;
    FixedText                               m_aHelpWindow;

    OFieldExpressionControl*                m_pFieldExpression;
    ::rptui::OReportController*             m_pController;
    ::rtl::Reference< comphelper::OPropertyChangeMultiplexer>                       m_pCurrentGroupListener;
    ::rtl::Reference< comphelper::OPropertyChangeMultiplexer>                       m_pReportListener;
    ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroups>            m_xGroups;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    m_xColumns;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >          m_xHoldAlive;
    sal_Bool                                m_bReadOnly;
private:
    DECL_LINK( OnControlFocusLost, Control* );
    DECL_LINK( OnControlFocusGot, Control* );
    DECL_LINK( LBChangeHdl, ListBox* );
//BTN   DECL_LINK( ClickHdl, ImageButton* );
    DECL_LINK( OnFormatAction,      ToolBox* );

    /** returns the groups
        @return the groups which now have to check which one changes
    */
    ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroups>& getGroups() { return m_xGroups; }

    ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroup> getGroup(sal_Int32 _nPos)
    {
        OSL_ENSURE(_nPos >= 0 && _nPos < m_xGroups->getCount(),"Invalid count!");
        return ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroup>(m_xGroups->getByIndex(_nPos),::com::sun::star::uno::UNO_QUERY);
    }

    /** updates the listboxes with the new group properties
        @param  _nRow   the new group pos
    */
    void DisplayData( sal_Int32 _nRow );

    /** saves the values from the listboxes into the group at position _nRow
        @param  _nRow   the group pos to store in
    */
    void SaveData( sal_Int32 _nRow );

    /** returns <TRUE/> when the dialog should be read only
    */
    sal_Bool isReadOnly( ) const;

    /** returns the data type for the given column name
        @param _sColumnName
    */
    sal_Int32 getColumnDataType(const ::rtl::OUString& _sColumnName);

    /** shows the text given by the id in the multiline edit
        @param  _nResId the string id
    */
    void showHelpText(USHORT _nResId);
    /** display the group props
        @param  _xGroup the group to display
    */
    void displayGroup(const ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroup>& _xGroup);

    /** enables or diables the up and down button
        @param  _nRow   the row which will be active
    */
    void checkButtons(sal_Int32 _nRow);

    /** clears the m_xColumns member and reset the fields
    *
    */
    void fillColumns();
    OGroupsSortingDialog(OGroupsSortingDialog&);
    void operator =(OGroupsSortingDialog&);
protected:
    // window
    virtual void    Resize();
    // OPropertyChangeListener
    virtual void    _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& _rEvent) throw( ::com::sun::star::uno::RuntimeException);
public:
    OGroupsSortingDialog( Window* pParent
                        ,sal_Bool _bReadOnly
                        ,::rptui::OReportController* _pController);
    virtual ~OGroupsSortingDialog();

    /** sets the newe columns at the groups dialog.
        @param  _xColumns the new columns
    */
    void setColumns(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _xColumns);

    /* updates the current view
    */
    void UpdateData( );

        /** will be called when the controls need to be resized.
            @param  _rDiff
                Contains the difference of the old and new toolbox size.
        */
        virtual void resizeControls(const Size& _rDiff);

        /** will be called when the image list is needed.
            @param  _eSymbolsSize
                <svtools/imgdef.hxx>
            @param  _bHiContast
                <TRUE/> when in high contrast mode.
        */
    virtual ImageList getImageList(sal_Int16 _eSymbolsSize,sal_Bool _bHiContast) const;

    // ImageListProvider interface
    virtual ImageList getImageList(vcl::ImageListType) SAL_THROW ((com::sun::star::lang::IllegalArgumentException ));

};
// =============================================================================
} // namespace rptui
// =============================================================================
#endif // RPTUI_GROUPS_SORTING_HXX
<commit_msg>CWS gnumake2: merging minibranches<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef RPTUI_GROUPS_SORTING_HXX
#define RPTUI_GROUPS_SORTING_HXX

#include <vcl/floatwin.hxx>
#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#include <vcl/lstbox.hxx>
#include <vcl/edit.hxx>
#include <vcl/field.hxx>
#include <vcl/button.hxx>
#include <vcl/toolbox.hxx>
#include <com/sun/star/report/XGroups.hpp>
#include <com/sun/star/report/XGroup.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include "GroupProperties.hxx"
#include <comphelper/propmultiplex.hxx>
#include "cppuhelper/basemutex.hxx"
#include <svtools/svmedit.hxx>
#include <rtl/ref.hxx>

#include <vector>

#include <dbaccess/ToolBoxHelper.hxx>

#include <vcl/ImageListProvider.hxx>

namespace comphelper
{
    class OPropertyChangeMultiplexer;
}
namespace rptui
{
class OFieldExpressionControl;
class OReportController;
/*************************************************************************
|*
|* Groups and Sorting dialog
|*
\************************************************************************/

class OGroupsSortingDialog :    public FloatingWindow
                            ,   public ::cppu::BaseMutex
                                ,   public ::comphelper::OPropertyChangeListener
                           ,public dbaui::OToolBoxHelper
                           ,public vcl::IImageListProvider
{
    friend class OFieldExpressionControl;

    FixedLine                               m_aFL2;
    FixedText                               m_aMove;
//BTN   ImageButton                             m_aPB_Up;
//BTN   ImageButton                             m_aPB_Down;
//BTN   ImageButton                             m_aPB_Delete;
    ToolBox                                 m_aToolBox;

    FixedLine                               m_aFL3;
    FixedText                               m_aOrder;
    ListBox                                 m_aOrderLst;
    FixedText                               m_aHeader;
    ListBox                                 m_aHeaderLst;
    FixedText                               m_aFooter;
    ListBox                                 m_aFooterLst;
    FixedText                               m_aGroupOn;
    ListBox                                 m_aGroupOnLst;
    FixedText                               m_aGroupInterval;
    NumericField                            m_aGroupIntervalEd;
    FixedText                               m_aKeepTogether;
    ListBox                                 m_aKeepTogetherLst;
    FixedLine                               m_aFL;
    FixedText                               m_aHelpWindow;

    OFieldExpressionControl*                m_pFieldExpression;
    ::rptui::OReportController*             m_pController;
    ::rtl::Reference< comphelper::OPropertyChangeMultiplexer>                       m_pCurrentGroupListener;
    ::rtl::Reference< comphelper::OPropertyChangeMultiplexer>                       m_pReportListener;
    ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroups>            m_xGroups;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >    m_xColumns;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >          m_xHoldAlive;
    sal_Bool                                m_bReadOnly;
private:
    DECL_LINK( OnControlFocusLost, Control* );
    DECL_LINK( OnControlFocusGot, Control* );
    DECL_LINK( LBChangeHdl, ListBox* );
//BTN   DECL_LINK( ClickHdl, ImageButton* );
    DECL_LINK( OnFormatAction,      ToolBox* );

    /** returns the groups
        @return the groups which now have to check which one changes
    */
    ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroups>& getGroups() { return m_xGroups; }

    ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroup> getGroup(sal_Int32 _nPos)
    {
        OSL_ENSURE(_nPos >= 0 && _nPos < m_xGroups->getCount(),"Invalid count!");
        return ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroup>(m_xGroups->getByIndex(_nPos),::com::sun::star::uno::UNO_QUERY);
    }

    /** updates the listboxes with the new group properties
        @param  _nRow   the new group pos
    */
    void DisplayData( sal_Int32 _nRow );

    /** saves the values from the listboxes into the group at position _nRow
        @param  _nRow   the group pos to store in
    */
    void SaveData( sal_Int32 _nRow );

    /** returns <TRUE/> when the dialog should be read only
    */
    sal_Bool isReadOnly( ) const;

    /** returns the data type for the given column name
        @param _sColumnName
    */
    sal_Int32 getColumnDataType(const ::rtl::OUString& _sColumnName);

    /** shows the text given by the id in the multiline edit
        @param  _nResId the string id
    */
    void showHelpText(USHORT _nResId);
    /** display the group props
        @param  _xGroup the group to display
    */
    void displayGroup(const ::com::sun::star::uno::Reference< ::com::sun::star::report::XGroup>& _xGroup);

    /** enables or diables the up and down button
        @param  _nRow   the row which will be active
    */
    void checkButtons(sal_Int32 _nRow);

    /** clears the m_xColumns member and reset the fields
    *
    */
    void fillColumns();
    OGroupsSortingDialog(OGroupsSortingDialog&);
    void operator =(OGroupsSortingDialog&);
protected:
    // window
    virtual void    Resize();
    // OPropertyChangeListener
    virtual void    _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& _rEvent) throw( ::com::sun::star::uno::RuntimeException);
public:
    OGroupsSortingDialog( Window* pParent
                        ,sal_Bool _bReadOnly
                        ,::rptui::OReportController* _pController);
    virtual ~OGroupsSortingDialog();

    /** sets the newe columns at the groups dialog.
        @param  _xColumns the new columns
    */
    void setColumns(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _xColumns);

    /* updates the current view
    */
    void UpdateData( );

        /** will be called when the controls need to be resized.
            @param  _rDiff
                Contains the difference of the old and new toolbox size.
        */
        virtual void resizeControls(const Size& _rDiff);

        /** will be called when the image list is needed.
            @param  _eSymbolsSize
                <svtools/imgdef.hxx>
            @param  _bHiContast
                <TRUE/> when in high contrast mode.
        */
    virtual ImageList getImageList(sal_Int16 _eSymbolsSize,sal_Bool _bHiContast) const;

    // ImageListProvider interface
    virtual ImageList getImageList(vcl::ImageListType) SAL_THROW ((com::sun::star::lang::IllegalArgumentException ));

};
// =============================================================================
} // namespace rptui
// =============================================================================
#endif // RPTUI_GROUPS_SORTING_HXX
<|endoftext|>


<commit_before>#include <Core/Asset/Camera.hpp>
#include <Engine/Scene/CameraComponent.hpp>

#include <Core/Containers/MakeShared.hpp>
#include <Core/Math/Math.hpp>

namespace Ra {

using Core::Math::Pi;
using Core::Math::PiDiv2;
using Core::Math::PiDiv4;

namespace Core {

namespace Asset {

Camera::Camera( Scalar width, Scalar height ) :
    m_width {width}, m_height {height}, m_aspect {width / height} {}

Camera& Camera::operator=( const Camera& rhs ) {
    m_frame      = rhs.getFrame();
    m_projMatrix = rhs.getProjMatrix();
    m_projType   = rhs.getType();
    m_zoomFactor = rhs.getZoomFactor();
    m_fov        = rhs.getFOV();
    m_zNear      = rhs.getZNear();
    m_zFar       = rhs.getZFar();
    setViewport( rhs.getWidth(), rhs.getHeight() );
    return *this;
}

void Camera::setDirection( const Core::Vector3& direction ) {
    Core::Transform T = Core::Transform::Identity();

    auto d0 = getDirection();
    auto d1 = direction.normalized();

    auto c = d0.cross( d1 );
    auto d = d0.dot( d1 );

    // Special case if two directions are exactly opposites we constrain.
    // to rotate around the up vector.
    if ( c.isApprox( Core::Vector3::Zero() ) && d < 0.0 )
    { T.rotate( Core::AngleAxis( Core::Math::PiDiv2, Core::Vector3::UnitY() ) ); }
    else
    { T.rotate( Core::Quaternion::FromTwoVectors( d0, d1 ) ); }
    applyTransform( T );
}

void Camera::setViewport( Scalar width, Scalar height ) {
    m_width  = width;
    m_height = height;
    m_aspect = width / height;
    updateProjMatrix();
}

void Camera::applyTransform( const Core::Transform& T ) {
    Core::Transform t1 = Core::Transform::Identity();
    Core::Transform t2 = Core::Transform::Identity();
    t1.translation()   = -getPosition();
    t2.translation()   = getPosition();

    m_frame = t2 * T * t1 * m_frame;
}

void Camera::updateProjMatrix() {

    switch ( m_projType )
    {
    case ProjType::ORTHOGRAPHIC: {
        const Scalar dx = m_zoomFactor * .5_ra;
        const Scalar dy = dx / m_aspect;
        // ------------
        // Compute projection matrix as describe in the doc of glOrtho()
        const Scalar l = -dx; // left
        const Scalar r = dx;  // right
        const Scalar t = dy;  // top
        const Scalar b = -dy; // bottom
        m_projMatrix   = ortho( b, t, l, r, m_zNear, m_zFar );
    }
    break;

    case ProjType::PERSPECTIVE: {
        // Compute projection matrix as describe here
        // https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix
        auto scale = std::tan( m_fov * .5_ra ) * m_zNear;

        auto r = scale;
        auto l = -r;
        auto t = scale / m_aspect;
        auto b = -t;

        m_projMatrix = frustum( b, t, l, r, m_zNear, m_zFar );
    }
    break;

    default:
        break;
    }
}

Core::Matrix4 Camera::frustum( Scalar b, Scalar t, Scalar l, Scalar r, Scalar n, Scalar f ) {
    Core::Matrix4 projMatrix;
    projMatrix.setZero();
    const Scalar diff           = ( n - f );
    projMatrix.coeffRef( 0, 0 ) = 2_ra * n / ( r - l );
    projMatrix.coeffRef( 1, 1 ) = 2_ra * n / ( t - b );
    projMatrix.coeffRef( 2, 2 ) = ( f + n ) / diff;
    projMatrix.coeffRef( 2, 3 ) = ( 2_ra * f * n ) / diff;
    projMatrix.coeffRef( 3, 2 ) = -1_ra;
    return projMatrix;
}

Core::Matrix4 Camera::ortho( Scalar b, Scalar t, Scalar l, Scalar r, Scalar n, Scalar f ) {
    Core::Matrix4 projMatrix;
    projMatrix.setZero();

    Core::Vector3 tr( -( r + l ) / ( r - l ), -( t + b ) / ( t - b ), -( ( f + n ) / ( f - n ) ) );

    projMatrix.setIdentity();
    projMatrix.coeffRef( 0, 0 )    = 2_ra / ( r - l );
    projMatrix.coeffRef( 1, 1 )    = 2_ra / ( t - b );
    projMatrix.coeffRef( 2, 2 )    = -2_ra / ( f - n );
    projMatrix.block<3, 1>( 0, 3 ) = tr;

    return projMatrix;
}

void Camera::fitZRange( const Core::Aabb& aabb ) {
    const auto& position        = getPosition();
    Ra::Core::Vector3 direction = getDirection();

    const auto& minAabb = aabb.min();
    const auto& maxAabb = aabb.max();
    m_zNear = m_zFar = direction.dot( minAabb - position );

    auto adaptRange = [position, direction, this]( Scalar x, Scalar y, Scalar z ) {
        Ra::Core::Vector3 corner( x, y, z );
        auto d        = direction.dot( corner - position );
        this->m_zNear = std::min( d, this->m_zNear );
        this->m_zFar  = std::max( d, this->m_zFar );
    };

    adaptRange( minAabb[0], minAabb[1], maxAabb[2] );
    adaptRange( minAabb[0], maxAabb[1], minAabb[2] );
    adaptRange( minAabb[0], maxAabb[1], maxAabb[2] );
    adaptRange( maxAabb[0], maxAabb[1], maxAabb[2] );
    adaptRange( maxAabb[0], maxAabb[1], minAabb[2] );
    adaptRange( maxAabb[0], minAabb[1], maxAabb[2] );
    adaptRange( maxAabb[0], minAabb[1], minAabb[2] );

    if ( m_zNear < m_minZNear ) { m_zNear = m_minZNear; }
    if ( ( m_zFar - m_zNear ) < m_minZRange ) { m_zFar = m_zNear + m_minZRange; }

    updateProjMatrix();
}

Core::Ray Camera::getRayFromScreen( const Core::Vector2& pix ) const {
    // Ray starts from the camera's current position.
    return Core::Ray::Through( getPosition(), unProject( pix ) );
}

} // namespace Asset
} // namespace Core
} // namespace Ra
<commit_msg>[core] fix frustum.<commit_after>#include <Core/Asset/Camera.hpp>
#include <Engine/Scene/CameraComponent.hpp>

#include <Core/Containers/MakeShared.hpp>
#include <Core/Math/Math.hpp>

namespace Ra {

using Core::Math::Pi;
using Core::Math::PiDiv2;
using Core::Math::PiDiv4;

namespace Core {

namespace Asset {

Camera::Camera( Scalar width, Scalar height ) :
    m_width {width}, m_height {height}, m_aspect {width / height} {}

Camera& Camera::operator=( const Camera& rhs ) {
    m_frame      = rhs.getFrame();
    m_projMatrix = rhs.getProjMatrix();
    m_projType   = rhs.getType();
    m_zoomFactor = rhs.getZoomFactor();
    m_fov        = rhs.getFOV();
    m_zNear      = rhs.getZNear();
    m_zFar       = rhs.getZFar();
    setViewport( rhs.getWidth(), rhs.getHeight() );
    return *this;
}

void Camera::setDirection( const Core::Vector3& direction ) {
    Core::Transform T = Core::Transform::Identity();

    auto d0 = getDirection();
    auto d1 = direction.normalized();

    auto c = d0.cross( d1 );
    auto d = d0.dot( d1 );

    // Special case if two directions are exactly opposites we constrain.
    // to rotate around the up vector.
    if ( c.isApprox( Core::Vector3::Zero() ) && d < 0.0 )
    { T.rotate( Core::AngleAxis( Core::Math::PiDiv2, Core::Vector3::UnitY() ) ); }
    else
    { T.rotate( Core::Quaternion::FromTwoVectors( d0, d1 ) ); }
    applyTransform( T );
}

void Camera::setViewport( Scalar width, Scalar height ) {
    m_width  = width;
    m_height = height;
    m_aspect = width / height;
    updateProjMatrix();
}

void Camera::applyTransform( const Core::Transform& T ) {
    Core::Transform t1 = Core::Transform::Identity();
    Core::Transform t2 = Core::Transform::Identity();
    t1.translation()   = -getPosition();
    t2.translation()   = getPosition();

    m_frame = t2 * T * t1 * m_frame;
}

void Camera::updateProjMatrix() {

    switch ( m_projType )
    {
    case ProjType::ORTHOGRAPHIC: {
        const Scalar dx = m_zoomFactor * .5_ra;
        const Scalar dy = dx / m_aspect;
        // ------------
        // Compute projection matrix as describe in the doc of glOrtho()
        const Scalar l = -dx; // left
        const Scalar r = dx;  // right
        const Scalar t = dy;  // top
        const Scalar b = -dy; // bottom
        m_projMatrix   = ortho( b, t, l, r, m_zNear, m_zFar );
    }
    break;

    case ProjType::PERSPECTIVE: {
        // Compute projection matrix as describe here
        // https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix
        auto scale = std::tan( m_fov * .5_ra ) * m_zNear;

        auto r = scale;
        auto l = -r;
        auto t = scale / m_aspect;
        auto b = -t;

        m_projMatrix = frustum( b, t, l, r, m_zNear, m_zFar );
    }
    break;

    default:
        break;
    }
}

Core::Matrix4 Camera::frustum( Scalar b, Scalar t, Scalar l, Scalar r, Scalar n, Scalar f ) {
    Core::Matrix4 projMatrix;
    projMatrix.setZero();
    projMatrix.coeffRef( 0, 0 ) = 2_ra * n / ( r - l );
    projMatrix.coeffRef( 1, 1 ) = 2_ra * n / ( t - b );

    /// (row, col)
    projMatrix.coeffRef( 0, 2 ) = ( r + l ) / ( r - l );
    projMatrix.coeffRef( 1, 2 ) = ( t + b ) / ( t - b );
    projMatrix.coeffRef( 2, 2 ) = -( f + n ) / ( f - n );
    projMatrix.coeffRef( 3, 2 ) = -1_ra;

    projMatrix.coeffRef( 2, 3 ) = -( 2_ra * f * n ) / ( f - n );

    return projMatrix;
}

Core::Matrix4 Camera::ortho( Scalar b, Scalar t, Scalar l, Scalar r, Scalar n, Scalar f ) {
    Core::Matrix4 projMatrix;
    projMatrix.setZero();

    Core::Vector3 tr( -( r + l ) / ( r - l ), -( t + b ) / ( t - b ), -( ( f + n ) / ( f - n ) ) );

    projMatrix.setIdentity();
    projMatrix.coeffRef( 0, 0 )    = 2_ra / ( r - l );
    projMatrix.coeffRef( 1, 1 )    = 2_ra / ( t - b );
    projMatrix.coeffRef( 2, 2 )    = -2_ra / ( f - n );
    projMatrix.block<3, 1>( 0, 3 ) = tr;

    return projMatrix;
}

void Camera::fitZRange( const Core::Aabb& aabb ) {
    const auto& position        = getPosition();
    Ra::Core::Vector3 direction = getDirection();

    const auto& minAabb = aabb.min();
    const auto& maxAabb = aabb.max();
    m_zNear = m_zFar = direction.dot( minAabb - position );

    auto adaptRange = [position, direction, this]( Scalar x, Scalar y, Scalar z ) {
        Ra::Core::Vector3 corner( x, y, z );
        auto d        = direction.dot( corner - position );
        this->m_zNear = std::min( d, this->m_zNear );
        this->m_zFar  = std::max( d, this->m_zFar );
    };

    adaptRange( minAabb[0], minAabb[1], maxAabb[2] );
    adaptRange( minAabb[0], maxAabb[1], minAabb[2] );
    adaptRange( minAabb[0], maxAabb[1], maxAabb[2] );
    adaptRange( maxAabb[0], maxAabb[1], maxAabb[2] );
    adaptRange( maxAabb[0], maxAabb[1], minAabb[2] );
    adaptRange( maxAabb[0], minAabb[1], maxAabb[2] );
    adaptRange( maxAabb[0], minAabb[1], minAabb[2] );

    if ( m_zNear < m_minZNear ) { m_zNear = m_minZNear; }
    if ( ( m_zFar - m_zNear ) < m_minZRange ) { m_zFar = m_zNear + m_minZRange; }

    updateProjMatrix();
}

Core::Ray Camera::getRayFromScreen( const Core::Vector2& pix ) const {
    // Ray starts from the camera's current position.
    return Core::Ray::Through( getPosition(), unProject( pix ) );
}

} // namespace Asset
} // namespace Core
} // namespace Ra
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __BSE_BLOCK_UTILS_H__
#define __BSE_BLOCK_UTILS_H__
#include <wchar.h> /* wmemset */
#include <bse/bseieee754.hh>

template<class TYPE> inline
void    bse_block_fill_0                          (size_t        n_values,        /* 4-byte variant of memset */
                                                   TYPE         *values);
/* --- C API --- */
const
char*   bse_block_impl_name                       (void);
static inline
void    bse_block_fill_uint32                     (guint          n_values,       /* 4-byte variant of memset for ints */
                                                   guint32       *values,
                                                   guint32        vuint32);
static inline
void    bse_block_fill_float                      (uint	          n_values,       /* 4-byte variant of memset for floats */
                                                   float         *values,
                                                   const float    value);
static inline
void    bse_block_copy_uint32                     (guint	  n_values,       /* 4-byte variant of memcpy for ints */
                                                   guint32       *values,
                                                   const guint32 *ivalues);
static inline
void    bse_block_copy_float                      (guint	  n_values,       /* 4-byte variant of memcpy for floats */
                                                   gfloat        *values,
                                                   const gfloat  *ivalues);
void    bse_block_add_floats                      (guint	  n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues);
void    bse_block_sub_floats                      (guint	  n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues);
void    bse_block_mul_floats                      (guint	  n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues);
void    bse_block_scale_floats                    (guint          n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues,
                                                   const float    level);
void    bse_block_interleave2_floats              (guint	  n_ivalues,
                                                   float         *ovalues,        /* length_ovalues = n_ivalues * 2 */
                                                   const float   *ivalues,
                                                   guint          offset);        /* 0=left, 1=right */
void    bse_block_interleave2_add_floats          (guint	  n_ivalues,
                                                   float         *ovalues,        /* length_ovalues = n_ivalues * 2 */
                                                   const float   *ivalues,
                                                   guint          offset);        /* 0=left, 1=right */
void    bse_block_calc_float_range                (guint          n_values,
                                                   const float   *ivalues,
	                                           float         *min_value,
	                                           float         *max_value);
float   bse_block_calc_float_square_sum           (guint          n_values,
                                                   const float   *ivalues);
float   bse_block_calc_float_range_and_square_sum (guint          n_values,
                                                   const float   *ivalues,
	                                           float         *min_value,
	                                           float         *max_value);

#ifdef  __cplusplus
#include <bse/bseresampler.hh>
namespace Bse {

/* --- C++ API --- */
class Block {
public:
  static const char*    impl_name            ()                              { return singleton->impl_name (); }
  static inline   void	fill                 (guint           n_values,
					      float          *values,
					      float           value);
  static inline   void	fill                 (guint           n_values,
					      guint32        *values,
					      guint32         value);
  static inline   void	copy                 (guint           n_values,
					      float          *values,
					      const float    *ivalues);
  static inline   void	copy                 (guint           n_values,
					      guint32        *values,
					      const guint32  *ivalues);
  static inline   void	add                  (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues)       { singleton->add (n_values, ovalues, ivalues); }
  static inline   void	sub                  (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues)       { singleton->sub (n_values, ovalues, ivalues); }
  static inline   void	mul                  (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues)       { singleton->mul (n_values, ovalues, ivalues); }
  static inline   void	scale                (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues,
					      const float     level)         { singleton->scale (n_values, ovalues, ivalues, level); }
  static inline   void	interleave2          (guint	      n_ivalues,
					      float          *ovalues,
					      const float    *ivalues,
					      guint           offset)        { singleton->interleave2 (n_ivalues, ovalues, ivalues, offset); }
  static inline   void	interleave2_add      (guint	      n_ivalues,
					      float          *ovalues,
					      const float    *ivalues,
					      guint           offset)        { singleton->interleave2_add (n_ivalues, ovalues, ivalues, offset); }
  static inline   void	range    	     (guint	      n_values,
					      const float    *ivalues,
					      float&          min_value,
					      float&          max_value)     { singleton->range (n_values, ivalues, min_value, max_value); }
  static inline   float	square_sum           (guint	      n_values,
					      const float    *ivalues)       { return singleton->square_sum (n_values, ivalues); }
  static inline   float	range_and_square_sum (guint	      n_values,
                                              const float    *ivalues,
					      float&          min_value,
					      float&          max_value)     { return singleton->range_and_square_sum (n_values, ivalues, min_value, max_value); }

  typedef Resampler::Resampler2 Resampler2;
  static inline
  Resampler2*           create_resampler2    (BseResampler2Mode      mode,
                                              BseResampler2Precision precision)	  { return singleton->create_resampler2 (mode, precision); }
  static inline
  bool                  test_resampler2	     (bool                   verbose)	  { return singleton->test_resampler2 (verbose); }

  class Impl {
  protected:
    virtual      ~Impl                  ();
    virtual const char* impl_name       () = 0;
    virtual void  add                   (guint	         n_values,
                                         float          *ovalues,
                                         const float    *ivalues) = 0;
    virtual void  sub                   (guint	         n_values,
                                         float          *ovalues,
                                         const float    *ivalues) = 0;
    virtual void  mul                   (guint	         n_values,
                                         float          *ovalues,
                                         const float    *ivalues) = 0;
    virtual void  scale                 (guint           n_values,
                                         float          *ovalues,
                                         const float    *ivalues,
                                         const float     level) = 0;
    virtual void  interleave2           (guint	         n_ivalues,
                                         float          *ovalues,	/* length_ovalues = n_ivalues * 2 */
                                         const float    *ivalues,
                                         guint           offset) = 0;   /* 0=left, 1=right */
    virtual void  interleave2_add       (guint	         n_ivalues,
                                         float          *ovalues,	/* length_ovalues = n_ivalues * 2 */
                                         const float    *ivalues,
                                         guint           offset) = 0;   /* 0=left, 1=right */
    virtual void  range                 (guint	         n_values,
                                         const float    *ivalues,
					 float&          min_value,
					 float&          max_value) = 0;
    virtual float square_sum            (guint	         n_values,
                                         const float    *ivalues) = 0;
    virtual float range_and_square_sum	(guint	         n_values,
                                         const float    *ivalues,
					 float&          min_value,
					 float&          max_value) = 0;
    virtual
    Resampler2*   create_resampler2     (BseResampler2Mode      mode,
                                         BseResampler2Precision precision) = 0;
    virtual bool  test_resampler2	(bool			verbose) = 0;
  friend class Block;
    static  void  substitute            (Impl           *substitute_impl);
  };
  static Impl*  default_singleton       ();
  static Impl*  current_singleton       ();
private:
  static Impl  *singleton;
};

/* --- C++ implementation bits --- */
inline void
Block::fill (guint           n_values,
             float          *values,
             float           value)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  const union { float f; guint32 vuint32; } u = { value };
  wmemset ((wchar_t*) values, u.vuint32, n_values);
}

inline void
Block::fill (guint           n_values,
             guint32        *values,
             guint32         value)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemset ((wchar_t*) values, value, n_values);
}

inline void
Block::copy (guint          n_values,
             guint32       *values,
             const guint32 *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}

inline void
Block::copy (guint         n_values,
             gfloat       *values,
             const gfloat *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}

} // Bse
#endif  /* __cplusplus */

/* --- C implementation bits --- */
static inline void
bse_block_fill_uint32 (guint    n_values,
		       guint32 *values,
		       guint32  vuint32)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemset ((wchar_t*) values, vuint32, n_values);
}

static inline void
bse_block_fill_float (guint	   n_values,
		      float       *values,
		      const float  value)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  const union { float f; guint32 vuint32; } u = { value };
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemset ((wchar_t*) values, u.vuint32, n_values);
}

static inline void
bse_block_copy_uint32 (guint	      n_values,
		       guint32       *values,
		       const guint32 *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}

static inline void
bse_block_copy_float (guint	    n_values,
		      gfloat       *values,
		      const gfloat *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}
// == C++ Implementations ==
template<class TYPE> inline void
bse_block_fill_0 (size_t n_values, TYPE *values)
{
  size_t n_bytes = n_values * sizeof (TYPE);
  char *p = (char*) values;
  uint r = size_t (p) & 3;
  if (RAPICORN_UNLIKELY (r))
    {
      r = MIN (r, n_values);    // rest for pointer alignment
      memset (p, 0, r);
      p += r;
      n_bytes -= r;
    }
  const size_t n_aligned = n_bytes / 4;
  wmemset ((wchar_t*) p, 0, n_aligned);
  n_bytes -= n_aligned * 4;
  if (RAPICORN_UNLIKELY (n_bytes))
    {
      p += n_aligned * 4;
      memset (p, 0, n_bytes);
    }
}

#endif /* __BSE_BLOCK_UTILS_H__ */
<commit_msg>BSE: use BSE_UNLIKELY instead of a Rapicorn macro<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __BSE_BLOCK_UTILS_H__
#define __BSE_BLOCK_UTILS_H__
#include <wchar.h> /* wmemset */
#include <bse/bseieee754.hh>

template<class TYPE> inline
void    bse_block_fill_0                          (size_t        n_values,        /* 4-byte variant of memset */
                                                   TYPE         *values);
/* --- C API --- */
const
char*   bse_block_impl_name                       (void);
static inline
void    bse_block_fill_uint32                     (guint          n_values,       /* 4-byte variant of memset for ints */
                                                   guint32       *values,
                                                   guint32        vuint32);
static inline
void    bse_block_fill_float                      (uint	          n_values,       /* 4-byte variant of memset for floats */
                                                   float         *values,
                                                   const float    value);
static inline
void    bse_block_copy_uint32                     (guint	  n_values,       /* 4-byte variant of memcpy for ints */
                                                   guint32       *values,
                                                   const guint32 *ivalues);
static inline
void    bse_block_copy_float                      (guint	  n_values,       /* 4-byte variant of memcpy for floats */
                                                   gfloat        *values,
                                                   const gfloat  *ivalues);
void    bse_block_add_floats                      (guint	  n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues);
void    bse_block_sub_floats                      (guint	  n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues);
void    bse_block_mul_floats                      (guint	  n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues);
void    bse_block_scale_floats                    (guint          n_values,
                                                   float         *ovalues,
                                                   const float   *ivalues,
                                                   const float    level);
void    bse_block_interleave2_floats              (guint	  n_ivalues,
                                                   float         *ovalues,        /* length_ovalues = n_ivalues * 2 */
                                                   const float   *ivalues,
                                                   guint          offset);        /* 0=left, 1=right */
void    bse_block_interleave2_add_floats          (guint	  n_ivalues,
                                                   float         *ovalues,        /* length_ovalues = n_ivalues * 2 */
                                                   const float   *ivalues,
                                                   guint          offset);        /* 0=left, 1=right */
void    bse_block_calc_float_range                (guint          n_values,
                                                   const float   *ivalues,
	                                           float         *min_value,
	                                           float         *max_value);
float   bse_block_calc_float_square_sum           (guint          n_values,
                                                   const float   *ivalues);
float   bse_block_calc_float_range_and_square_sum (guint          n_values,
                                                   const float   *ivalues,
	                                           float         *min_value,
	                                           float         *max_value);

#ifdef  __cplusplus
#include <bse/bseresampler.hh>
namespace Bse {

/* --- C++ API --- */
class Block {
public:
  static const char*    impl_name            ()                              { return singleton->impl_name (); }
  static inline   void	fill                 (guint           n_values,
					      float          *values,
					      float           value);
  static inline   void	fill                 (guint           n_values,
					      guint32        *values,
					      guint32         value);
  static inline   void	copy                 (guint           n_values,
					      float          *values,
					      const float    *ivalues);
  static inline   void	copy                 (guint           n_values,
					      guint32        *values,
					      const guint32  *ivalues);
  static inline   void	add                  (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues)       { singleton->add (n_values, ovalues, ivalues); }
  static inline   void	sub                  (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues)       { singleton->sub (n_values, ovalues, ivalues); }
  static inline   void	mul                  (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues)       { singleton->mul (n_values, ovalues, ivalues); }
  static inline   void	scale                (guint	      n_values,
					      float          *ovalues,
					      const float    *ivalues,
					      const float     level)         { singleton->scale (n_values, ovalues, ivalues, level); }
  static inline   void	interleave2          (guint	      n_ivalues,
					      float          *ovalues,
					      const float    *ivalues,
					      guint           offset)        { singleton->interleave2 (n_ivalues, ovalues, ivalues, offset); }
  static inline   void	interleave2_add      (guint	      n_ivalues,
					      float          *ovalues,
					      const float    *ivalues,
					      guint           offset)        { singleton->interleave2_add (n_ivalues, ovalues, ivalues, offset); }
  static inline   void	range    	     (guint	      n_values,
					      const float    *ivalues,
					      float&          min_value,
					      float&          max_value)     { singleton->range (n_values, ivalues, min_value, max_value); }
  static inline   float	square_sum           (guint	      n_values,
					      const float    *ivalues)       { return singleton->square_sum (n_values, ivalues); }
  static inline   float	range_and_square_sum (guint	      n_values,
                                              const float    *ivalues,
					      float&          min_value,
					      float&          max_value)     { return singleton->range_and_square_sum (n_values, ivalues, min_value, max_value); }

  typedef Resampler::Resampler2 Resampler2;
  static inline
  Resampler2*           create_resampler2    (BseResampler2Mode      mode,
                                              BseResampler2Precision precision)	  { return singleton->create_resampler2 (mode, precision); }
  static inline
  bool                  test_resampler2	     (bool                   verbose)	  { return singleton->test_resampler2 (verbose); }

  class Impl {
  protected:
    virtual      ~Impl                  ();
    virtual const char* impl_name       () = 0;
    virtual void  add                   (guint	         n_values,
                                         float          *ovalues,
                                         const float    *ivalues) = 0;
    virtual void  sub                   (guint	         n_values,
                                         float          *ovalues,
                                         const float    *ivalues) = 0;
    virtual void  mul                   (guint	         n_values,
                                         float          *ovalues,
                                         const float    *ivalues) = 0;
    virtual void  scale                 (guint           n_values,
                                         float          *ovalues,
                                         const float    *ivalues,
                                         const float     level) = 0;
    virtual void  interleave2           (guint	         n_ivalues,
                                         float          *ovalues,	/* length_ovalues = n_ivalues * 2 */
                                         const float    *ivalues,
                                         guint           offset) = 0;   /* 0=left, 1=right */
    virtual void  interleave2_add       (guint	         n_ivalues,
                                         float          *ovalues,	/* length_ovalues = n_ivalues * 2 */
                                         const float    *ivalues,
                                         guint           offset) = 0;   /* 0=left, 1=right */
    virtual void  range                 (guint	         n_values,
                                         const float    *ivalues,
					 float&          min_value,
					 float&          max_value) = 0;
    virtual float square_sum            (guint	         n_values,
                                         const float    *ivalues) = 0;
    virtual float range_and_square_sum	(guint	         n_values,
                                         const float    *ivalues,
					 float&          min_value,
					 float&          max_value) = 0;
    virtual
    Resampler2*   create_resampler2     (BseResampler2Mode      mode,
                                         BseResampler2Precision precision) = 0;
    virtual bool  test_resampler2	(bool			verbose) = 0;
  friend class Block;
    static  void  substitute            (Impl           *substitute_impl);
  };
  static Impl*  default_singleton       ();
  static Impl*  current_singleton       ();
private:
  static Impl  *singleton;
};

/* --- C++ implementation bits --- */
inline void
Block::fill (guint           n_values,
             float          *values,
             float           value)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  const union { float f; guint32 vuint32; } u = { value };
  wmemset ((wchar_t*) values, u.vuint32, n_values);
}

inline void
Block::fill (guint           n_values,
             guint32        *values,
             guint32         value)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemset ((wchar_t*) values, value, n_values);
}

inline void
Block::copy (guint          n_values,
             guint32       *values,
             const guint32 *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}

inline void
Block::copy (guint         n_values,
             gfloat       *values,
             const gfloat *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}

} // Bse
#endif  /* __cplusplus */

/* --- C implementation bits --- */
static inline void
bse_block_fill_uint32 (guint    n_values,
		       guint32 *values,
		       guint32  vuint32)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemset ((wchar_t*) values, vuint32, n_values);
}

static inline void
bse_block_fill_float (guint	   n_values,
		      float       *values,
		      const float  value)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  const union { float f; guint32 vuint32; } u = { value };
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemset ((wchar_t*) values, u.vuint32, n_values);
}

static inline void
bse_block_copy_uint32 (guint	      n_values,
		       guint32       *values,
		       const guint32 *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}

static inline void
bse_block_copy_float (guint	    n_values,
		      gfloat       *values,
		      const gfloat *ivalues)
{
  RAPICORN_STATIC_ASSERT (sizeof (float) == 4);
  RAPICORN_STATIC_ASSERT (sizeof (wchar_t) == 4);
  wmemcpy ((wchar_t*) values, (const wchar_t*) ivalues, n_values);
}
// == C++ Implementations ==
template<class TYPE> inline void
bse_block_fill_0 (size_t n_values, TYPE *values)
{
  size_t n_bytes = n_values * sizeof (TYPE);
  char *p = (char*) values;
  uint r = size_t (p) & 3;
  if (BSE_UNLIKELY (r))
    {
      r = MIN (r, n_values);    // rest for pointer alignment
      memset (p, 0, r);
      p += r;
      n_bytes -= r;
    }
  const size_t n_aligned = n_bytes / 4;
  wmemset ((wchar_t*) p, 0, n_aligned);
  n_bytes -= n_aligned * 4;
  if (BSE_UNLIKELY (n_bytes))
    {
      p += n_aligned * 4;
      memset (p, 0, n_bytes);
    }
}

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


<commit_before>#include "chainerx/routines/linalg.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <utility>
#include <vector>

#include <nonstd/optional.hpp>

#include "chainerx/array.h"
#include "chainerx/axes.h"
#include "chainerx/backend.h"
#include "chainerx/backprop_mode.h"
#include "chainerx/backward_builder.h"
#include "chainerx/backward_context.h"
#include "chainerx/dtype.h"
#include "chainerx/error.h"
#include "chainerx/graph.h"
#include "chainerx/kernels/linalg.h"
#include "chainerx/routines/creation.h"
#include "chainerx/routines/manipulation.h"
#include "chainerx/routines/type_util.h"
#include "chainerx/shape.h"

namespace chainerx {

Array Dot(const Array& a, const Array& b, nonstd::optional<Dtype> out_dtype) {
    Dtype real_out_dtype = out_dtype.has_value() ? *out_dtype : ResultType(a, b);

    if (a.ndim() == 0 || b.ndim() == 0) {
        return a * b;
    }

    Array modified_b{};

    Shape out_shape{};
    std::copy(a.shape().begin(), a.shape().end() - 1, std::back_inserter(out_shape));

    if (b.ndim() > 2) {
        std::vector<int> b_transpose_axes{};
        b_transpose_axes.reserve(b.ndim());
        std::vector<int> axes_index(b.ndim());
        std::iota(axes_index.begin(), axes_index.end(), 0);
        std::copy(axes_index.begin(), axes_index.end() - 2, std::back_inserter(b_transpose_axes));
        std::reverse_copy(axes_index.end() - 2, axes_index.end(), std::back_inserter(b_transpose_axes));

        Axes axes(b_transpose_axes.begin(), b_transpose_axes.end());
        modified_b = b.Transpose(axes);
        std::copy(modified_b.shape().begin(), modified_b.shape().end() - 1, std::back_inserter(out_shape));

        modified_b = modified_b.Reshape({-1, modified_b.shape().back()});
        modified_b = modified_b.Transpose();
    } else {
        std::copy(b.shape().begin() + 1, b.shape().end(), std::back_inserter(out_shape));
        modified_b = b;
    }

    int64_t k = a.shape()[a.ndim() - 1];
    if (modified_b.shape()[0] != k) {
        throw DimensionError{"Axis dimension mismatch"};
    }
    if (k == 0) {
        return Zeros(out_shape, real_out_dtype, a.device());
    }

    // Make each operand a matrix
    int64_t m = a.GetTotalSize() / k;
    int64_t n = b.GetTotalSize() / k;
    Array a_matrix = a.Reshape({m, k});
    Array b_matrix = modified_b.Reshape({k, n});

    // Matrix-matrix product
    Array out_matrix = Empty({m, n}, real_out_dtype, a.device());
    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<DotKernel>(a_matrix, b_matrix, out_matrix);
    }

    {
        BackwardBuilder bb{"dot", {a_matrix, b_matrix}, out_matrix};
        if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
            bt.Define([b_matrix_tok = bb.RetainInput(1), a_dtype = a.dtype()](BackwardContext& bctx) {
                const Array& b_matrix = bctx.GetRetainedInput(b_matrix_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = Dot(gout, b_matrix.Transpose(), a_dtype);
            });
        }
        if (BackwardBuilder::Target bt = bb.CreateTarget(1)) {
            bt.Define([a_matrix_tok = bb.RetainInput(0), b_dtype = b.dtype()](BackwardContext& bctx) {
                const Array& a_matrix = bctx.GetRetainedInput(a_matrix_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = Dot(a_matrix.Transpose(), gout, b_dtype);
            });
        }
        bb.Finalize();
    }

    return out_matrix.Reshape(out_shape);
}

Array Solve(const Array& a, const Array& b) {
    if (a.ndim() != 2) {
        throw DimensionError{"ChainerX solve supports only 2-dimensional arrays."};
    }
    if (a.shape()[0] != a.shape()[1]) {
        throw DimensionError{"Matrix is not square."};
    }
    CheckEqual(a.device(), b.device());
    CheckEqual(a.dtype(), b.dtype());
    Dtype dtype = internal::GetMathResultDtype(b.dtype());
    Array out = Empty(b.shape(), dtype, b.device());

    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<SolveKernel>(a, b, out);
    }

    // Reference:
    // https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf
    // Sec. 2.3.1 Matrix inverse product
    {
        BackwardBuilder bb{"solve", {a, b}, out};
        if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
            bt.Define([out_tok = bb.RetainOutput(0), a_tok = bb.RetainInput(0), a_dtype = a.dtype()](BackwardContext& bctx) {
                const Array& a = bctx.GetRetainedInput(a_tok);
                const Array& out = bctx.GetRetainedOutput(out_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = -Dot(ExpandDims(Solve(a.Transpose(), gout), 1), ExpandDims(out, 0), a_dtype);
            });
        }
        if (BackwardBuilder::Target bt = bb.CreateTarget(1)) {
            bt.Define([a_tok = bb.RetainInput(0)](BackwardContext& bctx) {
                const Array& a = bctx.GetRetainedInput(a_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = Solve(a.Transpose(), gout);
            });
        }
        bb.Finalize();
    }

    return out;
}

Array Inverse(const Array& a) {
    if (a.ndim() != 2) {
        throw DimensionError{"ChainerX inverse supports only 2-dimensional arrays."};
    }
    if (a.shape()[0] != a.shape()[1]) {
        throw DimensionError{"Matrix is not square."};
    }
    Dtype dtype = internal::GetMathResultDtype(a.dtype());
    Array out = Empty(a.shape(), dtype, a.device());

    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<InverseKernel>(a, out);
    }

    // Reference:
    // https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf
    // Sec. 2.2.3 Inverse
    {
        BackwardBuilder bb{"inv", a, out};
        if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
            bt.Define([out_tok = bb.RetainOutput(0), a_dtype = a.dtype()](BackwardContext& bctx) {
                const Array& out = bctx.GetRetainedOutput(out_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = -Dot(Dot(out.Transpose(), gout, a_dtype), out.Transpose(), a_dtype);
            });
        }
        bb.Finalize();
    }

    return out;
}

}  // namespace chainerx
<commit_msg>Added helper functions CheckSquareMatrix, CheckSquareMatrix<commit_after>#include "chainerx/routines/linalg.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <utility>
#include <vector>

#include <nonstd/optional.hpp>

#include "chainerx/array.h"
#include "chainerx/axes.h"
#include "chainerx/backend.h"
#include "chainerx/backprop_mode.h"
#include "chainerx/backward_builder.h"
#include "chainerx/backward_context.h"
#include "chainerx/dtype.h"
#include "chainerx/error.h"
#include "chainerx/graph.h"
#include "chainerx/kernels/linalg.h"
#include "chainerx/routines/creation.h"
#include "chainerx/routines/manipulation.h"
#include "chainerx/routines/type_util.h"
#include "chainerx/shape.h"

namespace chainerx {

Array Dot(const Array& a, const Array& b, nonstd::optional<Dtype> out_dtype) {
    Dtype real_out_dtype = out_dtype.has_value() ? *out_dtype : ResultType(a, b);

    if (a.ndim() == 0 || b.ndim() == 0) {
        return a * b;
    }

    Array modified_b{};

    Shape out_shape{};
    std::copy(a.shape().begin(), a.shape().end() - 1, std::back_inserter(out_shape));

    if (b.ndim() > 2) {
        std::vector<int> b_transpose_axes{};
        b_transpose_axes.reserve(b.ndim());
        std::vector<int> axes_index(b.ndim());
        std::iota(axes_index.begin(), axes_index.end(), 0);
        std::copy(axes_index.begin(), axes_index.end() - 2, std::back_inserter(b_transpose_axes));
        std::reverse_copy(axes_index.end() - 2, axes_index.end(), std::back_inserter(b_transpose_axes));

        Axes axes(b_transpose_axes.begin(), b_transpose_axes.end());
        modified_b = b.Transpose(axes);
        std::copy(modified_b.shape().begin(), modified_b.shape().end() - 1, std::back_inserter(out_shape));

        modified_b = modified_b.Reshape({-1, modified_b.shape().back()});
        modified_b = modified_b.Transpose();
    } else {
        std::copy(b.shape().begin() + 1, b.shape().end(), std::back_inserter(out_shape));
        modified_b = b;
    }

    int64_t k = a.shape()[a.ndim() - 1];
    if (modified_b.shape()[0] != k) {
        throw DimensionError{"Axis dimension mismatch"};
    }
    if (k == 0) {
        return Zeros(out_shape, real_out_dtype, a.device());
    }

    // Make each operand a matrix
    int64_t m = a.GetTotalSize() / k;
    int64_t n = b.GetTotalSize() / k;
    Array a_matrix = a.Reshape({m, k});
    Array b_matrix = modified_b.Reshape({k, n});

    // Matrix-matrix product
    Array out_matrix = Empty({m, n}, real_out_dtype, a.device());
    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<DotKernel>(a_matrix, b_matrix, out_matrix);
    }

    {
        BackwardBuilder bb{"dot", {a_matrix, b_matrix}, out_matrix};
        if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
            bt.Define([b_matrix_tok = bb.RetainInput(1), a_dtype = a.dtype()](BackwardContext& bctx) {
                const Array& b_matrix = bctx.GetRetainedInput(b_matrix_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = Dot(gout, b_matrix.Transpose(), a_dtype);
            });
        }
        if (BackwardBuilder::Target bt = bb.CreateTarget(1)) {
            bt.Define([a_matrix_tok = bb.RetainInput(0), b_dtype = b.dtype()](BackwardContext& bctx) {
                const Array& a_matrix = bctx.GetRetainedInput(a_matrix_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = Dot(a_matrix.Transpose(), gout, b_dtype);
            });
        }
        bb.Finalize();
    }

    return out_matrix.Reshape(out_shape);
}

namespace {

void CheckRankTwoArray(const Array& a) {
    if (a.ndim() != 2) {
        throw DimensionError{"ChainerX solve supports only 2-dimensional arrays."};
    }
}

void CheckSquareMatrix(const Array& a) {
    if (a.shape()[0] != a.shape()[1]) {
        throw DimensionError{"Matrix is not square."};
    }
}

}  // namespace

Array Solve(const Array& a, const Array& b) {
    CheckRankTwoArray(a);
    CheckSquareMatrix(a);
    CheckEqual(a.device(), b.device());
    CheckEqual(a.dtype(), b.dtype());
    Dtype dtype = internal::GetMathResultDtype(b.dtype());
    Array out = Empty(b.shape(), dtype, b.device());

    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<SolveKernel>(a, b, out);
    }

    // Reference:
    // https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf
    // Sec. 2.3.1 Matrix inverse product
    {
        BackwardBuilder bb{"solve", {a, b}, out};
        if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
            bt.Define([out_tok = bb.RetainOutput(0), a_tok = bb.RetainInput(0), a_dtype = a.dtype()](BackwardContext& bctx) {
                const Array& a = bctx.GetRetainedInput(a_tok);
                const Array& out = bctx.GetRetainedOutput(out_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = -Dot(ExpandDims(Solve(a.Transpose(), gout), 1), ExpandDims(out, 0), a_dtype);
            });
        }
        if (BackwardBuilder::Target bt = bb.CreateTarget(1)) {
            bt.Define([a_tok = bb.RetainInput(0)](BackwardContext& bctx) {
                const Array& a = bctx.GetRetainedInput(a_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = Solve(a.Transpose(), gout);
            });
        }
        bb.Finalize();
    }

    return out;
}

Array Inverse(const Array& a) {
    CheckRankTwoArray(a);
    CheckSquareMatrix(a);
    Dtype dtype = internal::GetMathResultDtype(a.dtype());
    Array out = Empty(a.shape(), dtype, a.device());

    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<InverseKernel>(a, out);
    }

    // Reference:
    // https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf
    // Sec. 2.2.3 Inverse
    {
        BackwardBuilder bb{"inv", a, out};
        if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
            bt.Define([out_tok = bb.RetainOutput(0), a_dtype = a.dtype()](BackwardContext& bctx) {
                const Array& out = bctx.GetRetainedOutput(out_tok);
                const Array& gout = *bctx.output_grad();
                bctx.input_grad() = -Dot(Dot(out.Transpose(), gout, a_dtype), out.Transpose(), a_dtype);
            });
        }
        bb.Finalize();
    }

    return out;
}

}  // namespace chainerx
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "DateScaling.hxx"
#include <com/sun/star/chart/TimeUnit.hpp>
#include <rtl/math.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"

namespace
{

static const ::rtl::OUString lcl_aServiceName_DateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.DateScaling" ));
static const ::rtl::OUString lcl_aServiceName_InverseDateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.InverseDateScaling" ));

static const ::rtl::OUString lcl_aImplementationName_DateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.DateScaling" ));
static const ::rtl::OUString lcl_aImplementationName_InverseDateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.InverseDateScaling" ));

static const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic
}

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using ::com::sun::star::chart::TimeUnit::DAY;
using ::com::sun::star::chart::TimeUnit::MONTH;
using ::com::sun::star::chart::TimeUnit::YEAR;

DateScaling::DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
        : m_aNullDate( rNullDate )
        , m_nTimeUnit( nTimeUnit )
        , m_bShifted( bShifted )
{
}

DateScaling::~DateScaling()
{
}

double SAL_CALL DateScaling::doScaling( double value )
    throw (uno::RuntimeException)
{
    double fResult(value);
    if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
        ::rtl::math::setNan( & fResult );
    else
    {
        Date aDate(m_aNullDate);
        aDate += static_cast<long>(::rtl::math::approxFloor(value));
        switch( m_nTimeUnit )
        {
            case DAY:
                fResult = value;
                if(m_bShifted)
                    fResult+=0.5;
                break;
            case YEAR:
            case MONTH:
            default:
                fResult = aDate.GetYear();
                fResult *= lcl_fNumberOfMonths;//asssuming equal count of months in each year
                fResult += aDate.GetMonth();

                double fDayOfMonth = aDate.GetDay();
                fDayOfMonth -= 1.0;
                double fDaysInMonth = aDate.GetDaysInMonth();
                fResult += fDayOfMonth/fDaysInMonth;
                if(m_bShifted)
                {
                    if( YEAR==m_nTimeUnit )
                        fResult += 0.5*lcl_fNumberOfMonths;
                    else
                        fResult += 0.5;
                }
                break;
        }
    }
    return fResult;
}

uno::Reference< XScaling > SAL_CALL DateScaling::getInverseScaling()
    throw (uno::RuntimeException)
{
    return new InverseDateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
}

::rtl::OUString SAL_CALL DateScaling::getServiceName()
    throw (uno::RuntimeException)
{
    return lcl_aServiceName_DateScaling;
}

uno::Sequence< ::rtl::OUString > DateScaling::getSupportedServiceNames_Static()
{
    return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_DateScaling, 1 );
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( DateScaling, lcl_aServiceName_DateScaling )

// ----------------------------------------

InverseDateScaling::InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
        : m_aNullDate( rNullDate )
        , m_nTimeUnit( nTimeUnit )
        , m_bShifted( bShifted )
{
}

InverseDateScaling::~InverseDateScaling()
{
}

double SAL_CALL InverseDateScaling::doScaling( double value )
    throw (uno::RuntimeException)
{
    double fResult(value);
    if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
        ::rtl::math::setNan( & fResult );
    else
    {
        switch( m_nTimeUnit )
        {
            case DAY:
                if(m_bShifted)
                    value -= 0.5;
                fResult = value;
                break;
            case YEAR:
            case MONTH:
            default:
                //Date aDate(m_aNullDate);
                if(m_bShifted)
                {
                    if( YEAR==m_nTimeUnit )
                        value -= 0.5*lcl_fNumberOfMonths;
                    else
                        value -= 0.5;
                }
                Date aDate;
                double fYear = ::rtl::math::approxFloor(value/lcl_fNumberOfMonths);
                double fMonth =  ::rtl::math::approxFloor(value-(fYear*lcl_fNumberOfMonths));
                aDate.SetYear( static_cast<USHORT>(fYear) );
                aDate.SetMonth( static_cast<USHORT>(fMonth) );
                aDate.SetDay( 1 );
                double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth;
                double fDay = (value-fMonthCount)*aDate.GetDaysInMonth();
                fDay += 1.0;
                aDate.SetDay( static_cast<USHORT>(::rtl::math::round(fDay)) );
                fResult = aDate - m_aNullDate;
                break;
        }
    }
    return fResult;
}

uno::Reference< XScaling > SAL_CALL InverseDateScaling::getInverseScaling()
    throw (uno::RuntimeException)
{
    return new DateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
}

::rtl::OUString SAL_CALL InverseDateScaling::getServiceName()
    throw (uno::RuntimeException)
{
    return lcl_aServiceName_InverseDateScaling;
}

uno::Sequence< ::rtl::OUString > InverseDateScaling::getSupportedServiceNames_Static()
{
    return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_InverseDateScaling, 1 );
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( InverseDateScaling, lcl_aServiceName_InverseDateScaling )

//.............................................................................
} //namespace chart
//.............................................................................
<commit_msg>chart46: #i25706# implement date axis - #i116406# december dates wrongly interpreted<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "DateScaling.hxx"
#include <com/sun/star/chart/TimeUnit.hpp>
#include <rtl/math.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"

namespace
{

static const ::rtl::OUString lcl_aServiceName_DateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.DateScaling" ));
static const ::rtl::OUString lcl_aServiceName_InverseDateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.InverseDateScaling" ));

static const ::rtl::OUString lcl_aImplementationName_DateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.DateScaling" ));
static const ::rtl::OUString lcl_aImplementationName_InverseDateScaling(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.InverseDateScaling" ));

static const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic
}

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using ::com::sun::star::chart::TimeUnit::DAY;
using ::com::sun::star::chart::TimeUnit::MONTH;
using ::com::sun::star::chart::TimeUnit::YEAR;

DateScaling::DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
        : m_aNullDate( rNullDate )
        , m_nTimeUnit( nTimeUnit )
        , m_bShifted( bShifted )
{
}

DateScaling::~DateScaling()
{
}

double SAL_CALL DateScaling::doScaling( double value )
    throw (uno::RuntimeException)
{
    double fResult(value);
    if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
        ::rtl::math::setNan( & fResult );
    else
    {
        Date aDate(m_aNullDate);
        aDate += static_cast<long>(::rtl::math::approxFloor(value));
        switch( m_nTimeUnit )
        {
            case DAY:
                fResult = value;
                if(m_bShifted)
                    fResult+=0.5;
                break;
            case YEAR:
            case MONTH:
            default:
                fResult = aDate.GetYear();
                fResult *= lcl_fNumberOfMonths;//asssuming equal count of months in each year
                fResult += aDate.GetMonth();

                double fDayOfMonth = aDate.GetDay();
                fDayOfMonth -= 1.0;
                double fDaysInMonth = aDate.GetDaysInMonth();
                fResult += fDayOfMonth/fDaysInMonth;
                if(m_bShifted)
                {
                    if( YEAR==m_nTimeUnit )
                        fResult += 0.5*lcl_fNumberOfMonths;
                    else
                        fResult += 0.5;
                }
                break;
        }
    }
    return fResult;
}

uno::Reference< XScaling > SAL_CALL DateScaling::getInverseScaling()
    throw (uno::RuntimeException)
{
    return new InverseDateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
}

::rtl::OUString SAL_CALL DateScaling::getServiceName()
    throw (uno::RuntimeException)
{
    return lcl_aServiceName_DateScaling;
}

uno::Sequence< ::rtl::OUString > DateScaling::getSupportedServiceNames_Static()
{
    return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_DateScaling, 1 );
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( DateScaling, lcl_aServiceName_DateScaling )

// ----------------------------------------

InverseDateScaling::InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
        : m_aNullDate( rNullDate )
        , m_nTimeUnit( nTimeUnit )
        , m_bShifted( bShifted )
{
}

InverseDateScaling::~InverseDateScaling()
{
}

double SAL_CALL InverseDateScaling::doScaling( double value )
    throw (uno::RuntimeException)
{
    double fResult(value);
    if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
        ::rtl::math::setNan( & fResult );
    else
    {
        switch( m_nTimeUnit )
        {
            case DAY:
                if(m_bShifted)
                    value -= 0.5;
                fResult = value;
                break;
            case YEAR:
            case MONTH:
            default:
                //Date aDate(m_aNullDate);
                if(m_bShifted)
                {
                    if( YEAR==m_nTimeUnit )
                        value -= 0.5*lcl_fNumberOfMonths;
                    else
                        value -= 0.5;
                }
                Date aDate;
                double fYear = ::rtl::math::approxFloor(value/lcl_fNumberOfMonths);
                double fMonth = ::rtl::math::approxFloor(value-(fYear*lcl_fNumberOfMonths));
                if( fMonth==0.0 )
                {
                    fYear--;
                    fMonth=12.0;
                }
                aDate.SetYear( static_cast<USHORT>(fYear) );
                aDate.SetMonth( static_cast<USHORT>(fMonth) );
                aDate.SetDay( 1 );
                double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth;
                double fDay = (value-fMonthCount)*aDate.GetDaysInMonth();
                fDay += 1.0;
                aDate.SetDay( static_cast<USHORT>(::rtl::math::round(fDay)) );
                fResult = aDate - m_aNullDate;
                break;
        }
    }
    return fResult;
}

uno::Reference< XScaling > SAL_CALL InverseDateScaling::getInverseScaling()
    throw (uno::RuntimeException)
{
    return new DateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
}

::rtl::OUString SAL_CALL InverseDateScaling::getServiceName()
    throw (uno::RuntimeException)
{
    return lcl_aServiceName_InverseDateScaling;
}

uno::Sequence< ::rtl::OUString > InverseDateScaling::getSupportedServiceNames_Static()
{
    return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_InverseDateScaling, 1 );
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( InverseDateScaling, lcl_aServiceName_InverseDateScaling )

//.............................................................................
} //namespace chart
//.............................................................................
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2017 ScyllaDB Ltd.
 */

#pragma once

#include <utility>
#include <type_traits>
#include <functional>

namespace seastar {

template <typename Signature>
class noncopyable_function;

/// A clone of \c std::function, but only invokes the move constructor
/// of the contained function.
template <typename Ret, typename... Args>
class noncopyable_function<Ret (Args...)> {
    static constexpr size_t nr_direct = 32;
    union [[gnu::may_alias]] storage {
        char direct[nr_direct];
        void* indirect;
    };
    using call_type = Ret (*)(const noncopyable_function* func, Args...);
    using move_type = void (*)(noncopyable_function* from, noncopyable_function* to);
    using destroy_type = void (*)(noncopyable_function* func);
    struct vtable {
        const call_type call;
        const move_type move;
        const destroy_type destroy;
    };
private:
    const vtable* _vtable;
    storage _storage;
private:
    static Ret empty_call(const noncopyable_function* func, Args... args) {
        throw std::bad_function_call();
    }
    static void empty_move(noncopyable_function* from, noncopyable_function* to) {}
    static void empty_destroy(noncopyable_function* func) {}
    static constexpr vtable _s_empty_vtable = {empty_call, empty_move, empty_destroy};

    static void indirect_move(noncopyable_function* from, noncopyable_function* to) {
        using void_ptr = void*;
        new (&to->_storage.indirect) void_ptr(from->_storage.indirect);
    }

    template <typename Func>
    struct direct_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.direct); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.direct); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(func))(std::forward<Args>(args)...);
        }
        static void move(noncopyable_function* from, noncopyable_function* to) {
            new (access(to)) Func(std::move(*access(from)));
            destroy(from);
        }
        static void destroy(noncopyable_function* func) {
            access(func)->~Func();
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            new (access(to)) Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func>
    struct indirect_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.indirect); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.indirect); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(func))(std::forward<Args>(args)...);
        }
        static void destroy(noncopyable_function* func) {
            delete access(func);
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            to->_storage.indirect = new Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, indirect_move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func, bool Direct = true>
    struct select_vtable_for : direct_vtable_for<Func> {};
    template <typename Func>
    struct select_vtable_for<Func, false> : indirect_vtable_for<Func> {};
    template <typename Func>
    static constexpr bool is_direct() {
        return sizeof(Func) <= nr_direct && alignof(Func) <= alignof(storage);
    }
    template <typename Func>
    struct vtable_for : select_vtable_for<Func, is_direct<Func>()> {};
public:
    noncopyable_function() noexcept : _vtable(&_s_empty_vtable) {}
    template <typename Func>
    noncopyable_function(Func func) noexcept {
        // If we want, we can support throwing move constructible functions by using the indirect path
        static_assert(std::is_nothrow_move_constructible<Func>::value, "must be nothrow move constructible");
        vtable_for<Func>::initialize(std::move(func), this);
        _vtable = &vtable_for<Func>::s_vtable;
    }
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...)) noexcept : noncopyable_function(std::mem_fn(member)) {}
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...) const) noexcept : noncopyable_function(std::mem_fn(member)) {}

    ~noncopyable_function() {
        _vtable->destroy(this);
    }

    noncopyable_function(const noncopyable_function&) = delete;
    noncopyable_function& operator=(const noncopyable_function&) = delete;

    noncopyable_function(noncopyable_function&& x) noexcept : _vtable(std::exchange(x._vtable, &_s_empty_vtable)) {
        _vtable->move(&x, this);
    }

    noncopyable_function& operator=(noncopyable_function&& x) noexcept {
        if (this != &x) {
            this->~noncopyable_function();
            new (this) noncopyable_function(std::move(x));
        }
        return *this;
    }

    Ret operator()(Args... args) const {
        return _vtable->call(this, std::forward<Args>(args)...);
    }
};

template <typename Ret, typename... Args>
constexpr typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::_s_empty_vtable;

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::make_vtable();

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::make_vtable();

}

<commit_msg>noncopyable_function add bool operator<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2017 ScyllaDB Ltd.
 */

#pragma once

#include <utility>
#include <type_traits>
#include <functional>

namespace seastar {

template <typename Signature>
class noncopyable_function;

/// A clone of \c std::function, but only invokes the move constructor
/// of the contained function.
template <typename Ret, typename... Args>
class noncopyable_function<Ret (Args...)> {
    static constexpr size_t nr_direct = 32;
    union [[gnu::may_alias]] storage {
        char direct[nr_direct];
        void* indirect;
    };
    using call_type = Ret (*)(const noncopyable_function* func, Args...);
    using move_type = void (*)(noncopyable_function* from, noncopyable_function* to);
    using destroy_type = void (*)(noncopyable_function* func);
    struct vtable {
        const call_type call;
        const move_type move;
        const destroy_type destroy;
    };
private:
    const vtable* _vtable;
    storage _storage;
private:
    static Ret empty_call(const noncopyable_function* func, Args... args) {
        throw std::bad_function_call();
    }
    static void empty_move(noncopyable_function* from, noncopyable_function* to) {}
    static void empty_destroy(noncopyable_function* func) {}
    static constexpr vtable _s_empty_vtable = {empty_call, empty_move, empty_destroy};

    static void indirect_move(noncopyable_function* from, noncopyable_function* to) {
        using void_ptr = void*;
        new (&to->_storage.indirect) void_ptr(from->_storage.indirect);
    }

    template <typename Func>
    struct direct_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.direct); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.direct); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(func))(std::forward<Args>(args)...);
        }
        static void move(noncopyable_function* from, noncopyable_function* to) {
            new (access(to)) Func(std::move(*access(from)));
            destroy(from);
        }
        static void destroy(noncopyable_function* func) {
            access(func)->~Func();
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            new (access(to)) Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func>
    struct indirect_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.indirect); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.indirect); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(func))(std::forward<Args>(args)...);
        }
        static void destroy(noncopyable_function* func) {
            delete access(func);
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            to->_storage.indirect = new Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, indirect_move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func, bool Direct = true>
    struct select_vtable_for : direct_vtable_for<Func> {};
    template <typename Func>
    struct select_vtable_for<Func, false> : indirect_vtable_for<Func> {};
    template <typename Func>
    static constexpr bool is_direct() {
        return sizeof(Func) <= nr_direct && alignof(Func) <= alignof(storage);
    }
    template <typename Func>
    struct vtable_for : select_vtable_for<Func, is_direct<Func>()> {};
public:
    noncopyable_function() noexcept : _vtable(&_s_empty_vtable) {}
    template <typename Func>
    noncopyable_function(Func func) noexcept {
        // If we want, we can support throwing move constructible functions by using the indirect path
        static_assert(std::is_nothrow_move_constructible<Func>::value, "must be nothrow move constructible");
        vtable_for<Func>::initialize(std::move(func), this);
        _vtable = &vtable_for<Func>::s_vtable;
    }
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...)) noexcept : noncopyable_function(std::mem_fn(member)) {}
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...) const) noexcept : noncopyable_function(std::mem_fn(member)) {}

    ~noncopyable_function() {
        _vtable->destroy(this);
    }

    noncopyable_function(const noncopyable_function&) = delete;
    noncopyable_function& operator=(const noncopyable_function&) = delete;

    noncopyable_function(noncopyable_function&& x) noexcept : _vtable(std::exchange(x._vtable, &_s_empty_vtable)) {
        _vtable->move(&x, this);
    }

    noncopyable_function& operator=(noncopyable_function&& x) noexcept {
        if (this != &x) {
            this->~noncopyable_function();
            new (this) noncopyable_function(std::move(x));
        }
        return *this;
    }

    Ret operator()(Args... args) const {
        return _vtable->call(this, std::forward<Args>(args)...);
    }

    explicit operator bool() const {
        return _vtable != &_s_empty_vtable;
    }
};

template <typename Ret, typename... Args>
constexpr typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::_s_empty_vtable;

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::make_vtable();

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::make_vtable();

}

<|endoftext|>