3 releases (breaking)

0.2.0 Aug 14, 2020
0.1.0 Dec 20, 2019
0.0.0 Dec 19, 2019

#1173 in Algorithms

Download history 27131/week @ 2024-07-22 29970/week @ 2024-07-29 23580/week @ 2024-08-05 27407/week @ 2024-08-12 32717/week @ 2024-08-19 35479/week @ 2024-08-26 33795/week @ 2024-09-02 34547/week @ 2024-09-09 28127/week @ 2024-09-16 26773/week @ 2024-09-23 34328/week @ 2024-09-30 40623/week @ 2024-10-07 33622/week @ 2024-10-14 38533/week @ 2024-10-21 34588/week @ 2024-10-28 27077/week @ 2024-11-04

134,880 downloads per month
Used in 83 crates (3 directly)

MIT/Apache

13KB
186 lines

addchain: Rust crate for generating addition chains

Usage

To find a short addition chain:

let chain = addchain::find_shortest_chain(num_bigint::BigUint::from(87u32));

To build the steps for an addition chain:

let steps = addchain::build_addition_chain(num_bigint::BigUint::from(87u32));

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


lib.rs:

Library for generating addition chains

An addition chain C for some positive integer n is a sequence of integers that have the following properties:

  • The first integer is 1.
  • The last integer is n.
  • Integers only appear once.
  • Every integer is either the sum of two earlier integers, or double an earlier integer.

An addition chain corresponds to a series of len(C) - 1 primitive operations (doubling and addition) that can be used to compute a target integer. An optimal addition chain for n has the shortest possible length, and therefore requires the fewest operations to compute n. This is particularly useful in cryptographic algorithms such as modular exponentiation, where n is usually at least 2^128.

Example

To compute the number 87, we can represent it in binary as 1010111, and then using the binary double-and-add algorithm (where we double for every bit, and add 1 for every bit that is set to 1) we have the following steps:

 i | n_i | Operation | b_i
---|-----|-----------|-----
 0 |  1  |           |  1
 1 |  2  | n_0 * 2   |  0
 2 |  4  | n_1 * 2   |  1
 3 |  5  | n_2 + n_0 |
 4 | 10  | n_3 * 2   |  0
 5 | 20  | n_4 * 2   |  1
 6 | 21  | n_5 + n_0 |
 7 | 42  | n_6 * 2   |  1
 8 | 43  | n_7 + n_0 |
 9 | 86  | n_8 * 2   |  1
10 | 87  | n_9 + n_0 |

This corresponds to the addition chain [1, 2, 4, 5, 10, 20, 21, 42, 43, 86, 87], which has length 11. However, the optimal addition chain length for 87 is 10, and several addition chains can be constructed with optimal length. One such chain is [1, 2, 3, 6, 7, 10, 20, 40, 80, 87], which corresponds to the following steps:

 i | n_i | Operation
---|-----|----------
 0 |  1  |
 1 |  2  | n_0 * 2
 2 |  3  | n_1 + n_0
 3 |  6  | n_2 * 2
 4 |  7  | n_3 + n_0
 5 | 10  | n_4 + n_2
 6 | 20  | n_5 * 2
 7 | 40  | n_6 * 2
 8 | 80  | n_7 * 2
 9 | 87  | n_8 + n_4

Usage

use addchain::{build_addition_chain, Step};
use num_bigint::BigUint;

assert_eq!(
    build_addition_chain(BigUint::from(87u32)),
    vec![
        Step::Double { index: 0 },
        Step::Add { left: 1, right: 0 },
        Step::Double { index: 2 },
        Step::Add { left: 3, right: 0 },
        Step::Add { left: 4, right: 2 },
        Step::Double { index: 5 },
        Step::Double { index: 6 },
        Step::Double { index: 7 },
        Step::Add { left: 8, right: 4 },
    ],
);

Dependencies

~500KB
~11K SLoC