kzrnm / ac-library-csharp

42 stars 5 forks source link

ModIntFenwickTree を作成 #56

Closed kzrnm closed 4 years ago

kzrnm commented 4 years ago

55 の実装を FenwickTree に適用

key-moon commented 4 years ago

WIP なものですが、私は比較周辺は例外を投げたほうが嬉しい挙動かと思いました。いかがでしょうか?

kzrnm commented 4 years ago

検討してみました。 例外を投げたり適当に実装したりするより、算術演算インターフェイスと比較演算インターフェイスを分割してしまうのが良いのではないかと考えました。

FenwickTree では算術演算のみを使用します。

対応する場合は、#47 と衝突するので #47 のマージ後にします。

public interface IArithmeticOperator<T> where T : struct
{
    /// <summary>
    /// Addition operator +
    /// </summary>
    /// <returns><paramref name="x"/> + <paramref name="y"/></returns>
    T Add(T x, T y);
    /// <summary>
    /// Subtraction operator -
    /// </summary>
    /// <returns><paramref name="x"/> - <paramref name="y"/></returns>
    T Subtract(T x, T y);
    /// <summary>
    /// Multiplication operator *
    /// </summary>
    /// <returns><paramref name="x"/> * <paramref name="y"/></returns>
    T Multiply(T x, T y);
    /// <summary>
    /// Division operator /
    /// </summary>
    /// <returns><paramref name="x"/> / <paramref name="y"/></returns>
    T Divide(T x, T y);
    /// <summary>
    /// Remainder operator %
    /// </summary>
    /// <returns><paramref name="x"/> % <paramref name="y"/></returns>
    T Modulo(T x, T y);

}

public interface IComparisonPperator<T> : IEqualityComparer<T>, IComparer<T> where T : struct
{
    /// <summary>
    /// Greater than operator &gt;
    /// </summary>
    /// <returns><paramref name="x"/> &gt; <paramref name="y"/></returns>
    bool GreaterThan(T x, T y);
    /// <summary>
    /// Greater than or equal operator &gt;=
    /// </summary>
    /// <returns><paramref name="x"/> &gt;= <paramref name="y"/></returns>
    bool GreaterThanOrEqual(T x, T y);
    /// <summary>
    /// Less than operator &lt;
    /// </summary>
    /// <returns><paramref name="x"/> &lt; <paramref name="y"/></returns>
    bool LessThan(T x, T y);
    /// <summary>
    /// Less than or equal operator &lt;=
    /// </summary>
    /// <returns><paramref name="x"/> &lt;= <paramref name="y"/></returns>
    bool LessThanOrEqual(T x, T y);
}

public interface INumOperator<T> : IArithmeticOperator<T>, IComparisonPperator<T> where T : struct
{
    /// <summary>
    /// MinValue
    /// </summary>
    public T MinValue { get; }
    /// <summary>
    /// MaxValue
    /// </summary>
    public T MaxValue { get; }
}
key-moon commented 4 years ago

この実装については、そこだけ分けるならば他も分けるべきなのではと思ってしまいます。

IArithmeticOperator を実装するものでも DivideModulo が実装されることのない、ましてや Add 以外無い等のケースがありえますので、意味のある実装ができない部分に例外を投げるのが不適であるならば細かく分けるべきだと思います。 なので、それよりは現状のように一旦全ての実装されうる演算子をまとめて提供していしまうのが良いのではないかと思っていました。

なので、もしインターフェイスを複数に分けるならば

interface IAddOperator<T> { T Add(T x, T y); }
interface ISubtractOperator<T> { T Subtract(T x, T y); }
︙
interface IModuloOperator<T> { T Modulo(T x, T y); }

としてしまい、実装側で


interface IMFOperator<T> : IAddOperator<T>, … { }

class MFGraph<TValue, TOp>
     where TValue : struct
     where TOp : IMFOperator<T> … //又は IAddOperator<T>等を直書き

のようにするべきだと感じます。 実装し直すならばこの実装で私は問題ないと思うのですが、いかがでしょうか?

それはそれとして、一旦インターフェイスを改良するならば #33 での再議論をするべきだとも思います。