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

invlerp and remap implementation #2654

Merged
merged 37 commits into from
Jun 2, 2024

Conversation

bilhox
Copy link
Contributor

@bilhox bilhox commented Jan 4, 2024

Implementation of #2649
Docs will come in a short time.

@bilhox bilhox requested a review from a team as a code owner January 4, 2024 10:16
Copy link
Member

@Matiiss Matiiss left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, I left a couple of notes:

I don't think you should change anything about math.lerp in this PR, you can submit a separate PR for that (that includes both the implementation and the docs).

Also this needs tests too.

buildconfig/stubs/pygame/math.pyi Show resolved Hide resolved
docs/reST/ref/math.rst Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
@bilhox
Copy link
Contributor Author

bilhox commented Jan 4, 2024

I don't think you should change anything about math.lerp in this PR, you can submit a separate PR for that (that includes both the implementation and the docs).

It's because I had to use lerp and invlerp in remap, So I updated it. Technically I can make python calls. Should I point it out btw ?

@Matiiss
Copy link
Member

Matiiss commented Jan 4, 2024

I don't think you should change anything about math.lerp in this PR, you can submit a separate PR for that (that includes both the implementation and the docs).

It's because I had to use lerp and invlerp in remap, So I updated it. Technically I can make python calls. Should I point it out btw ?

I'm just saying to not touch math_lerp in this PR, you can submit another PR that implements the changes in math_lerp using your helper functions and the change in the docs (although the docs change can maybe stay here, but if you're gonna submit another PR for math_lerp, might as well move that change to there too).

Also, not sure how much it really matters, but you could inline those two helpers, perhaps.

@Starbuck5 Starbuck5 added New API This pull request may need extra debate as it adds a new class or function to pygame math pygame.math labels Jan 5, 2024
Copy link
Member

@Matiiss Matiiss left a comment

Choose a reason for hiding this comment

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

This also needs unit tests

buildconfig/stubs/pygame/math.pyi Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
@ankith26 ankith26 linked an issue Jan 6, 2024 that may be closed by this pull request
src_c/math.c Outdated

if (!PyNumber_Check(min) || !PyNumber_Check(max) || !PyNumber_Check(value))
return RAISE(PyExc_TypeError,
"invlerp requires all the arguments to be numbers");
Copy link
Member

Choose a reason for hiding this comment

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

improvement suggestion: instead of checking this explicitly, we can instead call PyFloat_AsDouble directly, and then handle the error on a per-argument basis? That we can also tell which of the arguments is incorrect

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So If I understood, I should write something like this ? :

double v = PyFloat_AsDouble(value);
if (PyErr_Occurred())
    return RAISE(PyExc_ValueError,
                 "invalid `arg` values passed to remap, the value might "
                 "be too small or too big");
double a = PyFloat_AsDouble(i_min);
// same here
double b = PyFloat_AsDouble(i_max);
// same here
double c = PyFloat_AsDouble(o_min);
// same here
double d = PyFloat_AsDouble(o_max);
// same here

Copy link
Member

Choose a reason for hiding this comment

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

Well, we could do a simple return NULL as the error is already set. But the error won't be really specific

src_c/math.c Show resolved Hide resolved
src_c/math.c Show resolved Hide resolved
Copy link
Member

@MyreMylar MyreMylar left a comment

Choose a reason for hiding this comment

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

At the minute the float version of the inverse lerp implementation doesn't work how I would expect. It does not reverse a lerp() operation - except if the result is between 0 and 1.

the remap() seems ok 👍

src_c/math.c Outdated Show resolved Hide resolved
@Matiiss
Copy link
Member

Matiiss commented Feb 25, 2024

There is one thing I didn't understand from what ankith asked me to do, and with my exams I didn't have time sorry. Anyways, if you can explain me how to specificly now which variable is incorrect, rather than copy/pasting the error condition.

Good question, one approach would of course be a macro that does that, just add it after every double conversion and give it the argument number or name or whatever and make it just add the error message with that name in that place using the macro (make sure you undef it after usage). I guess another approach is a function, but that seems somewhat unnecessary for this. So yeah, probably a macro if you want to do that.

@bilhox bilhox requested a review from a team as a code owner May 25, 2024 21:05
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Show resolved Hide resolved
src_c/math.c Show resolved Hide resolved
@Starbuck5
Copy link
Member

Why is this implemented in C?

@MyreMylar
Copy link
Member

Why is this implemented in C?

Why not? I think for this current PR it would be a bit awkward & somewhat confusing to have 90% of the current math library in C and just two functions not written in C. It is a worthwhile question to ask though and I would like more of pygame's code to be written in python.

If you are pondering re-implementing the whole of pygame.math in python then that would be interesting to see how the current speed of python 3.12 stacks up against C implementations.

@Starbuck5
Copy link
Member

Why not?

Because bigwhoop's feature request had the functions written in Python. It would be trivial to just monkey patch them in in __init__.py.

Less code on our end, might even be more performant.

@MyreMylar
Copy link
Member

Why not?

Because bigwhoop's feature request had the functions written in Python. It would be trivial to just monkey patch them in in __init__.py.

Less code on our end, might even be more performant.

I'd like to see a pull request like this - both to see how it looks as an example case, and to see some performance testing. I think performance is definitely relevant for a math function like this that could be called repeatedly in tight loop drawing code.

@ankith26
Copy link
Member

Here is a simple performance test script for testing the invlerp implemented here

import pygame
import random
import time


use_python = False

objs = [
    (
        random.uniform(-100, 100),
        random.uniform(-100, 100),
        random.uniform(0, 1),
    )
    for _ in range(5000)
]

def py_invlerp(a, b, v, /):
    return (v - a) / (b - a)


start = time.time()

if use_python:
    for arg in objs:
        py_invlerp(*arg)


else:
    for arg in objs:
        pygame.math.invlerp(*arg)


print(time.time() - start)

I'm on python 3.12 and the C version implemented in this PR is more performant than the python version. However, at the rate at which the language is evolving (with the jit compiler and stuff), the difference is only going to lessen over the years, seems like.

On this specific case, I still would support the C implementation because it is simple enough, and if we ever decide to do a python re-implementation: it's a one-liner.

@bilhox
Copy link
Contributor Author

bilhox commented May 31, 2024

I highly believe that at this stage of implementation, and because the rest of math lib is written in C, that we keep this implementation.

docs/reST/ref/math.rst Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
src_c/math.c Outdated Show resolved Hide resolved
@MyreMylar MyreMylar merged commit 19a17c9 into pygame-community:main Jun 2, 2024
39 checks passed
@ankith26 ankith26 added this to the 2.5.0 milestone Jun 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
math pygame.math New API This pull request may need extra debate as it adds a new class or function to pygame
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add invlerp() and remap() functions to pygame.math
6 participants