/**
 * nbrescongruents.java - 13/12/09
 * 
 * Auteur : Jean-Paul QUELEN
 * 
 * ajout de main() le 07/01/18 et modifications le 28/08/22
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.math.BigInteger;

public class nbrescongruents extends JPanel implements ActionListener {
	static final long serialVersionUID = 220828L;
	JTextField tp1 = new JTextField ("2", 10);
	JTextField tp2 = new JTextField ("2", 10);
	TextArea tableau = new TextArea (20, 80);
	BigInteger p1, p2, p, q, a, b, c, deux, S;
	JButton ok = new JButton ("Ok");

	public nbrescongruents() {
		setFont (new Font ("Arial, Helvetica, sans-serif", Font.PLAIN, 10));
		setBackground (Color.lightGray);
		setLayout (new BorderLayout());
		JPanel pn = new JPanel();
		add (pn, BorderLayout.NORTH);
		deux = new BigInteger ("2");
		pn.add (new JLabel ("p min ="));
		pn.add (tp1);
		p1 = deux;
		pn.add (new JLabel ("p max ="));
		pn.add (tp2);
		p2 = deux;
		pn.add (ok);
		ok.addActionListener (this);
		add (tableau, BorderLayout.CENTER);
	}

	private void ta (BigInteger bi) {
		tableau.append (bi.toString());
		tableau.append ("\t");
	}

// retourne "true" si bi divise bi1
	private boolean divise (BigInteger bi, BigInteger bi1) {
		return bi1.remainder(bi).compareTo (BigInteger.ZERO) == 0;
	}

	public void actionPerformed (ActionEvent evt) {
		if (evt.getSource() == ok ) {
			try {
				BigInteger pp = new BigInteger (tp1.getText());
				if (pp.compareTo (BigInteger.ONE) == 1)				// p > 1
					p1 = pp;
				else
					p1 = deux;
			}
			catch (NumberFormatException nfe) {}
			try {
				BigInteger pp = new BigInteger (tp2.getText());
				if (pp.compareTo (BigInteger.ONE) == 1)				// p > 1
					p2 = pp;
				else
					p2 = deux;
			}
			catch (NumberFormatException nfe) {}
			if (p2.compareTo (p1) == -1) {							// si p2 < p1 échange de p1 et p2
				BigInteger pp = p1;
				p1 = p2;
				p2 = pp;
			}
			tp1.setText (p1.toString());
			tp2.setText (p2.toString());
			tableau.setText ("m\tn\ta\tb\tc\tS...\n");
			BigInteger p = p1;
			while (p.compareTo (p2) <= 0) {								// p <= p2
				BigInteger q = p.subtract (BigInteger.ONE);
// p > q, p et q de parité différente et plus généralement p, q premiers entre eux
				while (q.compareTo (BigInteger.ONE) >= 0) {
					if (q.gcd(p).compareTo(BigInteger.ONE) == 0) {
						ta (p);
						ta (q);
						BigInteger pp2 = p.pow(2);
						BigInteger qp2 = q.pow(2);
						a = pp2.subtract(qp2);
						b = deux.multiply(p.multiply(q));
						c = pp2.add (qp2);
						S = a.multiply(b).divide(deux);
						ta (a);
						ta (b);
						ta (c);
						ta (S);
// retire de S tous ses diviseurs de la forme k2. On commence par 4
						BigInteger k2 = new BigInteger ("4");
						while (divise (k2, S)) {
							S = S.divide (k2);
							ta (S);
						}
// puis on continue avec les diviseurs impairs carrés
						BigInteger k = new BigInteger ("3");
						k2 = new BigInteger ("9");
						while (k2.compareTo (S) <= 0) {
							if (divise (k2, S)) {
								S = S.divide (k2);
								ta (S);
							} else {
								k = k.add (deux);
								k2 = k.pow (2);
							}
						}
						tableau.append("\n");
					}
					q = q.subtract (deux);
				}
				p = p.add (BigInteger.ONE);
			}
		}
	}

	public static void main (String args []) {
		int w = 600;
		int h = 400;

		nbrescongruents nc = new nbrescongruents();
		JFrame f = new JFrame ("Nombres congruents");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (nc);
		f.setSize (w, h);
		f.setVisible (true);
	}

}
