#Bitwise operators

1 messages · Page 1 of 1 (latest)

storm girder
#

I wanted to see if anyone can help me understand the practical usage of bitwise operators. I believed previously that they were either too complex or a bad practice, but I wanted to know if anyone has good use cases for them.

dawn stirrup
#

lots of algorithms and optimisations use bitwise operators

#

so if you're a normal user you won't really get to use them

storm girder
#

I understand that bitshifting left and right can achieve the same thing as multiplication and division by powers of 2

#

But I'm still a bit uncertain of things like bitwise and, or, xor etc

#

I'm sure there are higher level equivalents of them

#

for outcome but not performance *

elfin fractal
#

a good example is instead of using 1 byte boolean arrays, you can use each individual bit as a boolean, since obviously a boolean only needs 1 bit to represent both false & true

storm girder
#

is there any use in applying bitwise operators to non-primitive values or is that too unpredictable?

jagged idol
#

Only for syntactic sugars

near dawn
storm girder
#

unless its absolutely performance critical

#

like in graphics processing and the like

near dawn
#

yeah

agile karma
#

someone link that evil fast square root from doom codebase

storm girder
#

For the bitwise comparison operators such as AND and OR, how can I expect those to behave differently than logical operators (& vs && / | vs ||)

jagged idol
#

Doing a bunch of boolean operations at once is also very useful in case you have lots of those flags for a single thing: bitfields.
Say you have a bitfield like this, representing different flags that can be on or off:

mod body_feats {
    const HAS_LEGS: u32     = 0b0001;
    const HAS_ARMS: u32     = 0b0010;
    const HAS_LONGNECK: u32 = 0b0100;
    const HAS_BIGBRAIN: u32 = 0b1000;
}
```Notice each flag is a binary number with a single `1` digit and everywhere else is 0.

Say you have a variable that contains a u32, and its goal is to contain flags for body features. You can construct it like this:
```rs
let my_body_features = HAS_LEGS | HAS_ARMS | HAS_BIG_BRAIN;
```with a struct of booleans it would take more space, be more verbose, and less readable.

And then, you can even check whether it has a specific feature like this:
```rs
fn has_legs(features: u32) -> bool {
    features & HAS_LEGS > 0
}
near dawn
#

its better than some operations in my kernel (if task queue is empty then add task if its not then pause the cpu, add task, and then let the cpu continue running)

near dawn
willow locust
#

bitwise operators are most important for encoding, decoding, hashing, etc

solemn birch
willow locust
#

encoding can also just be sending over the internet or something

solemn birch
#

An entire video on bitwise float shenanigans

jagged idol
#

You even get the notion of a "mask", a number which is meant to "mask" out a certain flag when it has 0 or keep it when it has 1.
For example, say you want a mask that only keeps HAS_LEGS and HAS_ARMS:

//                            v--- keep HAS_ARMS
const MEMBERS_MASK: u32 = 0b0011;
//                             ^-- keep HAS_LEGS

let my_body_features = HAS_LEGS | HAS_BIG_BRAIN;

// now only has HAS_LEGS, HAS_BIG_BRAIN has been masked out
let masked_features = my_body_features & MEMBERS_MASK;
agile karma
#

oh yeah, bitflags. reminds me that combining it with enums is one of C# features i actually miss

jagged idol
#

me too

agile karma
#

although there's probably a crate for that

jagged idol
#

I wish people didn't need to make a whole crate just for that

#

and there is: bitflags

#

but I hate that it has to be a crate

#

it feels so unidiomatic

#

builtin typesafe bitflags would be amazing

solemn birch
#

C# is bae

agile karma
#

C# is okay

jagged idol
agile karma
#

I'm just sick of it because i did it for 2.5 years

#

probably meant bad

jagged idol
#

oh

solemn birch
jagged idol
#

