1. 24 Nov, 2017 2 commits
    • Jason Rhinelander's avatar
      New right/tolerance argument syntax; remove domain_t deduction · 6a75e5f5
      Jason Rhinelander authored
      This changes the `right` and `tolerance` argument into more complex
      objects that allow both a literal, or special objects returned by
      `search_right()`, `absolute_tolerance(.001)`, or
      This allows the much more descriptive syntax:
          constrained_maximum_search(f, 0, search_right(), relative_tolerance(.001))
      This also reintroduces the ability to specify an absolute tolerance
      level, which was there once (as a separate argument) but got lost along
      the way.
      This commit also changes the `domain_t` argument to be no longer
      deduced.  Previously it was deduced from `left`, which would have made
      the above example rather broken: `domain_t` would have been `int` (from
      the 0) rather than `double` (which would require 0.0).  Overriding
      `domain_t` now requires an explicitly template parameter:
          constrained_maximum_search<float>(f, 0, search_right(), relative_tolerance(.001))
    • Jason Rhinelander's avatar
      Made readLock/writeLock arguments more generic · 512cdae1
      Jason Rhinelander authored
      This allows readLock/writeLock to take any number of arguments, where
      each argument can be a container or a member.  Previously you could
      pass a single container, or any number of members, but not combinations
      of both or multiple containers.
  2. 13 Nov, 2017 4 commits
    • Jason Rhinelander's avatar
      Add output stream support for members · 7c5fb975
      Jason Rhinelander authored
      This outputs something like `Member[n]` or `Firm[n]`, and can be
      overridden on a per-subclass basis.  It also works for shared members
      and weak members.
    • Jason Rhinelander's avatar
      Dedent various header classes · 708abdc0
      Jason Rhinelander authored
      No code changes: just removing extra class body indentation and comment
      rewrapping.  Applies to:
      There are still more left, but these in particular are changed in the
      subsequent commit.
    • Jason Rhinelander's avatar
      range(): accept (code-wise) iterator pair · bba1a1d1
      Jason Rhinelander authored
      Previously `eris::range(...)` only accepted a `std::pair` argument.
      This commit adds support for also accepting a code-wise pair (e.g.
      `eris::range(it1, it2)`).
    • Jason Rhinelander's avatar
      constrained_maximum_search fixes · 642f7423
      Jason Rhinelander authored
      - Specifying NaN for automatic `right` selection resulted in an infinite
        loop when `left` was 0.  Changed to start searching at 1.0 when that
      - The `constrained_minimum_search` didn't implement automatic `right`
        selection; fixed.
      - Minor tweaks to calculation to avoid promotion to double; the main
        change was introducing a `half()` function to handle division by 2
        without resorting to actual division for floating points while still
        working for non-floating point domain types.
      - Fixed a typo in the static_assert for a `bool` return type in
  3. 31 Oct, 2017 5 commits
    • Jason Rhinelander's avatar
      Clarify time_t/id_t ambiguity · a8320ac6
      Jason Rhinelander authored
      `using namespace eris;` from within a namespace doesn't resolve the
      ambiguity for `time_t`/`id_t` -- they need an explicit symbol import, or
      full qualification.
    • Jason Rhinelander's avatar
      single_peak_search - better argument type handling · 779a7ae2
      Jason Rhinelander authored
      The previous change to single_peak_search which deduced the domain type
      from the arguments was pretty undesirable: if you specified both left
      and right as integers, you'd get a search over the integer domain.
      This removes the type deduction, instead using an optional template
      parameter which defaults to double and isn't deduced, thus allowing
      custom types to be used, but falling back to double if not specified.
      This also fixes the test code to remove the tests that specified both
      relative and absolute tolerances (the latter was removed).
    • Jason Rhinelander's avatar
      Small bundle print optimization · c74adfec
      Jason Rhinelander authored
      Using a `std::set` to sort is typically less efficient than building a
      vector then sorting it (once).
    • Jason Rhinelander's avatar
      De-prefix eris_id_t and eris_time_t · 4d881c7e
      Jason Rhinelander authored
      This lets external code use `eris::id_t` and `eris::time_t` which is
      far nicer than `eris::eris_id_t`.
      The existing `eris_id_t` and `eris_time_t` are kept as deprecated
      aliases for the new ones.
    • Jason Rhinelander's avatar
      Fix WeakMember assignment operators · e197b4ff
      Jason Rhinelander authored
      The operators weren't returning `*this`; this somehow magically worked
      properly under gcc; clang noticed and generated an illegal instruction.
  4. 28 Oct, 2017 2 commits
  5. 21 Aug, 2017 2 commits
    • Jason Rhinelander's avatar
      Allow `constrained_maximum_search` to find `right` · 83b09164
      Jason Rhinelander authored
      This adds support for automatically finding `right` based on `left`: if
      `right` is given as NaN, a search starts at `2*left` (if `left`
      positive) or `-left` (if `left` negative) and continuously doubles the
      potential `right` value until a constraint-violating value is found;
      this then forms the RHS limit.
    • Jason Rhinelander's avatar
      Fix pair; implement tuple; deprotect load/store · c6a2a2b7
      Jason Rhinelander authored
      - std::pair was missing a load_from/store_to implementation
      - reimplemented std::pair support as std::tuple support, with std::pair
        being just a specialization of the tuple serializer.
      - De-protected load_from/store_to; they require friend classes all over
        the place because they aren't really "protected".
      - remove serializer.cpp in favour of just inlining its three small
        functions in the .hpp.
  6. 06 Aug, 2017 2 commits
    • Jason Rhinelander's avatar
      algorithms: add a constrained_{max,min}imum_search · 33e11b3a
      Jason Rhinelander authored
      This lets you numerically find the largest or smallest value satisfying
      some condition.
      For example, to determine the highest price that has at least `x` sales:
          auto quantity_demanded = [](double p) { return (int)(99 - 2*p); };
          int x = 10;
          double min = 0.0, max = 100.0;
          auto r = eris::constrained_maximum_search(
              [&](double p) { return quantity_demanded(p) >= x; },
              min, max, 0 /* maximum precision */);
          std::cout << std::setprecision(16) << "p = " << r.arg << "\n";
          // p = 44.5
      With less precision for `tol_rel` (e.g. the default, 1e-10) you'll
      generally get some number slightly smaller than 44.5.
    • Jason Rhinelander's avatar
      Make single_peak_search templated; remove abs_tol · 2bf6d8d3
      Jason Rhinelander authored
      This makes single_peak_search templated (so that it doesn't have to be
      implemented with double).  It also updates the return type struct with
      templated types, a constructor, and an iterator counter.
  7. 22 Jun, 2017 1 commit
  8. 21 Jun, 2017 1 commit
    • Jason Rhinelander's avatar
      Use a C++14 std::shared_timed_mutex for locking · 7df75988
      Jason Rhinelander authored
      This significantly simplifies the member locking implementation since we
      no longer have to worry about tracking the number of active locks;
      instead read locks are shared locks and write locks are exclusive locks;
      the stl implementation can worry about the details beyond that.
      This also disallows recursive member locks; instead calling code has to
      manage itself to avoid double-locking a member.  Note also that
      switching a write lock to a read lock is no longer guaranteed to be
      non-blocking as there is no way to downgrade an exclusive lock to a
      shared lock.  boost::upgrade_mutex could allow this, but this importance
      of this is minor and it seems nicer to get rid of the boost dependency.
      It also changes the main Simulation run lock to be the same stl
      implementation; previously it was using the boost implementation.
      With that, the boost thread, date_time, and atomic library components
      are no longer required.
  9. 26 May, 2017 1 commit
    • Jason Rhinelander's avatar
      Callbacks: support priority, simplify implementation · 72031ec7
      Jason Rhinelander authored
      Add a second parameter (priority) to the callback constructors and
      provide an override for the associated priority.
      This also simplifies the structure by moving the constructors and
      function/priority storage into a common base class.
      Everything also gets inlined as every method here is extremely simple.
  10. 24 May, 2017 1 commit
  11. 23 May, 2017 13 commits
  12. 29 Apr, 2017 4 commits
    • Jason Rhinelander's avatar
      Member ids: global, permanent; no implicit conversion · 05aae08d
      Jason Rhinelander authored
      This changes several things related to the handling of member ids.
      This is an API-breaking change, but cleans up some of the eris_id_t
      handling.  Making SharedMember and Member implicit convertible to
      eris_id_t everywhere was a mistake; this commit corrects it by
      introducing an implicit-converting object in those places where
      accepting either eris_id_t or a Member is desirable, without leaving
      implicit conversion to integer semantics in place everywhere else.
      Member and SharedMember<T> are no longer implicitly convertible
      to eris_id_t.
      Assigned member id()'s are now permanent and globally unique (rather
      than just within-Simulation unique), and are assigned when the Member is
      constructed and never unassigned.
      SharedMember<T> is now *explicitly* convertible to bool, but the meaning
      has changed somewhat: it no longer means "in a simulation" but now just
      "has a Member", like std::shared_ptr.  Thus shared members without a
      simulation used to be false in boolean context (which was via the
      eris_id_t) but are now true.
      SharedMember equality and inequality now work differently: since member
      ids are never unassigned and are global equality between shared members
      now works as expected across in- and out-of-simulation members.
      Previously `a == a` was false when `a` was not in a simulation.
      Equality is newly also true for null shared members: that is,
      `SharedMember<Member>() == SharedMember<Member>()` is true when both are
      nullptr members.  If just one is null, the comparison is false;
      otherwise the comparison comes down to id() values.  `operator <` now
      treats all nullptr members as if they had an id() of 0 (real id() values
      start at 1).
      To limit some of the compatibility annoyance, various methods like
      remove(), dependsOn(), and many of the methods in Bundle now accept a
      MemberID object (defined in types.hpp) instead of an eris_id_t that is
      implicitly convertible to and from an eris_id_t, and from anything with
      a direct or indirect id() method.
      Since this changes breaks some compatibility already, at the same time
      this also removes the second argument (the old id) from
      Member::weakDepRemoved() since the concept of an "old" id no longer
      exists.  (The member keeps its id even if removed and/or readded to a
    • Jason Rhinelander's avatar
      Switch time types to eris_time_t · 5bfbe410
      Jason Rhinelander authored
      This silences a clang signed-compare warning
    • Jason Rhinelander's avatar
    • Jason Rhinelander's avatar
      Added container versions of add and supplemental · e019217e
      Jason Rhinelander authored
      add(container) can be much more efficient than calling add(el) for each
      container element: if one of the adds fails, we can release the lock,
      add all remaining elements, then reestablish the whole lock; thus there
      is at most one blocking waiting for locking, while the loop approach
      could require `n` blocking waits.
  13. 26 Apr, 2017 2 commits