|
1 | 1 | // adapted from: https://github.com/geometryxyz/msl-secp256k1
|
2 | 2 |
|
3 |
| -use core::borrow; |
4 |
| - |
5 | 3 | use crate::msm::metal_msm::host::gpu::{
|
6 | 4 | create_buffer, create_empty_buffer, get_default_device, read_buffer,
|
7 | 5 | };
|
8 | 6 | use crate::msm::metal_msm::host::shader::{compile_metal, write_constants};
|
9 | 7 | use crate::msm::metal_msm::utils::limbs_conversion::{FromLimbs, ToLimbs};
|
10 |
| -use ark_ff::{BigInt, BigInteger}; |
| 8 | +use ark_ff::{BigInt, BigInteger, UniformRand}; |
| 9 | +use ark_std::rand; |
11 | 10 | use metal::*;
|
12 | 11 |
|
13 | 12 | #[test]
|
14 | 13 | #[serial_test::serial]
|
15 |
| -pub fn test_bigint_sub() { |
16 |
| - let log_limb_size = 13; |
17 |
| - let num_limbs = 20; |
18 |
| - |
19 |
| - let mut a = BigInt::new([0xf09f8fb3, 0xefb88fe2, 0x808df09f, 0x8c880010]); |
20 |
| - let b = BigInt::new([0xf09f8fb3, 0xefb88fe2, 0x808df09f, 0x8c880001]); |
| 14 | +pub fn test_bigint_sub_no_underflow() { |
| 15 | + // adjusted by bn254 scalar bits and mont_mul cios optimal limb size |
| 16 | + let log_limb_size = 16; |
| 17 | + let num_limbs = 16; |
| 18 | + |
| 19 | + // Create two test numbers that do not cause underflow |
| 20 | + let mut rng = rand::thread_rng(); |
| 21 | + let (a, b, expected) = loop { |
| 22 | + let a = BigInt::rand(&mut rng); |
| 23 | + let b = BigInt::rand(&mut rng); |
| 24 | + |
| 25 | + let mut expected = a.clone(); |
| 26 | + let underflow = expected.sub_with_borrow(&b); |
| 27 | + |
| 28 | + // Break the loop if subtraction does not underflow |
| 29 | + if !underflow { |
| 30 | + break (a, b, expected); |
| 31 | + } |
| 32 | + }; |
21 | 33 |
|
22 | 34 | let device = get_default_device();
|
23 | 35 | let a_buf = create_buffer(&device, &a.to_limbs(num_limbs, log_limb_size));
|
24 | 36 | let b_buf = create_buffer(&device, &b.to_limbs(num_limbs, log_limb_size));
|
25 | 37 | let result_buf = create_empty_buffer(&device, num_limbs);
|
26 | 38 |
|
27 |
| - // perform a - b |
28 |
| - let _borrow = a.sub_with_borrow(&b); |
29 |
| - let expected_limbs = a.to_limbs(num_limbs, log_limb_size); |
30 |
| - |
31 | 39 | let command_queue = device.new_command_queue();
|
32 | 40 | let command_buffer = command_queue.new_command_buffer();
|
33 | 41 |
|
@@ -81,46 +89,38 @@ pub fn test_bigint_sub() {
|
81 | 89 | command_buffer.wait_until_completed();
|
82 | 90 |
|
83 | 91 | let result_limbs: Vec<u32> = read_buffer(&result_buf, num_limbs);
|
84 |
| - let result = BigInt::from_limbs(&result_limbs, log_limb_size); |
| 92 | + let expected_limbs = expected.to_limbs(num_limbs, log_limb_size); |
| 93 | + assert_eq!(result_limbs, expected_limbs); |
85 | 94 |
|
86 |
| - assert!(result_limbs.eq(&expected_limbs)); |
87 |
| - assert!(result.eq(&a)); |
| 95 | + let result = BigInt::from_limbs(&result_limbs, log_limb_size); |
| 96 | + assert_eq!(result, expected); |
88 | 97 | }
|
89 | 98 |
|
90 | 99 | #[test]
|
91 | 100 | #[serial_test::serial]
|
92 | 101 | fn test_bigint_sub_underflow() {
|
93 |
| - let device = Device::system_default().expect("no device found"); |
94 |
| - let num_limbs = 20; |
95 |
| - let log_limb_size = 13; |
96 |
| - |
97 |
| - // Create smaller number a and larger number b |
98 |
| - let mut a = BigInt::from_u32(100); |
99 |
| - let b = BigInt::from_u32(200); |
100 |
| - |
101 |
| - let a_limbs = a.to_limbs(num_limbs, log_limb_size); |
102 |
| - let b_limbs = b.to_limbs(num_limbs, log_limb_size); |
103 |
| - |
104 |
| - let a_buf = device.new_buffer_with_data( |
105 |
| - unsafe { std::mem::transmute(a_limbs.as_ptr()) }, |
106 |
| - (a_limbs.len() * std::mem::size_of::<u32>()) as u64, |
107 |
| - MTLResourceOptions::StorageModeShared, |
108 |
| - ); |
109 |
| - |
110 |
| - let b_buf = device.new_buffer_with_data( |
111 |
| - unsafe { std::mem::transmute(b_limbs.as_ptr()) }, |
112 |
| - (b_limbs.len() * std::mem::size_of::<u32>()) as u64, |
113 |
| - MTLResourceOptions::StorageModeShared, |
114 |
| - ); |
115 |
| - |
116 |
| - let result_buf = device.new_buffer( |
117 |
| - (num_limbs * std::mem::size_of::<u32>()) as u64, |
118 |
| - MTLResourceOptions::StorageModeShared, |
119 |
| - ); |
| 102 | + let num_limbs = 16; |
| 103 | + let log_limb_size = 16; |
| 104 | + |
| 105 | + // Create two test numbers that cause underflow |
| 106 | + let mut rng = rand::thread_rng(); |
| 107 | + let (a, b, expected) = loop { |
| 108 | + let a = BigInt::rand(&mut rng); |
| 109 | + let b = BigInt::rand(&mut rng); |
| 110 | + |
| 111 | + let mut expected = a.clone(); |
| 112 | + let underflow = expected.sub_with_borrow(&b); |
| 113 | + |
| 114 | + // Break the loop if subtraction does not underflow |
| 115 | + if underflow { |
| 116 | + break (a, b, expected); |
| 117 | + } |
| 118 | + }; |
120 | 119 |
|
121 |
| - // Expected result is 2^256 - 100 (since we're doing a - b where b > a) |
122 |
| - let _expected = a.sub_with_borrow(&b); |
123 |
| - let expected_limbs = a.to_limbs(num_limbs, log_limb_size); |
| 120 | + let device = get_default_device(); |
| 121 | + let a_buf = create_buffer(&device, &a.to_limbs(num_limbs, log_limb_size)); |
| 122 | + let b_buf = create_buffer(&device, &b.to_limbs(num_limbs, log_limb_size)); |
| 123 | + let result_buf = create_empty_buffer(&device, num_limbs); |
124 | 124 |
|
125 | 125 | let command_queue = device.new_command_queue();
|
126 | 126 | let command_buffer = command_queue.new_command_buffer();
|
@@ -175,8 +175,9 @@ fn test_bigint_sub_underflow() {
|
175 | 175 | command_buffer.wait_until_completed();
|
176 | 176 |
|
177 | 177 | let result_limbs: Vec<u32> = read_buffer(&result_buf, num_limbs);
|
178 |
| - let result = BigInt::from_limbs(&result_limbs, log_limb_size); |
| 178 | + let expected_limbs = expected.to_limbs(num_limbs, log_limb_size); |
| 179 | + assert_eq!(result_limbs, expected_limbs); |
179 | 180 |
|
180 |
| - // assert!(result_limbs.eq(&expected_limbs)); // TODO: leading limb is incorrect |
181 |
| - assert!(result.eq(&a)); |
| 181 | + let result = BigInt::from_limbs(&result_limbs, log_limb_size); |
| 182 | + assert_eq!(result, expected); |
182 | 183 | }
|
0 commit comments