001/*
002 * $Id: MonoidElem.java 5940 2018-10-19 08:53:13Z kredel $
003 */
004
005package edu.jas.structure;
006
007
008/**
009 * Monoid element interface. Defines the multiplicative methods.
010 * @param <C> element type
011 * @author Heinz Kredel
012 */
013
014public interface MonoidElem<C extends MonoidElem<C>> extends Element<C> {
015
016
017    /**
018     * Test if this is one.
019     * @return true if this is 1, else false.
020     */
021    public boolean isONE();
022
023
024    /**
025     * Test if this is a unit. I.e. there exists x with this.multiply(x).isONE()
026     * == true.
027     * @return true if this is a unit, else false.
028     */
029    public boolean isUnit();
030
031
032    /**
033     * Multiply this with S.
034     * @param S
035     * @return this * S.
036     */
037    public C multiply(C S);
038
039
040    /**
041     * Divide this by S.
042     * @param S
043     * @return this / S.
044     */
045    public C divide(C S);
046
047
048    /**
049     * Remainder after division of this by S.
050     * @param S
051     * @return this - (this / S) * S.
052     */
053    public C remainder(C S);
054
055
056    /**
057     * Quotient and remainder by division of this by S.
058     * @param S
059     * @return [this/S, this - (this/S)*S].
060     */
061    @SuppressWarnings("unchecked")
062    default public C[] quotientRemainder(C S) {
063        return (C[]) new MonoidElem[] { divide(S), remainder(S) }; 
064    }
065
066
067    /**
068     * Right division.
069     * Returns commutative divide if not overwritten.
070     * @param a element.
071     * @return right, with a * right = this
072     */
073    default public C rightDivide(C a) {
074        return divide(a);
075    }
076
077
078    /**
079     * Left division.
080     * Returns commutative divide if not overwritten.
081     * @param a element.
082     * @return left, with left * a = this
083     */
084    default public C leftDivide(C a) {
085        return divide(a);
086    }
087
088
089    /**
090     * Right remainder.
091     * Returns commutative remainder if not overwritten.
092     * @param a element.
093     * @return r = this - a * (1/right), where a * right = this.
094     */
095    default public C rightRemainder(C a) {
096        return remainder(a);
097    }
098
099
100    /**
101     * Left remainder.
102     * Returns commutative remainder if not overwritten.
103     * @param a element.
104     * @return r = this - (1/left) * a, where left * a = this.
105     */
106    default public C leftRemainder(C a) {
107        return remainder(a);
108    }
109
110
111    /**
112     * Two-sided division.
113     * Returns commutative divide if not overwritten.
114     * @param a element.
115     * @return [left,right], with left * a * right = this
116     */
117    @SuppressWarnings("unchecked")
118    default public C[] twosidedDivide(C a) {
119        C[] ret = (C[]) new MonoidElem[2];
120        ret[0] = divide(a);
121        ret[1] = ((MonoidFactory<C>)factory()).getONE();
122        return ret;
123    }
124
125
126    /**
127     * Two-sided remainder.
128     * Returns commutative remainder if not overwritten.
129     * @param a element.
130     * @return r = this - (a/left) * a * (a/right), where left * a * right = this.
131     */
132    default public C twosidedRemainder(C a){
133        return remainder(a);
134    }
135
136
137    /**
138     * Inverse of this. Some implementing classes will throw
139     * NotInvertibleException if the element is not invertible.
140     * @return x with this * x = 1, if it exists.
141     */
142    public C inverse(); /*throws NotInvertibleException*/
143
144
145    /**
146     * Power of this to the n-th.
147     * @param n integer exponent.
148     * @return a**n, with a**0 = 1 and a**{-n} = {1/a}**n.
149     * Java 8 only
150     */ 
151    @SuppressWarnings("unchecked")
152    default public C power(long n) {
153        //System.out.println("this = " + this + ", n = " + n);
154        return Power.<C>power((MonoidFactory<C>)factory(), (C)this, n);
155    }
156
157}