Skip to content

Commit 89d661e

Browse files
committed
Annihilator max degree is optional, and bump version 0.1.0
1 parent 65cdb2f commit 89d661e

File tree

4 files changed

+80
-45
lines changed

4 files changed

+80
-45
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "boolean_function"
33
description = "Mathematical analysis of Boolean functions"
4-
version = "0.0.6"
4+
version = "0.1.0"
55
edition = "2021"
66
rust-version = "1.56.0"
77
authors = ["Thomas Prévost"]

src/big_boolean_function.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,15 @@ impl BigBooleanFunction {
9696
/// Computes the [annihilator](crate::BooleanFunctionImpl::annihilator) of the Boolean function for a given maximum degree.
9797
///
9898
/// # Parameters
99-
/// * `max_degree` - The maximum degree of the wished annihilator.
99+
/// * `max_degree` - An optional maximum degree of the annihilator to search for. If set to `None`, the value is set to the variable count.
100100
///
101101
/// # Returns
102102
/// A tuple containing the annihilator function, its degree and the dimension of the annihilator vector space, or `None` no annihilator was found.
103103
pub fn annihilator_inner(
104104
&self,
105-
max_degree: usize,
105+
max_degree: Option<usize>,
106106
) -> Option<(BigBooleanFunction, usize, usize)> {
107+
let max_degree = max_degree.unwrap_or(self.variables_count);
107108
if self.truth_table == BigUint::zero() {
108109
let max_possible_function_tt =
109110
(BigUint::one() << (1 << self.variables_count)) - BigUint::one();
@@ -408,7 +409,7 @@ impl BooleanFunctionImpl for BigBooleanFunction {
408409
AnfPolynomial::from_anf_big(&anf_form, self.variables_count)
409410
}
410411

411-
fn annihilator(&self, max_degree: usize) -> Option<(BooleanFunction, usize, usize)> {
412+
fn annihilator(&self, max_degree: Option<usize>) -> Option<(BooleanFunction, usize, usize)> {
412413
let annihilator = self.annihilator_inner(max_degree)?;
413414
Some(((annihilator.0).into(), annihilator.1, annihilator.2))
414415
}
@@ -745,7 +746,7 @@ mod tests {
745746
BigUint::from_str_radix("00000000000000000000000000000000", 16).unwrap(),
746747
7,
747748
);
748-
let annihilator = boolean_function.annihilator_inner(0).unwrap();
749+
let annihilator = boolean_function.annihilator_inner(Some(0)).unwrap();
749750
assert_eq!(
750751
annihilator.0.printable_hex_truth_table(),
751752
"ffffffffffffffffffffffffffffffff"
@@ -757,25 +758,40 @@ mod tests {
757758
BigUint::from_str_radix("ffffffffffffffffffffffffffffffff", 16).unwrap(),
758759
7,
759760
);
760-
let annihilator = boolean_function.annihilator_inner(7);
761+
let annihilator = boolean_function.annihilator_inner(Some(7));
762+
assert!(annihilator.is_none());
763+
764+
let boolean_function = BigBooleanFunction::from_truth_table(
765+
BigUint::from_str_radix("ffffffffffffffffffffffffffffffff", 16).unwrap(),
766+
7,
767+
);
768+
let annihilator = boolean_function.annihilator_inner(None);
761769
assert!(annihilator.is_none());
762770

763771
let boolean_function = BigBooleanFunction::from_truth_table(
764772
BigUint::from_str_radix("7969817CC5893BA6AC326E47619F5AD0", 16).unwrap(),
765773
7,
766774
);
767-
let annihilator = boolean_function.annihilator_inner(2);
775+
let annihilator = boolean_function.annihilator_inner(Some(2));
768776
assert!(annihilator.is_none());
769777

770-
let annihilator = boolean_function.annihilator_inner(3).unwrap();
778+
let annihilator = boolean_function.annihilator_inner(Some(3)).unwrap();
771779
assert_eq!(
772780
annihilator.0.printable_hex_truth_table(),
773781
"80921c010276c440400810a80e200425"
774782
);
775783
assert_eq!(annihilator.1, 3);
776784
assert_eq!(annihilator.2, 2);
777785

778-
let annihilator = boolean_function.annihilator_inner(7).unwrap();
786+
let annihilator = boolean_function.annihilator_inner(Some(7)).unwrap();
787+
assert_eq!(
788+
annihilator.0.printable_hex_truth_table(),
789+
"80921c010276c440400810a80e200425"
790+
);
791+
assert_eq!(annihilator.1, 3);
792+
assert_eq!(annihilator.2, 64);
793+
794+
let annihilator = boolean_function.annihilator_inner(None).unwrap();
779795
assert_eq!(
780796
annihilator.0.printable_hex_truth_table(),
781797
"80921c010276c440400810a80e200425"
@@ -787,10 +803,10 @@ mod tests {
787803
BigUint::from_str_radix("80921c010276c440400810a80e200425", 16).unwrap(),
788804
7,
789805
);
790-
let annihilator = boolean_function.annihilator_inner(1);
806+
let annihilator = boolean_function.annihilator_inner(Some(1));
791807
assert!(annihilator.is_none());
792808

793-
let annihilator = boolean_function.annihilator_inner(2).unwrap();
809+
let annihilator = boolean_function.annihilator_inner(Some(2)).unwrap();
794810
assert_eq!(
795811
annihilator.0.printable_hex_truth_table(),
796812
"22442244118811882244224411881188"
@@ -802,26 +818,34 @@ mod tests {
802818
BigUint::from_str_radix("0000000000000000ffffffffffffffff", 16).unwrap(),
803819
7,
804820
);
805-
let annihilator = boolean_function.annihilator_inner(0);
821+
let annihilator = boolean_function.annihilator_inner(Some(0));
806822
assert!(annihilator.is_none());
807823

808-
let annihilator = boolean_function.annihilator_inner(1).unwrap();
824+
let annihilator = boolean_function.annihilator_inner(Some(1)).unwrap();
809825
assert_eq!(
810826
annihilator.0.printable_hex_truth_table(),
811827
"ffffffffffffffff0000000000000000"
812828
);
813829
assert_eq!(annihilator.1, 1);
814830
assert_eq!(annihilator.2, 1);
815831

816-
let annihilator = boolean_function.annihilator_inner(4).unwrap();
832+
let annihilator = boolean_function.annihilator_inner(Some(4)).unwrap();
817833
assert_eq!(
818834
annihilator.0.printable_hex_truth_table(),
819835
"ffffffffffffffff0000000000000000"
820836
);
821837
assert_eq!(annihilator.1, 1);
822838
assert_eq!(annihilator.2, 42);
823839

824-
let annihilator = boolean_function.annihilator_inner(7).unwrap();
840+
let annihilator = boolean_function.annihilator_inner(Some(7)).unwrap();
841+
assert_eq!(
842+
annihilator.0.printable_hex_truth_table(),
843+
"ffffffffffffffff0000000000000000"
844+
);
845+
assert_eq!(annihilator.1, 1);
846+
assert_eq!(annihilator.2, 64);
847+
848+
let annihilator = boolean_function.annihilator_inner(None).unwrap();
825849
assert_eq!(
826850
annihilator.0.printable_hex_truth_table(),
827851
"ffffffffffffffff0000000000000000"
@@ -837,20 +861,20 @@ mod tests {
837861
.unwrap(),
838862
8,
839863
);
840-
let annihilator = boolean_function.annihilator_inner(0);
864+
let annihilator = boolean_function.annihilator_inner(Some(0));
841865
assert!(annihilator.is_none());
842-
let annihilator = boolean_function.annihilator_inner(1);
866+
let annihilator = boolean_function.annihilator_inner(Some(1));
843867
assert!(annihilator.is_none());
844868

845-
let annihilator = boolean_function.annihilator_inner(2).unwrap();
869+
let annihilator = boolean_function.annihilator_inner(Some(2)).unwrap();
846870
assert_eq!(
847871
annihilator.0.printable_hex_truth_table(),
848872
"2244224411881188d2b4d2b4e178e178d2b4d2b4e178e1782244224411881188"
849873
);
850874
assert_eq!(annihilator.1, 2);
851875
assert_eq!(annihilator.2, 2);
852876

853-
let annihilator = boolean_function.annihilator_inner(5).unwrap();
877+
let annihilator = boolean_function.annihilator_inner(Some(5)).unwrap();
854878
assert_eq!(
855879
annihilator.0.printable_hex_truth_table(),
856880
"2244224411881188d2b4d2b4e178e178d2b4d2b4e178e1782244224411881188"
@@ -866,7 +890,7 @@ mod tests {
866890
.unwrap(),
867891
8,
868892
);
869-
let annihilator = boolean_function.annihilator_inner(4);
893+
let annihilator = boolean_function.annihilator_inner(Some(4));
870894
assert!(annihilator.is_none());
871895

872896
let boolean_function = BigBooleanFunction::from_truth_table(
@@ -877,7 +901,7 @@ mod tests {
877901
.unwrap(),
878902
8,
879903
);
880-
let annihilator = boolean_function.annihilator_inner(4).unwrap();
904+
let annihilator = boolean_function.annihilator_inner(Some(4)).unwrap();
881905
assert_eq!(
882906
annihilator.0.printable_hex_truth_table(),
883907
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"

src/lib.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -414,15 +414,15 @@ pub trait BooleanFunctionImpl: Debug {
414414
/// **Special case**: annihilator of zero function is constant one function, by convention.
415415
///
416416
/// # Parameters
417-
/// - `max_degree`: The maximum degree of the annihilator to search for.
417+
/// - `max_degree`: An optional maximum degree of the annihilator to search for. If set to `None`, the value is set to the variable count.
418418
///
419419
/// # Returns
420420
/// - `None` if no annihilator is found (this is the case for constant one function).
421421
/// - `Some((annihilator, degree, dimension))` if an annihilator is found:
422422
/// - `annihilator`: The annihilator function.
423423
/// - `degree`: The degree of the returned annihilator function.
424424
/// - `dimension`: The dimension of the annihilator vector space.
425-
fn annihilator(&self, max_degree: usize) -> Option<(BooleanFunction, usize, usize)>; // TODO max degree in Option
425+
fn annihilator(&self, max_degree: Option<usize>) -> Option<(BooleanFunction, usize, usize)>;
426426

427427
/// Returns the algebraic immunity of the Boolean function.
428428
///
@@ -431,7 +431,7 @@ pub trait BooleanFunctionImpl: Debug {
431431
/// # Returns
432432
/// The algebraic immunity of the Boolean function, or 0 if the function has no annihilator.
433433
fn algebraic_immunity(&self) -> usize {
434-
match self.annihilator(self.variables_count()) {
434+
match self.annihilator(Some(self.variables_count())) {
435435
None => 0,
436436
Some(annihilator) => annihilator.1,
437437
}
@@ -1543,14 +1543,14 @@ mod tests {
15431543
fn test_annihilator() {
15441544
let boolean_function =
15451545
BooleanFunction::from_hex_string_truth_table("00000000").unwrap();
1546-
let annihilator = boolean_function.annihilator(0).unwrap();
1546+
let annihilator = boolean_function.annihilator(Some(0)).unwrap();
15471547
assert_eq!(annihilator.0.printable_hex_truth_table(), "ffffffff");
15481548
assert_eq!(annihilator.1, 0);
15491549
assert_eq!(annihilator.2, 1);
15501550

15511551
let boolean_function =
15521552
BooleanFunction::from_hex_string_truth_table("abcdef0123456789").unwrap();
1553-
let annihilator = boolean_function.annihilator(4).unwrap();
1553+
let annihilator = boolean_function.annihilator(Some(4)).unwrap();
15541554
assert_eq!(
15551555
annihilator.0.printable_hex_truth_table(),
15561556
"1010101010101010"
@@ -1562,14 +1562,14 @@ mod tests {
15621562
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
15631563
)
15641564
.unwrap();
1565-
let annihilator = boolean_function.annihilator(4);
1565+
let annihilator = boolean_function.annihilator(Some(4));
15661566
assert!(annihilator.is_none());
15671567

15681568
let boolean_function = BooleanFunction::from_hex_string_truth_table(
15691569
"0000000000000000000000000000000000000000000000000000000000000000",
15701570
)
15711571
.unwrap();
1572-
let annihilator = boolean_function.annihilator(4).unwrap();
1572+
let annihilator = boolean_function.annihilator(Some(4)).unwrap();
15731573
assert_eq!(
15741574
annihilator.0.printable_hex_truth_table(),
15751575
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
@@ -1581,9 +1581,9 @@ mod tests {
15811581
"80921c010276c44224422441188118822442244118811880400810a80e200425",
15821582
)
15831583
.unwrap();
1584-
let annihilator = boolean_function.annihilator(1);
1584+
let annihilator = boolean_function.annihilator(Some(1));
15851585
assert!(annihilator.is_none());
1586-
let annihilator = boolean_function.annihilator(5).unwrap();
1586+
let annihilator = boolean_function.annihilator(Some(5)).unwrap();
15871587
assert_eq!(
15881588
annihilator.0.printable_hex_truth_table(),
15891589
"2244224411881188d2b4d2b4e178e178d2b4d2b4e178e1782244224411881188"

src/small_boolean_function.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,15 @@ impl SmallBooleanFunction {
110110
/// Computes the [annihilator](crate::BooleanFunctionImpl::annihilator) of the Boolean function for a given maximum degree.
111111
///
112112
/// # Parameters
113-
/// * `max_degree` - The maximum degree of the wished annihilator.
113+
/// * `max_degree` - An optional maximum degree of the annihilator to search for. If set to `None`, the value is set to the variable count.
114114
///
115115
/// # Returns
116116
/// A tuple containing the annihilator function, its degree and the dimension of the annihilator vector space, or `None` no annihilator was found.
117117
pub fn annihilator_inner(
118118
&self,
119-
max_degree: usize,
119+
max_degree: Option<usize>,
120120
) -> Option<(SmallBooleanFunction, usize, usize)> {
121+
let max_degree = max_degree.unwrap_or(self.variables_count);
121122
if self.truth_table == 0 {
122123
let max_possible_function_tt = u64::MAX >> (64 - (1 << self.variables_count));
123124
let dim_annihilator_vec_space = (0..=max_degree)
@@ -431,9 +432,9 @@ impl BooleanFunctionImpl for SmallBooleanFunction {
431432
AnfPolynomial::from_anf_small(anf_form, self.variables_count)
432433
}
433434

434-
fn annihilator(&self, max_degree: usize) -> Option<(BooleanFunction, usize, usize)> {
435+
fn annihilator(&self, max_degree: Option<usize>) -> Option<(BooleanFunction, usize, usize)> {
435436
let annihilator = self.annihilator_inner(max_degree)?;
436-
Some(((annihilator.0).into(), annihilator.1, annihilator.2))
437+
Some((annihilator.0.into(), annihilator.1, annihilator.2))
437438
}
438439

439440
fn get_1_local_neighbor(&self, position: u32) -> BooleanFunction {
@@ -773,63 +774,73 @@ mod tests {
773774
#[test]
774775
fn test_annihilator_inner() {
775776
let boolean_function = SmallBooleanFunction::from_truth_table(0xaa55aa55, 5).unwrap();
776-
let annihilator = boolean_function.annihilator_inner(1).unwrap();
777+
let annihilator = boolean_function.annihilator_inner(Some(1)).unwrap();
777778
assert_eq!(annihilator.0.get_truth_table_u64(), 0x55aa55aa);
778779
assert_eq!(annihilator.1, 1);
779780
assert_eq!(annihilator.2, 1);
780781

781-
let annihilator = boolean_function.annihilator_inner(6).unwrap();
782+
let annihilator = boolean_function.annihilator_inner(Some(6)).unwrap();
783+
assert_eq!(annihilator.0.get_truth_table_u64(), 0x55aa55aa);
784+
assert_eq!(annihilator.1, 1);
785+
assert_eq!(annihilator.2, 16);
786+
787+
let annihilator = boolean_function.annihilator_inner(None).unwrap();
782788
assert_eq!(annihilator.0.get_truth_table_u64(), 0x55aa55aa);
783789
assert_eq!(annihilator.1, 1);
784790
assert_eq!(annihilator.2, 16);
785791

786792
let boolean_function = SmallBooleanFunction::from_truth_table(0x1e, 3).unwrap();
787-
let annihilator = boolean_function.annihilator_inner(1);
793+
let annihilator = boolean_function.annihilator_inner(Some(1));
788794
assert!(annihilator.is_none());
789795

790-
let annihilator = boolean_function.annihilator_inner(2).unwrap();
796+
let annihilator = boolean_function.annihilator_inner(Some(2)).unwrap();
791797
assert_eq!(annihilator.0.get_truth_table_u64(), 0xe1);
792798
assert_eq!(annihilator.1, 2);
793799
assert_eq!(annihilator.2, 3);
794800

795801
let boolean_function = SmallBooleanFunction::from_truth_table(0, 4).unwrap();
796-
let annihilator = boolean_function.annihilator_inner(0).unwrap();
802+
let annihilator = boolean_function.annihilator_inner(Some(0)).unwrap();
797803
assert_eq!(annihilator.0.get_truth_table_u64(), 0xffff);
798804
assert_eq!(annihilator.1, 0);
799805
assert_eq!(annihilator.2, 1);
800806

801-
let annihilator = boolean_function.annihilator_inner(3).unwrap();
807+
let annihilator = boolean_function.annihilator_inner(Some(3)).unwrap();
802808
assert_eq!(annihilator.0.get_truth_table_u64(), 0xffff);
803809
assert_eq!(annihilator.1, 0);
804810
assert_eq!(annihilator.2, 15);
805811

806812
let boolean_function =
807813
SmallBooleanFunction::from_truth_table(0xffffffffffffffff, 6).unwrap();
808-
let annihilator = boolean_function.annihilator_inner(6);
814+
let annihilator = boolean_function.annihilator_inner(Some(6));
815+
assert!(annihilator.is_none());
816+
817+
let boolean_function =
818+
SmallBooleanFunction::from_truth_table(0xffffffffffffffff, 6).unwrap();
819+
let annihilator = boolean_function.annihilator_inner(None);
809820
assert!(annihilator.is_none());
810821

811822
let boolean_function =
812823
SmallBooleanFunction::from_truth_table(0xabcdef0123456789, 6).unwrap();
813-
let annihilator = boolean_function.annihilator_inner(2);
824+
let annihilator = boolean_function.annihilator_inner(Some(2));
814825
assert!(annihilator.is_none());
815826

816-
let annihilator = boolean_function.annihilator_inner(3);
827+
let annihilator = boolean_function.annihilator_inner(Some(3));
817828
assert_eq!(
818829
annihilator.unwrap().0.get_truth_table_u64(),
819830
0x1010101010101010
820831
);
821832
assert_eq!(annihilator.unwrap().1, 3);
822833
assert_eq!(annihilator.unwrap().2, 10);
823834

824-
let annihilator = boolean_function.annihilator_inner(4);
835+
let annihilator = boolean_function.annihilator_inner(Some(4));
825836
assert_eq!(
826837
annihilator.unwrap().0.get_truth_table_u64(),
827838
0x1010101010101010
828839
);
829840
assert_eq!(annihilator.unwrap().1, 3);
830841
assert_eq!(annihilator.unwrap().2, 25);
831842

832-
let annihilator = boolean_function.annihilator_inner(5);
843+
let annihilator = boolean_function.annihilator_inner(Some(5));
833844
assert_eq!(
834845
annihilator.unwrap().0.get_truth_table_u64(),
835846
0x1010101010101010

0 commit comments

Comments
 (0)