llvm/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td

//===- PolynomialOps.td - Polynomial dialect ---------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef POLYNOMIAL_ATTRIBUTES
#define POLYNOMIAL_ATTRIBUTES

include "mlir/IR/BuiltinAttributes.td"
include "mlir/Dialect/Polynomial/IR/PolynomialDialect.td"

class Polynomial_Attr<string name, string attrMnemonic, list<Trait> traits = []>
    : AttrDef<Polynomial_Dialect, name, traits> {
  let mnemonic = attrMnemonic;
}

def Polynomial_IntPolynomialAttr : Polynomial_Attr<"IntPolynomial", "int_polynomial"> {
  let summary = "an attribute containing a single-variable polynomial with integer coefficients";
  let description = [{
    A polynomial attribute represents a single-variable polynomial with integer
    coefficients, which is used to define the modulus of a `RingAttr`, as well
    as to define constants and perform constant folding for `polynomial` ops.

    The polynomial must be expressed as a list of monomial terms, with addition
    or subtraction between them. The choice of variable name is arbitrary, but
    must be consistent across all the monomials used to define a single
    attribute. The order of monomial terms is arbitrary, each monomial degree
    must occur at most once.

    Example:

    ```mlir
    #poly = #polynomial.int_polynomial<x**1024 + 1>
    ```
  }];
  let parameters = (ins "::mlir::polynomial::IntPolynomial":$polynomial);
  let hasCustomAssemblyFormat = 1;
}

def Polynomial_FloatPolynomialAttr : Polynomial_Attr<"FloatPolynomial", "float_polynomial"> {
  let summary = "an attribute containing a single-variable polynomial with double precision floating point coefficients";
  let description = [{
    A polynomial attribute represents a single-variable polynomial with double
    precision floating point coefficients.

    The polynomial must be expressed as a list of monomial terms, with addition
    or subtraction between them. The choice of variable name is arbitrary, but
    must be consistent across all the monomials used to define a single
    attribute. The order of monomial terms is arbitrary, each monomial degree
    must occur at most once.

    Example:

    ```mlir
    #poly = #polynomial.float_polynomial<0.5 x**7 + 1.5>
    ```
  }];
  let parameters = (ins "FloatPolynomial":$polynomial);
  let hasCustomAssemblyFormat = 1;
}

def Polynomial_TypedIntPolynomialAttr : Polynomial_Attr<
    "TypedIntPolynomial", "typed_int_polynomial", [TypedAttrInterface]> {
  let summary = "a typed int_polynomial";
  let description = [{
    Example:

    ```mlir
    !poly_ty = !polynomial.polynomial<ring=<coefficientType=i32>>
    #poly = int<1 x**7 + 4> : !poly_ty
    #poly_verbose = #polynomial.typed_int_polynomial<1 x**7 + 4> : !poly_ty
    ```
  }];
  let parameters = (ins "::mlir::Type":$type, "::mlir::polynomial::IntPolynomialAttr":$value);
  let assemblyFormat = "$value `:` $type";
  let builders = [
    AttrBuilderWithInferredContext<(ins "Type":$type,
                                        "const IntPolynomial &":$value), [{
      return $_get(
        type.getContext(),
        type,
        IntPolynomialAttr::get(type.getContext(), value));
    }]>,
    AttrBuilderWithInferredContext<(ins "Type":$type,
                                        "const Attribute &":$value), [{
      return $_get(type.getContext(), type, ::llvm::cast<IntPolynomialAttr>(value));
    }]>
  ];
  let extraClassDeclaration = [{
    using ValueType = ::mlir::Attribute;
  }];
}

