Hashiryo's Library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub hashiryo/Library

:heavy_check_mark: 代数的構造 (src/Math/Algebra.hpp)

群の演算をoperator+operator-にしてBITやポテンシャルUFに乗せたり,半環にして行列に乗せたりするために用意した.

struct M{
  using T = int;
  static inline T o = 0;
  static inline T i = 1;
  static T add(T a,T b){return a+b;}
  static T neg(T a){return -a;}
  static T mul(T a,T b){return a*b;}
};

Verify

Depends on

Verified with

Code

#pragma once
#include "src/Internal/detection_idiom.hpp"
template <class M> struct Algebra {
 using T= typename M::T;
 _DETECT_BOOL(has_zero, decltype(T::o));
 _DETECT_BOOL(has_one, decltype(T::i));
 static inline T zero= has_zero_v<M> ? M::o : T();
 static inline T one= has_one_v<M> ? M::i : T();
 T x;
 Algebra(): x(zero) {}
 Algebra(bool y): x(y ? one : zero) {}
 template <class U, typename= std::enable_if_t<std::is_convertible_v<U, T>>> Algebra(U y): x(y) {}
 Algebra &operator+=(const Algebra &r) { return *this= *this + r; }
 Algebra &operator-=(const Algebra &r) { return *this= *this - r; }
 Algebra &operator*=(const Algebra &r) { return *this= *this * r; }
 Algebra operator+(const Algebra &r) const { return Algebra(M::add(x, r.x)); }
 Algebra operator-(const Algebra &r) const { return Algebra(M::add(x, M::neg(r.x))); }
 Algebra operator*(const Algebra &r) const { return Algebra(M::mul(x, r.x)); }
 Algebra operator-() const { return Algebra(M::neg(x)); }
 bool operator==(const Algebra &r) const { return x == r.x; }
 bool operator!=(const Algebra &r) const { return x != r.x; }
 friend std::istream &operator>>(std::istream &is, Algebra &r) { return is >> r.x, is; }
 friend std::ostream &operator<<(std::ostream &os, const Algebra &r) { return os << r.x; }
};
#line 2 "src/Internal/detection_idiom.hpp"
#include <type_traits>
#define _DETECT_BOOL(name, ...) \
 template <class, class= void> struct name: std::false_type {}; \
 template <class T> struct name<T, std::void_t<__VA_ARGS__>>: std::true_type {}; \
 template <class T> static constexpr bool name##_v= name<T>::value
#define _DETECT_TYPE(name, type1, type2, ...) \
 template <class T, class= void> struct name { \
  using type= type2; \
 }; \
 template <class T> struct name<T, std::void_t<__VA_ARGS__>> { \
  using type= type1; \
 }
#line 3 "src/Math/Algebra.hpp"
template <class M> struct Algebra {
 using T= typename M::T;
 _DETECT_BOOL(has_zero, decltype(T::o));
 _DETECT_BOOL(has_one, decltype(T::i));
 static inline T zero= has_zero_v<M> ? M::o : T();
 static inline T one= has_one_v<M> ? M::i : T();
 T x;
 Algebra(): x(zero) {}
 Algebra(bool y): x(y ? one : zero) {}
 template <class U, typename= std::enable_if_t<std::is_convertible_v<U, T>>> Algebra(U y): x(y) {}
 Algebra &operator+=(const Algebra &r) { return *this= *this + r; }
 Algebra &operator-=(const Algebra &r) { return *this= *this - r; }
 Algebra &operator*=(const Algebra &r) { return *this= *this * r; }
 Algebra operator+(const Algebra &r) const { return Algebra(M::add(x, r.x)); }
 Algebra operator-(const Algebra &r) const { return Algebra(M::add(x, M::neg(r.x))); }
 Algebra operator*(const Algebra &r) const { return Algebra(M::mul(x, r.x)); }
 Algebra operator-() const { return Algebra(M::neg(x)); }
 bool operator==(const Algebra &r) const { return x == r.x; }
 bool operator!=(const Algebra &r) const { return x != r.x; }
 friend std::istream &operator>>(std::istream &is, Algebra &r) { return is >> r.x, is; }
 friend std::ostream &operator<<(std::ostream &os, const Algebra &r) { return os << r.x; }
};
Back to top page