Skip to content

Conversation

jarca0123
Copy link
Contributor

Also fixes some tests.

@jarca0123 jarca0123 force-pushed the math branch 2 times, most recently from e5a86b5 to 04de8f1 Compare July 17, 2025 09:02
@Lord-McSweeney
Copy link
Collaborator

Lord-McSweeney commented Jul 17, 2025

For round, ceil, and floor, I think we'd prefer to avoid the path that generates Integers instead of Numbers and instead add the logic to impl From<f64> for Value later so that it can apply everywhere.

let n = args[0].as_f64();
let p = args[1].as_f64();
let n = args[0].coerce_to_number(activation)?;
let p = args[1].coerce_to_number(activation)?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think these two lines can still use as_f64, as the argument is already coerced to a Number by the ActionScript-side function signature

args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let input = args[0];
let num = input.as_f64();
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: this can just be

let input = args[0].as_f64();

return Ok(f64::NAN.into());
} else if val > cur_max {
} else if val > cur_max
|| (val == cur_max && !val.is_sign_negative() && cur_max.is_sign_negative())
Copy link
Member

Choose a reason for hiding this comment

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

That's an oddly specific condition. Why does it have to be here? Can't it be somehow generalized? (Similarly the min one.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It handles signed zero cases. In max, positive zero takes priority, while in min, the negative zero takes priority. Rust cannot compare positive zero with negative zero, so that's why it is needed.

let n = args[0].coerce_to_number(activation)?;
let p = args[1].coerce_to_number(activation)?;

// If y is NaN, the result is NaN.
Copy link
Member

Choose a reason for hiding this comment

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

Comments refer to values as x and y whereas code refers to them as n and p. This should be unified somehow (it's better to use the names from docs if possible I guess).

) -> Result<Value<'gc>, Error<'gc>> {
let input = args[0];
match input {
Value::Integer(i) => Ok(i.abs().into()),
Copy link
Member

Choose a reason for hiding this comment

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

Why do we have dedicated Integer cases? How is that observable from AS?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a pushbyte instruction in the test from_avmplus/as3/Types/Number/abs, which (if I understand it correctly) pushes a byte (and therefore an integer) to the abs function. And Ruffle does seem to separate Value::Number and Value::Integer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

However, the test verifies (when 1 is passed or when Number(-0.0) is passed), if it returns int. In other cases, it returns Number.

Copy link
Collaborator

@adrian17 adrian17 Jul 31, 2025

Choose a reason for hiding this comment

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

I don't think this should need a special handling per-method. Just like @Lord-McSweeney said, there should probably be a "if the float is integral*, generate a Value::Integer" in impl From<f64> for Value instead. (for avmplus reference, see AvmCore::doubleToAtom which does exactly that)

(*and within 1<<28 range)

IMO adding missing methods to Number and adding new logic to core Value should go into separate PRs?

@jarca0123 jarca0123 force-pushed the math branch 2 times, most recently from 12a7265 to 2d3d1f3 Compare July 20, 2025 15:18
@danielhjacobs danielhjacobs added A-avm2 Area: AVM2 (ActionScript 3) T-compat Type: Compatibility with Flash Player labels Jul 23, 2025
@jarca0123 jarca0123 force-pushed the math branch 2 times, most recently from 27b2e08 to 991fee1 Compare July 31, 2025 10:26
@jarca0123 jarca0123 marked this pull request as ready for review July 31, 2025 10:26
// Note that Flash Math.round always rounds toward infinity,
// unlike Rust f32::round which rounds away from zero.
let ret = (x + 0.5).floor();
Ok(ret.into())
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should probably also return Ok(ret.into()) directly- as Adrian said, it'd be better to keep the Number -> int optimization a general optimization and implement it in a separate PR

@Lord-McSweeney Lord-McSweeney added the waiting-on-author Waiting on the PR author to make the requested changes label Aug 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-avm2 Area: AVM2 (ActionScript 3) T-compat Type: Compatibility with Flash Player waiting-on-author Waiting on the PR author to make the requested changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants