[Feature Request] - Modulus/Remainder

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
matthew180
User
User
Posts: 64
Joined: Mon Jun 30, 2003 5:36 pm
Location: Michigan
Contact:

Post by matthew180 »

You need to go look at my post in the General forum:

"Inline ASM slower than equivalent PB code..."

The extra MUL and SUB insturction add only 3.2 milliseconds of overhead over a million iterations! Maybe not on an old 8086, but on today's CPU's with multiple pipelines, the PB code is almost as effiecient as the raw ASM code.

I wrote several MOD functions that I'm including in a math library for PB, here they are if you like. If you use the ASM versions you need to make sure the "inline assembly" option is set in your compiler options.

Matthew

Code: Select all


;
; FISHLIB MATH
;
; Matthew Hagerty - 2003.07.10
;


; Math Function Summary
Declare.l fl_mod(dividend.l, divisor.l)
Declare.l fl_mod_asm(dividend.l, divisor.l)
Declare.l fl_mod_asm_u(dividend.l, divisor.l)


;
; Returns the remainder (modulus) obtained by dividing
; one numeric expression into another.  The return
; value will have the same sign (+/-) as the dividend.
;
; Examples:
;
;   mod(6, 10) returns: 6
;   mod(10, 10) returns: 0
;   mod(-67, 10) returns: -7
;
Procedure.l fl_mod(dividend.l, divisor.l)

  ; Division by zero is illegal.
  If divisor = 0
    ProcedureReturn 0
  EndIf

  ProcedureReturn dividend - ((dividend / divisor) * divisor)

EndProcedure
; fl_mod()


;
; Same as fl_mod(), but implemented with inline assembly instead
; of PB code.
;
Procedure.l fl_mod_asm(dividend.l, divisor.l)

  ; Division by zero is illegal.
  If divisor = 0
    ProcedureReturn 0
  EndIf

  ; Oh yeah, assembly is great!  Saves a whole
  ; multiplication and subtraction!
  MOV eax, dividend
  CDQ
  IDIV divisor
  MOV dividend, edx

  ProcedureReturn dividend

EndProcedure
; fl_mod_asm()


;
; Returns the remainder (modulus) obtained by dividing
; one numeric expression into another.  This is the
; UNSIGNED version of the mod() function and will ignore
; any sign a number might have.
;
; Until PB supports unsigned vars, this function is only
; implemented with ASM.
;
; Examples:
;
;   mod(6, 10) returns: 6
;   mod(10, 10) returns: 0
;   mod(-67, 10) returns: 9 <-- This is correct, since -67 unsigned is 4294967229.
;
Procedure.l fl_mod_asm_u(dividend.l, divisor.l)

  ; Division by zero is illegal.
  If divisor = 0
    ProcedureReturn 0
  EndIf

  ; Oh yeah, assembly is great!  Saves a whole
  ; multiplication and subtraction!
  MOV eax, dividend
  XOR edx, edx
  DIV divisor
  MOV dividend, edx

  ProcedureReturn dividend

EndProcedure
; fl_mod_asm_u()

mp303

Post by mp303 »

This is a better workaround for sure, but it doesn't solve the problem - you still need a function call to calculate the modulus ... what we need is a modulus OPERATOR, like every other programming language has.

Or, of course, support for inline functions.

Although I would much prefer an operator for readability...
matthew180
User
User
Posts: 64
Joined: Mon Jun 30, 2003 5:36 pm
Location: Michigan
Contact:

Post by matthew180 »

mp303 wrote:This is a better workaround for sure, but it doesn't solve the problem - you still need a function call to calculate the modulus ... what we need is a modulus OPERATOR, like every other programming language has.

Or, of course, support for inline functions.

Although I would much prefer an operator for readability...
Oh, I totally agree, a modulus operator would be the best solution, but most BASIC langauges I've seen provide modulus as a function. The traditional mod operator '%' has other meanings in BASIC, and specifically PB. Any number starting with % is considered binary, and since space between numbers and operators is usually optional, you would never know if the user wanted mod or binary... I suppose you could choose another symbol, or the word Mod, just like And and Or.

However, the ASM version of my function is about as fast as you are going to get, even with an optimized inline operator. The only difference is the call to the function adds a little overhead. So, if you need it in a critical loop and can't spare a few cycles, just include it inline, or call it with GOSUB/RETURN.

Matthew
freedimension
Enthusiast
Enthusiast
Posts: 613
Joined: Tue May 06, 2003 2:50 pm
Location: Germany
Contact:

Post by freedimension »

matthew180 wrote:Any number starting with % is considered binary, and since space between numbers and operators is usually optional, you would never know if the user wanted mod or binary... I suppose you could choose another symbol, or the word Mod, just like And and Or.
This is fairly easy to tell. If there is another Operator directly in Front of the % the second Term (where a number) is supposed to be a binary. If in Front of the % there is another Term, this has to be a Modulo.
This is functioning perfectly, just look at the *. This also has two functions (pointer and multiplier).
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: [Feature Request] - Modulus/Remainder

Post by Trond »

There is still no % for floating point, why not add it? It should be simple with fprem.
Post Reply