All OS supported - Windows, OSX, Linux. x86 + x64. (Ascii+Unicode but not relevant).
Public domain. No warranty. Use at your own risk. I'm not liable. No credits requested.
Static libs pre-compiled for all OS, and full source provided.
---
WHY? I really need high confidence in operations with unsigned 32bit and 64bit integers. Unfortunately Purebasic doesn't support them yet (it has 8bit and 16bit unsigned support but not 32/64), i don't really trust myself with bit hacks or things like knowing where or where not to throw in "& $FFFFFFFF" here and there, not all existing solutions are cross-OS, and tricks like using Quad instead of Long for 32bit unsigned ops don't extend to 64bit unsigned ops, which had me especially stumped today! But unsigned integers aren't going away and they must be operated on properly or it's Miscalculation City if using signed ops on them.
SO! I ended up making a little C library to provide those operators, which to my surprise turned out very straightforward as there aren't many operators and they're all so fundamentally simple themselves! Some that aren't required are provided as macros for set completeness. All operators are provided/supported (Arithmetic, Logical, Relational, Bitwise, and even a few Misc).
Highly modular by design, each function in the .a library is its own .o object file, so only the functions you use get included in your executable! (and most functions are tiny!) And even if you use every function you're still only adding ~3kb, so it's very little overhead, but each operator is essentially a Call to a small Procedure, so it's slightly less efficient than if PB supported it inline natively, but nonetheless the trust/confidence in the calculations/operations should be high and the libs are compiled with gcc's highest optimization. Hopefully a future version of PB will make this lib redundant, but until then...!
USAGE is very simple - just IncludeFile the PBI, then all the u32/u64 functions from the lib are available (and again, only the functions you use (and actually use - not just declare) get compiled into your executable).
Simply use PB's .l long variables for 32bit unsigned dwords, and .q quad for 64bit unsigned quads. (The lib doesn't automatically change or cast all variables to all-unsigned, no... we simply use .l and .q as the placeholders, and you're then free to use both signed and/or unsigned ops on them).
There's a Demo.pb included in the zip for a quick intro, as well as TestAll32.pb and TestAll64.pb for more thorough tests.
Each C procedure is essentially nothing more than the single operation, eg:
Code: Select all
int u64isgreater (unsigned long long int quad1, unsigned long long int quad2) {
if (quad1 > quad2) { return 1; } else { return 0; }
}
DOWNLOAD: (v1.2) http://www.mediafire.com/download/wlvns ... d-v1.2.zip
(if that doesn't exist try this Backup thanks to RSBasic!)
__________________________________________________________________________
LIBUNSIGNED.PBI (excerpt of the main functions)
Code: Select all
ImportC "libunsigned.a"
;### ARITHMETIC: returns calculation result
;### 32bit DWORD
Macro u32add (dword1, dword2): (dword1 + dword2) : EndMacro
u32addq.q (dword1.l, dword2.l) As #prefix$+"u32addq"
Macro u32sub (dword1, dword2): (dword1 - dword2) : EndMacro
u32subq.q (dword1.l, dword2.l) As #prefix$+"u32subq"
u32div.l (dword1.l, dword2.l) As #prefix$+"u32div"
u32divq.q (dword1.l, dword2.l) As #prefix$+"u32divq"
u32mod.l (dword1.l, dword2.l) As #prefix$+"u32mod"
Macro u32mul (dword1, dword2): (dword1 * dword2) : EndMacro
u32mulq.q (dword1.l, dword2.l) As #prefix$+"u32mulq"
;### 64bit QUAD
Macro u64add (uquad1, uquad2): (uquad1 + uquad2) : EndMacro
Macro u64sub (uquad1, uquad2): (uquad1 - uquad2) : EndMacro
u64div.q (uquad1.q, uquad2.q) As #prefix$+"u64div"
u64divd.d (uquad1.q, uquad2.q) As #prefix$+"u64divd"
u64mod.q (uquad1.q, uquad2.q) As #prefix$+"u64mod"
Macro u64mul (uquad1, uquad2): (uquad1 * uquad2) : EndMacro
;### RELATIONAL: returns 0 false or 1 true
;### 32bit DWORD
u32isgreater.i (dword1.l, dword2.l) As #prefix$+"u32isgreater"
u32isgreaterorequal.i (dword1.l, dword2.l) As #prefix$+"u32isgreaterorequal"
u32isless.i (dword1.l, dword2.l) As #prefix$+"u32isless"
u32islessorequal.i (dword1.l, dword2.l) As #prefix$+"u32islessorequal"
Macro u32isequal (dword1, dword2): (dword1 = dword2) : EndMacro
Macro u32notequal (dword1, dword2): Not (dword1 = dword2) : EndMacro
;### 64bit QUAD
u64isgreater.i (uquad1.q, uquad2.q) As #prefix$+"u64isgreater"
u64isgreaterorequal.i (uquad1.q, uquad2.q) As #prefix$+"u64isgreaterorequal"
u64isless.i (uquad1.q, uquad2.q) As #prefix$+"u64isless"
u64islessorequal.i (uquad1.q, uquad2.q) As #prefix$+"u64islessorequal"
Macro u64isequal (uquad1, uquad2): (uquad1 = uquad2) : EndMacro
Macro u64notequal (uquad1, uquad2): Not (uquad1 = uquad2) : EndMacro
;### BITWISE: returns calculation result
;### 32bit DWORD
u32shr.l (dword1.l, shiftbytes.l) As #prefix$+"u32shr"
Macro u32shl (dword1, shiftbytes): (dword1 << shiftbytes) : EndMacro
Macro u32and (dword1, dword2): (dword1 & dword2) : EndMacro
Macro u32or (dword1, dword2): (dword1 | dword2) : EndMacro
Macro u32xor (dword1, dword2): (dword1 ! dword2) : EndMacro
Macro u32not (dword1): (~dword1) : EndMacro
;### 64bit QUAD
u64shr.q (uquad1.q, shiftbytes.l) As #prefix$+"u64shr"
Macro u64shl (uquad1, shiftbytes): (uquad1 << shiftbytes) : EndMacro
Macro u64and (uquad1, uquad2): (uquad1 & uquad2) : EndMacro
Macro u64or (uquad1, uquad2): (uquad1 | uquad2) : EndMacro
Macro u64xor (uquad1, uquad2): (uquad1 ! uquad2) : EndMacro
Macro u64not (uquad1): (~uquad1) : EndMacro
;### LOGICAL: returns 0 false or 1 true. (no Logical functions are required as PB's functions handle them fine)
;### 32bit DWORD
Macro u32_And (dword1, dword2): (dword1 And dword2) : EndMacro
Macro u32_Or (dword1, dword2): (dword1 Or dword2) : EndMacro
Macro u32_Not (dword1): Not (dword1) : EndMacro
;### 64bit QUAD
Macro u64_And (uquad1, uquad2): (uquad1 And uquad2) : EndMacro
Macro u64_Or (uquad1, uquad2): (uquad1 Or uquad2) : EndMacro
Macro u64_Not (uquad1): Not (uquad1) : EndMacro
;### TYPECAST
;### 32bit DWORD
u32tofloat.f (dword1.l) As #prefix$+"u32tofloat"
u32todouble.d (dword1.l) As #prefix$+"u32todouble"
u32fromfloat.l (float1.f) As #prefix$+"u32fromfloat"
u64fromu32.q (dword1.l) As #prefix$+"u64fromu32"
;### 64bit QUAD
u64todouble.d (uquad1.q) As #prefix$+"u64todouble"
u64fromdouble.q (double1.d) As #prefix$+"u64fromdouble"
;### MISC (Non-fundamental) #################################################
;Min/Max
u32min.l (dword1.l, dword2.l) As #prefix$+"u32min"
u32max.l (dword1.l, dword2.l) As #prefix$+"u32max"
u64min.q (uquad1.q, uquad2.q) As #prefix$+"u64min"
u64max.q (uquad1.q, uquad2.q) As #prefix$+"u64max"
;MinOf3/MaxOf3
u32minof3.l (dword1.l, dword2.l, dword3.l) As #prefix$+"u32minof3"
u32maxof3.l (dword1.l, dword2.l, dword3.l) As #prefix$+"u32maxof3"
u64minof3.q (uquad1.q, uquad2.q, uquad3.q) As #prefix$+"u64minof3"
u64maxof3.q (uquad1.q, uquad2.q, uquad3.q) As #prefix$+"u64maxof3"
;Mean
u32mean.l (dword1.l, dword2.l) As #prefix$+"u32mean"
u32meanf.f (dword1.l, dword2.l) As #prefix$+"u32meanf"
u64mean.q (uquad1.q, uquad2.q) As #prefix$+"u64mean"
u64meand.d (uquad1.q, uquad2.q) As #prefix$+"u64meand"
;Pow
u32pow.l (dwbase.l, dwexponent.l) As #prefix$+"u32pow"
u32powq.q (dwbase.l, dwexponent.l) As #prefix$+"u32powq"
u32fpow.f (dwbase.l, fexponent.f) As #prefix$+"u32fpow"
u32fpowq.d (dwbase.l, fexponent.f) As #prefix$+"u32fpowq"
u64pow.q (qbase.q, qexponent.q) As #prefix$+"u64pow"
u64fpow.d (qbase.q, dexponent.d) As #prefix$+"u64fpow"
;IsPow2
u32ispow2.i (dword1.l) As #prefix$+"u32ispow2"
u64ispow2.i (uquad1.q) As #prefix$+"u64ispow2"