:( how rude of u to hit me with ur recursive answering /j

solemn birch
#

No, I love C#

#

Best OOP language

jagged idol
#

I hate OOP but I agree

solemn birch
#

Idk OOP has its place

#

Imo

jagged idol
#

Some of its concepts in isolation yeah

solemn birch
#

The problem comes when trying to make everything oop

jagged idol
#

For example, I think inheritance is good for UI

#

to some degree

agile karma
#

C# will never free itself from its past. which i think is sad because i like the .net platform

solemn birch
#

What past?

#

Inheritance can be great in many places when applied correctly

agile karma
#

it's full of like awkward things that keep reminding you that it wasn't very forward-designed
like void not being a part of the type system

#

bitflag enum features falling off in certain scenarios

solemn birch
#

Idk when was the last time I used pointers in C#

agile karma
#

switch statements being stupid

autumn fossil
agile karma
#

anxiety inducing ambiguity with operator overloads

solemn birch
#

Oh I love operator overloading

#

For tho things

#

Math and events

#

Curse you if you use it anywhere else

#

But it makes vector/matrix/quaternion math much nicer to look at

jagged idol
autumn fossil
#

abolish quaternions

jagged idol
#

I don't have any other example

agile karma
#

i still haven't internalised the behaviour of equality operator in c#
like what's needed for it to stop being ReferenceEquals and start calling user defined methods

#

is it consistent if the compiler doesn't know the exact types?

solemn birch
#

yeahhh

#

thats one of the problems with operator overloading

#

its a reference check, unless it was operator overloaded

#

so it depends on the library

dawn stirrup
#

or if it's passed by value

solemn birch
#

also its a value check for value types

#

(structs)

agile karma
#

oh yeah

dawn stirrup
#

okay you can't use == on structs without overloading it which makes sense
record structs automatically implement it for you

agile karma
#

the differences in behaviour between value types and reference types are so annoying

dawn stirrup
#

I don't think they're that bad. They're just two different rulesets

#

not much more difficult to learn that the borrow checker, as in you need some time to get used to it

agile karma
#

when i tried working with mainly structs in c# it felt like the standard lib and the language were fighting me

solemn birch
#

I havent used structs much at all

#

in my own code

#

I have with libraries

agile karma
#

ref being a weird additional thing rather than part of the type system is bad

dawn stirrup
#

okay yeah ref can be confusing to use

solemn birch
#

probably an unpopular opinion: I hate var

dawn stirrup
#

it's a balancing thing. It's sometimes important to mention the type and other times it's obvious and you can just use var

agile karma
solemn birch
jagged idol
#

so probably not that unpopular

dawn stirrup
solemn birch
#

Rider actually gives you the type if you use bar

#

wich is pretty amusing to me

#

the fact that you write var to ommit the type, then the IDE writes it as a hint thing anyways

agile karma
#

it's quite common

solemn birch
agile karma
#

omnisharp does this

solemn birch
agile karma
#

rust analyser does this

solemn birch
#

yes

#

I hate var

agile karma
#

global using let = System.Object

dawn stirrup
#

bruh

solemn birch
#

no please

dawn stirrup
#

don't do that

agile karma
#

continuing with things i find annoying about c#
no streamlined way to "include dependency by pasting in code" without writing your own damn source analyser

autumn fossil
agile karma
#

no macros

dawn stirrup
#

bad Nebula

agile karma
#

very limited type aliases

#

(no genetics)

dawn stirrup
#

aren't type aliases a new thing?

agile karma
#

wait I'm kind of derailing the thread

#

it was supposed to be about bitwise operators

solemn birch
#

oh dependencies

#

not imports

#

well guess thats an IDE problem? because the IDE could prefectly fine suggest NuGet packages

agile karma
#

as someone who had to target .net Framework 3.5 in a slightly fucked up environment (modding) i would have found it extremely helpful to not be dependent on assembly files being there at runtime

near dawn
#

doesn't rust compile dependencies into the binary itself. that feels like it would make modding a rust game/program very hard unless the source program had modding systems built into it

dawn stirrup
#

I mean you could probably just patch the binary but that's not really the biggest issue

#

langs like C# are relatively easy to decompile to relatively human readable code cause they compile to an intermediate language

#

so it's a looot easier to reverse engineer the code and write patches for it

near dawn
#

right

#

i mean.

#

rust does technically use an IL

#

it just then compiles that to machine code

ionic fulcrum
#

for example the number 0xFF8800 represents a kind of orange

#

but you might want to get the individual r, g and b values

#

the easiest way of doing that is bitwise operations

#

r = hexcode >> 16 & 0xFF
g = hexcode >> 8 & 0xFF
b = hexcode (>> 0) & 0xFF

#

it's just the most easy way of getting & setting bits/ranges of bits in a number

#

they're definitely not bad practice unless you're using them when it would be clearer to use something else. on the contrary if you go out of your way not to use them I'd say that would be bad practice because it's less clear what you're trying to do

inner cedar
#

you use << 1 when you need to multiply by 2 but don't have a multiply operation

ionic fulcrum
#

also true

solemn birch
#

I hate it when I need to multiply by exactly 2 but dont have a multiply operation

inner cedar
#

hey, it happens

#

with a few <<s and add instructions you can implement fast multiplication yourself

solemn birch
#

in 2023?

ionic fulcrum
#

yes

#

lemme look some stuff up

solemn birch
#

for mere cents you have microcontrollers more powerful than most computers in the 80s

ionic fulcrum
#

of course but they have to sacrifice some stuff

#

e.g. the ATTiny85 has no multiply instruction

#

although the SDK will probably include a software multiply algorithm and most decent C compilers will optimise *2 to <<1 anyway

solemn birch
#

well it has no hardware multiplication

ionic fulcrum
#

but it certainly doesnt have hardware div

inner cedar
#

what if you're writing assembly tho, because you hate yourself for fun?

solemn birch
#

idk I dont hate myself that much

#

I refuse to go any lower level than C

inner cedar
#
INC $D020
JMP *-3``` hahahahaha you can't stop me
solemn birch
#

I have no clue what that means so go on

inner cedar
#

nothing

#

sometimes I make stupid jokes for no reason

solemn birch
#

what is the $D020 registry

#

its a loop that increases that but idk what $D020 is

ionic fulcrum
#

i believe it's a memory address

#

so it would be equivalent to the C code (*(int*)0xD020)++

solemn birch
#

yeah

#

my question was, if its a specific registry, or if it is just some random memory address

ionic fulcrum
#

oh I get it sorry

#

without knowing what CPU this is running on it's impossible to know

inner cedar
solemn birch
#

So that program makes a rainbow border

inner cedar
#

Kinda. It flickers a lot and you can see the funny effects the video chip has on the CPU, but yes. It's Hello World in C64 ASM.

#

it was a stupid and distracting joke and I regret making it :)

solemn birch