@@ -1869,4 +1869,148 @@ mod test {
1869
1869
assert_eq ! ( P . compress( ) , R . compress( ) ) ;
1870
1870
assert_eq ! ( Q . compress( ) , R . compress( ) ) ;
1871
1871
}
1872
+
1873
+ #[ test]
1874
+ #[ cfg( feature = "alloc" ) ]
1875
+ fn partial_precomputed_mixed_multiscalar_empty ( ) {
1876
+ let mut rng = rand:: thread_rng ( ) ;
1877
+
1878
+ let n_static = 16 ;
1879
+ let n_dynamic = 8 ;
1880
+
1881
+ let static_points = ( 0 ..n_static)
1882
+ . map ( |_| RistrettoPoint :: random ( & mut rng) )
1883
+ . collect :: < Vec < _ > > ( ) ;
1884
+
1885
+ // Use zero scalars
1886
+ let static_scalars = Vec :: new ( ) ;
1887
+
1888
+ let dynamic_points = ( 0 ..n_dynamic)
1889
+ . map ( |_| RistrettoPoint :: random ( & mut rng) )
1890
+ . collect :: < Vec < _ > > ( ) ;
1891
+
1892
+ let dynamic_scalars = ( 0 ..n_dynamic)
1893
+ . map ( |_| Scalar :: random ( & mut rng) )
1894
+ . collect :: < Vec < _ > > ( ) ;
1895
+
1896
+ // Compute the linear combination using precomputed multiscalar multiplication
1897
+ let precomputation = VartimeRistrettoPrecomputation :: new ( static_points. iter ( ) ) ;
1898
+ let result_multiscalar = precomputation. vartime_mixed_multiscalar_mul (
1899
+ & static_scalars,
1900
+ & dynamic_scalars,
1901
+ & dynamic_points,
1902
+ ) ;
1903
+
1904
+ // Compute the linear combination manually
1905
+ let mut result_manual = RistrettoPoint :: identity ( ) ;
1906
+ for i in 0 ..static_scalars. len ( ) {
1907
+ result_manual += static_points[ i] * static_scalars[ i] ;
1908
+ }
1909
+ for i in 0 ..n_dynamic {
1910
+ result_manual += dynamic_points[ i] * dynamic_scalars[ i] ;
1911
+ }
1912
+
1913
+ assert_eq ! ( result_multiscalar, result_manual) ;
1914
+ }
1915
+
1916
+ #[ test]
1917
+ #[ cfg( feature = "alloc" ) ]
1918
+ fn partial_precomputed_mixed_multiscalar ( ) {
1919
+ let mut rng = rand:: thread_rng ( ) ;
1920
+
1921
+ let n_static = 16 ;
1922
+ let n_dynamic = 8 ;
1923
+
1924
+ let static_points = ( 0 ..n_static)
1925
+ . map ( |_| RistrettoPoint :: random ( & mut rng) )
1926
+ . collect :: < Vec < _ > > ( ) ;
1927
+
1928
+ // Use one fewer scalars
1929
+ let static_scalars = ( 0 ..n_static - 1 )
1930
+ . map ( |_| Scalar :: random ( & mut rng) )
1931
+ . collect :: < Vec < _ > > ( ) ;
1932
+
1933
+ let dynamic_points = ( 0 ..n_dynamic)
1934
+ . map ( |_| RistrettoPoint :: random ( & mut rng) )
1935
+ . collect :: < Vec < _ > > ( ) ;
1936
+
1937
+ let dynamic_scalars = ( 0 ..n_dynamic)
1938
+ . map ( |_| Scalar :: random ( & mut rng) )
1939
+ . collect :: < Vec < _ > > ( ) ;
1940
+
1941
+ // Compute the linear combination using precomputed multiscalar multiplication
1942
+ let precomputation = VartimeRistrettoPrecomputation :: new ( static_points. iter ( ) ) ;
1943
+ let result_multiscalar = precomputation. vartime_mixed_multiscalar_mul (
1944
+ & static_scalars,
1945
+ & dynamic_scalars,
1946
+ & dynamic_points,
1947
+ ) ;
1948
+
1949
+ // Compute the linear combination manually
1950
+ let mut result_manual = RistrettoPoint :: identity ( ) ;
1951
+ for i in 0 ..static_scalars. len ( ) {
1952
+ result_manual += static_points[ i] * static_scalars[ i] ;
1953
+ }
1954
+ for i in 0 ..n_dynamic {
1955
+ result_manual += dynamic_points[ i] * dynamic_scalars[ i] ;
1956
+ }
1957
+
1958
+ assert_eq ! ( result_multiscalar, result_manual) ;
1959
+ }
1960
+
1961
+ #[ test]
1962
+ #[ cfg( feature = "alloc" ) ]
1963
+ fn partial_precomputed_multiscalar ( ) {
1964
+ let mut rng = rand:: thread_rng ( ) ;
1965
+
1966
+ let n_static = 16 ;
1967
+
1968
+ let static_points = ( 0 ..n_static)
1969
+ . map ( |_| RistrettoPoint :: random ( & mut rng) )
1970
+ . collect :: < Vec < _ > > ( ) ;
1971
+
1972
+ // Use one fewer scalars
1973
+ let static_scalars = ( 0 ..n_static - 1 )
1974
+ . map ( |_| Scalar :: random ( & mut rng) )
1975
+ . collect :: < Vec < _ > > ( ) ;
1976
+
1977
+ // Compute the linear combination using precomputed multiscalar multiplication
1978
+ let precomputation = VartimeRistrettoPrecomputation :: new ( static_points. iter ( ) ) ;
1979
+ let result_multiscalar = precomputation. vartime_multiscalar_mul ( & static_scalars) ;
1980
+
1981
+ // Compute the linear combination manually
1982
+ let mut result_manual = RistrettoPoint :: identity ( ) ;
1983
+ for i in 0 ..static_scalars. len ( ) {
1984
+ result_manual += static_points[ i] * static_scalars[ i] ;
1985
+ }
1986
+
1987
+ assert_eq ! ( result_multiscalar, result_manual) ;
1988
+ }
1989
+
1990
+ #[ test]
1991
+ #[ cfg( feature = "alloc" ) ]
1992
+ fn partial_precomputed_multiscalar_empty ( ) {
1993
+ let mut rng = rand:: thread_rng ( ) ;
1994
+
1995
+ let n_static = 16 ;
1996
+
1997
+ let static_points = ( 0 ..n_static)
1998
+ . map ( |_| RistrettoPoint :: random ( & mut rng) )
1999
+ . collect :: < Vec < _ > > ( ) ;
2000
+
2001
+ // Use zero scalars
2002
+ let static_scalars = Vec :: new ( ) ;
2003
+
2004
+ // Compute the linear combination using precomputed multiscalar multiplication
2005
+ let precomputation = VartimeRistrettoPrecomputation :: new ( static_points. iter ( ) ) ;
2006
+ let result_multiscalar = precomputation. vartime_multiscalar_mul ( & static_scalars) ;
2007
+
2008
+ // Compute the linear combination manually
2009
+ let mut result_manual = RistrettoPoint :: identity ( ) ;
2010
+ for i in 0 ..static_scalars. len ( ) {
2011
+ result_manual += static_points[ i] * static_scalars[ i] ;
2012
+ }
2013
+
2014
+ assert_eq ! ( result_multiscalar, result_manual) ;
2015
+ }
1872
2016
}
0 commit comments