andyvand / gmpy

Automatically exported from code.google.com/p/gmpy
GNU Lesser General Public License v3.0
0 stars 0 forks source link

xmpz slice assignment does not work as advertised #56

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. n = gmpy2.xmpz(2**10)
2. n.__format__("b") # outputs '10000000000'
3. n[1::2] = True
4. n.__format__("b") # outputs '10000000010'

What is the expected output? What do you see instead?
   I expect all odd indexed bits to have been set: '11010101010'

What version of the product are you using? On what operating system?
   http://code.google.com/p/gmpy/downloads/detail?name=gmpy2-2.0.0b1.win-amd64-py2.7.exe&can=2&q=

Please provide any additional information below.

Code snippet found on:
http://stackoverflow.com/questions/2897297/speed-up-bitstring-bit-operations-in-
python/2901856#2901856
See edit #3. Posted by "casevh" who claims to be a maintainer.
The posted prime sieve does not work obviously because of this issue. 

Original issue reported on code.google.com by jan.feit...@gmail.com on 21 May 2012 at 11:17

GoogleCodeExporter commented 9 years ago
How to interpret True has changed during the development phases. Python 
normally treats True and 1 identically.  This interpretation is currently what 
I'm using but differs from what I was using when I made the post on 
Stackoverflow. Since only a single bit is provided as a source, only one bit 
gets set. To provide an infinite stream of bits, you can use -1. Using -1 
instead of True should work  with the current 2.0.0b1 version. (-1 works 
because it 2s-complement format uses an "infinite" number of 1 bits.)

However, I personally prefer treating True as an infinite source of bits. But 
this might break an application that considers 1 and True to be equivalent.

Which would you prefer?

1) Leave it "as is"? (And I should edit my StackOverflow post  to use -1 
instead of True. :) )

2) Special-case True to provide an infinite source of 1 bits?

I have fixed a couple of other bugs with xmpz slice assignment. The current 
version also recognizes the stop parameter in the slice so the useless upper 
bit does not need to set. For example, the following code now works:

>>> n=gmpy2.xmpz(0)
>>> n[1:10:2] = -1
>>> n.__format__("b")
'0b1010101010'                                                                  

>>>         

I will be be releasing 2.0.0b2 fairly soon and I'm willing to change the 
behavior of True. If you want to test the next version, let me know and I can 
build a new Windows  installer for you.

Original comment by casevh on 21 May 2012 at 1:56

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
You can use 0 to slice assign 0bits.

Original comment by casevh on 3 Jun 2012 at 2:20

GoogleCodeExporter commented 9 years ago
I don't really like both options you mentioned. They feel obfuscated to me.
I'd prefer a matlab-like approach: when assigning a constant to a slice, each 
element of the slice gets the constant value. Would that be possible?

Original comment by jan.feit...@gmail.com on 3 Jun 2012 at 8:35

GoogleCodeExporter commented 9 years ago
The current implement allows for assigning slices of bit values to
slices. For example,

'0b101101'

'0b1010001'

assigns bit positions a[0], a[2], a[4], a[8] to the value of bits 0,
1, 2, 3 of 45. Slice notation can be use on the right hand side also.
With this implementation, clearing all bits in a slice assignment
requires 0 on the right hand side and setting all bits in a slice
assignment requires -1 on the right hand side (since in 2s complement
notation, -1 has all bits set).

I can change the behavior to special case the Python objects "True"
and "False". "False" is numerically equivalent to 0 so I can treat
them identically. "True" is numerically equivalent to +1 so it would
break the assumption that int(True) == 1.

You could write code using bool(1) and bool(0) on the right hand side.
It would be identical to using True/False but may clarify the intent.

The SVN repository special-cases True/False but I still haven't
decided if I like the change.

I don't want to give up the ability to assign slices to slices.

I'm open to suggestions.

Original comment by casevh on 3 Jun 2012 at 4:45

GoogleCodeExporter commented 9 years ago
I also had a bit of trouble getting my head around this functionality, trying 
it after seeing the stackoverflow question, but I like the current 
implementation now that I understand it. Using -1 encourages you to think 
clearly about what you're doing (binary arithmetic), where -1 makes perfect 
sense.

There could be an argument for letting True represent an "infinite source of 
bits" as you put it above. In my opinion, the identity True==1 is much more 
important in comparisons than assignments, and it will not be effected in 
comparisons.

But personally, as soon as I have understood that slice assignment assigns bits 
of a an integer rather than simply assigning a single bit (0 or 1) to every 
index in the slice, I would rather stick to that model and use -1.

a = xmpz(255) # 11111111
a[::2] = 0    # 10101010     zero the slice
a[::2] = 8    # 11101010     set bit 6 (bit 3 of the slice)
a[::2] = 4    # 10111010     set bit 4 (bit 2 of the slice)
a[::2] = 2    # 10101110     set bit 2 (bit 1 of the slice)
a[::2] = 1    # 10101011     set bit 0 (bit 0 of the slice)
a[::2] = 15   # 11111111     '1' the slice by setting bits 0-3
a[::2] = -1   # 11111111     '1' the slice by setting all bits

Original comment by nicksp...@gmail.com on 3 Jun 2012 at 10:16

GoogleCodeExporter commented 9 years ago
I've decided to leave the 0 and -1 behavior as-is. Python's ~ operator performs 
bit inversion. Since ~0 is -1, this behavior is consistent with using ~ to 
invert bits.

Original comment by casevh on 15 Jun 2012 at 6:27

GoogleCodeExporter commented 9 years ago
Well, you gave it proper thought and edited the post on stackoverflow so I am 
fine with the decision. Thanks!

Original comment by jan.feit...@gmail.com on 15 Jun 2012 at 8:47