• R/O
  • SSH
  • HTTPS

magic-rw:


File Info

Rev. 82
Size 19,204 bytes
Time 2020-09-07 19:57:25
Author quiret
Log Message

- branding.

Content

/*****************************************************************************
*
*  PROJECT:     Magic-RW
*  LICENSE:     See LICENSE in the top level directory
*  FILE:        include/renderware.math.matview.h
*  PURPOSE:     Matview submodule for matrix operations.
*
*  Multi Theft Auto is available from http://www.multitheftauto.com/
*  Project location: https://osdn.net/projects/magic-rw/
*
*****************************************************************************/

/*
    The matview submodule of the math module.

    This is a beast of its own.
*/

#ifndef _RENDERWARE_MATH_MATVIEW_
#define _RENDERWARE_MATH_MATVIEW_

namespace mview
{

#define MATVIEW_GENERAL_PROPS   size_t x, size_t y
#define MATVIEW_GENERAL_IMPL    x, y

    // Matrix views.
    template <MATVIEW_GENERAL_PROPS, typename... next>
    struct matview
    {
        static constexpr size_t x_pos = x;
        static constexpr size_t y_pos = y;
    };

#define MATVIEW_SKIPTHRESH_PROPS    size_t thresh_x, size_t thresh_y, size_t blockadd_x, size_t blockadd_y
#define MATVIEW_SKIPTHRESH_IMPL     thresh_x, thresh_y, blockadd_x, blockadd_y

    template <MATVIEW_SKIPTHRESH_PROPS>
    struct matview_thresh_updateskip
    {};

#define MATVIEW_SKIPPARAM_X     size_t block_x
#define MATVIEW_SKIPPARAM_Y     size_t block_y
#define MATVIEW_SKIPPARAM       size_t block_x, size_t block_y

#define MATVIEW_SKIPPROP_X      MATVIEW_SKIPPARAM_X
#define MATVIEW_SKIPPROP_Y      MATVIEW_SKIPPARAM_Y
#define MATVIEW_SKIPPROP        MATVIEW_SKIPPARAM

#define MATVIEW_SKIPPARAMIMPL_X block_x
#define MATVIEW_SKIPPARAMIMPL_Y block_y
#define MATVIEW_SKIPPARAMIMPL   block_x, block_y

#define MATVIEW_SKIPIMPL_X      MATVIEW_SKIPPARAMIMPL_X
#define MATVIEW_SKIPIMPL_Y      MATVIEW_SKIPPARAMIMPL_Y
#define MATVIEW_SKIPIMPL        MATVIEW_SKIPPARAMIMPL

    template <MATVIEW_SKIPPARAM>
    struct matview_maybe_skip
    {};

    template <MATVIEW_SKIPPARAM_X>
    struct matview_maybe_skip_x
    {};

    template <MATVIEW_SKIPPARAM_Y>
    struct matview_maybe_skip_y
    {};

    // We can validate maybe-skips into regular skips.
    struct matview_skip_x_validate
    {};

    struct matview_skip_y_validate
    {};

    struct matview_skip_validate
    {};

    struct matview_skip_validate_end
    {};

    template <MATVIEW_SKIPPARAM>
    struct matview_skip
    {};

    // Template math helpers.
    template <size_t num, size_t num2>
    struct matview_isgreaterequal
    {
        static constexpr bool value = ( num >= num2 );
    };

    template <bool b, size_t num1, size_t num2>
    struct matview_num_cond
    {
        static constexpr size_t value = num1;
    };

    template <size_t num1, size_t num2>
    struct matview_num_cond <false, num1, num2>
    {
        static constexpr size_t value = num2;
    };

    template <size_t left, size_t right, size_t addLeft, template <size_t num1, size_t num2> class cond>
    struct matview_cond_add : public matview_num_cond <cond <left, right>::value, left + addLeft, left>
    {};

    // This is some heavy shit.
    // Constructs a new matview from a matview state.
    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP, bool hasDoneX, bool hasDoneY, typename... next>
    struct matview_skip_metaconstructor
    {};

