Skip to content
Colin B. Macdonald edited this page Nov 7, 2018 · 15 revisions

Octave-Forge Symbolic Package Development Guide

Development Philosophy

  • In general, we want to be a thin layer on top of SymPy.
    • We prefer fixing upstream SymPy than hacking our own solutions (E.g., fourier/laplace transforms).
    • We prefer to follow the design choices of upstream SymPy.
  • When reasonable, we want to maintain high-level compatibility with Mathworks' Symbolic Math Toolbox ("SMT").
    • E.g., we use x = sym('x') whereas SymPy would probably be x = S('x').
    • E.g., we implement vpa() and syms.
  • When reasonable, we want things to behave the way an Octave user experienced with doubles would expect.
    • E.g., the * and .* methods.
    • E.g., A + 1 broadcasts the 1 to be the same shape as matrix A.

Adding new functions / designing interfaces / etc

  • See "Philosophy" above.
  • Do it like either SymPy or SMT or core Octave. Don't invent a new way. Unless you've thought very carefully about it.
  • Can you fix SymPy instead of making the change here?
  • Consider carefully the future maintenance cost of diverging from SymPy.
  • Consider write expensive code in python because its faster than Octave/Matlab.
  • Avoid use mpmath directly, unless the function is in @double/.

Testing

We have two testing frameworks:

  1. regular %! Octave tests.
    • Every function should have at least one of these.
    • They should pass on the currently supported Octave and SymPy combinations.
    • Tests that will pass on future SymPy or Octave releases can be marked with xtest and a comment.
    • Ideally, they would pass when OctSymPy is running on Matlab as well (although this is currently harder to test).
  2. doctests.
    • pkg install -forge doctest
    • These only need to pass on one version of SymPy and Octave (see the .travis.xml file).

Sending changes

We very much welcome contributions. Send a pull request (aka "merge request"). There are various guides for how to do this: the SymPy Development Workflow is very good.

If you don't want to use Github, we also accept .patch files: submit those to the patch tracker at https://savannah.gnu.org/projects/octave.

Both types of tests mentioned above are run by a continuous integration service. If you make changes, in most cases the tests will need to pass before merging your work to master.

Coding Style

Some ideas about the style we use in this code:

  • no tabs (there may be some b/c I've been sloppy in the past).
  • 1-space indent for Octave code in documentation, doctests and tests.
  • 2-spaces indent for Octave code.
  • 4-spaces indent for Octave doctests results.
  • 4-spaces indent for Python code.
  • 4-spaces indent for Python code, even when embedded inside strings within Octave code.
  • In comparison operators use spaces in both sides A == B or A = B.
  • Use space between , and ; with the next expression, [1, 2; 3, 4].
  • Between the documentation and the code, and the code to the tests must be a separation of two new lines.
  • In test try use doubleinstead of vpa.
  • New code should use GNU Octave style fcn_call (arg1, arg2) (with a space), but indexing should not have a space. There are exceptions:
    • inside square brackets this space may cause a parse error: e.g., `[myfcn(1); sym(7)]
    • currently, we recommend no spaces with the sym() command, that is sym(7) not sym (7). No particularly good reason so this could change.

Other good practice

Its not essential but each commit should be reasonably self-contained. If you want to clean up parts of the code, do that in a separate commit. This should not be an excuse to exercise our OCD.

Ideally, each pull request should do one small self-contained change. We all have limited time and this will help the review process go much faster.