def Polynomial_TypedFloatPolynomialAttr : Polynomial_Attr<
    "TypedFloatPolynomial", "typed_float_polynomial", [TypedAttrInterface]> {
  let summary = "a typed float_polynomial";
  let description = [{
    Example:

    ```mlir
    !poly_ty = !polynomial.polynomial<ring=<coefficientType=f32>>
    #poly = float<1.4 x**7 + 4.5> : !poly_ty
    #poly_verbose = #polynomial.typed_float_polynomial<1.4 x**7 + 4.5> : !poly_ty
    ```
  }];
  let parameters = (ins "::mlir::Type":$type, "::mlir::polynomial::FloatPolynomialAttr":$value);
  let assemblyFormat = "$value `:` $type";
  let builders = [
    AttrBuilderWithInferredContext<(ins "Type":$type,
                                        "const FloatPolynomial &":$value), [{
      return $_get(
        type.getContext(),
        type,
        FloatPolynomialAttr::get(type.getContext(), value));
    }]>,
    AttrBuilderWithInferredContext<(ins "Type":$type,
                                        "const Attribute &":$value), [{
      return $_get(type.getContext(), type, ::llvm::cast<FloatPolynomialAttr>(value));
    }]>
  ];
  let extraClassDeclaration = [{
    using ValueType = ::mlir::Attribute;
  }];
}

def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
  let summary = "an attribute specifying a polynomial ring";
  let description = [{
    A ring describes the domain in which polynomial arithmetic occurs. The ring
    attribute in `polynomial` represents the more specific case of polynomials
    with a single indeterminate; whose coefficients can be represented by
    another MLIR type (`coefficientType`); and, if the coefficient type is
    integral, whose coefficients are taken modulo some statically known modulus
    (`coefficientModulus`).

    Additionally, a polynomial ring can specify a _polynomialModulus_, which converts
    polynomial arithmetic to the analogue of modular integer arithmetic, where
    each polynomial is represented as its remainder when dividing by the
    modulus. For single-variable polynomials, an "polynomialModulus" is always specificed
    via a single polynomial, which we call `polynomialModulus`.

    An expressive example is polynomials with i32 coefficients, whose
    coefficients are taken modulo `2**32 - 5`, with a polynomial modulus of
    `x**1024 - 1`.

    ```mlir
    #poly_mod = #polynomial.int_polynomial<-1 + x**1024>
    #ring = #polynomial.ring<coefficientType=i32,
                             coefficientModulus=4294967291:i32,
                             polynomialModulus=#poly_mod>

    %0 = ... : polynomial.polynomial<#ring>
    ```

    In this case, the value of a polynomial is always "converted" to a
    canonical form by applying repeated reductions by setting `x**1024 = 1`
    and simplifying.

    The coefficient and polynomial modulus parameters are optional, and the
    coefficient modulus is only allowed if the coefficient type is integral.
  }];

  let parameters = (ins
    "Type": $coefficientType,
    OptionalParameter<"::mlir::IntegerAttr">: $coefficientModulus,
    OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">: $polynomialModulus
  );
  let assemblyFormat = "`<` struct(params) `>`";
  let builders = [
    AttrBuilderWithInferredContext<
        (ins "::mlir::Type":$coefficientTy,
              CArg<"::mlir::IntegerAttr", "nullptr"> :$coefficientModulusAttr,
              CArg<"::mlir::polynomial::IntPolynomialAttr", "nullptr"> :$polynomialModulusAttr), [{
      return $_get(
        coefficientTy.getContext(),
        coefficientTy,
        coefficientModulusAttr,
        polynomialModulusAttr);
    }]>,
  ];
}

def Polynomial_PrimitiveRootAttr: Polynomial_Attr<"PrimitiveRoot", "primitive_root"> {
  let summary = "an attribute containing an integer and its degree as a root of unity";
  let description = [{
    A primitive root attribute stores an integer root `value` and an integer
    `degree`, corresponding to a primitive root of unity of the given degree in
    an unspecified ring.

    This is used as an attribute on `polynomial.ntt` and `polynomial.intt` ops
    to specify the root of unity used in lowering the transform.

    Example:

    ```mlir
    #poly = #polynomial.primitive_root<value=123 : i32, degree : 7 index>
    ```
  }];
  let parameters = (ins
    "::mlir::IntegerAttr":$value,
    "::mlir::IntegerAttr":$degree
  );
  let assemblyFormat = "`<` struct(params) `>`";
}


#endif // POLYNOMIAL_ATTRIBUTES