Re: bigatom in The Archive
- Posted by cargoan Dec 22, 2014
- 1892 views
Also I have trigonometric functions (sin, cos, arctan), but I can not work well with my bigatoms. If someone who knows more than I want to review and perhaps find and fix.
This is what I have:
-- ##################################### -- ### FUNCIONES TRIGONOMÉTRICAS ### -- ##################################### -- -- sin(x) = x - x^3/3! + x^5/5! - x^7/7! ... override function sin(atom x) integer n = 3 atom curr = x, res = x atom nfact = 6, x2 = -x * x atom xpow = x2 * x while curr do curr = xpow / nfact res += curr n += 2 nfact *= n * n - n xpow *= x2 end while return res end function export function ba_sin(object x) if not bigatom(x) then if atom(x) then return ba_new(sin(x)) end if x = ba_new(x) end if integer n = 1 sequence curr, prev, res sequence nfact, mx2 sequence mx, xpow sequence sc = scale(SCALE + 2, 0) nfact = {1, 0, {6}} mx = x mx[SIGN] = -mx[SIGN] res = ZERO prev = ZERO curr = x mx2 = ba_multiply(mx, x) xpow = x -- ba_multiply(x, mx2) while not eu:equal(prev, curr) do -- while curr[SIGN] do prev = curr res = ba_add(res, curr) n += 2 nfact = ba_sub(ba_multiply(n, n), n) xpow = ba_multiply(xpow, mx2) curr = ba_divide(xpow, nfact) end while scale(sc) res[DIGITS] = remove(res[DIGITS], res[EXPONENT] + 2 + SCALE, length(res[DIGITS])) return normalize(res) end function -- cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8! - ... override function cos(atom x) integer n = 2 atom curr = 1, res = x atom nfact = 2, x2 = -x * x atom xpow = x2 while curr do curr = xpow / nfact res += curr n += 2 nfact *= n * n - n xpow *= x2 end while return res end function -- sacada de bc -- Usa la fórmula: -- atan(x) = atan(c) + atan((x-c)/(1+xc)) para c pequeño (0.2 en este caso) -- Por debajo de 0.2, usa la serie: -- atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ... -- override function arctan(atom x) integer sg = 1, mult = 0, n = 3 atom curr, res, xpow, x2 atom ap2 = 0.0 if x < 0 then sg = -1 x = -x end if if x > 0.2 then ap2 = arctan(0.2) end if -- hacer x <= 0.2 while x > 0.2 do mult += 1 x = (x - 0.2) / (1 + x * 0.2) end while curr = x xpow = x res = x x2 = -x * x while curr do xpow *= x2 curr = xpow / n res += curr n += 2 end while return sg * (res + mult * ap2) end function export function ba_arctan(object x) if not bigatom(x) then if atom(x) then return ba_new(arctan(x)) end if x = ba_new(x) end if sequence sc = scale(SCALE + (SCALE + 1)/ 2, 0) integer sg = 1, mult = 0, n = 3 sequence curr, res, xpow, x2 sequence ap2 = ZERO, p2 = {1,-1,{2}} if x[SIGN] < 0 then sg = -1 x[SIGN] = -x[SIGN] end if if eu:compare(x, p2) = SG_PLUS then ap2 = ba_arctan(0.2) end if -- hacer x <= 0.2 sequence a, b while eu:compare(x, p2) = SG_PLUS do mult += 1 -- x = (x - 0.2) / (1 + x * 0.2) a = ba_sub(x, p2) b = ba_add(ONE, ba_multiply(x, p2)) x = ba_divide(a, b) end while sequence limit = {x[SIGN], -(SCALE + 1), {1}} -- ba_power({x[SIGN],1,{1}}, -(SCALE + 6)) -- sequence prev = ZERO curr = x xpow = x res = x x2 = ba_multiply(x, x) x2[SIGN] = -x2[SIGN] -- while eu:compare(curr, prev) do -- esto es interminable -- while curr[SIGN] do -- como esto, es lo mismo while eu:compare(curr, limit) > 0 do -- esto no es correcto, sale antes de tiempo -- prev = curr xpow = ba_multiply(x, x2) curr = ba_divide(xpow, n) res = ba_add(res, curr) n += 2 limit[SIGN] = -limit[SIGN] end while scale(sc) res = ba_add(res, ba_multiply(mult, ap2)) return ba_multiply(res, sg) end function --
Atoms seem to go well with, but not bigatom. I do not know more, maybe later when I learn more ... but it would be very good to include sin, cos and arctan to complete the library. (arctan is a very important function)
Greets.
cargoan