ValueError: Shapes, positional gradients or coefficient dtypes are unsupported.
RuntimeError: Inputs are not on NPU or the required extension is missing.
"""
if tensor.ndim != 4 or unsqueeze_dim not in (1, 2):
raise ValueError("Partial RoPE requires a 4D tensor and unsqueeze_dim 1 or 2")
_validate_rotary_coefficients(tensor, cos, sin)
if tensor.device.type != "npu":
raise RuntimeError(f"Fused partial RoPE requires NPU inputs; got device={tensor.device}")
value = tensor if unsqueeze_dim == 2 else tensor.transpose(1, 2)
if cos.shape[0] not in (1, value.shape[0]) or cos.shape[1] not in (1, value.shape[1]):
raise ValueError("Partial RoPE cos/sin batch and sequence dimensions must broadcast to the input")
rotary_dim = cos.shape[-1] * 2
if rotary_dim > tensor.shape[-1]:
raise ValueError("Partial RoPE frequencies cannot exceed the input head dimension")
if not tensor.numel() or not rotary_dim:
return tensor.clone()
cosine = cos.expand(value.shape[0], -1, -1).repeat_interleave(2, dim=-1).unsqueeze(2).contiguous()
sine = sin.expand(value.shape[0], -1, -1).repeat_interleave(2, dim=-1).unsqueeze(2).contiguous()
output = _PartialRotaryMul.apply(value, cosine, sine)
return output if unsqueeze_dim == 2 else output.transpose(1, 2)