// ptest.cc -- test program for arith functions
//////////////////////////////////////////////////////////////////////////
//
// Copyright 1990-2026 John Cremona
// 
// This file is part of the eclib package.
// 
// eclib is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
// 
// eclib is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// 
// You should have received a copy of the GNU General Public License
// along with eclib; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
// 
//////////////////////////////////////////////////////////////////////////
 
#include <eclib/arith.h>

int main()
{
 long n, p;

 cout<<"Initialized table of " << nprimes() << " primes, up to "<<maxprime() << endl;

 cout<<"Enter an index: ";  cin >> n;
 p=prime_number(n);  cout << "prime_number("<<n<<") = "<<p<<endl;

 cout<<"How many primes do you want to see (as a vector<long>)? ";  cin >> n;
 vector<long> plist=primes(n);
 cout << plist << endl;

 cout<<"Enter a number to see if it is that list: "; cin>>p;
 auto pi=find(plist.begin(),plist.end(),p);
 if(pi==plist.end()) cout<<"NOT in the list"<<endl;
 else    cout<<p<<" is list item "<<(pi-plist.begin())<<" (counting from 0)"<<endl;

 long x = 5*11*31;
 cout << "First 10 primes coprime to " << x << " = 5*11*31: "
      << the_primes.getfirst(10,x) << endl;

 vector<long> v(10);
 iota(v.begin(),v.end(),1);
 cout<<"iota(10): "<<v<<endl;

 n=2310*210*64*17;
 cout<<"n = "<<n<<endl;

 vector<long> exps(plist.size());
 transform(plist.begin(),plist.end(),
           exps.begin(),
           [n](long p) {return val(p,n);}
           );

 cout<<"exps = "<<exps<<endl;

 vector<long> plist1=primes(10);
 cout<<"Comparing previous prime list with "<<plist1<<endl;;
 cout<<"First starts with second, 10 items from 0: "<<startswith(plist,plist1,10)<<endl;
 cout<<"First starts with second,  5 items from 5: "<<startswith(plist,plist1,5,5)<<endl;
 cout<<"Second starts with first, 10 items from 0: "<<startswith(plist1,plist,10)<<endl;
 cout<<"Second starts with first,  5 items from 5: "<<startswith(plist1,plist,5,5)<<endl;

 //initialize a prime iterator for n primes
 cout<<"How many primes do you want to see (one by one)? ";  cin >> n;
 for(primevar pr(n); pr.ok(); pr++)
   cout << "Prime number " << pr.index() << " = " << pr << endl;

 long m;
 while (cout << "\nEnter an integer m (0 to stop): ", cin >> m, m!=0) 
   {
     cout << "Smallest prime factor of " << m << " is " << primdiv(m) << endl;
     plist=pdivs(m);
     cout << "m has " << plist.size() << " prime divisors: " << plist << endl;
     cout << "with exponents: "; 
     for( const auto& pri : plist)
       cout << pri <<":"<<val(pri,m) << "\t";
     cout<<endl;

     vector<long> dlist=alldivs(m,plist);
     cout << "m has " << dlist.size() << " divisors: " << dlist << endl;
     dlist = posdivs(m,plist);
     cout << "m has " << dlist.size() 
          << " positive divisors: " << dlist << endl;
     dlist = sqdivs(m,plist);
     cout << "m has " << dlist.size() 
          << " positive divisors whose square divides m: " << dlist << endl;
     dlist = sqfreedivs(m,plist);
     cout << "m has " << dlist.size() 
          << " positive square-free divisors: " << dlist << endl;
 }

 long a,b;
 int cont=1;
 while(cont)
   {
     cout<<"Enter integers a b (0 0 to stop): ";
     cin>>a>>b;
     long g=gcd(a,b);
     if(g==0) cont=0;
     else
       {
	 cout<<"gcd = "<<g<<endl;
	 long l=lcm(a,b);
	 cout<<"lcm = "<<l<<endl;
       }
   }
 cout << endl;

 int dim = 3;
 int bound = 2;
 vector<vector<int>> combos = all_linear_combinations(dim, bound, 1); // sorted
 cout << "All " << combos.size() << " linear combinations (up to sign) of length " << dim
      << " with coefficients bounded by " << bound << " (sorted)"
      << endl;
 for (auto combo: combos) cout << combo <<endl;

 BoundedWeightVectorGenerator combo_generator(dim, bound);
 int ncombos = 0;
 cout << "All linear combinations (up to sign) of length " << dim
      << " with coefficients bounded by " << bound << " (generated one by one)"
      << endl;
 while (!combo_generator.at_last())
   {
     vector<int> vec = combo_generator.next();
     if (combo_generator.at_last())
       break;
     cout << vec << endl;
     ncombos++;
   }
 if (ncombos!=combos.size())
   cout << "Error: sequential generator computes " << ncombos
        << " vectors, but static generator computes " << combos.size() << endl;
}  /* main() */