    // NOT UPDATE MIRROR.
    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP, typename... next>
    struct matview_skip_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL, false, false, next...>
    {
        typedef
            matview <x, y,
                     next...,
                     matview_maybe_skip <block_x, block_y>> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP, typename... next>
    struct matview_skip_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL, true, false, next...>
    {
        typedef
            matview <x + 1, y,
                     matview_skip_x_validate, next..., matview_skip_validate_end,
                     matview_maybe_skip_y <block_y>> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP, typename... next>
    struct matview_skip_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL, false, true, next...>
    {
        typedef
            matview <x, y + 1,
                     matview_skip_y_validate, next..., matview_skip_validate_end,
                     matview_maybe_skip_x <block_x>> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP, typename... next>
    struct matview_skip_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL, true, true, next...>
    {
        typedef
            matview <x + 1, y + 1,
                     matview_skip_validate, next..., matview_skip_validate_end> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP, typename... next>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview_skip_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL,
                                               matview_isgreaterequal <x, block_x>::value,
                                               matview_isgreaterequal <y, block_y>::value,
                                               next...>::new_view
    {};

    template <MATVIEW_SKIPPARAM_Y>
    struct matview_skip_y
    {};

    // Construct a new matview from a matview state, for skip_y.
    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_Y, bool hasDoneY, typename... next>
    struct matview_skip_y_metaconstructor
    {};

    // NOT UPDATE MIRROR.
    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_Y, typename... next>
    struct matview_skip_y_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL_Y, true, next...>
    {
        typedef
            matview <x, y + 1,
                     matview_skip_y_validate, next..., matview_skip_validate_end> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_Y, typename... next>
    struct matview_skip_y_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL_Y, false, next...>
    {
        typedef
            matview <x, y,
                     next...,
                     matview_maybe_skip_y <block_y>> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_Y, typename... next>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview_skip_y_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL_Y,
                                                 matview_isgreaterequal <y, block_y>::value,
                                                 next...>::new_view
    {};

    template <MATVIEW_SKIPPARAM_X>
    struct matview_skip_x
    {};

    // Construct a new matview from a matview state, for skip_x.
    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_X, bool hasDoneX, typename... next>
    struct matview_skip_x_metaconstructor
    {};

    // NOT UPDATE MIRROR.
    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_X, typename... next>
    struct matview_skip_x_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL_X, true, next...>
    {
        typedef
            matview <x + 1, y,
                     matview_skip_x_validate, next..., matview_skip_validate_end> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_X, typename... next>
    struct matview_skip_x_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL_X, false, next...>
    {
        typedef
            matview <x, y,
                     next...,
                     matview_maybe_skip_x <block_x>> new_view;
    };

    template <MATVIEW_GENERAL_PROPS, MATVIEW_SKIPPROP_X, typename... next>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview_skip_x_metaconstructor <MATVIEW_GENERAL_IMPL, MATVIEW_SKIPIMPL_X,
                                                 matview_isgreaterequal <x, block_x>::value,
                                                 next...>::new_view
    {};

    // If a maybe-skip was not determined at time of encounter, we remove it.
    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_maybe_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, next...>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_maybe_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, next...>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_maybe_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, next...>
    {};

    // If a skip has been performed, previously not triggered skips can be asked to trigger.
    // We must turn all relevant maybe-skips into regular skips then.
    // This is called validation.
    // A maybe token has emitted an update to skips after it.
    // That is why we do not want it to emit any more updates, hence we set the flag.
    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_maybe_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, next..., matview_skip_x <MATVIEW_SKIPIMPL_X>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, next..., matview_skip_x <MATVIEW_SKIPIMPL_X>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, next..., matview_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_maybe_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, next..., matview_maybe_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, next..., matview_skip <MATVIEW_SKIPIMPL>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_maybe_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, next..., matview_skip_x <MATVIEW_SKIPIMPL_X>, matview_maybe_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_x_validate, matview_skip_validate_end, next...>
        : public matview <MATVIEW_GENERAL_IMPL, next...>
    {};

    // Same thing for y validation.
    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_maybe_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, next..., matview_maybe_skip_x <MATVIEW_SKIPIMPL_X>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, next..., matview_skip_x <MATVIEW_SKIPIMPL_X>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, next..., matview_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_maybe_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, next..., matview_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, next..., matview_skip <MATVIEW_SKIPIMPL>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_maybe_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, next..., matview_maybe_skip_x <MATVIEW_SKIPIMPL_X>, matview_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_y_validate, matview_skip_validate_end, next...>
        : public matview <MATVIEW_GENERAL_IMPL, next...>
    {};

