1 #include "conversion.h"
2 #include "evalue_convert.h"
3 #include "lattice_point.h"
9 static struct argp_option argp_options
[] = {
10 { "convert", 'c', 0, 0, "convert fractionals to periodics" },
11 { "combine", 'C', 0, 0 },
12 { "floor", 'f', 0, 0, "convert fractionals to floorings" },
13 { "list", 'l', 0, 0 },
14 { "range-reduction", 'R', 0, 0 },
18 static error_t
parse_opt(int key
, char *arg
, struct argp_state
*state
)
20 struct convert_options
*options
= (struct convert_options
*)state
->input
;
48 return ARGP_ERR_UNKNOWN
;
53 struct argp convert_argp
= {
54 argp_options
, parse_opt
, 0, 0
57 static int type_offset(enode
*p
)
59 return p
->type
== fractional
? 1 :
60 p
->type
== flooring
? 1 : 0;
63 static Lattice
*extract_lattice(evalue
*e
, int nparam
)
69 /* For some mysterious reason, SolveDiophantine expects an extra
70 * [0 0 0 1] row in its input matrix.
72 Matrix
*M
= Matrix_Alloc(2, nparam
+1+1);
73 value_set_si(M
->p
[1][nparam
+1], 1);
74 evalue_extract_affine(e
, M
->p
[0], M
->p
[0]+nparam
+1, M
->p
[0]+nparam
);
76 value_set_si(M
->p
[0][nparam
+1], 0);
77 SolveDiophantine(M
, &U
, &X
);
80 L
= Matrix_Alloc(nparam
+1, nparam
+1);
81 for (i
= 0; i
< nparam
; ++i
)
82 Vector_Copy(U
->p
[i
], L
->p
[i
], nparam
);
83 value_set_si(L
->p
[nparam
][nparam
], 1);
88 /* Returns a lattice such that the quasi-polynomial e can be represented
89 * by a list of polynomials, one for each point in the fundamental
90 * parallelepiped of the lattice.
91 * If e is a polynomial, then this function returns NULL.
93 static Lattice
*extract_common_lattice(evalue
*e
, Lattice
*L
, int nparam
)
97 if (value_notzero_p(e
->d
))
100 assert(e
->x
.p
->type
!= partition
);
102 if (e
->x
.p
->type
== fractional
) {
103 Lattice
*L2
= extract_lattice(&e
->x
.p
->arr
[0], nparam
);
107 Lattice
*L3
= LatticeIntersection(L
, L2
);
114 offset
= type_offset(e
->x
.p
);
115 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
116 L
= extract_common_lattice(&e
->x
.p
->arr
[i
], L
, nparam
);
120 /* Construct an evalue dst from src corresponding to the coset represented
121 * by coset, a vector of size number of parameters plus one.
122 * The final value in this vector should be 1.
124 static void evalue_coset(const evalue
*src
, const Vector
*coset
, evalue
*dst
)
126 if (value_notzero_p(src
->d
)) {
127 value_assign(dst
->d
, src
->d
);
128 value_init(dst
->x
.n
);
129 value_assign(dst
->x
.n
, src
->x
.n
);
133 if (src
->x
.p
->type
== fractional
) {
136 Vector
*c
= Vector_Alloc(coset
->Size
);
139 evalue_extract_affine(&src
->x
.p
->arr
[0], c
->p
, c
->p
+c
->Size
-1, &f
.d
);
140 Inner_Product(coset
->p
, c
->p
, c
->Size
, &f
.x
.n
);
142 mpz_fdiv_r(f
.x
.n
, f
.x
.n
, f
.d
);
144 evalue_set_si(dst
, 0, 1);
145 for (int i
= src
->x
.p
->size
-1; i
>= 1; --i
) {
148 evalue_coset(&src
->x
.p
->arr
[i
], coset
, &t
);
150 free_evalue_refs(&t
);
152 free_evalue_refs(&f
);
156 assert(src
->x
.p
->type
== polynomial
);
157 value_set_si(dst
->d
, 0);
158 dst
->x
.p
= new_enode(src
->x
.p
->type
, src
->x
.p
->size
, src
->x
.p
->pos
);
159 for (int i
= 0; i
< src
->x
.p
->size
; ++i
)
160 evalue_coset(&src
->x
.p
->arr
[i
], coset
, &dst
->x
.p
->arr
[i
]);
163 static void evalue_print_list_evalue(FILE *out
, evalue
*e
, int nparam
,
167 L
= extract_common_lattice(e
, NULL
, nparam
);
169 print_evalue(out
, e
, params
);
171 Vector
*coset
= Vector_Alloc(nparam
+1);
172 value_set_si(coset
->p
[nparam
], 1);
175 matrix2zz(L
, RT
, nparam
, nparam
);
178 lattice_point(coset
->p
, R
, vertices
, to_ulong(abs(determinant(R
))), NULL
);
180 for (int i
= 0; i
< vertices
.NumRows(); ++i
) {
182 cout
<< vertices
[i
] << endl
;
183 zz2values(vertices
[i
], coset
->p
);
185 evalue_coset(e
, coset
, &t
);
186 print_evalue(stdout
, &t
, params
);
187 free_evalue_refs(&t
);
193 static void evalue_print_list(FILE *out
, evalue
*e
, int nparam
, char **params
)
196 assert(value_zero_p(e
->d
));
197 assert(e
->x
.p
->type
== partition
);
199 for (i
= 0; i
< e
->x
.p
->size
/2; i
++) {
200 Print_Domain(out
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), params
);
201 evalue_print_list_evalue(out
, &e
->x
.p
->arr
[2*i
+1], nparam
, params
);
205 void evalue_convert(evalue
*EP
, struct convert_options
*options
, unsigned nparam
,
208 if (options
->combine
)
211 evalue_range_reduction(EP
);
213 print_evalue(stdout
, EP
, params
);
214 if (options
->floor
) {
215 fprintf(stderr
, "WARNING: floor conversion not supported\n");
216 evalue_frac2floor2(EP
, 0);
218 print_evalue(stdout
, EP
, params
);
219 } else if (options
->list
&& params
) {
220 evalue_print_list(stdout
, EP
, nparam
, params
);
221 } else if (options
->convert
) {
222 evalue_mod2table(EP
, nparam
);
224 print_evalue(stdout
, EP
, params
);