group_concept.h

Back to Algebra

pastel/sys/algebra/

// Description: Group concept
// Documentation: algebra.txt

#ifndef PASTELSYS_GROUP_CONCEPT_H
#define PASTELSYS_GROUP_CONCEPT_H

#include "pastel/sys/algebra/monoid_concept.h"

#include "pastel/sys/algebra/native_group.h"

namespace Pastel
{

    //! An additive group.
    /*!
   A group (X, +, 0) is a monoid (X, +, 0)
   such that for every x in X there exists y in X
   such that x + y = 0. Since the y is unique,
   it is denoted by -x.
   */
    template <typename T>
    concept Additive_Group_Concept_ = 
        Additive_Monoid_Concept<T> && 
        requires(T t) {
        //! Adds -that to the element.
        {t -= t} -> std::convertible_to<T>;
        //! Returns left * (-right).
        {t - t} -> std::convertible_to<T>;
        //! Returns -x for an element x.
        {-t} -> std::convertible_to<T>;
    };

    template <typename T>
    concept Additive_Group_Concept = 
        Additive_Group_Concept_<RemoveCvRef<T>>;

    //! A multiplicative group.
    /*!
   A group (X, *, 1) is a monoid (X, *, 1)
   such that for every x in X there exists y in X
   such that x * y = 1. Since the y is unique,
   it is denoted by inverse(x).
   */
    template <typename T>
    concept Multiplicative_Group_Concept_ = 
        Multiplicative_Monoid_Concept<T> && 
        requires(T t) {
        //! Multiplies with inverse(that) from the right.
        {t /= t} -> std::convertible_to<T>;
        //! Returns left * inverse(right).
        {t / t} -> std::convertible_to<T>;
        //! Returns inverse(x) for an element x.
        {inverse(t)} -> std::convertible_to<T>;
    };

    template <typename T>
    concept Multiplicative_Group_Concept = 
        Multiplicative_Group_Concept_<RemoveCvRef<T>>;

}

namespace Pastel
{

    //! Computes x^p, for p an integer.
    template <Multiplicative_Group_Concept T>
    T groupPower(T x, integer p)
    {
        T result = monoidPower(std::move(x), std::abs(p));

        if (p < 0)
        {
            result = inverse(result);
        }

        return result;
    }

}

#endif