    // And finally some special sauce for full validation.
    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_maybe_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, next..., matview_skip_x <MATVIEW_SKIPIMPL_X>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_X>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_skip_x <MATVIEW_SKIPIMPL_X>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, next..., matview_skip_x <MATVIEW_SKIPIMPL_X>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, next..., matview_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP_Y>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_maybe_skip_y <MATVIEW_SKIPIMPL_Y>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, next..., matview_skip_y <MATVIEW_SKIPIMPL_Y>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, next..., matview_skip <MATVIEW_SKIPIMPL>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next, MATVIEW_SKIPPROP>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_maybe_skip <MATVIEW_SKIPIMPL>, next...>
        : public matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, next..., matview_skip <MATVIEW_SKIPIMPL>>
    {};

    template <MATVIEW_GENERAL_PROPS, typename... next>
    struct matview <MATVIEW_GENERAL_IMPL, matview_skip_validate, matview_skip_validate_end, next...>
        : public matview <MATVIEW_GENERAL_IMPL, next...>
    {};

    // Iterative building of matview skips.
    template <size_t rel_x, typename... cmdlist>
    struct matview_skip_x_constructor
    {
        typedef matview <rel_x, 0, cmdlist...> cstr_view;

        typedef matview_skip_x <cstr_view::x> type;
    };

    template <size_t rel_y, typename... cmdlist>
    struct matview_skip_y_constructor
    {
        typedef matview <0, rel_y, cmdlist...> cstr_view;

        typedef matview_skip_y <cstr_view::y> type;
    };

    // Example module: calculation of determinants for NxN matrix.
    template <typename numberType, typename matrixType, size_t detdimm, typename... viewmod>
    struct detcalc
    {
        template <size_t subdetdimm, bool isPositive, size_t iter, typename... subviewmod>
        struct detcalc_iter
        {
            AINLINE static numberType calc( const matrixType& mat )
            {
                numberType ourval = detcalc <numberType, matrixType, subdetdimm, subviewmod..., typename matview_skip_x_constructor <iter, subviewmod...>::type>::calc( mat );

                typedef matview <iter, 0, viewmod...> curview;

                ourval *= mat[ curview::y ][ curview::x ];

                numberType nextval = detcalc_iter <subdetdimm, !isPositive, iter + 1, subviewmod...>::calc( mat );

                if ( isPositive )
                {
                    return ( nextval + ourval );
                }

                return ( nextval - ourval );
            }
        };

        template <size_t subdetdimm, bool isPositive, typename... subviewmod>
        struct detcalc_iter <subdetdimm, isPositive, subdetdimm, subviewmod...>
        {
            AINLINE static numberType calc( const matrixType& mat )
            {
                numberType val = detcalc <numberType, matrixType, subdetdimm, subviewmod..., typename matview_skip_x_constructor <subdetdimm, subviewmod...>::type>::calc( mat );

                typedef matview <subdetdimm, 0, viewmod...> curview;

                val *= mat[ curview::y ][ curview::x ];

                if ( !isPositive )
                {
                    val = -val;
                }

                return val;
            }
        };

        AINLINE static numberType calc( const matrixType& mat )
        {
            return ( detcalc_iter <detdimm - 1, true, 0, viewmod..., typename matview_skip_y_constructor <0, viewmod...>::type>::calc( mat ) );
        }
    };

    template <typename numberType, typename matrixType, typename... viewmod>
    struct detcalc <numberType, matrixType, 2, viewmod...>
    {
        AINLINE static numberType calc( const matrixType& mat )
        {
            typedef matview <0, 0, viewmod...> top_left_view;
            typedef matview <1, 1, viewmod...> bottom_right_view;

            typedef matview <1, 0, viewmod...> top_right_view;
            typedef matview <0, 1, viewmod...> bottom_left_view;

            return (
                mat[ top_left_view::y ][ top_left_view::x ] * mat[ bottom_right_view::y ][ bottom_right_view::x ]
                -
                mat[ top_right_view::y ][ top_right_view::x ] * mat[ bottom_left_view::y ][ bottom_left_view::x ]
                );
        }
    };

    template <typename numberType, typename matrixType, typename... viewmod>
    struct detcalc <numberType, matrixType, 1, viewmod...>
    {
        AINLINE static numberType calc( const matrixType& mat )
        {
            typedef matview <0, 0, viewmod...> item_view;

            return mat[ item_view::y ][ item_view::x ];
        }
    };
};

#endif //_RENDERWARE_MATH_MATVIEW_
Show on old repository browser