Floor()

Share your advanced PureBasic knowledge/code with the community.
remi_meier
Enthusiast
Enthusiast
Posts: 468
Joined: Sat Dec 20, 2003 6:19 pm
Location: Switzerland

Post by remi_meier »

Is it more accurate than the normal FPU rounding?

Code: Select all

Structure s_Round 
  StructureUnion 
    ; 
    i.q 
    u.q 
    f.d 
    ; 
  EndStructureUnion 
EndStructure 
Procedure.l Round2(Value.d) 
  ; 
  Protected temp.s_Round 
  ; 
  temp\f = Value + 6755399441055744.0 
  ; 
  ProcedureReturn temp\u 
  ; 
EndProcedure 

Procedure.l Round3(Value.d)
  ProcedureReturn Value
EndProcedure

Debug Round2(328569072.31) 
Debug Round2(328569072.51)
Debug Round3(328569072.31) 
Debug Round3(328569072.51)
Athlon64 3700+, 1024MB Ram, Radeon X1600
citystate
Enthusiast
Enthusiast
Posts: 638
Joined: Sun Feb 12, 2006 10:06 pm

what about negative numbers?

Post by citystate »

Your procedure seems to work fine for positive numbers, but FLOOR should calculate negative numbers differently. Seeing that the function of FLOOR is to round down, a negative number should round down to the number with a larger absolute value. That is FLOOR( -7.8 ) should equal -8 not -7.

Code: Select all

 floor = INT(number*POW(10,precision))/POW(10,precision) 
does the same thing as your proposed FLOOR procedure
there is no sig, only zuul (and the following disclaimer)

WARNING: may be talking out of his hat
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Re: Floor()

Post by jack »

I know it's an old thread but why make a new thread of the same subject?
for 32-bit change rax to eax

btw in the procedure PBfrac the result is not returned unless assigned to a variable

Code: Select all

ImportC ""
  floor.d( doubleValue.d)
  ceil.d( doubleValue.d)
  trunc.d( doubleValue.d)
EndImport

Procedure.i PBfloor(x.d)
	EnableASM
    movsd xmm0,[p.v_x]
		!roundsd   xmm0, xmm0, 9
		!cvttsd2si rax,  xmm0
  DisableASM
  ProcedureReturn
EndProcedure

Procedure.i PBceil(x.d)
	EnableASM
    movsd xmm0,[p.v_x]
		!roundsd   xmm0, xmm0, 10
		!cvttsd2si rax,  xmm0
  DisableASM
  ProcedureReturn
EndProcedure

Procedure.i PBtrunc(x.d)
	EnableASM
    movsd xmm0,[p.v_x]
		!cvttsd2si rax,  xmm0
  DisableASM
  ProcedureReturn
EndProcedure

Procedure.d PBfrac(x.d)
  frc.d
	EnableASM
    movsd xmm0,[p.v_x]
		!cvttsd2si rax,  xmm0
		!cvtsi2sd xmm1,rax
		!subsd  xmm0,xmm1
		movsd [p.v_frc],xmm0
  DisableASM
  ProcedureReturn frc
EndProcedure

i.i
x.d=4
y.d=0.1
Debug "PBfloor CRTfloor  PBceil   CRTceil  PBtrunc CRTtrunc  PBfrac"
For i=1 To 12
  s.s="("+StrD(PBfloor(x),4)+" , "+StrD(floor(x),4)+"), ("+StrD(PBceil(x),4)+" , "+StrD(ceil(x),4)
  s+"), ("+StrD(PBtrunc(x),4)+" , "+StrD(trunc(x),4)+")  "+StrD(PBfrac(x),15)
  Debug s
  x+y
Next
x=-4
Debug "PBfloor  CRTfloor   PBceil    CRTceil    PBtrunc CRTtrunc    PBfrac"
For i=1 To 12
  s.s="("+StrD(PBfloor(x),4)+" , "+StrD(floor(x),4)+"), ("+StrD(PBceil(x),4)+" , "+StrD(ceil(x),4)
  s+"), ("+StrD(PBtrunc(x),4)+" , "+StrD(trunc(x),4)+")  "+StrD(PBfrac(x),15)
  Debug s
  x-y
Next
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Floor()

Post by wilbert »

roundsd requires SSE4.1
If you use it, it might be a good idea to check if the cpu supports it.
When SSE 4.1 isn't present, the MXCSR register could be used instead to control rounding mode.

x86 alternative for frac which uses 64 bit integer instead of 32.

Code: Select all

Procedure.d frac(x.d)
  !fld qword [p.v_x]
  !fld st0
  !fisttp qword [p.v_x]
  !fild qword [p.v_x]
  !fsubp
  !fstp qword [p.v_x]
  ProcedureReturn x
EndProcedure
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply