Skip to main content

generate

Function generate 

Source
pub fn generate(
    source: &str,
    file: &str,
    regenerate: &str,
) -> Result<Vec<Generated>, Error>
Expand description

Generates the code of every predicate defined in source.

file labels errors and is named in the header of the generated code, for instance predicates/orient3d.pred. regenerate tells how to regenerate the code, for instance the command that produced it; it is written in the header of every generated file after “To regenerate,”, one comment line per line of text. The command line tool passes the command it was run with.

For each predicate the module of its stages holds the constants of its filter and the ranges of its exact stages, and the functions filter (with one size and one uncertainty per axis when every term of the main form has the same degree in each axis, see crate::filter_form), exact_differences, expansions_translated, expansions_untranslated (only when the predicate has an #[exact] form) on stack buffers, the same two expansion forms over arena spans, expansions_translated_in and expansions_untranslated_in, which take the exact coordinates of any point type, and staged, which runs the filter and then the exact stages in the order: differences that are exact, the translated expansion form, then the #[exact] form if one is given. The order is the same for every predicate for now. A stage on the stack is emitted only when its temporaries take at most 4,096 f64; when one does not fit, staged takes an arena and runs the stage over spans of the same form in its place, on the exact coordinates of the explicit points. For points of any type that implements Point, staged_in runs filter_points, the filter with the uncertainty of the errors of the points, then exact_stages, the exact stages of staged, when every point is explicit, and otherwise exact_stages_in, the stages over spans on the exact coordinates of the points, the translated form first. The module of its checks holds exact, the main form evaluated with the exact numbers of implicit-predicates-oracle, bound_edge_cases, pairs of inputs at the edge of the error bound of the filter for explicit points, and, for a per-axis filter, uncertainty_edge_cases, the same with an uncertainty.

§Errors

Returns the first problem found in the definitions: a syntax error, a main form that is not homogeneous in differences of coordinates, a degree above the 1022 that the filter accepts, a definition too large to derive the filter bound for or to expand, an #[exact] form that is a different polynomial, a main form with more than 256 distinct subexpressions, or a predicate that the exact stages cannot support.

§Work

The checks run from the cheapest to the most expensive, and each step whose work can grow faster than the size of the definition has a budget, checked before the work it limits:

  • parse nests brackets at most 32 deep, and the difference form and the degree of the #[exact] form take one pass each;
  • crate::filter_bound keeps its exact coefficients within 2^26 bits in all;
  • crate::canonical keeps every expansion within 2^16 terms, 2^16 bits per coefficient and 2^20 units of work;
  • the exact plans reject temporaries of 2^32 components or more, or of more than 2^51 operations on the stack and 2^50 over spans, and take a few passes over the graph for each power of two they try; the plans over spans stop each pass at the first node whose bound overflows;
  • the search for the edge cases of the checks, the most expensive step per node, runs only on main forms of at most 256 distinct subexpressions, and makes at most a fixed number of exact evaluations of the form.

So the work of generate is bounded for every definition, and the slowest definitions accepted take a few seconds in a debug build, most of it in the search for the edge cases; a definition beyond a budget is rejected with an error that names the limit.