semigroup_concept.h

Back to Algebra

pastel/sys/algebra/

// Description: Semi-group concept
// Documentation: algebra.txt

#ifndef PASTELSYS_SEMIGROUP_CONCEPT_H
#define PASTELSYS_SEMIGROUP_CONCEPT_H

#include "pastel/sys/algebra/element_concept.h"
#include "pastel/sys/algebra/native_semigroup.h"

#include "pastel/sys/mytypes.h"
#include "pastel/sys/ensure.h"

namespace Pastel
{

    //! An additive semi-group.
    /*!
   A semi-group is a pair (X, +), where X is a set 
   and + : X^2 --> X is associative.
   */
    struct Additive_SemiGroup_Concept
    : Refines<Element_Concept>
    {
        template <typename Type>
        auto requires_(Type&& t) -> decltype
        (
            conceptCheck(
                //! Adds 'that' to the element.
                Concept::hasType<Type&>(t += t),
                //! Returns left + right.
                Concept::convertsTo<Type>(t + t)
            )
        );
    };

    // For native types the operators += and + are inbuilt.

    //! A multiplicative semi-group.
    /*!
   A semi-group is a pair (X, *), where X is a set 
   and * : X^2 --> X is associative.
   */
    struct Multiplicative_SemiGroup_Concept
    : Refines<Element_Concept>
    {
        template <typename Type>
        auto requires_(Type&& t) -> decltype
        (
            conceptCheck(
                //! Adds 'that' to the element.
                Concept::hasType<Type&>(t *= t),
                //! Returns left * right.
                Concept::convertsTo<Type>(t * t),
                //! Returns the power t^p, for p in NN^{> 0}.
                Concept::convertsTo<Type>(pow(t, (integer)1))
            )
        );
    };

    // For native types the operators *= and * are inbuilt.

}

namespace Pastel
{

    //! Computes x^p, for p in NN^{> 0}.
    /*!
   The notation x^p means to multiply x with itself p times.
   */
    template <typename Multiplicative_SemiGroup>
    Multiplicative_SemiGroup semiGroupPower(
        Multiplicative_SemiGroup x,
        integer p)
    {
        ENSURE_OP(p, >, 0);

        // The binary expansion of p in NN^{>= 0} is
        //
        //     p = sum_{i in [0, n]} b_i 2^i,
        //
        // where b_i in {0, 1}. It follows that
        //
        //     x^p = prod_{i in [0, n]} x^{b_i 2^i}.
        //
        // On the other hand, consider 
        //
        //     a_0 = x
        //     a_i = a_{i - 1}^2.
        //
        // Then
        //
        //     a_i = x^{2^i}.
        //
        // Therefore, we can compute the power as
        //
        //     x^p = prod_{i in [0, n]} a_i^{b_i}.
        //         = prod_{i in [0, n] : b_i = 1} a_i.

        Multiplicative_SemiGroup result = x;

        --p;
        if (p == 0)
        {
            return result;
        }

        while (true)
        {
            ASSERT_OP(p, >, 0);

            if ((p & 1) != 0)
            {
                result *= x;
            }

            p >>= 1;
            if (p == 0)
            {
                break;
            }

            x *= x;
        }

        return result;
    }

}

#endif