ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
@ 2020-10-09 14:18 universato
  2020-10-10  6:54 ` [ruby-core:100355] " nobu
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: universato @ 2020-10-09 14:18 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been reported by universato (Yoshimine Sato).

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257

* Author: universato (Yoshimine Sato)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return value shoud be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100355] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
@ 2020-10-10  6:54 ` nobu
  2020-10-10  9:18 ` [ruby-core:100356] " universato
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: nobu @ 2020-10-10  6:54 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by nobu (Nobuyoshi Nakada).

Assignee set to mrkn (Kenta Murata)
Status changed from Open to Assigned

I'm not sure if it should be 0.
As `x.pow(y, m)` equals multiplying `x % m` to 1 `y` times, isn't 1 ok when `x == 0`?

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87967

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100356] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
  2020-10-10  6:54 ` [ruby-core:100355] " nobu
@ 2020-10-10  9:18 ` universato
  2020-10-10 18:12 ` [ruby-core:100359] " midnight_w
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: universato @ 2020-10-10  9:18 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by universato (Yoshimine Sato).


According to RDoC, `x.pow(y, m)`  equals `(x**y) % m`. 
In fact, `x.pow(y, m)`  returns same value as `(x**y) % m` except for `x.pow(0, 1)`.


```ruby
p (12**0) % 1  #=> 0
p 12.pow(0, 1) #=> 1
```

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87968

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100359] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
  2020-10-10  6:54 ` [ruby-core:100355] " nobu
  2020-10-10  9:18 ` [ruby-core:100356] " universato
@ 2020-10-10 18:12 ` midnight_w
  2020-10-10 19:28 ` [ruby-core:100361] " marcandre-ruby-core
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: midnight_w @ 2020-10-10 18:12 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by midnight (Sarun R).


This is undefined
`0.pow(0, 1)`
https://www.wolframalpha.com/input/?i=0%5E0

This is clearly out of the space (thus a bug)
`1.pow(0, 1)`
https://www.wolframalpha.com/input/?i=%281%5E0%29+mod+1

It is practically pointless to mod by 1; I don't think this change will break anything in the wild.
Nobody would rely on 1%1 == 0.
The problem is what to do with 0 ** 0.

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87970

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100361] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (2 preceding siblings ...)
  2020-10-10 18:12 ` [ruby-core:100359] " midnight_w
@ 2020-10-10 19:28 ` marcandre-ruby-core
  2020-10-11  2:48 ` [ruby-core:100363] " nobu
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: marcandre-ruby-core @ 2020-10-10 19:28 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by marcandre (Marc-Andre Lafortune).


It's a bug.

Additional tests look good.

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87972

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100363] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (3 preceding siblings ...)
  2020-10-10 19:28 ` [ruby-core:100361] " marcandre-ruby-core
@ 2020-10-11  2:48 ` nobu
  2020-10-11  3:32 ` [ruby-core:100365] " midnight_w
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: nobu @ 2020-10-11  2:48 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by nobu (Nobuyoshi Nakada).


I agree that the behavior and documentation **may** be inconsistent, and think one option is to fix the latter.

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87974

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100365] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (4 preceding siblings ...)
  2020-10-11  2:48 ` [ruby-core:100363] " nobu
@ 2020-10-11  3:32 ` midnight_w
  2020-10-11  3:41 ` [ruby-core:100366] " midnight_w
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: midnight_w @ 2020-10-11  3:32 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by midnight (Sarun R).


So the proposal is to change the document from
"Returns (modular) exponentiation"
to
"multiplying x % m to 1 y times"?

IMHO `% m` is the space, `** y` is the operation performed inside the space, so the result should be within the space.
If `% m` is the operation itself, that would be a different story.

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87976

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100366] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (5 preceding siblings ...)
  2020-10-11  3:32 ` [ruby-core:100365] " midnight_w
@ 2020-10-11  3:41 ` midnight_w
  2020-10-11  5:54 ` [ruby-core:100367] " universato
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: midnight_w @ 2020-10-11  3:41 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by midnight (Sarun R).


Wait a minute, I just changed my mind.
Actually since `0.pow(0)` is mathematically undefined.

See WolframAlpha for references:
https://www.wolframalpha.com/input/?i=0%5E0

 `0.pow(0, 1)` should be undefined too, so do `1.pow(0, 1)`.
Because inside the `% 1` space, `1 == 0` and `12 == 0` too.

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87977

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100367] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (6 preceding siblings ...)
  2020-10-11  3:41 ` [ruby-core:100366] " midnight_w
@ 2020-10-11  5:54 ` universato
  2020-10-11 12:09 ` [ruby-core:100373] " sawadatsuyoshi
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: universato @ 2020-10-11  5:54 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by universato (Yoshimine Sato).


`x.pow(y, m)` doesn't equal multiplying `x % m` to 1 `y` times.

```ruby
p 1 * (3 % 4) * (3 % 4) #=> 9 
p 3.pow(2, 4) #=> 1
```

it is the last to mod.
Method `pow` should be simply defined as `(x**y) % m`. 

And, `0.pow(0)` is not necessarily undefined.
Many programming languages define `0 ** 0` returns 1 because it is useful.
For example, Python, R, C++, C#, Java, JavaScript, PHP, Perl, MATLAB, Octave, Haskell, Julia, Crystal and Ruby e.t.c.

For reference, Python has pow function like ruby's pow.
Python define pow as `(x**y) % m`, and Python's pow return 0. 
```python
print((12 ** 0) % 1) # 0
print(pow(12, 0, 1)) # 0
```

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87978

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100373] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (7 preceding siblings ...)
  2020-10-11  5:54 ` [ruby-core:100367] " universato
@ 2020-10-11 12:09 ` sawadatsuyoshi
  2020-10-11 13:18 ` [ruby-core:100374] " midnight_w
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: sawadatsuyoshi @ 2020-10-11 12:09 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by sawa (Tsuyoshi Sawada).


I cannot follow the discussion because of the expression "multiplying `x % m` to 1 `y` times." What does that mean?

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87983

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100374] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (8 preceding siblings ...)
  2020-10-11 12:09 ` [ruby-core:100373] " sawadatsuyoshi
@ 2020-10-11 13:18 ` midnight_w
  2020-10-11 18:46 ` [ruby-core:100375] " universato
  2020-10-12  4:35 ` [ruby-core:100379] " mame
  11 siblings, 0 replies; 13+ messages in thread
From: midnight_w @ 2020-10-11 13:18 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by midnight (Sarun R).


The point of undefinition is:
There is nothing definitely right or wrong.
Neither 0 nor 1 is wrong; it is just a different point of view.

You are thinking that 0 ** 0 == 1 is useful because you are looking from the perspective of x ** 0 == 1 for most of x
while 0 ** x == 0 is also true for most of x too, and it is as useful as x ** 0 == 1.

Weather 0 ** 0 should return 0 or 1 is subjective, and whatever the actual implementation is, it is not entirely wrong, same for little-endian vs. big-endian.
This is the reason why the value is undefined.
Regardless of mathematical definitions, I second for `x.pow(y, 1)` should return 0, as I said initially, `% m` is the space and every value inside `% 1` space is 0.

Mathematical wise this is considered undefined behavior. Implementation wise there is an advantage that we follow other popular languages in this matter.

I just want to point out that people who oppose the behavior change has some merit.
Even if the current behavior sounds wildly wrong, most people are not going to care, because the value is mathematically undefined in the first place.
And no practical result will be obtained from `% 1` space.

Anyway, `x % 1 == 0` sound more "correct" to me too.

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87984

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100375] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (9 preceding siblings ...)
  2020-10-11 13:18 ` [ruby-core:100374] " midnight_w
@ 2020-10-11 18:46 ` universato
  2020-10-12  4:35 ` [ruby-core:100379] " mame
  11 siblings, 0 replies; 13+ messages in thread
From: universato @ 2020-10-11 18:46 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by universato (Yoshimine Sato).


sawa (Tsuyoshi Sawada) wrote in #note-10:
> I cannot follow the discussion because of the expression "multiplying `x % m` to 1 `y` times." What does that mean?

"multiplying x % m to 1 y times"の意味は、「1に対して(x % m)をy回乗じること(又は、その値)」ですかね。

想像以上に議論が活発で嬉しいですが慣れない英語で疲れたし読み誤っているかもしれないので、自分のために日本語で整理します。

nobuさんが、最初に#1で「x.pow(y, m)は1に(x % m)をy回乗じた値に等しいから、y == 0のときは1でいいのではないでしょうか」と言ってます。

そして、自分の#9を言い直すと「`3.pow(2, 4)`が1に対して、`1に(3 % 4)`を2回乗じた値は9であるため、`x.pow(y, m)`は1に`(x % m)`を`y`回乗じた値に等しいとは限りません。powの計算結果はm未満になるはずです。x.pow(0, 1)の挙動に合わせるために、現状のシンプルな定義`(x**y) % m`から`x.pow(0, 1)`だけ例外的に1を返す特別な理由を付け加えたり変更することは難しいと思いました。」と言いたかったです。

midnightさんの#7の意見もおそらく同様で「ドキュメントを"1に対して`(x % m)`を`y`回乗じること"に変更するのですか。私の考えでは、`% m`とは空間であり、その空間の中で掛け算が行われるから、計算結果は空間に収まるべきです(≒`m`未満になるべき)。」と言ってます。

......

あと話が変わりますが、「mod 1を使うケースは普通ない」という意見もあり、半分同意です。ただ、あらゆるmodのケースを想定して最小正数の1でもテストしたら自分が詰まったので決してmod 1を使うケースは0ではないはずで、小さいけどバグだと思ったので変更されてもいいはずと思い、今回提案しました。また、変更するにあたってのデメリットも小さいはずと考えました。x.pow(0, 1)の挙動を積極的に使う人はいないはずで後方互換性の影響を気にしなくても大丈夫だと思います。また、コードの修正も基本的には`if(m == 1){ return 0 }`を加えるだけだと想像しました。このあたりは、コードを書いた担当者のmrknさんの意見も聞きたいところです。その他の提案理由は、Pythonのmod_powは正しい動作をしてる気がするのに悔しいなぐらいです。

Sorry for writing only in Japanese

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87986

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [ruby-core:100379] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect
  2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
                   ` (10 preceding siblings ...)
  2020-10-11 18:46 ` [ruby-core:100375] " universato
@ 2020-10-12  4:35 ` mame
  11 siblings, 0 replies; 13+ messages in thread
