 }
 
 extension MultivariatePolynomial: ExpressibleByIntegerLiteral where R: ExpressibleByIntegerLiteral {}
+
+// MARK: MultivariateLaurentPolynomial
+
+public struct MultivariateLaurentPolynomial<R: Ring, xn: MultivariatePolynomialIndeterminates>: MultivariatePolynomialType {
+    public typealias BaseRing = R
+    public typealias Indeterminate = xn
+
+    public let elements: [Exponent : R]
+    public init(elements: [Exponent : R]) {
+        self.elements = elements
+    }
+    
+    public var inverse: Self? {
+        if isMonomial && leadCoeff.isInvertible {
+            let d = degree
+            let a = leadCoeff
+            return .init(elements: [-d: a.inverse!])
+        } else {
+            return nil
+        }
+    }
+}
+
+

    
    public static func descriptionOfMonomial(withExponent e: Exponent) -> String {
        let s = e.indices.enumerated().map{ (i, d) in
            (d > 0) ? Format.power(symbolOfIndeterminate(at: i), d) : ""
        }.joined()
        return s.isEmpty ? "1" : s
    }

    }
}

// MARK: MultivariateLaurentPolynomial

public struct MultivariatePolynomial<R: Ring, xn: MultivariatePolynomialIndeterminates>: MultivariatePolynomialType {
    public typealias BaseRing = R
    public typealias Indeterminate = xn

    public let elements: [Exponent : R]
    public init(elements: [Exponent : R]) {
        assert(elements.keys.allSatisfy{ e in e.indices.allSatisfy{ $0 >= 0 } })
        self.elements = elements
    }
    
