TorchLean API

NN.Spec.Core.TensorOps

Elementwise tensor operations (TorchLean.Tensor.*_spec) #

This file defines shape-preserving, elementwise operations on Tensor α s.

Naming convention:

Domain / smoothness notes #

Some operations are domain-sensitive or non-smooth:

The spec layer is where these semantics are defined; the proof layer decides which assumptions/variants to use for theorems.

def TorchLean.Tensor.detachSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (x : Tensor α s) :
Tensor α s

Keep a tensor's primal values while removing scalar differentiation metadata.

For ordinary numeric tensors, this returns the same tensor. Dual-valued tensors need a pointwise map as well as the graph's zero JVP and VJP: otherwise a later operation could still read a tangent from the detached value while computing a higher-order derivative.

Instances For

    Axis-parametric indexing #

    def TorchLean.Tensor.selectBackwardSpec {α : Type} [Storage α] [Zero α] (axis : ) {s : Spec.Shape} [_h : Spec.Shape.AxisInBounds axis s] :
    Fin (s.axisSize axis)Tensor α (s.eraseAxis axis)Tensor α s

    Place one selected slice back into an otherwise-zero tensor.

    This is the adjoint of selectSpec and therefore its reverse-mode rule.

    Instances For
      def TorchLean.Tensor.indexSelectSpec {α : Type} [Storage α] (axis : ) {s : Spec.Shape} (tensor : Tensor α s) [_h : Spec.Shape.AxisInBounds axis s] {count : } :
      Tensor (Fin (s.axisSize axis)) [count]Tensor α (s.replaceAxis axis count)

      Select coordinates from an arbitrary axis using an index vector.

      The selected axis is replaced by the index count. Repeated indices are preserved, matching torch.index_select.

      Instances For
        def TorchLean.Tensor.sliceAxisRangeBackwardSpec {α : Type} [Storage α] [Zero α] (axis : ) {s : Spec.Shape} [_h : Spec.Shape.AxisInBounds axis s] (start count : ) :
        start + count s.axisSize axisTensor α (s.replaceAxis axis count)Tensor α s

        Insert a sliced gradient back along an arbitrary axis, filling coordinates outside it with zero.

        Instances For
          def TorchLean.Tensor.mapSpec {α : Type} [Storage α] {s : Spec.Shape} (f : αα) :
          Tensor α sTensor α s

          Map a scalar function over a tensor (shape preserved).

          This is the core packed pointwise combinator for spec tensors. Most elementwise ops are direct instances of mapSpec f.

          PyTorch analogy: f applied pointwise (like torch.<op> broadcasting over all entries), but here shape is fixed and enforced by the type.

          Instances For
            @[simp]
            theorem TorchLean.Tensor.mapSpec_scalar {α : Type} [Storage α] (f : αα) (x : α) :
            mapSpec f (scalar x) = scalar (f x)

            Elementwise mapping computes directly on a scalar tensor.

            @[simp]
            theorem TorchLean.Tensor.mapSpec_dim {α : Type} [Storage α] {n : } {s : Spec.Shape} (f : αα) (values : Fin nTensor α s) :
            mapSpec f (dim values) = dim fun (i : Fin n) => mapSpec f (values i)

            Elementwise mapping distributes over the leading tensor dimension.

            @[simp]
            theorem TorchLean.Tensor.toScalar_mapSpec {α : Type} [Storage α] (f : αα) (x : Tensor α Spec.Shape.scalar) :
            (mapSpec f x).item = f x.item

            Extracting a scalar after an elementwise map applies the scalar function once.

            @[simp]
            theorem TorchLean.Tensor.getScalar_mapSpec {α : Type} [Storage α] {n : } (f : αα) (tensor : Tensor α [n]) (index : Fin n) :
            (mapSpec f tensor).getScalar index = f (tensor.getScalar index)

            Vector indexing commutes with an elementwise operation.

            theorem TorchLean.Tensor.forall_mapSpec {α : Type} [Storage α] {p q : αProp} {f : αα} {s : Spec.Shape} {x : Tensor α s} (hx : Forall p x) (hf : ∀ (a : α), p aq (f a)) :
            Forall q (mapSpec f x)

            Transport a pointwise tensor property through an elementwise operation.

            def TorchLean.Tensor.map2Spec {α β γ : Type} [Storage α] [Storage β] [Storage γ] {s : Spec.Shape} (f : αβγ) (left : Tensor α s) (right : Tensor β s) :
            Tensor γ s

            Map a binary function over two tensors of the same shape.

            This is the packed zipWith combinator for spec tensors. It is intentionally shape-preserving: if the shapes differ, the term is not well-typed.

            PyTorch analogy: elementwise binary ops when tensors already have the same shape (no broadcasting). Broadcasting is handled separately in NN/Spec/Core/TensorReductionShape.lean.

            Instances For
              @[simp]
              theorem TorchLean.Tensor.map2Spec_scalar {α β γ : Type} [Storage α] [Storage β] [Storage γ] (f : αβγ) (left : α) (right : β) :
              map2Spec f (scalar left) (scalar right) = scalar (f left right)

              A pointwise binary operation computes directly on scalar tensors.

              @[simp]
              theorem TorchLean.Tensor.toScalar_map2Spec {α β γ : Type} [Storage α] [Storage β] [Storage γ] (f : αβγ) (left : Tensor α Spec.Shape.scalar) (right : Tensor β Spec.Shape.scalar) :
              (map2Spec f left right).item = f left.item right.item

              Extracting a scalar after a pointwise binary map combines the two scalar values.

              @[simp]
              theorem TorchLean.Tensor.map2Spec_dim {α β γ : Type} [Storage α] [Storage β] [Storage γ] {n : } {s : Spec.Shape} (f : αβγ) (left : Fin nTensor α s) (right : Fin nTensor β s) :
              map2Spec f (dim left) (dim right) = dim fun (i : Fin n) => map2Spec f (left i) (right i)

              Pointwise binary operations distribute over the leading tensor dimension.

              @[simp]
              theorem TorchLean.Tensor.map2Spec_apply {α β γ : Type} [Storage α] [Storage β] [Storage γ] {s : Spec.Shape} (f : αβγ) (left : Tensor α s) (right : Tensor β s) (coordinate : s.Coord) :
              Internal.Rep.get (map2Spec f left right) coordinate = f (Internal.Rep.get left coordinate) (Internal.Rep.get right coordinate)

              Evaluating a pointwise binary operation combines both scalar entries.

              @[simp]
              theorem TorchLean.Tensor.get_map2Spec {α β γ : Type} [Storage α] [Storage β] [Storage γ] {f : αβγ} {n : } {s : Spec.Shape} (left : Tensor α (Spec.Shape.dim n s)) (right : Tensor β (Spec.Shape.dim n s)) (i : Fin n) :
              get (map2Spec f left right) i = map2Spec f (get left i) (get right i)

              Indexing a pointwise binary operation applies the scalar operation after indexing.

              @[simp]
              theorem TorchLean.Tensor.getScalar_map2Spec {α β γ : Type} [Storage α] [Storage β] [Storage γ] (f : αβγ) {n : } (left : Tensor α [n]) (right : Tensor β [n]) (i : Fin n) :
              (map2Spec f left right).getScalar i = f (left.getScalar i) (right.getScalar i)

              Vector indexing commutes with a pointwise binary tensor operation.

              @[simp]
              theorem TorchLean.Tensor.get2_map2Spec {α β γ : Type} [Storage α] [Storage β] [Storage γ] {f : αβγ} {m n : } (left : Tensor α [m, n]) (right : Tensor β [m, n]) (i : Fin m) (j : Fin n) :
              get2 (map2Spec f left right) i j = f (get2 left i j) (get2 right i j)

              Matrix indexing commutes with a pointwise binary tensor operation.

              @[simp]
              theorem TorchLean.Tensor.get2_mapSpec {α : Type} [Storage α] {m n : } (f : αα) (tensor : Tensor α [m, n]) (i : Fin m) (j : Fin n) :
              get2 (mapSpec f tensor) i j = f (get2 tensor i j)

              Matrix indexing commutes with a pointwise unary tensor operation.

              theorem TorchLean.Tensor.forall_map2Spec {α β γ : Type} [Storage α] [Storage β] [Storage γ] {p : αProp} {q : βProp} {r : γProp} {f : αβγ} {s : Spec.Shape} {x : Tensor α s} {y : Tensor β s} (hx : Forall p x) (hy : Forall q y) (hf : ∀ (a : α) (b : β), p aq br (f a b)) :
              Forall r (map2Spec f x y)

              Transport two pointwise properties through a binary shape-preserving operation.

              def TorchLean.Tensor.addSpec {α : Type} [Storage α] [Add α] {s : Spec.Shape} (T₁ T₂ : Tensor α s) :
              Tensor α s

              Element‑wise addition (shape preserved).

              Instances For
                theorem TorchLean.Tensor.castShape_addSpec {α : Type} [Storage α] [Add α] {shape shape' : Spec.Shape} (left right : Tensor α shape) (h : shape = shape') :
                (left.addSpec right).castShape h = (left.castShape h).addSpec (right.castShape h)

                Shape transport commutes with pointwise tensor addition.

                def TorchLean.Tensor.scatterAddSpec {α : Type} [Storage α] [Add α] (axis : ) {s : Spec.Shape} (base : Tensor α s) [_h : Spec.Shape.AxisInBounds axis s] {count : } :
                Tensor (Fin (s.axisSize axis)) [count]Tensor α (s.replaceAxis axis count)Tensor α s

                Add indexed source slices into an arbitrary axis of a tensor.

                Repeated indices accumulate. This is the pure tensor semantics used by the backward rule for indexSelectSpec and corresponds to torch.scatter_add with an index vector.

                Instances For
                  theorem TorchLean.Tensor.addSpec_eq_add {α : Type} [Storage α] [Add α] {s : Spec.Shape} (left right : Tensor α s) :
                  left.addSpec right = left + right

                  addSpec is the tensor + (both are Rep.zipWith (· + ·)).

                  def TorchLean.Tensor.mulSpec {α : Type} [Storage α] [Mul α] {s : Spec.Shape} (T₁ T₂ : Tensor α s) :
                  Tensor α s

                  Element‑wise multiplication (shape preserved).

                  Instances For
                    @[simp]
                    theorem TorchLean.Tensor.toScalar_mulSpec {α : Type} [Storage α] [Mul α] (left right : Tensor α Spec.Shape.scalar) :
                    (left.mulSpec right).item = left.item * right.item

                    Scalar extraction commutes with pointwise tensor multiplication.

                    @[simp]
                    theorem TorchLean.Tensor.mulSpec_full_left {α : Type} [Storage α] [Mul α] {s : Spec.Shape} (coefficient : α) (tensor : Tensor α s) :
                    (full s coefficient).mulSpec tensor = mapSpec (fun (x : α) => coefficient * x) tensor

                    Multiplication by a filled tensor is coordinatewise multiplication by its scalar value.

                    @[instance_reducible]
                    instance TorchLean.Tensor.instMul {α : Type} [Storage α] [Mul α] {s : Spec.Shape} :
                    Mul (Tensor α s)

                    Mul instance for shape-indexed tensors: multiply pointwise, preserving the shape.

                    def TorchLean.Tensor.subSpec {α : Type} [Storage α] [Sub α] {s : Spec.Shape} :
                    Tensor α sTensor α sTensor α s

                    Element‑wise subtraction (shape preserved).

                    Instances For
                      theorem TorchLean.Tensor.subSpec_eq_sub {α : Type} [Storage α] [Sub α] {s : Spec.Shape} (left right : Tensor α s) :
                      left.subSpec right = left - right

                      subSpec is the tensor - (both are Rep.zipWith (· - ·)).

                      def TorchLean.Tensor.divSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} :
                      Tensor α sTensor α sTensor α s

                      Element‑wise division (shape preserved).

                      Instances For
                        @[instance_reducible]
                        instance TorchLean.Tensor.instDiv {α : Type} [Storage α] [Context α] {s : Spec.Shape} :
                        Div (Tensor α s)

                        Div instance for shape-indexed tensors: divide pointwise, preserving the shape.

                        def TorchLean.Tensor.safedivSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t1 t2 : Tensor α s) :
                        Tensor α s

                        Epsilon-shifted division, $x/(y+\varepsilon)$. The denominator can still be zero.

                        Instances For
                          def TorchLean.Tensor.scaleSpec {α : Type} [Storage α] [Mul α] {s : Spec.Shape} (t : Tensor α s) (scalar : α) :
                          Tensor α s

                          Scale a tensor by a scalar.

                          Instances For
                            def TorchLean.Tensor.squareSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                            Tensor α s

                            Square each element of a tensor.

                            Instances For

                              Squaring is elementwise multiplication with the same tensor on both inputs.

                              def TorchLean.Tensor.sqrtSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                              Tensor α s

                              Square root of each element (clamped to max x 0 to stay total).

                              Instances For
                                def TorchLean.Tensor.absSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                                Tensor α s

                                Absolute value of each element.

                                Instances For
                                  def TorchLean.Tensor.logSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                                  Tensor α s

                                  Element‑wise natural log.

                                  Instances For
                                    def TorchLean.Tensor.expSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                                    Tensor α s

                                    Element‑wise exponential.

                                    Instances For
                                      def TorchLean.Tensor.negSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                                      Tensor α s

                                      Element‑wise negation.

                                      Instances For
                                        theorem TorchLean.Tensor.negSpec_eq_neg {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :

                                        negSpec is the tensor negation (both are Rep.map Neg.neg).

                                        def TorchLean.Tensor.powSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t1 t2 : Tensor α s) :
                                        Tensor α s

                                        Element‑wise power.

                                        Instances For

                                          Element‑wise comparisons (returning Bool tensors).

                                          Instances For
                                            def TorchLean.Tensor.lessEqualSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (x y : Tensor α s) :

                                            Element-wise $\le$ test, implemented via $\neg(>)$ so we only depend on DecidableRel (· > ·). This agrees with for a total order; IEEE unordered comparisons involving NaN return true here.

                                            Instances For
                                              def TorchLean.Tensor.lessThanSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (x y : Tensor α s) :

                                              Element‑wise < test (defined as y > x).

                                              Instances For

                                                Element-wise $\ge$ test (defined as $\neg(y>x)$). Like lessEqualSpec, this returns true for IEEE unordered comparisons involving NaN.

                                                Instances For

                                                  Boolean NOT, pointwise on a Bool tensor.

                                                  Instances For
                                                    def TorchLean.Tensor.invSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (x : Tensor α s) :
                                                    Tensor α s

                                                    Element‑wise reciprocal (1/x).

                                                    Instances For
                                                      @[simp]

                                                      Scalar extraction commutes with coordinatewise reciprocal.

                                                      def TorchLean.Tensor.clampSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (x : Tensor α s) (minVal maxVal : α) :
                                                      Tensor α s

                                                      Clamp each entry into [minVal, maxVal].

                                                      The runtime uses zero derivative outside the open interval, including at either endpoint. Clearing scalar tangents on that branch gives dual-number execution the same convention as the recorded JVP and VJP. The underlying minimum and maximum still determine the primal value.

                                                      Instances For
                                                        def TorchLean.Tensor.minSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t1 t2 : Tensor α s) :
                                                        Tensor α s

                                                        Element‑wise minimum.

                                                        Instances For
                                                          def TorchLean.Tensor.maxSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t1 t2 : Tensor α s) :
                                                          Tensor α s

                                                          Element‑wise maximum.

                                                          Instances For
                                                            def TorchLean.Tensor.signSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) :
                                                            Tensor α s

                                                            Element‑wise sign function: returns -1, 0, or 1.

                                                            Instances For
                                                              def TorchLean.Tensor.sinSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} :
                                                              Tensor α sTensor α s

                                                              Elementwise sine, with each input interpreted as an angle in radians.

                                                              Instances For
                                                                def TorchLean.Tensor.cosSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} :
                                                                Tensor α sTensor α s

                                                                Elementwise cosine, with each input interpreted as an angle in radians.

                                                                Instances For
                                                                  def TorchLean.Tensor.coshSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} :
                                                                  Tensor α sTensor α s

                                                                  Element‑wise cosh.

                                                                  Instances For
                                                                    def TorchLean.Tensor.sinhSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} :
                                                                    Tensor α sTensor α s

                                                                    Element‑wise sinh.

                                                                    Instances For
                                                                      def TorchLean.Tensor.clampDerivativeSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (x : Tensor α s) (minVal maxVal : α) :
                                                                      Tensor α s

                                                                      Derivative mask for clamp: 1 strictly inside (minVal, maxVal), else 0.

                                                                      Instances For
                                                                        def TorchLean.Tensor.gtMaskSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (a b : Tensor α s) :
                                                                        Tensor α s

                                                                        Numeric mask: 1 where a > b, else 0.

                                                                        Instances For
                                                                          def TorchLean.Tensor.ltMaskSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (a b : Tensor α s) :
                                                                          Tensor α s

                                                                          Numeric mask: 1 where a < b, else 0.

                                                                          Instances For

                                                                            Convert a Bool to α using 1/0.

                                                                            Instances For
                                                                              def TorchLean.Tensor.mulBoolMaskSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) (mask : Tensor Bool s) :
                                                                              Tensor α s

                                                                              Multiply a tensor by a Bool mask (casts the mask to 0/1).

                                                                              Instances For
                                                                                def TorchLean.Tensor.clampHuberMaskSpec {α : Type} [Storage α] [Context α] {s : Spec.Shape} (t : Tensor α s) (mask : Tensor Bool s) (delta : α) :
                                                                                Tensor α s

                                                                                Apply a Huber-style clamp on entries selected by mask (leaves others unchanged).

                                                                                Instances For
                                                                                  def TorchLean.Tensor.updateTensorSpec {α : Type} [Storage α] [Storage.Update α] {s : Spec.Shape} (tensor : Tensor α s) (indices : List ) (newValue : α) :
                                                                                  Tensor α s

                                                                                  Update a tensor at a runtime index path.

                                                                                  The index path is interpreted outermost-first. Out-of-bounds indices leave the tensor unchanged. The implementation validates the path once, then performs one copy-on-write physical-buffer replacement.

                                                                                  Instances For

                                                                                    Like updateTensorSpec, but replaces a subtree with another tensor.

                                                                                    Instances For
                                                                                      def TorchLean.Tensor.updateSpec {α : Type} [Storage α] [Storage.Update α] {n : } {s : Spec.Shape} (tensor : Tensor α (Spec.Shape.dim n s)) (indices : List ) (newValue : α) :

                                                                                      Specialization of updateTensorSpec for a top-level vector dimension.

                                                                                      Instances For