Page 2 of 2

Posted: Fri Dec 29, 2006 6:33 pm
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)

what about negative numbers?

Posted: Tue Jan 02, 2007 6:35 am
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

Re: Floor()

Posted: Mon Jan 30, 2017 1:08 am
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

Re: Floor()

Posted: Mon Jan 30, 2017 7:10 am
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