fp/vector/
impl_fqslice.rs1use itertools::Itertools;
2
3use super::{
4 inner::{FqSlice, FqVector},
5 iter::{FqVectorIterator, FqVectorNonZeroIterator},
6};
7use crate::{
8 constants,
9 field::{Field, element::FieldElement},
10 limb::Limb,
11 prime::{Prime, ValidPrime},
12};
13
14impl<'a, F: Field> FqSlice<'a, F> {
17 pub fn prime(&self) -> ValidPrime {
18 self.fq().characteristic().to_dyn()
19 }
20
21 pub fn len(&self) -> usize {
22 self.end() - self.start()
23 }
24
25 pub const fn is_empty(&self) -> bool {
26 self.start() == self.end()
27 }
28
29 pub fn entry(&self, index: usize) -> FieldElement<F> {
30 debug_assert!(
31 index < self.len(),
32 "Index {} too large, length of vector is only {}.",
33 index,
34 self.len()
35 );
36 let bit_mask = self.fq().bitmask();
37 let limb_index = self.fq().limb_bit_index_pair(index + self.start());
38 let mut result = self.limbs()[limb_index.limb];
39 result >>= limb_index.bit_index;
40 result &= bit_mask;
41 self.fq().decode(result)
42 }
43
44 pub fn iter(self) -> FqVectorIterator<'a, F> {
46 FqVectorIterator::new(self)
47 }
48
49 pub fn iter_nonzero(self) -> FqVectorNonZeroIterator<'a, F> {
50 FqVectorNonZeroIterator::new(self)
51 }
52
53 pub fn first_nonzero(&self) -> Option<(usize, FieldElement<F>)> {
54 self.iter_nonzero().next()
55 }
56
57 pub fn is_zero(&self) -> bool {
58 let limb_range = self.limb_range();
59 if limb_range.is_empty() {
60 return true;
61 }
62 let (min_mask, max_mask) = self.limb_masks();
63 if self.limbs()[limb_range.start] & min_mask != 0 {
64 return false;
65 }
66
67 let inner_range = self.limb_range_inner();
68 if !inner_range.is_empty() && self.limbs()[inner_range].iter().any(|&x| x != 0) {
69 return false;
70 }
71 if self.limbs()[limb_range.end - 1] & max_mask != 0 {
72 return false;
73 }
74 true
75 }
76
77 #[must_use]
78 pub fn restrict(self, start: usize, end: usize) -> Self {
79 assert!(start <= end && end <= self.len());
80
81 FqSlice::new(
82 self.fq(),
83 self.into_limbs(),
84 self.start() + start,
85 self.start() + end,
86 )
87 }
88
89 #[must_use]
91 pub fn to_owned(self) -> FqVector<F> {
92 let mut new = FqVector::new(self.fq(), self.len());
93 if self.start().is_multiple_of(self.fq().entries_per_limb()) {
94 let limb_range = self.limb_range();
95 new.limbs_mut()[0..limb_range.len()].copy_from_slice(&self.limbs()[limb_range]);
96 if !new.limbs().is_empty() {
97 let len = new.limbs().len();
98 new.limbs_mut()[len - 1] &= self.limb_masks().1;
99 }
100 } else {
101 new.as_slice_mut().assign(self);
102 }
103 new
104 }
105}
106
107impl<F: Field> FqSlice<'_, F> {
109 #[inline]
110 pub(super) fn offset(&self) -> usize {
111 let bit_length = self.fq().bit_length();
112 let entries_per_limb = self.fq().entries_per_limb();
113 (self.start() % entries_per_limb) * bit_length
114 }
115
116 #[inline]
117 pub(super) fn limb_range(&self) -> std::ops::Range<usize> {
118 self.fq().range(self.start(), self.end())
119 }
120
121 #[inline]
126 pub(super) fn limb_range_inner(&self) -> std::ops::Range<usize> {
127 let range = self.limb_range();
128 (range.start + 1)..(usize::max(range.start + 1, range.end - 1))
129 }
130
131 #[inline(always)]
132 pub(super) fn min_limb_mask(&self) -> Limb {
133 !0 << self.offset()
134 }
135
136 #[inline(always)]
137 pub(super) fn max_limb_mask(&self) -> Limb {
138 let num_entries = 1 + (self.end() - 1) % self.fq().entries_per_limb();
139 let bit_max = num_entries * self.fq().bit_length();
140
141 (!0) >> (constants::BITS_PER_LIMB - bit_max)
142 }
143
144 #[inline(always)]
145 pub(super) fn limb_masks(&self) -> (Limb, Limb) {
146 if self.limb_range().len() == 1 {
147 (
148 self.min_limb_mask() & self.max_limb_mask(),
149 self.min_limb_mask() & self.max_limb_mask(),
150 )
151 } else {
152 (self.min_limb_mask(), self.max_limb_mask())
153 }
154 }
155}
156
157impl<'a, F: Field> From<&'a FqVector<F>> for FqSlice<'a, F> {
158 fn from(v: &'a FqVector<F>) -> Self {
159 v.slice(0, v.len())
160 }
161}
162
163impl<F: Field> std::fmt::Display for FqSlice<'_, F> {
164 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
177 if f.alternate() {
178 for v in self.iter() {
179 write!(f, "{v}")?;
181 }
182 Ok(())
183 } else {
184 write!(f, "[{}]", self.iter().format(", "))
185 }
186 }
187}