Works only on positive integers from (0; 2^denominator_cap_2k). For the initial approximation of 1/n, we use would like to compute x that is different form 1/n no more than twice. We compute the highest bit of n and than return 1 / 2^(highest_bit + 1). Idea from: https://codeforces.com/blog/entry/10330?#comment-157145 Another approach to approximate the initial value is proposed here: https://www.
(
context: &Context,
t: Type,
denominator_cap_2k: u64,
)
| 237 | // https://www.ifca.ai/pub/fc10/31_47.pdf section 3.4 |
| 238 | // However, the current approach seems to work fine for Goldschmidt's as well as Newton's method. |
| 239 | pub fn inverse_initial_approximation( |
| 240 | context: &Context, |
| 241 | t: Type, |
| 242 | denominator_cap_2k: u64, |
| 243 | ) -> Result<Graph> { |
| 244 | let sc = t.get_scalar_type(); |
| 245 | let g = context.create_graph()?; |
| 246 | let divisor = g.input(t)?; |
| 247 | let divisor_bits = pull_out_bits(divisor.a2b()?)?; |
| 248 | let cum_or = cumulative_or(divisor_bits, denominator_cap_2k)?; |
| 249 | let highest_one_bit_binary = g.add( |
| 250 | cum_or.get_slice(vec![SliceElement::SubArray( |
| 251 | None, |
| 252 | Some(denominator_cap_2k as i64), |
| 253 | None, |
| 254 | )])?, |
| 255 | cum_or.get_slice(vec![SliceElement::SubArray( |
| 256 | Some(1), |
| 257 | Some(denominator_cap_2k as i64 + 1), |
| 258 | None, |
| 259 | )])?, |
| 260 | )?; |
| 261 | let mut result = vec![]; |
| 262 | for i in 0..denominator_cap_2k { |
| 263 | result.push(highest_one_bit_binary.get(vec![denominator_cap_2k - i - 1])?); |
| 264 | } |
| 265 | for _ in denominator_cap_2k..sc.size_in_bits() { |
| 266 | result.push(zeros_like(result[0].clone())?); |
| 267 | } |
| 268 | let approximation = g |
| 269 | .create_vector(result[0].get_type()?, result)? |
| 270 | .vector_to_array()?; |
| 271 | let approximation = put_in_bits(approximation)?.b2a(sc)?; |
| 272 | |
| 273 | approximation.set_as_output()?; |
| 274 | g.finalize() |
| 275 | } |
| 276 | // Another incarnation of `expand_dims`, following the contract https://pytorch.org/docs/stable/generated/torch.unsqueeze.html |
| 277 | // (in particular, the `axis` argument can be negative). |
| 278 | pub fn unsqueeze(x: Node, axis: i64) -> Result<Node> { |