Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Touch class to extract Brush and Rub classes as their own touch features #26

Open
wants to merge 7 commits into
base: development
Choose a base branch
from

Conversation

vberthiaume
Copy link
Member

Fixes #22 and #23.

.gitignore Show resolved Hide resolved
// Large movement -> integrate with 0
else if(std::abs(movement) > 1)
{
integrate(0);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took this from the OG algorithm, but tbh I'm not entirely sure why we're ignoring values above 1?

Copy link
Collaborator

@jcelerier jcelerier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll let Edu take the descision about the code semantics, here are just a few comments about the code. Thanks for this great patch !

* @param new_tie Pointer to the external value to tie the feature to.
* @return True if the tie was successful; false if `new_tie` is null.
*/
bool tie(float* new_tie)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this, maybe we should bass a reference to the float instead of a pointer. This way, the language itself prevents the null case as a reference must always point to something.

It would simply become

void tie(float& new_tie) {
    tied_data = &new_tie;
 }

as now we don't need a boolean to record if this worked :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah of course, great one!

class TouchFeature
{
public:
TouchFeature() = default;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if all these constructors are even needed, it should be equivalent to just not declare them as per rule-of-zero

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue is that if we want a constructor for the tied value (see the protected section), and I think we want one, then we also need at least a default one, and then might as well have all of them right. We could also rely on users explicitly calling tie to tie a value but that's a bit awkward

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm basically copying what was done (I think by you lol) here:

explicit Jab(double* tied)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, that was me 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe simplifying might be good, there are indeed too many constructors

assert(start >= 0 && end >= start);

float sum{};
for(int i = start; i < end; ++i)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

 const float sum = std::reduce(array + start, array + end); 

likely it will also give some performance boost as it may parallelize operations / use SIMD or funky stuff like that

Copy link
Member Author

@vberthiaume vberthiaume Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm personally reluctant to include anything that isn't necessary in embedded projects, so here <numeric>, but I guess it's all tradeoffs -- @edumeneses what do you think?

@jcelerier jcelerier self-requested a review January 14, 2025 16:04
template <typename T>
float arrayAverage(const T* array, int start, int end)
{
static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type!");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually with concepts this can be done in a very built-in way:

#include <concepts>
float arrayAverage(const std::arithmetic auto* array, int start, int end) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideal code in an ideal world:

#include <concepts>
#include <numeric>
#include <print>

template<typename T>
concept arithmetic =  std::integral<T> || std::floating_point<T>;
float arrayAverage(const arithmetic auto* array, int start, int end)
// in a couple years, with C++ contracts (https://www.modernescpp.com/index.php/contracts-in-c26/)
//  pre(start >= 0)
//  pre(end >= start)
// until then it's asserts...
{
  return std::reduce(array + start, array + end) / float(end - start);
}

int main()
{
  {
    int foo[3]{0, 10, 20};
    std::println("{}", arrayAverage(foo, 0, 3));
  }

  {
    std::string foo[3]{"foo", "bar", "baz"};
    // build error since std::string is not arithmetic
    // std::println("{}", arrayAverage(foo, 0, 3));
  }
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(std::arithmetic seems to be missing from stdlib)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right... so in an ideal world concepts would be supported by the toolchain that platformIO uses, but for now they aren't 😅

@vberthiaume vberthiaume force-pushed the refactor/touch branch 3 times, most recently from ecc7782 to d8ce298 Compare January 16, 2025 16:15
…e, make everything else more agnostic, and address PR comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants