Author Topic: Picking a random bitwise value from a given number  (Read 2527 times)

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #30 on: November 13, 2011, 04:16:32 am »


               I have never heard it called 0 padding with a shift operation either, simply since there was no reason to call it that.   a simple logical shift right padds zeros.  It just does not appear like we have one in NWScript at the moment.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #31 on: November 13, 2011, 04:54:37 am »


               

Lightfoot8 wrote...

I have never heard it called 0 padding with a shift operation either, simply since there was no reason to call it that.   a simple logical shift right padds zeros.  It just does not appear like we have one in NWScript at the moment.


Well in C you never really had a logical right shift.  You had two's complement notation in which you can do arithmetic right shifts, and you had one's complement system where the terms 'arithmetic' and 'logical' didn't make sense to use as a right shift was a right shift.  NWScript preserved the one's compliment shift as far as numeric values were concerned, but did not bring with it the one's complement system.  So >> is just a speedy way to divide by powers of 2 (if truncation is desired) with no real relevance to the bit representation as there is no one's complement bit representation.

Edit: Misspellings
               
               

               


                     Modifié par WhiZard, 13 novembre 2011 - 05:03 .
                     
                  


            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #32 on: November 13, 2011, 01:07:31 pm »


               Hello,

to my understanding, the >>> NWscript operator is meant to
perform a logical shift, just like the >> C operator does
on unsigned integers (and much like the Java >>>, in fact).

To rephrase with code, these should all be equivalent:

// C
unsigned int a   = -100;
             a >>= 3;

// C
int a = -100;
    a = signed (unsigned (a) >> 3);

// NWscript
int a    = -100;
    a >>>= 3;


Lightfoot8 wrote...

@the.gray.fox

Just to make sure we are reading from the same book.   Are you running the game on an X86 system?

Confirmed -- This is a WinXP Pro, 32 bit, only for games.


-fox
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #33 on: November 13, 2011, 08:52:29 pm »


               

the.gray.fox wrote...

Hello,

to my understanding, the >>> NWscript operator is meant to
perform a logical shift,


Then what is meant to perform the arithmetic shift?  >> in NWScript falls short of this.  Also, do you have a source where BioWare documented this?  The lexicon is devoid of 32 bit examples, and never uses it outside the short definition and 8 bit example.  But given the way it defines >> as actually causing the trailing bit to loop around and describing this as "division by two" seems that whoever wrote it, wrote many contradictary things with no one firm way of interpretation.

EDIT: Do not take my demands with offense, I am more looking at a possible new article on NWN wiki for shift operators, and BioWare documentation would be helpful in showing these operators are not working as intended.
               
               

               


                     Modifié par WhiZard, 13 novembre 2011 - 09:38 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #34 on: November 13, 2011, 10:25:27 pm »


               I am pretty sure the Operator was just made to mimic C++:  So in NWscript it will most likely always be arithmetic shift.  In when compiled in C++, Note I have never programed C++,  It would not always have to be an arithmetic shift,  there are more data types for the compiler to account for.  

 in the following  x << y;
an arithmetic shift would make no since if a was a unsinged 32bit integer,  byte,  word, dword, or any of the other data types that are not singed intengers.   The compiler would take into account the data types in the expression when it was compiled.  the same way it would compile  x + y differently according to the data types of x and y;    

I will try and get more information on how the operator works in NWN shortly,  As long as I nothing else goes wrong around here again.   After all understanding how it works in NWN is what we are really after here.  

Hopfully reporting back soon.
L8.
               
               

               
            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #35 on: November 14, 2011, 03:07:58 am »


               Hello WhiZard,

No offense taken, I perfectly understand your inquiry.
But I have no official documentation to support my claim.

I can only go by logic, seeing how NWscript inarguably replicates a subset of C++ syntax
and operators. The sole extraneous element is the very >>> operator, likely borrowed
from Java (given its popularity) and likely to workaround the absence of unsigned datatypes.
And yes, the >> operator I believe was meant to perform the aritmetic shift.

Now _if_ I am correct, this makes both the >> and the >>> operators bugged.
As much as I like the game, frankly it would not shock me to learn that they are indeed
so, and have never worked as intended from day zero.

Other parts of the language were never fixed in 69 official patches, after all:

-- UDTs are bugged to the point they can trash the compiler if you dare nest them.
-- The switch() construct fails to treat "string literals" as constants.
-- The const keyword is a joke, to the point you better code without it.
-- A constant declared at script level invades the ::scope and takes precedence over any local struct member that happens to possess its same identifier name.
-- The implementation of the float datatype is bugged.
-- The ternary conditional ?: may incorrectly return its false expression if its evaluation directly supplies the argument for a function call (must wrap the whole ?: expression within () to enforce correct token parsing precedence).

