opensim-org / opensim-core

SimTK OpenSim C++ libraries and command-line applications, and Java/Python wrapping.
https://opensim.stanford.edu
Apache License 2.0
783 stars 316 forks source link

Refactor `OpenSim::Array` to internally use `std::vector` #3678

Closed adamkewley closed 7 months ago

adamkewley commented 8 months ago

Fixes a deep dark hole in my heart - and makes adding iterators, range for-loop support, etc. etc. much easier, because I'm getting bored of seeing for (int...) in modern C++.

WIP:

Brief summary of changes

Testing I've completed

Looking for feedback on...

CHANGELOG.md (choose one)


This change is Reviewable

adamkewley commented 8 months ago

Nice! Looks very reasonable to me.

I noticed that searchBinary is used in various parts of the codebase. Did you test that change locally or confirm that we already test coverage for it? My only comment is to consider a short unit test if it seems useful (perhaps for theManager class, which depends on it for retrieving integrator time steps).

Reviewed 17 of 17 files at r1, all commit messages. Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @adamkewley)

I haven't tested it yet, but I think that one way to do it would be to copy+paste the old implementation into a unit test and confirm it gives similar results.

From what I can see of it, its main usage purpose is to find an insertion point for data, but (imo) std::lower_bound alone would be better for this (it's used elsewhere): the behavior (as documented) seems likely to insert data one-too-early in a sequence (I'll have to check)

nickbianco commented 8 months ago

I haven't tested it yet, but I think that one way to do it would be to copy+paste the old implementation into a unit test and confirm it gives similar results.

Even if you confirmed this locally it would likely be fine, but a unit test would be safer. I'm fine with replacing usages of searchBinary with std::lower_bound if you want to add that here too.

adamkewley commented 7 months ago

I added a legacy-exercising unit test to ensure that the results will be the same. It found a bug in the implementation!

Assuming this passes CI, it should be ready to merge

aymanhab commented 7 months ago

@adamkewley Looks great, I'd only ask that you run swig and diff/compare the swig output since the Array class is used in numerous places across the API. It would be great to verify that the GUI builds with this branch. Thank you 🥇

adamkewley commented 7 months ago

This is held up by the SWIG check: building /w swig on Linux/WSL2 results in a missing preliminaries file and it's not entirely clear why the build depends on a file that doesn't exist

adamkewley commented 7 months ago

Think I found the bug: SWIG generation will fail if cmake is ran while the current working directory is opensim-core, because this execute_process call to generate SWIG's dependencies:

Will short-circuit some of the dependencies to (e.g.) Bindings/preliminaries.i because SWIG prioritizes the current dir as the highest-prio search path. However, all paths from that step must be absolute because the build can run from a different directory (it usually does).

adamkewley commented 7 months ago

Java SWIG diff, before and after:

adamkewley commented 7 months ago

All changes in the java diff appear to be due to renamed variables and/or updated comment strings, so I'm guessing the SWIG API is going to be fine (unless someone's code depended on variable names O_o).

adamkewley commented 7 months ago

Not sure if this is ever used but is aSize == _size still noop?

@ayman to reply to this question, it's still a noop. resize only "fills in" with _defaultValue on vector growth, and will only ever reallocate if the new size is greater than the current capacity of the vector.