+static void addcost(double *energy, double tweight, double tcost, int pr);
+
+/*---------- main energy computation, weights, etc. ----------*/
+
+typedef double CostComputation(const Vertices vertices, int section);
+typedef void PreComputation(const Vertices vertices, int section);
+
+typedef struct {
+ double weight;
+ CostComputation *fn;
+} CostContribution;
+
+#define NPRECOMPS ((sizeof(precomps)/sizeof(precomps[0])))
+#define NCOSTS ((sizeof(costs)/sizeof(costs[0])))
+#define COST(weight, compute) { (weight),(compute) },
+
+static PreComputation *const precomps[]= {
+ compute_edge_lengths,
+ compute_vertex_areas
+};
+
+static const CostContribution costs[]= {
+
+#if XBITS==3
+#define STOP_EPSILON 1e-6
+ COST( 3e3, line_bending_cost)
+ COST( 3e3, edge_length_variation_cost)
+ COST( 0.4e3, rim_proximity_cost)
+ COST( 1e6, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.7)
+// COST( 1e1, small_triangles_cost)
+ COST( 1e12, noncircular_rim_cost)
+#endif
+
+#if XBITS==4
+#define STOP_EPSILON 1.2e-4
+ COST( 3e5, line_bending_cost)
+ COST( 10e3, edge_length_variation_cost)
+ COST( 9.0e3, rim_proximity_cost) // 5e1 is too much
+ // 2.5e1 is too little
+ // 0.2e1 grows compared to previous ?
+ // 0.6e0 shrinks compared to previous ?
+
+// COST( 1e12, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.3)
+ COST( 1e18, noncircular_rim_cost)
+#endif
+
+#if XBITS==5
+#define STOP_EPSILON 1.2e-4
+ COST( 3e7, line_bending_cost)
+ COST( 10e2, prop_edge_length_variation_cost)
+ COST( 9.0e3, rim_proximity_cost) // 5e1 is too much
+ // 2.5e1 is too little
+ // 0.2e1 grows compared to previous ?
+ // 0.6e0 shrinks compared to previous ?
+
+// COST( 1e12, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.3)
+ COST( 1e18, noncircular_rim_cost)
+#endif
+
+#if XBITS>=6 /* nonsense follows but never mind */
+#define STOP_EPSILON 1e-6
+ COST( 3e5, line_bending_cost)
+ COST( 10e2, edge_length_variation_cost)
+ COST( 9.0e1, rim_proximity_cost) // 5e1 is too much
+ // 2.5e1 is too little
+ // 0.2e1 grows compared to previous ?
+ // 0.6e0 shrinks compared to previous ?
+
+ COST( 1e12, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.3)
+ COST( 1e18, noncircular_rim_cost)
+#endif
+
+};
+
+const double edge_angle_cost_circcircrat= EDGE_ANGLE_COST_CIRCCIRCRAT;
+
+void energy_init(void) {
+ stop_epsilon= STOP_EPSILON;
+}
+
+/*---------- energy computation machinery ----------*/
+
+void compute_energy_separately(const struct Vertices *vs,
+ int section, void *energies_v, void *totals_v) {
+ double *energies= energies_v;
+ int ci;
+
+ for (ci=0; ci<NPRECOMPS; ci++) {
+ precomps[ci](vs->a, section);
+ inparallel_barrier();
+ }
+ for (ci=0; ci<NCOSTS; ci++)
+ energies[ci]= costs[ci].fn(vs->a, section);
+}