proofs revision 5f19756f48574526dda8abedebf811c9d1456e80
25cf1a301a396c38e8adf52c15f537b80d2483f7jlThis file contains some loose proofs of a few properties. It's somewhat
25cf1a301a396c38e8adf52c15f537b80d2483f7jlad-hoc. At least it gives an indication of what assert/g_assert calls have
25cf1a301a396c38e8adf52c15f537b80d2483f7jlbeen checked by a developer. If an assertion does trigger, then this file may
25cf1a301a396c38e8adf52c15f537b80d2483f7jlhelp in debugging that assertion failure.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlIt's currently ordered by caller.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl(Re-ordering to avoid forward references in proofs might be a good idea,
25cf1a301a396c38e8adf52c15f537b80d2483f7jlthough this would in some cases require splitting up the proofs for a routine,
25cf1a301a396c38e8adf52c15f537b80d2483f7jle.g. proving preconditions of g called from f, then proving g's postcondition,
25cf1a301a396c38e8adf52c15f537b80d2483f7jlthen using that to prove something else in f again. Furthermore it may not
25cf1a301a396c38e8adf52c15f537b80d2483f7jleven be possible to avoid forward references for recursive/looping code.)
25cf1a301a396c38e8adf52c15f537b80d2483f7jlVery loose proof of !sp_curve_empty (pc->red_curve) assertion:
25cf1a301a396c38e8adf52c15f537b80d2483f7jlfit_and_split is called successively with its input varying only by appending a point.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlFor the n_segs > 0 && unsigned(pc->npoints) < G_N_ELEMENTS(pc->p) condition to fail,
25cf1a301a396c38e8adf52c15f537b80d2483f7jlwe must have at least 3 distinct points, which means that a previous call had 2 distinct points,
25cf1a301a396c38e8adf52c15f537b80d2483f7jlin which case we'd have filled in pc->red_curve to a non-empty curve.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlExpansion of the above claim of at least 3 distinct points: We know n_segs <= 0 ||
25cf1a301a396c38e8adf52c15f537b80d2483f7jlunsigned(dc->npoints) >= G_N_ELEMENTS(pc->p) from the negation of the containing `if' condition.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlG_N_ELEMENTS(pc->p) is greater than 3 (in int arithmetic), from PencilTool::p array definition
25cf1a301a396c38e8adf52c15f537b80d2483f7jlin pencil-context.h. npoints grows by no more than one per fit_and_split invocation; we should be
25cf1a301a396c38e8adf52c15f537b80d2483f7jlable to establish that dc->npoints == G_N_ELEMENTS(pc->p) if unsigned(dc->npoints) >=
25cf1a301a396c38e8adf52c15f537b80d2483f7jlG_N_ELEMENTS(pc->p), in which case 3 <= dc->npoints in int arithmetic. We know that dc->npoints >=
25cf1a301a396c38e8adf52c15f537b80d2483f7jl2 from assertion at head of fit_and_split; in which case if n_segs <= 0 then fit_and_split has
25cf1a301a396c38e8adf52c15f537b80d2483f7jlfailed, which implies that dc->npoints > 2 (since the fitter can always exactly fit 2 points,
25cf1a301a396c38e8adf52c15f537b80d2483f7jli.e. it never fails if npoints == 2; TODO: add sp_bezier_fit_cubic postcondition for this).
25cf1a301a396c38e8adf52c15f537b80d2483f7jlProof of precondition: The only caller is spdc_add_freehand_point (by
25cf1a301a396c38e8adf52c15f537b80d2483f7jltextual search in that file, and staticness). See proof for that
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsrc/pencil-context.cpp:spdc_add_freehand_point
25cf1a301a396c38e8adf52c15f537b80d2483f7jlProof of fit_and_split `pc->npoints > 1' requirement:
25cf1a301a396c38e8adf52c15f537b80d2483f7jlIt initially unconditionally asserts `pc->npoints > 0'. There are no function calls or modifications
25cf1a301a396c38e8adf52c15f537b80d2483f7jlof pc or pc->npoints other than incrementing pc->npoints after that assertion.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlWe assume that integer overflow doesn't occur during that increment,
25cf1a301a396c38e8adf52c15f537b80d2483f7jlso we get pc->npoints > 1.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsrc/pencil-context.cpp:spdc_set_endpoint
25cf1a301a396c38e8adf52c15f537b80d2483f7jlVery loose proof of npoints > 0: Should be preceded by spdc_set_startpoint(pc) according to state
25cf1a301a396c38e8adf52c15f537b80d2483f7jltransitions. spdc_set_startpoint sets pc->npoints to 0 (handled at beginning of function) or 1.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsrc/display/bezier-utils.cpp:compute_max_error
25cf1a301a396c38e8adf52c15f537b80d2483f7jlProof of postcondition: *splitPoint is set only from i, which goes from 1 to less than last.
25cf1a301a396c38e8adf52c15f537b80d2483f7jli isn't written to in the loop body: only uses are indexing built-in arrays d and u
25cf1a301a396c38e8adf52c15f537b80d2483f7jl(and RHS of assignment).
25cf1a301a396c38e8adf52c15f537b80d2483f7jlsrc/display/bezier-utils.cpp:sp_bezier_fit_cubic_full
25cf1a301a396c38e8adf52c15f537b80d2483f7jlProof of `nsegs1 != 0' assertion: nsegs1 is const. Have already
25cf1a301a396c38e8adf52c15f537b80d2483f7jlreturned in the (nsegs1 < 0) case, so !(nsegs1 < 0), i.e. nsegs1 >= 0
25cf1a301a396c38e8adf52c15f537b80d2483f7jl(given that nsegs1 is gint). nsegs1 is set to
splitPoint would have been set s.t. 0 < splitPoint. splitPoint is not
more formal in use of inductive proof (e.g. clearly stating what the
exact arithmetic): nsegs1 + nsegs2 <= len - 1, i.e. nsegs1 + nsegs2 <
src/display/bezier-utils.cpp:sp_darray_right_tangent(Point const[], unsigned)
src/display/bezier-utils.cpp:sp_darray_right_tangent(Point const[], unsigned, double)
src/extension/internal/ps.cpp:PrintPS::print_fill_style:
g_return_if_fail( style->fill.type == SP_PAINT_TYPE_COLOR
|| ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
rgrep print_fill_style reveals no callers in any other files. There are two calls in ps.cpp, both
g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
The g_return_if_fail(style->fill.type == SP_PAINT_TYPE_COLOR
|| ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
style->fill.type == SP_PAINT_TYPE_COLOR, and style is a const pointer to const, so it's likely that
src/extensions/internal/ps.cpp:PrintPS::fill:
g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
Each is in the `else' branch of a test for `style->fill.type == SP_PAINT_TYPE_COLOR',
( style->fill.type == SP_PAINT_TYPE_COLOR
|| ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
src/seltrans.cpp:sp_sel_trans_update_handles
sp_show_handles requirements: !arg1.empty.
Before any call to sp_show_handles is a test `if (... || seltrans.empty) { ...; return; }'
seltrans is a reference. There are no calls between that failing seltrans.empty test
src/seltrans.cpp:sp_show_handles
sp_show_handles is static. Searching reveals calls only in sp_sel_trans_update_handles (proof above).
src/sp-spiral.cpp:sp_spiral_fit_and_draw
Proof of unconditionalness: Not inside if/for/while. No previous `return'.
src/sp-spiral.cpp:sp_spiral_set_shape
src/style.cpp:sp_css_attr_from_style:
src/style.cpp:sp_css_attr_from_object
$ grep sp_css_attr_from_object `sed 's,#.*,,' make.files `
file.cpp: SPCSSAttr *style = sp_css_attr_from_object (SP_DOCUMENT_ROOT (doc));
selection-chemistry.cpp: SPCSSAttr *css = sp_css_attr_from_object (SP_OBJECT(item), SP_STYLE_FLAG_ALWAYS);
selection-chemistry.cpp: SPCSSAttr *temp = sp_css_attr_from_object (last_element, SP_STYLE_FLAG_IFSET);
style.cpp:sp_css_attr_from_object (SPObject *object, guint flags)
style.h:SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint flags = SP_STYLE_FLAG_IFSET);
src/style.cpp:sp_css_attr_from_style
$ grep sp_css_attr_from_style `sed 's,#.*,,' make.files `
selection-chemistry.cpp: SPCSSAttr *css = sp_css_attr_from_style (query, SP_STYLE_FLAG_ALWAYS);
style.cpp:sp_css_attr_from_style (SPStyle const *const style, guint flags)
style.cpp: return sp_css_attr_from_style (style, flags);
style.h:SPCSSAttr *sp_css_attr_from_style (SPStyle const *const style, guint flags);
selection-chemistry.cpp caller: query is initialized from sp_style_new()
style.cpp caller: preceded by explicit test for NULL:
$ grep -B2 sp_css_attr_from_style style.cpp|tail -3