From: mame @ 2020-10-12  4:35 UTC (permalink / raw)
  To: ruby-core

Issue #17257 has been updated by mame (Yusuke Endoh).


I agree that it is a bug.  The pseudocode of modular exponentiation in Wikipedia includes `if modulus = 1 then return 0` as the first check.

https://en.wikipedia.org/wiki/Modular_exponentiation#Pseudocode

I agree that there are few real use cases of modulo 1, so few one will be affected by this change.  I'll fix it soon.

```diff
diff --git a/bignum.c b/bignum.c
index 65a50ea9ba..0515e2f0d6 100644
--- a/bignum.c
+++ b/bignum.c
@@ -7136,6 +7136,7 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
             long const half_val = (long)HALF_LONG_MSB;
             long const mm = FIX2LONG(m);
             if (!mm) rb_num_zerodiv();
+            if (mm == 1) return INT2FIX(0);
             if (mm <= half_val) {
                 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
             }
@@ -7145,6 +7146,7 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
         }
         else {
             if (rb_bigzero_p(m)) rb_num_zerodiv();
+           if (bignorm(m) == INT2FIX(1)) return INT2FIX(0);
             return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
         }
     }
```

----------------------------------------
Bug #17257: Integer#pow(0, 1) returns 1, which is incorrect
https://bugs.ruby-lang.org/issues/17257#change-87990

* Author: universato (Yoshimine Sato)
* Status: Assigned
* Priority: Normal
* Assignee: mrkn (Kenta Murata)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ruby 2.5.8, 2.6.6, 2.7.1


```ruby
p -1.pow(0, 1) #=> 1
p  0.pow(0, 1) #=> 1
p  1.pow(0, 1) #=> 1
p 1234567890.pow(0, 1) #=> 1
```

These return values should be 0.


Patch for test:

Let's add some boundary value tests to `test_pow` of [test_numeric.rb](https://github.com/ruby/ruby/blob/e014e6bf6685f681998238ff005f6d161d43ce51/test/ruby/test_numeric.rb).

```ruby
integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
integers.each do |i|
  assert_equal(0, i.pow(0, 1), '[Bug #17257]')
  assert_equal(1, i.pow(0, 2))
  assert_equal(1, i.pow(0, 3))
  assert_equal(1, i.pow(0, 6))
  assert_equal(1, i.pow(0, 1234567890123456789))
  
  assert_equal(0,  i.pow(0, -1))
  assert_equal(-1, i.pow(0, -2))
  assert_equal(-2, i.pow(0, -3))
  assert_equal(-5, i.pow(0, -6))
  assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
end

assert_equal(0,  0.pow(2, 1))
assert_equal(0,  0.pow(3, 1))
assert_equal(0,  2.pow(3, 1))
assert_equal(0, -2.pow(3, 1))



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-10-12  4:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-09 14:18 [ruby-core:100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect universato
2020-10-10  6:54 ` [ruby-core:100355] " nobu
2020-10-10  9:18 ` [ruby-core:100356] " universato
2020-10-10 18:12 ` [ruby-core:100359] " midnight_w
2020-10-10 19:28 ` [ruby-core:100361] " marcandre-ruby-core
2020-10-11  2:48 ` [ruby-core:100363] " nobu
2020-10-11  3:32 ` [ruby-core:100365] " midnight_w
2020-10-11  3:41 ` [ruby-core:100366] " midnight_w
2020-10-11  5:54 ` [ruby-core:100367] " universato
2020-10-11 12:09 ` [ruby-core:100373] " sawadatsuyoshi
2020-10-11 13:18 ` [ruby-core:100374] " midnight_w
2020-10-11 18:46 ` [ruby-core:100375] " universato
2020-10-12  4:35 ` [ruby-core:100379] " mame

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).