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

Behaviour of div / mod on Non-Ints #5388

Open
p6rt opened this issue Jun 17, 2016 · 5 comments
Open

Behaviour of div / mod on Non-Ints #5388

p6rt opened this issue Jun 17, 2016 · 5 comments
Labels
Bug

Comments

@p6rt
Copy link

@p6rt p6rt commented Jun 17, 2016

Migrated from rt.perl.org#128428 (status was 'open')

Searchable as RT128428$

@p6rt
Copy link
Author

@p6rt p6rt commented Jun 17, 2016

From @zoffixznet

Current implementation of `mod` has (Real, Real) signature and uses `div (Int,Int)` to perform the division. This creates an LTA error that mentions `div` when argumenemts aren't Ints​:

<Zoffix> m​: say 2 mod 1.5
<camelia> rakudo-moar 5ca43c​: OUTPUT«Cannot resolve caller infix​:<div>(Int, Rat); none of these signatures match​:␤ (Int​:D \a, Int​:D \b)␤ (int $a, int $b --> int)␤ in block <unit> at <tmp> line 1␤␤»

Reading the spec (http://design.perl6.org/S03.html), descriptions of infix​:<mod>/infix​:<div> suggest they should work on all numeric types, as long as LHS/RHS are the same type​:

-------------quote from spec----------------------

infix​:<div>, integer division

  $numerator div $denominator

Dispatches to the infix​:<div> multi most appropriate to the operand types, returning a value of the same type. Not coercive, so fails on differing types.

Policy on what to do about division by zero is up to the type, but for the sake of hyperoperators and junctions those types that can represent overflow (or that can contain an unthrown exception) should try to do so rather than simply throwing an exception. (And in general, other operators that might fail should also consider their use in hyperops and junctions, and whether they can profitably benefit from a lazy exception model.)

On the other hand, div wants to be very efficient and jittable when used as a low-level operation, so when you use div on two native ints, it relies on hardware to detect division by 0. Hence, it will always throw an exception rather than return a Failure.

In general, div should give the same result as

  $x div $y == floor($x/$y)

but the return value should be the same type as $x.

This identity stops holding when $x/$y degrades to a Num and runs into precision limits. A div operation on two Int objects must always be done precisely.

===========================
infix​:<mod>, integer modulo

  $x mod $y

Dispatches to the infix​:<mod> multi most appropriate to the operand types, returning a value of the same type. Not coercive, so fails on differing types.

This should preserve the identity

  $x mod $y == $x - ($x div $y) * $y
-------------/quote from spec----------------------

@p6rt
Copy link
Author

@p6rt p6rt commented Jun 20, 2016

From @zoffixznet

I've used a bad example in the OP.

The issue is mod/div only work on Int types and the spec specs all numerics, even though the method is non-coercive​:

See http://irclog.perlgeek.de/perl6-dev/2016-06-17#i_12687099

@p6rt
Copy link
Author

@p6rt p6rt commented Jul 28, 2016

From @moritz

Hi,

On 06/18/2016 12​:39 AM, Zoffix Znet (via RT) wrote​:

# New Ticket Created by Zoffix Znet
# Please include the string​: [perl #​128428]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl6/Ticket/Display.html?id=128428 >

Current implementation of `mod` has (Real, Real) signature and uses `div (Int,Int)` to perform the division. This creates an LTA error that mentions `div` when argumenemts aren't Ints​:

<Zoffix> m​: say 2 mod 1.5
<camelia> rakudo-moar 5ca43c​: OUTPUT«Cannot resolve caller infix​:<div>(Int, Rat); none of these signatures match​:␤ (Int​:D \a, Int​:D \b)␤ (int $a, int $b --> int)␤ in block <unit> at <tmp> line 1␤␤»

Reading the spec (http://design.perl6.org/S03.html), descriptions of infix​:<mod>/infix​:<div> suggest they should work on all numeric types, as long as LHS/RHS are the same type​:

But that's not what your example uses. It's Int mod Rat, so it
explicitly falls into this category​:

: Not coercive, so fails on differing types.

So I don't see the bug yet.

Cheers,
Moritz

-------------quote from spec----------------------

infix​:<div>, integer division

 $numerator div $denominator

Dispatches to the infix​:<div> multi most appropriate to the operand types, returning a value of the same type. Not coercive, so fails on differing types.

Policy on what to do about division by zero is up to the type, but for the sake of hyperoperators and junctions those types that can represent overflow (or that can contain an unthrown exception) should try to do so rather than simply throwing an exception. (And in general, other operators that might fail should also consider their use in hyperops and junctions, and whether they can profitably benefit from a lazy exception model.)

On the other hand, div wants to be very efficient and jittable when used as a low-level operation, so when you use div on two native ints, it relies on hardware to detect division by 0. Hence, it will always throw an exception rather than return a Failure.

In general, div should give the same result as

 $x div $y == floor\($x/$y\)

but the return value should be the same type as $x.

This identity stops holding when $x/$y degrades to a Num and runs into precision limits. A div operation on two Int objects must always be done precisely.

===========================
infix​:<mod>, integer modulo

 $x mod $y

Dispatches to the infix​:<mod> multi most appropriate to the operand types, returning a value of the same type. Not coercive, so fails on differing types.

This should preserve the identity

 $x mod $y == $x \- \($x div $y\) \* $y

-------------/quote from spec----------------------

@p6rt
Copy link
Author

@p6rt p6rt commented Jul 28, 2016

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

@p6rt p6rt commented Nov 25, 2016

From @zoffixznet

On Wed, 27 Jul 2016 17​:43​:39 -0700, moritz wrote​:

Hi,

On 06/18/2016 12​:39 AM, Zoffix Znet (via RT) wrote​:

# New Ticket Created by Zoffix Znet
# Please include the string​: [perl #​128428]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl6/Ticket/Display.html?id=128428 >

Current implementation of `mod` has (Real, Real) signature and uses
`div (Int,Int)` to perform the division. This creates an LTA error
that mentions `div` when argumenemts aren't Ints​:

<Zoffix> m​: say 2 mod 1.5
<camelia> rakudo-moar 5ca43c​: OUTPUT«Cannot resolve caller
infix​:<div>(Int, Rat); none of these signatures match​:␤ (Int​:D \a,
Int​:D \b)␤ (int $a, int $b --> int)␤ in block <unit> at <tmp>
line 1␤␤»

Reading the spec (http://design.perl6.org/S03.html), descriptions of
infix​:<mod>/infix​:<div> suggest they should work on all numeric
types, as long as LHS/RHS are the same type​:

But that's not what your example uses. It's Int mod Rat, so it
explicitly falls into this category​:

: Not coercive, so fails on differing types.

So I don't see the bug yet.

Cheers,
Moritz

Right, I've copy-pasted the wrong example. Different types aren't the issue. The Int-only impl is the issue​:

  m​: say 2.5 mod 2.5
  rakudo-moar 5ca43c​: OUTPUT«Cannot resolve caller infix​:<div>(Rat, Rat); none of these signatures match​:␤ (Int​:D \a, Int​:D \b)␤ (int $a, int $b --> int)␤ in block <unit> at <tmp> line 1␤␤»

The spec suggests that should work.

@p6rt p6rt added the Bug label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.