class_docstr: Linear Elliptical Slice Sampler.
  
  Ideas:
  - Add batch support, broadcasting over parallel chains.
  - Optimize computations if possible, potentially with torch.compile.
  - Extend fixed features constraint to general linear equality constraints.
class_docstr_tok: ["Linear","Elliptical","Slice","Sampler",".","Ideas",":","-","Add","batch","support",",","broadcasting","over","parallel","chains",".","-","Optimize","computations","if","possible",",","potentially","with","torch.compile",".","-","Extend","fixed","features","constraint","to","general","linear","equality","constraints","."]
docstr: Finds rotated intersections.
  
  Rotates the intersections by the rotation angle and makes sure that all
  angles lie in [0, 2*pi].
  
  Args:
      nu: A `d x 1`-dim tensor (the "new" direction, drawn from N(0, I)).
  
  Returns:
      A two-tuple containing rotation angle (scalar) and a
      `num_active / 2 x 2`-dim tensor of shifted angles.
docstr_tok: ["Finds","rotated","intersections",".","Rotates","the","intersections","by","the","rotation","angle","and","makes","sure","that","all","angles","lie","in","[","0",",","2","*","pi","]",".","Args",":","nu",":","A","`","d","x","1","`","-dim","tensor","(","the","``","new","''","direction",",","drawn","from","N","(","0",",","I",")",")",".","Returns",":","A","two-tuple","containing","rotation","angle","(","scalar",")","and","a","`","num_active","\/","2","x","2","`","-dim","tensor","of","shifted","angles","."]
code: def _find_rotated_intersections(
      self, nu: Tensor
  ) -> Tuple[Tensor, Tensor]:
      r"""Finds rotated intersections.
  
      Rotates the intersections by the rotation angle and makes sure that all
      angles lie in [0, 2*pi].
  
      Args:
          nu: A `d x 1`-dim tensor (the "new" direction, drawn from N(0, I)).
  
      Returns:
          A two-tuple containing rotation angle (scalar) and a
          `num_active / 2 x 2`-dim tensor of shifted angles.
      """
      slices = self._find_active_intersections(nu)
      rot_angle = slices[0]
      slices = (slices - rot_angle).reshape(-1, 2)
      # Ensuring that we don't sample within numerical precision of the boundaries
      # due to resulting instabilities in the constraint satisfaction.
      eps = 1e-6 if slices.dtype == torch.float32 else 1e-12
      eps = torch.tensor(eps, dtype=slices.dtype, device=slices.device)
      eps = eps.minimum(slices.diff(dim=-1).abs() / 4)
      slices = slices + torch.cat((eps, -eps), dim=-1)
      # NOTE: The remainder call relies on the epsilon contraction, since the
      # remainder of_twopi divided by _twopi is zero, not _twopi.
      return rot_angle, slices.remainder(_twopi)
  
imports: from __future__ import annotations
  import math
  from typing import List, Optional, Tuple, Union
  import torch
  from botorch.utils.sampling import PolytopeSampler
  from torch import Tensor
label_desc: Use image node_id 9 for calling the LinearEllipticalSliceSampler obj's underlying member method code with example usage: obj._find_rotated_intersections(nu) and returns: rot_angle,  slices