Closed Jookia closed 3 weeks ago
It should be simple to add a function with the expression \x&((1<<\y)-1))>>\z
(or my own variant \x%2^\y>>\z
). You can do this locally using qalc with the command function bits x&((1<<y)-1))>>z
.
I would prefer a less generic function name, and to me it seems more logical to specify the lowest bit first, as the 2nd argument (e.g. bits(0x12ABCDEF, 8, 15)
).
This works: function bits \x%2^(\y+1)>>\z otherwise it cuts off bit 15.
Maybe bitfield would be a better name? Flipping the arguments is fine too. Maybe even more so to make the input easier to change: So something like bits_at(8, 15, 0x12ABCDEF)? Then you can do function myfield bits_at(8, 15, x) easily or something.
To add to feature creep it would be nice to also have bits_set that would replace the bits at a position with a value. Maybe bits_mask too but I can't think of a time I'd need that in my personal calculations.
I will add the following functions:
bitget(number, bit[, number of bits])
(default value for 3rd argument is 1), or
bitget(number, bit[, last bit])
(default value for 3rd argument is 0, indicating that only one bit will be returned)
bitset(number, bit[, value])
(default value for 3rd argument is 1, multiple bits can be specified using a vector in 2nd argument), or
bitset(number, bit[, bit 2, ...])
and bitclear(number, bit[, bit 2, ...])
That sounds cool, though how will the first two be differentiated? If there's a PR I will test it
That sounds cool, though how will the first two be differentiated?
Only one of the two alternatives, for each function, will implemented.
Specifying bits by offset not length is the only usable one for me. I guess I could macro things if the other solution is implemented.
Done.
> info bitget
Function: Get Bit
bitget(Number, Position[, Last Position])
Returns the binary bit at the specified position. The index of the least significant bit is 1. If last index (third argument) is higher then (first) index, the bits from index to, and
including, last index is returned as a new binary number.
Example: bitget(12, 3) = 1; bitget(0b01011100, 2; 4) = 0b00000110 = 6
Arguments
Number: an integer
Position: an integer ≥ 1 and ≤ 18446744073709551615
Last Position: an integer ≥ 0 and ≤ 18446744073709551615 (optional, default: 0)
> info bitset
Function: Set Bit
bitset(Number, Position[, Value][, Bit Width][, Signed Integer])
Set binary bit at specified position. The index of the least significant bit is 1. Multiple bits get be set using a vector. Specify bit width and signedness to allow sign changes when
the most significant bit is set.
Example: bitset(8, 3) = 12; bitset(0b11111111, 2...8, 0) = 1
Arguments
Number: an integer
Position: an integer ≥ 1 and ≤ 18446744073709551615
Value: a boolean (0 or 1) (optional, default: 1)
Bit Width: an integer ≥ 0 and ≤ 4294967295 (optional, default: 0)
Signed Integer: a boolean (0 or 1) (optional, default: 0)
I tested these changes. I have a few questions:
bitset(0b11111111, 2...8, 0) = 1
warning: Misplaced decimal separator ignored
bitset(255, 2.8, 0) = 1 (base: 10)
bitset(255, 2.8, 0) − 1 = 0
- Re bitget, what happens if the last index is smaller than the the first index?
Only the first index is returned. Perhaps returning bits from first index to last index, in reverse order (e.g. bitget(0b1110, 4, 1) = 0b0111) would be preferable, if last index is non-zero.
The example 'bitset(0b11111111, 2...8, 0) = 1' gives this error
The syntax for 2...8 (creates a vector with integers 2 to 8) is new, and has not been committed to Git yet (I will also implement a similar syntax using colon).
I was thinking that it would return the bits by width. I can confirm that the code works when using an explicit vector.
(I will also implement a similar syntax using colon).
Add step (start:step:end or start:end:step).
Add step (start:step:end or start:end:step).
start:step:end, as in Matlab, but conflict with sexagesimal numbers forces additional syntax requirements; the colon expression will probably need to be enclosed in square brackets (or possibly parentheses).
So I spent some time with this last week. Bitget works great! Bitset looks like you can only set or clear a bit, not insert a value. For example:
bitget(0xFAF, 5, 8) to hex = 0xA
But if I want to set the 0xA in 0xFAF to 0xF I have to do this:
bitset(0xFAF, 5...8, 0) | 0xF << 4 to hex
So now there's two ways to index bits in a single line, 0 based and 1 based. I guess I could use a macro to do this for me but to my knowledge you can't define your own macros/functions that get loaded every time the program starts.
I guess I could use a macro to do this for me but to my knowledge you can't define your own macros/functions that get loaded every time the program starts.
Use the function
command (function name expression), or the save()
function with category (3rd argument) other than "Temporary". The GUIs provide more complete options for function creation.
[Feature request] support struct bit field in c language https://en.cppreference.com/w/c/language/bit_field
You don't have to calulate which bit to get/set, just read/write the variable(bits), it should be easier than "bitset(0xFAF, 5...8, 0) | 0xF << 4 to hex".
But if I want to set the 0xA in 0xFAF to 0xF I have to do this: bitset(0xFAF, 5...8, 0) | 0xF << 4 to hex
Now you can use bitset(0xFAF, 5, 0xF)
Edit: I did not think it through enough (bitset(0xFAF, 5...8, 1)
or bitset(0xFAF, 5, [1 1 1 1])
can still be used, but I assume that it's not as useful)
What will bitset(0xFFF,5,0x5) return? 0b1111 0101 1111 0b1111 1010 1111 0b1111 1101 1111 0b1111 1111 1111
On Tue, Feb 06, 2024 at 12:55:22AM -0800, Hanna Knutsson wrote:
But if I want to set the 0xA in 0xFAF to 0xF I have to do this: bitset(0xFAF, 5...8, 0) | 0xF << 4 to hex
Now you can use
bitset(0xFAF, 5, 0xF)
Is this in the latest Git commit?
Is this in the latest Git commit?
It was reverted in the latest commit (bitset(0xFAF, 5, [1 1 1 1])
syntax was not removed, but I assume that it's not as useful).
So official advice is to use a macro for this?
On Tue, Feb 06, 2024 at 11:53:49AM -0800, Hanna Knutsson wrote:
Is this in the latest Git commit?
It was reverted in the latest commit (
bitset(0xFAF, 5, [1 1 1 1])
syntax was not removed, but I assume that it's not as useful).-- Reply to this email directly or view it on GitHub: https://github.com/Qalculate/libqalculate/issues/615#issuecomment-1930650107 You are receiving this because you authored the thread.
Message ID: @.***>
So official advice is to use a macro for this?
Yes (at least for now).
I've now added integerDigits(), digitGet(), and digitSet() (e.g. digitSet(0xFAF, 1, 0xF, 16)
returns 0xFFF
) functions.
I think bitset() is different from digitSet(). Here is bitset() version.
1 to 1 assign bitset(0xFFF,[index1,index2,index3],[value1,value2,value3]) index1=value1 index2=value2 index3=value3
Check whether value can be express using n bits. 1bit: 0-1 2bit: 0-3 3bit: 0-7 4bit: 0-15 5bit: 0-31 Assigning 32 to 5 bits is invalid.
LSB is last element when convert value to vector. bitset(0xFFF,[9,8,7,6,5,4,3],0x13) =bitset(0xFFF,[9,8,7,6,5,4,3],[0,0,1,0,0,1,1]) =0b1110 0100 1111
If bitget() can accept vector, it should return same value if index is same as bitset(). bitget(0b111001001111,[9,8,7,6,5,4,3]) =0x13
bitset(0xFFF,[9,8,7,6,5,4,3],0x13) =bitset(0xFFF,[9,8,7,6,5,4,3],[0,0,1,0,0,1,1])
This would change bitset(0, 1:3)
from bitset(0, [1 2 3], [1 1 1]) = 7
to bitset(0, [1 2 3], [0 0 1]) = 4
.
I have no better solution, if making third argument optional is more useful than assigning value, stay unchanged.
If third argument is negative (default -1), don't convert it, just set all the bits to 1.
If third argument is negative (default -1), don't convert it, just set all the bits to 1.
Instead of making bitset
usage more complicated, it might be better to recommend use of bitset(0xFFF, 3, bitget(0x13, 1:7))
as alternative to bitset(0xFFF,[9,8,7,6,5,4,3],[0,0,1,0,0,1,1])
.
I actually consider removing the option to set multiple bits (primarily using argument 2), for consistency and to match the implementation in other software (e.g. Matlab).
bitset(0xFFF,[9,8,7,6,5,4,3],[0,0,1,0,0,1,1])
can reduce to bitset(0xFFF,[9:-1:3],0x13)
.
If third argument default to -1, bitset(0, [1 2 3], [1 1 1])
can reduce to bitset(0, [1 2 3])
.
The problem of bitset(0xFFF, 3, bitget(0x13, 1:7)
is that bitget(0x13, 1:7)
return a number, you don't know how many bits to set.
0x13
=19
=0b10011
=0b010011
=0b0010011
=0b0000000000010011
If you can specify how many bits to set in bitset(), this should be possible. And that is why I propose "1 to 1 assign".
Anyway, I respect your decision.
Another solution would be to add another function, e.g. setbits(0xFFF, 3, 9, 0x13)
(would change bits 3 to 9). This way I can completely remove the option to set multiple bits in bitset (and instead return a vector if one or more arguments contains vectors).
The problem of bitset(0xFFF, 3, bitget(0x13, 1:7) is that bitget(0x13, 1:7) return a number, you don't know how many bits to set.
As bitget(0x13, 1:7)
does not (while bitget(0x13, 1, 7)
does) return a number, it is not a problem.
setbits(0xFFF, 3, 9, 0x13) seems the best solution. Waiting for your release.
version 5.0.0
help bitset
will print
bitset(Number, Position[, Value][, Bit width][, Signed integer])
and
bitset(Number, First position, Last position, Value[, Bit width][, Signed integer])
setbits is missing
version 5.0.0
1. `help bitset` will print `bitset(Number, Position[, Value][, Bit width][, Signed integer])` and `bitset(Number, First position, Last position, Value[, Bit width][, Signed integer])` 2. setbits is missing
Fixed (bitset was set as name for setbits in data file).
Considering the many changes in version 5.0, at least some non-critical issues such as this are expected.
setbits function is totally missing. (not only in help message)
setbits function is totally missing. (not only in help message)
True, but still rectified by the tiny fix. You can try it yourself by editing functions.xml (replace second r:bitset
with r:setbits
).
I found functions.xml, but it only have two lines inside.
<?xml version="1.0"?>
<QALCULATE version="5.0.0"/>
Maybe this solution is not for self-contained binaries version.
> help setbits
Function: Set Multiple Bits
setbits(Number, First position, Last position, Value[, Bit width][, Signed integer])
Set binary bits at specified range with binary bits from an integer (index 1 to length of range). The index
of the least significant bit is 1. Specify bit width and signedness (use 1 for signed and 0 for unsigned) to
allow sign changes when the most significant bit is set.
Example: setbits(0xFFFF, 9, 12, 0xA) = 0xFAFF
Arguments
Number: an integer
First position: an integer >= 1 and <= 18446744073709551615
Last position: an integer >= 1 and <= 18446744073709551615
Value: an integer
Bit width: a boolean (0 or 1) (optional, default: 0)
Signed integer: a free value (optional, default: 0)
I want to know what "Bit width" and "Signed integer" do, is there an example? And why "Bit width" is boolean?
I want to know what "Bit width" and "Signed integer" do, is there an example?
setbits(25;8;8;1;8;1) = −103 (1111 1111 1001 1001)
setbits(25;8;8;1;8;0) = 153 (0000 0000 1001 1001)
And why "Bit width" is boolean?
Another unfortunate mistake in setbits (bit width should be integer and signed integer boolean).
This might be an odd request, but I spent a LOT of time digging through datasheets that have things like 'bits 8 through 16 of this 32-bit word are X value', and calculating that is something like '((0x12ABCDEF) & ((1<<16)-1)) >> 8)' to get 0xCD. These are not always nibble or byte aligned so it's a rather annoying task.
It would be nice to have something like 'bits(0x12ABCDEF, 15, 8)' to get bits 8 through 15 inclusive, with bits starting at 0. This is similar to what you would see written in a datasheet for a register field.
If this is wanted I can try and do a PR for it.