@@ -1766,6 +1766,7 @@ void walk_v(t_level *cur_level, mpz_t start) {
1766
1766
fail ("TODO: walk_v.end > 2^64" );
1767
1767
}
1768
1768
1769
+ /* test the case where v_i has all divisors accounted for */
1769
1770
void walk_1 (t_level * cur_level , uint vi ) {
1770
1771
#ifdef SQONLY
1771
1772
if (!cur_level -> have_square )
@@ -1836,6 +1837,101 @@ void walk_1(t_level *cur_level, uint vi) {
1836
1837
return ;
1837
1838
}
1838
1839
1840
+ /* test a set of cases where v_i will have all divisors accounted for */
1841
+ void walk_1_set (t_level * cur_level , uint vi , ulong plow , ulong phigh , uint x ) {
1842
+ #ifdef SQONLY
1843
+ if (!cur_level -> have_square )
1844
+ return ;
1845
+ #endif
1846
+ if (minp && cur_level -> maxp <= minp )
1847
+ plow = minp ;
1848
+
1849
+ uint t [k ];
1850
+ uint need_prime [k ];
1851
+ uint need_square [k ];
1852
+ uint need_other [k ];
1853
+ uint npc = 0 , nqc = 0 , noc = 0 ;
1854
+ for (uint vj = 0 ; vj < k ; ++ vj ) {
1855
+ if (vi == vj )
1856
+ continue ;
1857
+ t_value * vjp = & value [vj ];
1858
+ t_allocation * ajp = (vjp -> vlevel ) ? & vjp -> alloc [vjp -> vlevel - 1 ] : NULL ;
1859
+ t [vj ] = ajp ? ajp -> t : n ;
1860
+ if (t [vj ] == 1 )
1861
+ fail ("should never see multiple values with t==1" );
1862
+ if (t [vj ] == 2 )
1863
+ need_prime [npc ++ ] = vj ;
1864
+ else if (t [vj ] & 1 )
1865
+ need_prime [npc ++ ] = vj ;
1866
+ else
1867
+ need_other [noc ++ ] = vj ;
1868
+ }
1869
+
1870
+ level_setp (cur_level , plow );
1871
+ t_value * vip = & value [vi ];
1872
+ t_allocation * aip = vip -> vlevel ? & vip -> alloc [vip -> vlevel - 1 ] : NULL ;
1873
+ while (1 ) {
1874
+ ulong p = prime_iterator_next (& cur_level -> piter );
1875
+ if (p > phigh )
1876
+ break ;
1877
+ if (need_work ) {
1878
+ /* temporarily make this prime power visible to diag code */
1879
+ t_allocation * a2ip = & vip -> alloc [vip -> vlevel ++ ];
1880
+ a2ip -> p = p ;
1881
+ a2ip -> x = x ;
1882
+ diag_plain ();
1883
+ -- vip -> vlevel ;
1884
+ }
1885
+ mpz_ui_pow_ui (Z (w1_v ), p , x - 1 );
1886
+ if (aip )
1887
+ mpz_mul (Z (w1_v ), Z (w1_v ), aip -> q );
1888
+ mpz_sub_ui (Z (w1_v ), Z (w1_v ), TYPE_OFFSET (vi ));
1889
+
1890
+ if (mpz_cmp (Z (w1_v ), min ) < 0 )
1891
+ break ;
1892
+ ++ countw ;
1893
+
1894
+ for (uint vj = 0 ; vj < k ; ++ vj ) {
1895
+ t_value * vjp = & value [vj ];
1896
+ t_allocation * ajp = (vjp -> vlevel ) ? & vjp -> alloc [vjp -> vlevel - 1 ]
1897
+ : NULL ;
1898
+ mpz_add_ui (Z (w1_j ), Z (w1_v ), TYPE_OFFSET (vj ));
1899
+ if (ajp ) {
1900
+ mpz_fdiv_qr (Z (w1_j ), Z (w1_r ), Z (w1_j ), ajp -> q );
1901
+ if (mpz_sgn (Z (w1_r )) != 0 )
1902
+ goto reject_this_one ;
1903
+ mpz_gcd (Z (w1_r ), Z (w1_j ), ajp -> q );
1904
+ if (mpz_cmp (Z (w1_r ), Z (zone )) != 0 )
1905
+ goto reject_this_one ;
1906
+ }
1907
+ mpz_set (wv_o [vj ], Z (w1_j ));
1908
+ }
1909
+ ++ countwi ;
1910
+ for (uint i = 0 ; i < npc ; ++ i )
1911
+ if (!_GMP_is_prob_prime (wv_o [need_prime [i ]]))
1912
+ goto reject_this_one ;
1913
+ for (uint i = 0 ; i < nqc ; ++ i )
1914
+ if (!is_taux (wv_o [need_square [i ]], t [need_square [i ]], 1 ))
1915
+ goto reject_this_one ;
1916
+ oc_t = t ;
1917
+ qsort (need_other , noc , sizeof (uint ), & other_comparator );
1918
+ #ifdef PARALLEL
1919
+ if (!test_1multi (need_other , noc , t ))
1920
+ goto reject_this_one ;
1921
+ #else
1922
+ for (uint i = 0 ; i < noc ; ++ i )
1923
+ if (!is_taux (wv_o [need_other [i ]], t [need_other [i ]], 1 ))
1924
+ goto reject_this_one ;
1925
+ #endif
1926
+ candidate (Z (w1_v ));
1927
+ if (improve_max )
1928
+ return ;
1929
+ reject_this_one :
1930
+ ;
1931
+ }
1932
+ return ;
1933
+ }
1934
+
1839
1935
/* When some v_j is known to be of the form m.z^g, we keep a running set
1840
1936
* of possible values of z: z == ((rq + i)/q_j)^{ 1/g } mod aq/q_j.
1841
1937
* If no such residues exist, this returns FALSE to signal that this
@@ -2878,6 +2974,11 @@ e_pux prep_unforced_x(t_level *prev, t_level *cur, ulong p, bool forced) {
2878
2974
return PUX_ALL_DONE ;
2879
2975
} else if (limp < p + 1 )
2880
2976
return PUX_SKIP_THIS_X ; /* nothing to do here */
2977
+ if (nextt == 1 ) {
2978
+ walk_1_set (cur , vi , p , limp , x );
2979
+ return PUX_SKIP_THIS_X ;
2980
+ }
2981
+
2881
2982
mpz_add_ui (Z (r_walk ), max , vi );
2882
2983
#ifdef LARGE_MIN
2883
2984
mpz_sub (Z (r_walk ), Z (r_walk ), min );
0 commit comments