11 #define MAX_SUPPORTED_EDGE_NUM (((size_t) -1) >> 2)
12 #define MAX_SUPPORTED_VERTEX_NUM (((size_t) -1) >> 2)
14 /* Primes for reducing fractions */
15 static uint32_t primes
[] = {
17 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
18 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
19 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
20 227, 229, 233, 239, 241, 251
23 /* Attempt to store a fraction in out, reducing if possible */
24 static int reduce_fraction(int_fast32_t n
, uint_fast32_t d
, struct
25 rational
*out
, const char **out_errstr
)
30 for (j
= 0; j
< ((sizeof primes
) / (sizeof primes
[0])); ++j
) {
45 if (n
> INT_FAST8_MAX
||
48 IF_NZ_SET(out_errstr
, L("unrepresentable fraction"));
53 *out
= (struct rational
) { .p
= n
, .q
= d
};
58 /* Directly increment e's multiplicity */
59 static int add_edge_mult(struct edge
*e
, int_fast16_t twice_mult
, const
62 int32_t n
= twice_mult
* e
->weight
.q
+ e
->weight
.p
* 2;
63 uint32_t d
= e
->weight
.q
* 2;
65 return reduce_fraction(n
, d
, &e
->weight
, out_errstr
);
68 /* Increment e_{ij} by twice_mult / 2 */
69 int quiver_add_edge(struct quiver
*q
, size_t i
, size_t j
, int_fast16_t
70 twice_mult
, const char **out_errstr
)
79 IF_NZ_SET(out_errstr
, L("nonexistant quiver"));
84 if (i
>= q
->vertices_num
||
85 j
>= q
->vertices_num
) {
86 IF_NZ_SET(out_errstr
, L("edge includes nonexistant vertex"));
91 for (k
= 0; k
< q
->edges_num
; ++k
) {
96 return add_edge_mult(e
, twice_mult
, out_errstr
);
101 return add_edge_mult(e
, -1 * twice_mult
, out_errstr
);
105 if (q
->edges_num
+ 1 >= q
->edges_len
) {
106 if (q
->edges_num
+ 1 >= MAX_SUPPORTED_EDGE_NUM
) {
107 IF_NZ_SET(out_errstr
, L("too many edges"));
112 if (!(newmem
= realloc(q
->edges
, (q
->edges_len
+ 8) *
113 sizeof *(q
->edges
)))) {
115 IF_NZ_SET(out_errstr
, L("realloc"));
124 q
->edges
[q
->edges_num
] = (struct edge
) { .i
= i
, .j
= j
};
125 ret
= reduce_fraction(twice_mult
, 2, &(q
->edges
[q
->edges_num
].weight
),
135 /* Add a vertex with a name and weight */
136 int quiver_add_vertex(struct quiver
*q
, size_t *out_i
, const char *name
,
137 uint_fast16_t fatness
, const char **out_errstr
)
141 size_t l
= strlen(name
);
145 IF_NZ_SET(out_errstr
, L("invalid quiver"));
150 if (!(newname
= malloc(l
+ 1))) {
152 IF_NZ_SET(out_errstr
, L("malloc"));
157 if (q
->vertices_num
+ 1 >= q
->vertices_len
) {
158 if (q
->vertices_num
+ 1 >= MAX_SUPPORTED_VERTEX_NUM
) {
159 IF_NZ_SET(out_errstr
, L("too many vertices"));
164 if (!(newmem
= realloc(q
->vertices
, (q
->vertices_len
+ 8) *
165 sizeof *(q
->vertices
)))) {
167 IF_NZ_SET(out_errstr
, L("realloc"));
172 q
->vertices
= newmem
;
173 q
->vertices_len
+= 8;
176 q
->vertices
[q
->vertices_num
] = (struct vertex
) { .name
= newname
,
177 .fatness
= fatness
};
178 *out_i
= q
->vertices_num
;
184 int quiver_mutate(struct quiver
*q
, size_t k
, const char **out_errstr
)
192 IF_NZ_SET(out_errstr
, L("invalid quiver"));
197 for (s
= 0; s
< q
->edges_len
; ++s
) {
202 st
= es
->twice_weight
;
204 for (t
= 0; t
< s
; ++t
) {
205 if (q
->edges
[t
].i
== k
||
206 q
->edges
[t
].j
== k
) {