There is surely more it is not occurring me at the moment.


-fox
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #36 on: November 14, 2011, 04:38:25 am »


               After looking at how both shift right operators function, I do not think  I can call either one of them bugged.   I can say that both of them  have been misdocumented in the lexicon.  

If the number being shifted is negtive both operators will produce unwanted results for logical bit shifts, if that is what we are after.  

The >>> operator is the most stright forward.   It always proforms an arithmetic bit shift to the right.   This is a  problem for bit manipulation, because it  fills any bits shifted in with 1's instead of 0's, if the number was negtive. 


The  >>  operator now has a split personality.   If the number it is operatating on is Postive, it operats the exact same way as the >>> operator  does with  an arithmetic bit shift to the right.   If the number is negtive however,  it  takes three steps. 
It negates the number, does a arithmetic bit shift to the right, then negates the number again.  

i.e. 
nNumber = nNumber  >>x;  would be the same thing as. 

if (nNumber < 1)
{
   nNumber =  -( (-nNumber) >>> x)
}
else nNumber = nNumber >>> x;  
 

Here is the difference between the two,  if you look at them from a mathematical stand point.

In normal integer math the  remainders of numbers are always truncated downwards.  

so: 
 19/ 2  would equal  9.5    rounded down to 9  // (19 >>> 1)
and 
-19/2  would equal -9.5    rounded down to -10.   // (-19 >>>1)
always rounding down. 
 this is the way the >>> operator operates. 

the >> operator  instead of always rounding down,  attempts to  truncate twards 0.  
so. 

19/2 would still equal 9.5  rounded down to 9 // (19>>1)
but  
-19 / 2 equaling -9.5 is now rounded up to -9. // (-19>>1)  

So the entire differance in the two operators is the direction that they round negtive numbers.   

This does create serious problems for bit manipulation though.  One of the biggest is that if you have an odd negtive number and shift by one with the >> operator.    (nNumber>>1)   The bit in position 0 will never unset. It just keeps rounding up to a 1.  

The only solution I can see, If one insists on using the 32 bit,  for a logical right shift in all cases, would be to do a NOT, SHIFT, NOT  using the >>> operator for the shift. .  

i.e. 
nNumber  logicly shifted right x bits would be: 

~(~nNumber >>> x) 
    Whizard Pointed  out some bugs in the ~(~nNumber >>> x)  

EDIT3:  New method that will work for  nNumber  logicly shifted right x bits would be:

(nNumber>>>x) & ( (1<< 32-x )-1)
   Whizard pointes out a problem with x being equal to 0.  

 
And that is what I  found. Hope it answers some questions.   
L8


EDIT: Fixed the direction of my shift operators. 
EDIT2:  Fixed a bunch of  grammer/spelling/typos.
   
               
               

               


                     Modifié par Lightfoot8, 16 novembre 2011 - 11:32 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #37 on: November 14, 2011, 06:34:29 am »


               Nicely explained. '<img'>

Funky
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #38 on: November 14, 2011, 10:47:01 am »


               

Lightfoot8 wrote...
The  >>  operator now has a split personality.   If the number it is operatating on is Postive, it operats the exact same way as the >>> operator  does with  an arithmetic bit shift to the right.   If the number is negtive however,  it  takes three steps. 
It negates the number, does a arithmetic bit shift to the right, then negates the number again.

Your result confirms what I have concluded at the top of the page.

The rest is many corallaries which I did not spell out but had in my mind.  To justify >> as  a bit shift, you can also think of it as rewriting the bits to form a one's complelement system thus causing the negatives to parallel the positives and performing a bit shift on those bits.  Since we use two's complement, >>> is easy to see as a bit shift.

As for "not bugged" I will agree that what BioWare implemented is a straightfoward and consistent system that was misdocumented.  However, I also think that speculation the Bioware was trying to do more and settled for less may also be justified.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #39 on: November 14, 2011, 10:54:16 am »


               

Lightfoot8 wrote...

i.e. 
nNumber  logicly shifted right x bits would be: 

~(~nNumber >>> x)    
  


There is a flaw here.  ~nNumber would be using the master bit of 0, shifting it to the right, and then the next ~ would take the master bit and all its replications and turn them back into 1's.

EDIT This should work
int LogShift(int nNumber, int nPlaces)
  {
  if(nNumber < 0)
    {
    nNumber = nNumber ^ (1 << 31);
    nNumber = nNumber >>> nPlaces;
    //Reset the new bit position of the first bit
    nNumber = nNumber | (1 << (31 - nPlaces));
    }
  else nNumber = nNumber >>> nPlaces;
 return nNumber;
}
               
               

               


                     Modifié par WhiZard, 14 novembre 2011 - 11:07 .
                     
                  


            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #40 on: November 14, 2011, 02:42:29 pm »


               Hey, nice.
