Function DMS

Bare metal programming in PureBasic, for experienced users
Mesa
Enthusiast
Enthusiast
Posts: 342
Joined: Fri Feb 24, 2012 10:19 am

Function DMS

Post by Mesa »

Do you have in your archive, a function in assembler to convert decimal degrees to degree minutes seconds ?

Like that:
dms(10.50) = 10.30 (10 degrees and 30 minutes)
dms(10.50833333) = 10.3030

Thanks.

M.
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: Function DMS

Post by Helle »

For fun with FPU, SSE and SSE2; PB 64-bit:

Code: Select all

;PB 5.61 (x64)
Procedure.s DMS_FPU(DD.d)
  !fstcw word[CW_FPU]
  !mov ax,[CW_FPU]
  !or [CW_FPU],0000110000000000b  ;no rounding, truncation
  !fldcw word[CW_FPU]

  !fld qword[p.v_DD]         ;no check of range!
  !fist word[DMS_FPU]
  !fisub word[DMS_FPU]
  !fmul qword[V60_FPU]
  !fist word[DMS_FPU+2]
  !mov [CW_FPU],ax
  !fldcw word[CW_FPU]        ;restore ControlWord, rounding seconds
  !fisub word[DMS_FPU+2]
  !fmul qword[V60_FPU]
  !fistp word[DMS_FPU+4]     ;second as rounded integer

  DMS_FPU$ = Str(PeekW(?DMS_FPU)) + "." + RSet(Str(PeekW(?DMS_FPU + 2)), 2, "0") + RSet(Str(PeekW(?DMS_FPU + 4)), 2, "0")
 ProcedureReturn DMS_FPU$

  DataSection
    DMS_FPU:                 ;Degree Minute Second
      !DMS_FPU  dq ?
      !V60_FPU  dq 60.0  
      !CW_FPU   dw ?         ;FPU-ControlWord
  EndDataSection

EndProcedure

Debug DMS_FPU(10.50833333)
Debug DMS_FPU(10.50)
Debug DMS_FPU(123.987654)

Debug "============="

Procedure.s DMS_SSE(DD.f)
  !cvttss2si eax,xmm0
  !mov word[DMS_SSE],ax
  !cvtsi2ss xmm1,eax
  !subss xmm0,xmm1
  !mulss xmm0,[V60_SSE]
  !cvttss2si eax,xmm0
  !mov word[DMS_SSE+2],ax
  !cvtsi2ss xmm1,eax
  !subss xmm0,xmm1
  !mulss xmm0,[V60_SSE]
  !cvtss2si eax,xmm0
  !mov word[DMS_SSE+4],ax

  DMS_SSE$ = Str(PeekW(?DMS_SSE)) + "." + RSet(Str(PeekW(?DMS_SSE + 2)), 2, "0") + RSet(Str(PeekW(?DMS_SSE + 4)), 2, "0")
 ProcedureReturn DMS_SSE$

  DataSection
    DMS_SSE:                 ;Degree Minute Second
      !DMS_SSE  dq ?
      !V60_SSE  dd 60.0  
  EndDataSection

EndProcedure

Debug DMS_SSE(10.50833333)
Debug DMS_SSE(10.50)
Debug DMS_SSE(123.987654)

Debug "============="

Procedure.s DMS_SSE2(DD.d)
  !cvttsd2si eax,xmm0
  !mov word[DMS_SSE2],ax
  !cvtsi2sd xmm1,eax
  !subsd xmm0,xmm1
  !mulsd xmm0,[V60_SSE2]
  !cvttsd2si eax,xmm0
  !mov word[DMS_SSE2+2],ax
  !cvtsi2sd xmm1,eax
  !subsd xmm0,xmm1
  !mulsd xmm0,[V60_SSE2]
  !cvtsd2si eax,xmm0
  !mov word[DMS_SSE2+4],ax

  DMS_SSE2$ = Str(PeekW(?DMS_SSE2)) + "." + RSet(Str(PeekW(?DMS_SSE2 + 2)), 2, "0") + RSet(Str(PeekW(?DMS_SSE2 + 4)), 2, "0")
 ProcedureReturn DMS_SSE2$

  DataSection
    DMS_SSE2:                ;Degree Minute Second
      !DMS_SSE2  dq ?
      !V60_SSE2  dq 60.0  
  EndDataSection

EndProcedure

Debug DMS_SSE2(10.50833333)
Debug DMS_SSE2(10.50)
Debug DMS_SSE2(123.987654)
Mesa
Enthusiast
Enthusiast
Posts: 342
Joined: Fri Feb 24, 2012 10:19 am

Re: Function DMS

Post by Mesa »

Woah, very impressive.
Thanx.

DMS_FPU(DD.d) works very well with x86 but not DMS_SSE(DD.f) and DMS_SSE2(DD.d).

Could you tell me why DMS_SSE(DD.f) and DMS_SSE2(DD.d) return 0 with x86 ?
( they use 32b eax and xmm0,1 so they should work in x86, no ?)
Thanx.

M.
Post Reply