Newsgroup: it.scienza.informatica
Titolo: funzione tangente

qualcuno mi sa spiegare in breve come č discretizzata la funzione (C)
"double tan (double)" ? e qual'č il suo tempo di calcolo? ovvero, quanto
pesa? ci sono modi piů leggeri per computarla mantenendo una approssimazione
simile?
grazie
die

 writes:
diebugger> qualcuno mi sa spiegare in breve come č discretizzata la
diebugger> funzione (C) "double tan (double)" ?
Complimenti per la curiosita` della domanda, ho notato che nessuno ti
aveva risposto..
al compilatore dovrebbe spettare la decisione, solitamente
i microprocessori dispongono di una unita` di floating point, che
solitamente ha l'istruzione FTAN. Oppure ci sono casi in cui questa istruzione
va scomposta in istruzioni tipo FSINCOS seguito da FDIV come nei 287.
Inoltre per non appesantire troppo il firmware dell'FPU 80x87
ignegneri di Intel Corp hanno anche predisposto l'istruzione FPTAN.
a pagina 325 di
http://developer.intel.com/design/pentium4/manuals/25366615.pdf
si legge:
  <<The instruction does not raise an exception when the source
operand is out of range. It is up to the program to check the C2 flag
for out-of- range conditions.
Source values outside the range -263 to +263 can be reduced to
the range of the instruction by subtracting an appropriate
integer multiple of 2 or by using the FPREM instruction
with a divisor of 2. See the section titled "Pi" in Chapter 8 of the
IA-32 Intel Architecture Software Developer's Manual, Volume 1, for a
discussion of the proper value to use for in performing such reductions.>>
Questo e` solo un esempio di quello che il compilatore ci si
aspetta abbia considerato. Qui un grazie anche a Richard Stallman.
Infatti la libreria C ad esempio di GNU/linux compilata per x86
risolve la funzione tan (di <math.h> presa da libm.so (di libc5/6))
con le seguenti istruzioni (in stack l'input (operando di tan)):
;Dump of assembler code for function tan:
	fldl	0x4(%esp)	; Fpu LoaD CPU stack content to to fpu stack 
	fptan			; Fpu Partial TANgent
	fnstsw	%ax		; STore Status Word into ax register
	test	$0x400,%eax	; test C2 flag
	jne	outrng		; jump if not equal
	fstp	%st(0)		;
	ret			; return
outrng:	fldpi			; Fpu LoaD PI
	fadd	%st(0),%st	; aggiunge quindi PI allo stack dell'FPU
	fxch	%st(1)
loop:	fprem1			; resto della divisione intera con PI
	fstsw  %ax
	test   $0x400,%eax
	jne    loop
	fstp   %st(1)
	fptan
	fstp   %st(0)
	ret
Nota: le istruzioni f... sono per x87, se non ricordo male hanno un
      prefisso macchina 0xF0 che sposta l'opcode all'FPU, le altre
      sono istruzioni assembly per il microprocessore della famiglia x86+
Quindi solitamente la discretizzazione dipende prima dall'elettronica
che rappresentando il numero floating point in uno standard IEEE,
ed e` discretizzato in modo da ottenere tanto piu` precisi quanto piu`
vicini a zero e pi/2, nel rispetto della sua rappresentazione
nel minor tempo possibile.
Gli attuali microprocessori intel ad esempio dovrebbero rispettare
una precisone di 61bit su 64 nel caso peggiore (nell'intervallo 0..pi/2)
puoi approfondire con il test "paranoia" di gcc.
il firmware mi aspetto faccia un calcolo legato alla serie di Taylor
(non l'ho visto esplicitato nella documentazione)
o usando qualche proprieta` che puoi vedere in
http://functions.wolfram.com/ElementaryFunctions/Tan/
L'emulatore wm-emu387 ad opera di DJ Delorie scritto per djgpp di cui
e` rimasta traccia perfino nel sorgente del kernel di linux, questo
emulatore mostra un algoritmo efficiente per calcolare anche la tangente:
v dal sorgente   linux/arch/i386/math-emu/poly_tan.c
o lo stesso file (poly_tan.c) in versione navigabile:
 
http://joshua.raleigh.nc.us/docs/linux-2.4.7_html/46270.html
questo riporta il valore esadecimale approssimato di pigreco/2,
....l'inizio esadecimale di pigreco piu` preciso sarebbe:
3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D\
01377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD1310BA6\
98DFB5AC2FFD72DBD01ADFB7B8E1AFED6A267E969
e quindi pigreco mezzi (PI/2 hexadecimal) e` meglio approssimato da
1.921FB54442D18469898CC51701B839A252049C1114CF98E804177D4C76273644A29410F31C6\
809BBDF2A33679A748636605614DBE4BE286E9FC26ADADAA3848BC90B6AECC4BCFD8DE89885D3\
4C6FDAD617FEB96DE80D6FDBDC70D7F6B5133F4B4
si veda  
http://www.cecm.sfu.ca/~pborwein/PAPERS/P123.ps
per il metodo di calcolo efficiente di queste costanti polilogaritmiche
diebugger> e qual'č il suo tempo di calcolo?
diebugger> ovvero, quanto pesa? ci sono modi piů leggeri per
diebugger> computarla mantenendo una approssimazione simile?
se non ricordo male le istruzioni trigonometriche come FPTAN
eseguite dall'FPU impiegano una quarantina di cicli di clock,
quindi e` impensabile "alleggerirle", a meno che occorra un risultato
proprio molto approssimato, o meglio con dominio di calcolo a ridotta
cardinalita`, per cui una tabellina di calcoli prediscretizzati
o messi in una sorta di cache potrebbe risultare un po' piu` veloce
della quarantina di cicli di clock.
diebugger> grazie
diebugger> die
simpatico test della precisione per la tangente e` il multiplo numerico
abbastanza preciso di  pi:  8227740058411162616.0000000
(con le cifre significative indicate)
C'era anche una versione militare del chip 387, la trovate descritta in:
http://sunsite.rediris.es/sites/download.intel.nl/design/specenvn/INTARCH/DATASHTS/27107406.pdf
All the best,
MARco Munari
progress is due to perfect exception.
-- 
xref:    
http://mar.i.am/~u16568.20018/it.scienza.informatica/ftan,it
x(t),y(t) = th(3t-34.5)*e^[-(3t-34.5)^2]/2-4.3+e^(-1.8/t^2)/(.8*atg(t-
3)+2)(t-1.8)-.3th(5t-42.5),(1.4e^[-(3t-34.5)^2]+1-sgn[|t-8.5|-.5]*1.5*
|sin(pi*t)|^[2e^(-(t-11.5)^2)+.5+e^(-(.6t-3.3)^2)])/(.5+t)+1  ; 0<t<14