+1 for demistifying it.


But it makes no sense.
Let me explain. What _you_ said does make sense.
What _they_ have done with it does not.

The >>/> operators are not supposed to round anything.
They simply have to kick bits to the right, and out of the
picture...
... which incidentally causes a truncation of the input value,
but that is the side-effect, not the driving purpose of the
operator. Let alone taking it 1 step further and proceed to
a rounding according to sign.

I still believe these two operators are simply screwed
(but take this term with a grain of salt -- I better explain
myself at the end)

What would be the usefulness of a rounding up/down that is
to be performed through a bitwise operator (only applicable
to integers, no less) and that can only occur by dividing
by powers of 2?
Get the nonsense of it?

I can hardly identify this as a language intended feature.
Now I too would like to hear someone going official about
such extravagant implement.
But this is the most official thing I could fetch, and it says
pretty much nothing of interest.


-fox


*** End of the politically correct reply ***





*** Begin of personal thoughts about this matter ***
*** Not a required read, yet could teach something ***


It is clear the devs deemed appropriate to complied with "reinvent the wheel".
Whether intentional or not.
The >>/> operators exihibit complex function behavior while
they should just be a wrapper to bridge NWscript with the
very CPU RightShift ops, because anyway you look at it that
is the logical thing to do.
And the float datatype is handled internally by custom, flawed
code, instead of relying on the flawless conversion functions
already exposed by the C standard library (which is cross-platform
too, so there is no valid excuse for avoiding its use).
Reinventing the wheel is no professional decision. Never.

It does not smell so Twilight Zone if we understand they could
have done something unwise in the name of cutting the
development times.
Now _that_ is a professional decision, provided they can deal
with its consequences appropriately.
They may have recycled another project and sublimed the
actual NWscript out of it, in the process preserving its
original flaws -- namely: the foul reinventing the wheel,
and its side-effects. Probably they TODO-ed to fix it all
later, but the "go" for it never came (in the end it is not a critical
fault of the software).
Things such as this are done all the time when the project is
big and there is a strict deadline and someone has coughed
millions of real dollars upfront.

Hm.
Has anyone got copy of the book:
The Art of C++
by Herbert Schildt
ISBN:0072255129
McGraw-Hill/Osborne © 2004
?

At the end of it you find the complete listing of a mini C++
interpreter. Copy, paste, compile -> ready for use.
In its presented form it is raw and unoptimized. But it is
perfectly working, and it can do everything that NWscript
does (save for the UDTs which are not implemented).
Just an example of how cheap it is to recycle a very complex
piece of software that otherwise takes dozens of paid man hours
to develop from scratch.


-fox
               
               

               


                     Modifié par the.gray.fox, 14 novembre 2011 - 03:27 .
                     
                  


            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #41 on: November 14, 2011, 03:49:58 pm »


               

the.gray.fox wrote...
The const keyword is a joke, to the point you better code without it.


Sorry if I'm a little off topic, but could you please explain this a little further? I use constants a lot to organize my scripts so this is very interesting to me.

Thank you

Kato 
               
               

               


                     Modifié par Kato_Yang, 14 novembre 2011 - 03:51 .
                     
                  


            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #42 on: November 14, 2011, 04:25:15 pm »


               _You_ are being Off Topic? -- Haha.
If you say so... :-)


Do not worry about the const thing.
It is only that you are not allowed to compile something of
the like (to make one example):


const int nSomething = 1 << 10;

You see, the expresion 1 << 10 is perfectly evaluable at
compile time (it translates to 1024). Its value is known
from the start and it will not change during execution,
by virtue of the const qualifier...
So: it _is_ a proper constant.

Yet the above constant declaration is illegal according to
NWscript. For it, that is not a valid constant (my paw!)

But if you get rid of the const keyword, like this:


int nSomething = 1 << 10;

The silly compiler is happy and throws no objections.
That is all.


-fox
               
               

               
            

Legacy_Axe_Murderer

  • Full Member
  • ***
  • Posts: 199
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #43 on: November 14, 2011, 04:51:01 pm »


               Watch out for the circular shift operator in NWN. It doesn't sign extend correctly so it isn't any different than the regular shift right op.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Picking a random bitwise value from a given number
« Reply #44 on: November 14, 2011, 05:03:55 pm »


               

the.gray.fox wrote...

_You_ are being Off Topic? -- Haha.
If you say so... :-)


Do not worry about the const thing.
It is only that you are not allowed to compile something of
the like (to make one example):


const int nSomething = 1 << 10;

I dont think that this, neither other issues you did pointed are bugs, but rather impement limitation. Or missing functionality is a better term.
               
               

               


                     Modifié par ShaDoOoW, 14 novembre 2011 - 05:51 .