2022-06-13 10:05:34 +00:00
|
|
|
#include "coxeter.h"
|
|
|
|
#include "enumerate.h"
|
|
|
|
#include "generators.h"
|
|
|
|
#include "mat.h"
|
|
|
|
#include "qext.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2022-06-14 12:22:22 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
2022-06-14 14:03:40 +00:00
|
|
|
#include <string.h>
|
2022-06-14 12:22:22 +00:00
|
|
|
|
|
|
|
#define LOOP(i,n) for(int i = 0; i < (n); i++)
|
2022-06-14 13:41:43 +00:00
|
|
|
#define SWAP(t,x,y) do { t _tmp = (x); (x) = (y); (y) = _tmp; } while (0);
|
2022-06-14 12:22:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Elements up to length 0: 1
|
|
|
|
Elements up to length 1: 4
|
|
|
|
Elements up to length 2: 10
|
|
|
|
Elements up to length 3: 22
|
|
|
|
Elements up to length 4: 46
|
|
|
|
Elements up to length 5: 91
|
|
|
|
Elements up to length 6: 175
|
|
|
|
Elements up to length 7: 334
|
|
|
|
Elements up to length 8: 634
|
|
|
|
Elements up to length 9: 1198
|
|
|
|
Elements up to length 10: 2260
|
|
|
|
Elements up to length 11: 4261
|
|
|
|
Elements up to length 12: 8029
|
|
|
|
Elements up to length 13: 15124
|
|
|
|
Elements up to length 14: 28486
|
|
|
|
Elements up to length 15: 53650
|
|
|
|
Elements up to length 16: 101038
|
|
|
|
Elements up to length 17: 190279
|
|
|
|
Elements up to length 18: 358339
|
|
|
|
Elements up to length 19: 674830
|
|
|
|
Elements up to length 20: 1270846
|
|
|
|
Elements up to length 21: 2393266
|
|
|
|
Elements up to length 22: 4507012
|
|
|
|
Elements up to length 23: 8487625
|
|
|
|
*/
|
|
|
|
|
|
|
|
static double gaussian_sqrt5_real(NUMBER x)
|
|
|
|
{
|
|
|
|
double result = 0.0;
|
|
|
|
|
|
|
|
mpq_t tmp;
|
|
|
|
mpq_init(tmp);
|
|
|
|
|
|
|
|
// a_0 + sqrt(5)a_1 + 4a_2 + 2sqrt(5)a_3
|
|
|
|
mpq_set_si(tmp, 4, 1);
|
|
|
|
mpq_mul(tmp, tmp, x->a[2]);
|
|
|
|
mpq_add(tmp, tmp, x->a[0]);
|
|
|
|
result = mpq_get_d(tmp);
|
|
|
|
mpq_set_si(tmp, 2, 1);
|
|
|
|
mpq_mul(tmp, tmp, x->a[3]);
|
|
|
|
mpq_add(tmp, tmp, x->a[1]);
|
|
|
|
result += mpq_get_d(tmp)*sqrt(5);
|
|
|
|
|
|
|
|
mpq_clear(tmp);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static double gaussian_sqrt5_imag(NUMBER x)
|
|
|
|
{
|
|
|
|
double result = 0.0;
|
|
|
|
|
|
|
|
mpq_t tmp;
|
|
|
|
mpq_init(tmp);
|
|
|
|
|
|
|
|
// a_1 + 2sqrt(5)a_2 + 14a_3
|
|
|
|
mpq_set_si(tmp, 14, 1);
|
|
|
|
mpq_mul(tmp, tmp, x->a[3]);
|
|
|
|
mpq_add(tmp, tmp, x->a[1]);
|
|
|
|
result = mpq_get_d(tmp);
|
|
|
|
mpq_set_si(tmp, 2, 1);
|
|
|
|
mpq_mul(tmp, tmp, x->a[2]);
|
|
|
|
result += mpq_get_d(tmp)*sqrt(5);
|
|
|
|
|
|
|
|
mpq_clear(tmp);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2022-06-13 10:05:34 +00:00
|
|
|
|
2022-06-14 14:03:40 +00:00
|
|
|
enum mode {
|
|
|
|
MODE_HELP,
|
|
|
|
MODE_TRACES,
|
|
|
|
MODE_SUMMARY,
|
|
|
|
MODE_TRACE_IDS
|
|
|
|
};
|
|
|
|
|
2022-06-13 10:05:34 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2022-06-14 12:22:22 +00:00
|
|
|
char buf[100];
|
2022-06-14 14:03:40 +00:00
|
|
|
int mode;
|
|
|
|
|
|
|
|
if(argc < 2 || strcmp(argv[1], "help") == 0)
|
|
|
|
mode = MODE_HELP;
|
|
|
|
else if(strcmp(argv[1], "traces") == 0)
|
|
|
|
mode = MODE_TRACES;
|
|
|
|
else if(strcmp(argv[1], "summary") == 0)
|
|
|
|
mode = MODE_SUMMARY;
|
|
|
|
else if(strcmp(argv[1], "trace_ids") == 0)
|
|
|
|
mode = MODE_TRACE_IDS;
|
|
|
|
else
|
|
|
|
mode = MODE_HELP;
|
|
|
|
|
|
|
|
if(mode == MODE_HELP) {
|
|
|
|
fprintf(stderr, "Usage: %s <help|traces|summary|trace_ids> [arguments]\n", argv[0]);
|
|
|
|
fprintf(stderr, "%s help display this page\n", argv[0]);
|
|
|
|
fprintf(stderr, "%s traces <n> <qreal> <qimag> enumerate group and output unique trace/trace inverse pairs\n", argv[0]);
|
|
|
|
fprintf(stderr, "%s summary <n> <qreal> <qimag> only output max slope etc.\n", argv[0]);
|
|
|
|
fprintf(stderr, "%s trace_ids <n> <qreal> <qimag> list of ids of unique traces\n", argv[0]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(argc < 5) {
|
|
|
|
fprintf(stderr, "Not enough arguments!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int n = atoi(argv[2]);
|
2022-06-14 12:22:22 +00:00
|
|
|
|
|
|
|
mpq_t qreal, qimag;
|
|
|
|
mpq_inits(qreal, qimag, NULL);
|
2022-06-14 14:03:40 +00:00
|
|
|
mpq_set_str(qreal, argv[3], 10);
|
|
|
|
mpq_set_str(qimag, argv[4], 10);
|
|
|
|
// mpq_set_si(qreal, 50, 10);
|
|
|
|
// mpq_set_si(qimag, 1, 10);
|
2022-06-14 12:22:22 +00:00
|
|
|
mpq_canonicalize(qreal);
|
|
|
|
mpq_canonicalize(qimag);
|
|
|
|
|
|
|
|
/*
|
|
|
|
int length = 0;
|
|
|
|
LOOP(i, n) {
|
|
|
|
if(group->elements[i].length > length) {
|
|
|
|
printf("Elements up to length %d: %d\n", length, i);
|
|
|
|
length = group->elements[i].length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
LOOP(i, n) {
|
|
|
|
groupelement_t *cur = &group->elements[i];
|
|
|
|
groupelement_t *other;
|
|
|
|
|
|
|
|
cur->conjugacy_class = cur; // start with itself and reduce if possible
|
|
|
|
|
|
|
|
LOOP(j, 3) {
|
|
|
|
if(cur->left[j] && cur->left[j]->right[j]) {
|
|
|
|
other = cur->left[j]->right[j];
|
|
|
|
if(other->id < cur->id)
|
|
|
|
cur->conjugacy_class = other->conjugacy_class;
|
|
|
|
}
|
|
|
|
if(cur->right[j] && cur->right[j]->left[j]) {
|
|
|
|
other = cur->right[j]->left[j];
|
|
|
|
if(other->id < cur->id)
|
|
|
|
cur->conjugacy_class = other->conjugacy_class;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
group_t *group = coxeter_init_triangle(5, 5, 5, n);
|
|
|
|
|
|
|
|
mat gen[3];
|
|
|
|
LOOP(i, 3) mat_init(gen[i], 3, QT_GAUSS_SQRT5);
|
|
|
|
generators_triangle_reflection_group_555_complex(gen, 2, 2, 2, qreal, qimag);
|
|
|
|
|
|
|
|
struct tracedata *traces;
|
|
|
|
int nuniq = enumerate_coxeter_group_traces(group, gen, &traces);
|
|
|
|
|
2022-06-14 13:41:43 +00:00
|
|
|
mps_context *solver = mps_context_new();
|
|
|
|
mps_monomial_poly *poly = mps_monomial_poly_new(solver, 3);
|
|
|
|
mps_context_set_output_prec(solver, 20); // relative precision
|
|
|
|
mps_context_set_output_goal(solver, MPS_OUTPUT_GOAL_APPROXIMATE);
|
|
|
|
|
|
|
|
double ev_real[3], ev_imag[3], ev_abs2[3];
|
|
|
|
double max_slope = 0;
|
|
|
|
int max_slope_id = 0;
|
|
|
|
|
2022-06-14 12:22:22 +00:00
|
|
|
LOOP(i, nuniq) {
|
2022-06-14 13:41:43 +00:00
|
|
|
solve_characteristic_polynomial_d(solver, poly,
|
|
|
|
gaussian_sqrt5_real(traces[i].tr),
|
|
|
|
gaussian_sqrt5_imag(traces[i].tr),
|
|
|
|
gaussian_sqrt5_real(traces[i].trinv),
|
|
|
|
gaussian_sqrt5_imag(traces[i].trinv),
|
|
|
|
ev_real, ev_imag);
|
|
|
|
|
|
|
|
LOOP(j, 3) ev_abs2[j] = ev_real[j]*ev_real[j] + ev_imag[j]*ev_imag[j];
|
|
|
|
|
|
|
|
if(fabs(ev_abs2[0]) < fabs(ev_abs2[1]))
|
|
|
|
SWAP(double, ev_abs2[0], ev_abs2[1]);
|
|
|
|
if(fabs(ev_abs2[1]) < fabs(ev_abs2[2]))
|
|
|
|
SWAP(double, ev_abs2[1], ev_abs2[2]);
|
|
|
|
if(fabs(ev_abs2[0]) < fabs(ev_abs2[1]))
|
|
|
|
SWAP(double, ev_abs2[0], ev_abs2[1]);
|
|
|
|
|
|
|
|
if(log(ev_abs2[0]) < 1e-3) // we regard this as a finite order element
|
|
|
|
continue;
|
|
|
|
|
|
|
|
double slope = - log(ev_abs2[0]) / log(ev_abs2[2]);
|
|
|
|
if(slope > max_slope) {
|
|
|
|
max_slope = slope;
|
|
|
|
max_slope_id = traces[i].id;
|
|
|
|
}
|
|
|
|
|
2022-06-14 14:03:40 +00:00
|
|
|
if(mode == MODE_TRACES) {
|
|
|
|
printf("%d %f %f %f\n",
|
|
|
|
traces[i].id, log(ev_abs2[0]), log(ev_abs2[1]), log(ev_abs2[2]));
|
|
|
|
} else if(mode == MODE_TRACE_IDS) {
|
|
|
|
printf("%d\n", traces[i].id);
|
|
|
|
}
|
2022-06-14 12:22:22 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 13:41:43 +00:00
|
|
|
coxeter_snprint(buf, sizeof(buf), &group->elements[max_slope_id]);
|
2022-06-14 14:03:40 +00:00
|
|
|
|
|
|
|
if(mode == MODE_SUMMARY) {
|
|
|
|
gmp_fprintf(stdout, "%f %f %d %d %f %s\n", mpq_get_d(qreal), mpq_get_d(qimag), n, nuniq, max_slope, buf);
|
|
|
|
} else {
|
|
|
|
gmp_fprintf(stderr, "q = %Qd + i*%Qd\tElements: %d\tTraces: %d\tMaximal slope: %f at %s\n", qreal, qimag, n, nuniq, max_slope, buf);
|
|
|
|
}
|
2022-06-14 13:41:43 +00:00
|
|
|
|
|
|
|
mps_monomial_poly_free(solver, MPS_POLYNOMIAL(poly));
|
|
|
|
mps_context_free(solver);
|
2022-06-14 12:22:22 +00:00
|
|
|
enumerate_tracedata_clear(traces, nuniq);
|
|
|
|
LOOP(i, 3) mat_clear(gen[i]);
|
|
|
|
coxeter_clear(group);
|
|
|
|
mpq_clears(qreal, qimag, NULL);
|
|
|
|
|
2022-06-13 10:05:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|