Page 1 of 1

Comparison functions for unsigned integers

Posted: Wed Mar 08, 2017 1:52 am
by Demivec
Since the code itself comments on what it does I'll just mentioned briefly that I've implemented unsigned comparisons between two integers. The functions implemented were for '<', '<=', '>=', '>'.

It should be cross-platform and work with 32-bit and 64-bit compilations. It it is setup just for pointer (integer) sized values, which means if you need it to work with an unsigned quad in a 32-bit compilation it won't work as it currently is but all other size integers should work in 32-bit and all sizes in 64-bit.

Code: Select all

;File Name: Boolean unsigned integer comparisons.pbi
;Author: Demivec
;Created: 03/07/2017
;Version: v00.01
;OS: Windows, Linux, Mac (Only tested for Windows OS)
;Compiler: Compiler: PureBasic v5.44 LTS x64 (or PureBasic v5.44 LTS x32)
;License: Free to use and modify and comes without any guarantees of functionality or freedom from defects
;Forum: http://www.purebasic.fr/english/viewtopic.php?f=12&t=68050
;Description:  Boolean comparisons for unsigned integers.
;
;  Each function makes a comparison between its arguments (each treated as unsigned integers)
;  and returns either 1 if the comparison is true or 0 if it is false.
;
;  The four basic comparisons implemented are:
;
;    uIsLTEQ() ;'Is Less Than or Equal To'
;    uIsGT()   ;'Is Greater Than'
;    uIsGTEQ() ;'Is Greater Than or Equal To'
;    uIsLT()   ;'Is Less Than'
;
;  Each function was implemented on it's own and not in terms of each other.  For example,
;  uIsLTEQ() could have been implemented as 'Not uIsGT()', but wasn't.
;
;  PureBasic comparisons for 'Equal To' and 'Not Equal To' are the same for both signed and unsigned
;  values when the arguments are of the same type and thus don't require any special implementations.
;  
;  This set of functions were implemented to make more accurate comparisons between address pointers
;  without worry with regard to whether the addresses involved crossed over from positive to negative
;  values when interpreted as signed values (the way PureBasic deals with all integer values).
;
;  Hopefully this accomplishes that. ;)

;performs unsigned 'Is Less Than or Equal To' comparison
Procedure.i uIsLTEQ(val_1.i, val_2.i)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    XOr edx, edx  
    MOV eax, 1
    MOV ecx, val_1
    CMP ecx, val_2
    CMOVA eax, edx
  CompilerElse
    XOr rdx, rdx
    MOV rax, 1
    MOV rcx, val_1
    CMP rcx, val_2
    CMOVA rax, rdx
  CompilerEndIf
  DisableASM
  ProcedureReturn
EndProcedure

;performs unsigned 'Is Greater Than' comparison
Procedure.i uIsGT(val_1.i, val_2.i)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    XOr edx, edx  
    MOV eax, 1
    MOV ecx, val_1
    CMP ecx, val_2
    CMOVNA eax, edx
  CompilerElse
    XOr rdx, rdx
    MOV rax, 1
    MOV rcx, val_1
    CMP rcx, val_2
    CMOVNA rax, rdx
  CompilerEndIf
  DisableASM
  ProcedureReturn
EndProcedure

;performs unsigned 'Is Greater Than or Equal To' comparison
Procedure.i uIsGTEQ(val_1.i, val_2.i)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    XOr edx, edx  
    MOV eax, 1
    MOV ecx, val_1
    CMP ecx, val_2
    CMOVB eax, edx
  CompilerElse
    XOr rdx, rdx
    MOV rax, 1
    MOV rcx, val_1
    CMP rcx, val_2
    CMOVB rax, rdx
  CompilerEndIf
  DisableASM
  ProcedureReturn
EndProcedure

;performs unsigned 'Is Less Than' comparison
Procedure.i uIsLT(val_1.i, val_2.i)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    XOr edx, edx  
    MOV eax, 1
    MOV ecx, val_1
    CMP ecx, val_2
    CMOVNB eax, edx
  CompilerElse
    XOr rdx, rdx
    MOV rax, 1
    MOV rcx, val_1
    CMP rcx, val_2
    CMOVNB rax, rdx
  CompilerEndIf
  DisableASM
  ProcedureReturn
EndProcedure

CompilerIf #PB_Compiler_IsMainFile
  ;demo
  Procedure test(a, b)
    If uIsLTEQ(a, b)
      Debug "$" + Hex(a) + " <= $" + Hex(b)
    Else
      Debug "$" + Hex(a) + " > $" + Hex(b)
    EndIf
    
    If uIsGT(a, b)
      Debug "$" + Hex(a) + " > $" + Hex(b)
    Else
      Debug "$" + Hex(a) + " <= $" + Hex(b)
    EndIf
    
    If uIsLT(a, b)
      Debug "$" + Hex(a) + " < $" + Hex(b)
    Else
      Debug "$" + Hex(a) + " >= $" + Hex(b)
    EndIf
    
    If uIsGTEQ(a, b)
      Debug "$" + Hex(a) + " >= $" + Hex(b)
    Else
      Debug "$" + Hex(a) + " < $" + Hex(b)
    EndIf
    Debug "---------------"
  EndProcedure
  
  test(0, 1)
  test(0, 0)
  test(1, 0)
  test(-3, 5) ;arguments are treated as unsigned
  test(5, -3) ;arguments are treated as unsigned

;A test with pointers and a possible problem situation
  Debug "-------Without unsigned comparisons------"
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    *ReadByte = $7FFFFFF8 ;near boundary x86 
  CompilerElse
    *ReadByte = $7FFFFFFFFFFFFFF8 ;near boundary x64
  CompilerEndIf
  
  *ReadEnd = *ReadByte + 16 ;go past boundary
  While *ReadByte < (*ReadEnd - 3)
    
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
      Debug Hex(*ReadByte, #PB_Long)
    CompilerElse
      Debug Hex(*ReadByte, #PB_Quad)
    CompilerEndIf
    *ReadByte + 1
  Wend
  
  Debug "-------With unsigned comparisons---------"
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    *ReadByte = $7FFFFFF8 ;near boundary x86
  CompilerElse
    *ReadByte = $7FFFFFFFFFFFFFF8 ;near boundary x64
  CompilerEndIf
  *ReadEnd = *ReadByte + 16
  While uIsLT(*ReadByte, (*ReadEnd - 3))
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
      Debug Hex(*ReadByte, #PB_Long)
    CompilerElse
      Debug Hex(*ReadByte, #PB_Quad)
    CompilerEndIf
    *ReadByte + 1
  Wend
CompilerEndIf
Just for reference here is a link to some other unsigned integer functions, uMin(), uMax(), and a link to LibUnsigned Lib by Keya if you need an even more complete set.

Re: Comparison functions for unsigned integers

Posted: Fri Mar 10, 2017 6:20 pm
by mk-soft

Re: Comparison functions for unsigned integers

Posted: Fri Mar 10, 2017 7:56 pm
by Demivec
mk-soft wrote:Sorry... :wink:
Thanks for the link to a variant solution. :)


Here are two additional links to solutions or 'helps' for unsigned integers: EnableUnsigned() macro by idle & Peek4u() & Poke4u() by Little John.


@Edit: Added several other links.