ark_r1cs_std/fields/emulated_fp/
params.rs

1use super::NonNativeFieldConfig;
2
3/// Obtain the parameters from a `ConstraintSystem`'s cache or generate a new
4/// one
5#[must_use]
6pub const fn get_params(
7    target_field_size: usize,
8    base_field_size: usize,
9    optimization_type: OptimizationType,
10) -> NonNativeFieldConfig {
11    let (num_of_limbs, limb_size) =
12        find_parameters(base_field_size, target_field_size, optimization_type);
13    NonNativeFieldConfig {
14        num_limbs: num_of_limbs,
15        bits_per_limb: limb_size,
16    }
17}
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20/// The type of optimization target for the parameters searching
21pub enum OptimizationType {
22    /// Optimized for constraints
23    Constraints,
24    /// Optimized for weight
25    Weight,
26}
27
28/// A function to search for parameters for emulated field gadgets
29pub const fn find_parameters(
30    base_field_prime_length: usize,
31    target_field_prime_bit_length: usize,
32    optimization_type: OptimizationType,
33) -> (usize, usize) {
34    let mut found = false;
35    let mut min_cost = 0usize;
36    let mut min_cost_limb_size = 0usize;
37    let mut min_cost_num_of_limbs = 0usize;
38
39    let surfeit = 10;
40    let mut max_limb_size = (base_field_prime_length - 1 - surfeit - 1) / 2 - 1;
41    if max_limb_size > target_field_prime_bit_length {
42        max_limb_size = target_field_prime_bit_length;
43    }
44    let mut limb_size = 1;
45
46    while limb_size <= max_limb_size {
47        let num_of_limbs = (target_field_prime_bit_length + limb_size - 1) / limb_size;
48
49        let group_size =
50            (base_field_prime_length - 1 - surfeit - 1 - 1 - limb_size + limb_size - 1) / limb_size;
51        let num_of_groups = (2 * num_of_limbs - 1 + group_size - 1) / group_size;
52
53        let mut this_cost = 0;
54
55        match optimization_type {
56            OptimizationType::Constraints => {
57                this_cost += 2 * num_of_limbs - 1;
58            },
59            OptimizationType::Weight => {
60                this_cost += 6 * num_of_limbs * num_of_limbs;
61            },
62        };
63
64        match optimization_type {
65            OptimizationType::Constraints => {
66                this_cost += target_field_prime_bit_length; // allocation of k
67                this_cost += target_field_prime_bit_length + num_of_limbs; // allocation of r
68                                                                           // this_cost += 2 * num_of_limbs - 1; // compute kp
69                this_cost += num_of_groups + (num_of_groups - 1) * (limb_size * 2 + surfeit) + 1;
70                // equality check
71            },
72            OptimizationType::Weight => {
73                this_cost += target_field_prime_bit_length * 3 + target_field_prime_bit_length; // allocation of k
74                this_cost += target_field_prime_bit_length * 3
75                    + target_field_prime_bit_length
76                    + num_of_limbs; // allocation of r
77                this_cost += num_of_limbs * num_of_limbs + 2 * (2 * num_of_limbs - 1); // compute kp
78                this_cost += num_of_limbs
79                    + num_of_groups
80                    + 6 * num_of_groups
81                    + (num_of_groups - 1) * (2 * limb_size + surfeit) * 4
82                    + 2; // equality check
83            },
84        };
85
86        if !found || this_cost < min_cost {
87            found = true;
88            min_cost = this_cost;
89            min_cost_limb_size = limb_size;
90            min_cost_num_of_limbs = num_of_limbs;
91        }
92
93        limb_size += 1;
94    }
95
96    (min_cost_num_of_limbs, min_cost_limb_size)
97}