| 344 | } |
| 345 | |
| 346 | pub fn timestep_embedding(t: &Tensor, dim: usize, dtype: DType) -> Result<Tensor> { |
| 347 | const TIME_FACTOR: f64 = 1000.; |
| 348 | const MAX_PERIOD: f64 = 10000.; |
| 349 | if dim % 2 == 1 { |
| 350 | candle_core::bail!("{dim} is odd") |
| 351 | } |
| 352 | let dev = t.device(); |
| 353 | let half = dim / 2; |
| 354 | let t = (t * TIME_FACTOR)?; |
| 355 | // Compute frequency vector directly as f32 Vec — avoids arange + to_dtype + mul + exp |
| 356 | let decay = -MAX_PERIOD.ln() / half as f64; |
| 357 | let freqs_data: Vec<f32> = (0..half).map(|j| (j as f64 * decay).exp() as f32).collect(); |
| 358 | let freqs = Tensor::new(freqs_data.as_slice(), dev)?.unsqueeze(0)?; |
| 359 | let args = t.unsqueeze(1)?.to_dtype(DType::F32)?.broadcast_mul(&freqs)?; |
| 360 | Tensor::cat(&[args.cos()?, args.sin()?], D::Minus1)?.to_dtype(dtype) |
| 361 | } |
| 362 | |
| 363 | // ── Positional Embeddings ────────────────────────────────────────────────────── |
| 364 | |