Error in Eiffel implementation of Burnikel and Ziegler algorithm 2 - algorithm
I need another set of eyes to tell me what is wrong with my Eiffel implementation of Burnikel and Ziegler's division, specifically "Algorithm 2 - 3n/2n". The Eiffel feature is shown below. The type "like Current" is an ARRAYED_LIST [NATURAL_8]. In other words, the implementation uses digits (i.e. limbs) containing 8-bit values, so numbers are in base-256. A manual trace of a failing call follows. (Sorry the arguments are so large, but I cannot reproduce the error with shorter values.) Execution follows step 3b in this case.
Here's the problem. The algorithm seems to be fine to Step 5, where the remainder "r" ends up with more digits then the divisor. I believe the error is in step 3b, perhaps with the call to feature `ones' which is "supposed" to supply a value that is "Beta^n - 1". (Maybe I do not understand B&Z's "Beta^n" notation.
Here is the Eiffel code:
three_by_two_divide (a, a3, b: like Current): TUPLE [quot, rem: like Current]
-- Called by `two_by_one_divide'. It has similar structure as
-- `div_three_halves_by_two_halfs', but the arguments to this
-- function have type {JJ_BIG_NATURAL} instead of like `digit'.
-- See Burnikel & Zieler, "Fast Recursive Division", pp 4-8,
-- Algorithm 2.
require
n_not_odd: b.count >= div_limit and b.count \\ 2 = 0
b_has_2n_digits: b.count = a3.count * 2
a_has_2n_digits: a.count = a3.count * 2
local
n: INTEGER
a1, a2: like Current
b1, b2: like Current
tup: TUPLE [quot, rem: like Current]
q, q1, q2, r, r1: like Current
c, d: like Current
do
n := b.count // 2
-- 1) Split `a'
a1 := new_sub_number (n + 1, a.count, a)
a2 := new_sub_number (1, n.max (1), a)
-- 2) Split `b'.
b1 := new_sub_number (n + 1, b.count, b)
b2 := new_sub_number (1, n.max (1), b)
-- 3) Distinguish cases.
if a1 < b1 then
-- 3a) compute Q = floor ([A1,A2] / B1 with remainder.
if b1.count < div_limit then
tup := school_divide (a, b1)
else
tup := two_by_one_divide (a, b1)
end
q := tup.quot
r1 := tup.rem
else
-- 3b) Q = beta^n - 1 and ...
q := ones (n)
-- ... R1 = [A1,A2] - [B1,0] + [0,B1] = [A1,A2] - QB1.
r1 := a + b1
if n > 1 then
b1.shift_left (n)
else
b1.bit_shift_left (zero_digit.bit_count // 2)
end
r1.subtract (b1)
end
-- 4) D = Q * B2
d := q * b2
-- 5) R1 * B^n + A3 - D. (The paper says "a4".)
r1.shift_left (n)
r := r1 + a3 - d
-- 6) As long as R < 0, repeat
from
until not r.is_negative
loop
r := r + b
q.decrement
end
check
remainder_small_enough: r.count <= b.count
-- because remainder must be less than divisor.
end
Result := [q, r]
ensure
-- n_digit_remainder: Result.rem.count = b.count // 2
quotient_has_correct_count: Result.quot.count <= b.count // 2
end
In the trace, the arrow points to a line I believe is bad, but I don't know what to do with it. Here is the trace:
three_by_two_divide (a = [227,26,41,95,169,93,135,110],
a3 = [92,164,19,39],
b = [161,167,158,41,164,0,0,0])
n := b.count // 2 = 4
-- 1) Split `a'.
a1 := new_sub_number (n + 1, a.count, a) = [227,26,41,95]
a2 := new_sub_number (1, n.max (1), a) = [169,93,135,110]
-- 2) Split `b'.
b1 := new_sub_number (n + 1, b.count, b) = [161,167,158,41]
b2 := new_sub_number (1, n.max (1), b) = [164,0,0,0]
-- 3b) Q = beta^n -1 and ...
--> q := ones (4) = [255,255,255,255] <-- Is this the error?
-- ... R1 = [A1,A2] - [B1,0] + [0,B1].
r1 := a + b1 = [227,26,41,96,75,5,37,151]
b1.shift_left (n) = [161,167,158,41,0,0,0,0]
r1.subtract (b1) = [65,114,139,55,75,5,37,151]
d := q * b2 = [163,255,255,255,92,0,0,0]
r1.shift_left (n) = [227,25,135,184,172,220,37,151,0,0,0,0] -- too big!
r := r1 + a3 - d -= [227,25,135,184,8,220,37,152,0,164,19,39] -- too big!
I know this is long, but any help is appreciated.
I would suggest to check that r1 = [65,114,139,55,75,5,37,151] is still the same before doing r1.shift_left (n). There are two options:
d := q * b2 affects r1 while it should not. Most probably there is some aliasing, i.e. r1 is aliased with some other variable that is updated and this aliasing should be removed.
r1 is still the same after d := q * b2. The issue is with shift_left that fails to (re)initialize some data or uses global data that it should not.
Related
Binary splitting algorithm needed for nested hypergeometric-type rational sums
There are some good sources on-line to implement fast summation using binary splitting techniques. For example, Ch. 20, Jörg Arndt Book, (2004), Cheng et al. (2007) and papers from Haible and Papanikolaou (1997) and distributed with the CLN library source code. From this last article, the following notes apply to the evaluation of this kind of linearly convergent series (Type 1) S = SUM(n=0,+oo,a(n)/b(n)*PROD(k=0,n,p(k)/q(k))) where a(n), b(n), p(n), q(n) are integers with O(log N) bits. The most often used case is that a(n), b(n), p(n), q(n) are polynomials in n with integer coefficients. Sum S is computed considering the following sequence of partial series with given two index bounds [n1, n2] S(n1,n2) = SUM(n=n1,n2-1,a(n)/b(n)*PROD(k=n1,n,p(k)/q(k)) S(n1,n2) are not computed directly. Instead, the product of integers P = p(n1) ... p(n2-1) Q = q(n1) ... q(n2−1) B = b(n1) ... b(n2-1) T = B Q S are computed recursively by binary splitting until n2 - n1 < 5 when these are computed directly. Choose an index nm in the middle of n1 and n2, compute the components Pl, Ql, Bl , Tl belonging to the interval n1 =< n < nm, compute the components Pr, Qr , Br, Tr belonging to the interval nm =< n < n2 and set these products and sums P = Pl Pr Q = Ql Qr, B = Bl Br T = Br Qr Tl + Bl Pl Tr Finally, this algorithm is applied to n1 = 0 and n2 = nmax = O(N), and a final floating-point division S = T/(B Q) is performed. The bit complexity of computing S with N bits of precision is O((log N)^2 M(N)) where M(N) is the bit complexity of the multiplication of two N-bit numbers. A slightly modified but more complex series (Type 2) that is found in the last reference above can be also summed by binary splitting. It has an additional inner sum of rationals where c(n) and d(n) are integers with O(log N) bits U = SUM(n=0,+oo,a(n)/b(n) * PROD(k=0,n,p(k)/q(k)) * SUM(m=0,n,c(m)/d(m))) We consider these partial sums U(n1,n2) = SUM(n=n1,n2-1,a(n)/b(n) * PROD(k=n1,n,p(k)/q(k)) * SUM(m=n1,n,c(m)/d(m))) The algorithm is a variation of the above as follows. P = p(n1) ... p(n2-1) Q = q(n1) ... q(n2−1) B = b(n1) ... b(n2-1) T = B Q S D = d(n1) ... d(n2-1) C = D (c(n1)/d(n1) + ... + c(n2-1)/d(n2-1)) V = D B Q U If n2 - n1 =< 4 these values are computed directly. If n2 - n1 > 4 they are computed by binary splitting. Choose an index nm in the middle of n1 and n2, compute the components Pl, Ql, Bl , Tl, Dl, Cl, Vl belonging to the interval n1 =< n < nm, compute the components Pr, Qr , Br, Tr, Dr, Cr, Vr belonging to the interval nm =< n < n2 and set these products and sums P = Pl Pr Q = Ql Qr B = Bl Br T = Br Qr Tl + Bl Pl Tr D = Dl Dr C = Cl Dr + Cr Dl V = Dr Br Qr Vl + Dr Cl Bl Pl Tr + Dl Bl Pl Vr At last, this algorithm is applied to n1 = 0 and n2 = nmax = O(N), and final floating point divisions are performed S = T / (B Q) V = U / (D B Q) I have programmed both algorithms in Pari-GP and applied them to compute some mathematical constants using Chudnovsky's formula for Pi, this formula for Catalan Constant and more. (I have got more than 1000000 decimal digits in some cases under this platform). This code has been used to compute some difficult series as well. I want to go one step ahead to accelerate some series by mixing binary splitting algorithm and levin-type sequence transformations. To do this I need to find the binary splitting relationships for a slight extension of these series. W = SUM(n=0,+oo,a(n)/b(n) * PROD(k=0,n,p(k)/q(k)) * SUM(m=0,n,c(m)/d(m) * PROD(i=0,m,f(i)/g(i)))) It has has an additional product of rationals inside the inner sum where f(n) and g(n) are integers with O(log N) bits. These series are not hypergeometric but they are nested hypergeometric type sums. I think this algorithm might be derived from these partial series W(n1,n2) = SUM(n=n1,n2-1,a(n)/b(n) * PROD(k=n1,n,p(k)/q(k)) * SUM(m=n1,n,c(m)/d(m) * PROD(i=n1,m,f(i)/g(i)))) I would very much appreciate if someone can derive the product and sum steps to bin-split this type of series. I will leave the PARI-GP code for computing fast linearly convergent series of type 1 and 2 as explained. Use ?sumbinsplit for help. There are some Testing examples for Type 2 series as well. You can un-comment one of them and use precision(-log10(abs(sumbinsplit(~F)[1]/s-1)),ceil(log10(Digits()))); to check it. \\ ANSI COLOR CODES { DGreen = Dg = "\e[0;32m"; Brown = Br = "\e[0;33m"; DCyan = Dc = "\e[0;36m"; Purple = Pr = "\e[0;35m"; Gray = Gy = "\e[0;37m"; Red = Rd = "\e[0;91m"; Green = Gr = "\e[0;92m"; Yellow = Yw = "\e[0;93m"; Blue = Bl = "\e[0;94m"; Magenta = Mg = "\e[0;95m"; Cyan = Cy = "\e[0;96m"; Reset = "\e[0m"; White = Wh = "\e[0;97m"; Black = Bk = "\e[0;30m"; } eps()={ my(e=1.); while(e+1. != 1., e>>=1); e; } addhelp(eps,Str(Yw,"\n SMALLEST REAL NUMBER\n",Wh,"\n eps() ",Gr,"returns the minimum positive real number for current precision")); log10(x) = if(x==0,log(eps()),log(x))/log(10); Digits(n) = if(type(n) == "t_INT" && n > 0,default(realprecision,n); precision(1.), precision(1.)); addhelp(Digits,Str(Yw,"\n DIGITS\n",Wh,"\n Digits(n)",Gr," Sets global precision to",Wh," n",Gr," decimal digits.",Wh," Digits()",Gr," returns current global precision.")); addhelp(BinSplit2,Str(Yw,"\n SERIES BINARY SPLITTING (TYPE 2)\n\n",Wh,"BinSplit(~F,n1,n2)",Gr," for ",Wh,"F = [a(n),b(n),p(n),q(n),c(n),d(n)]",Gr," a vector of ",Br,"t_CLOSUREs",Gr," whose\n components are typically polynomials, computes by binary splitting method sums of type\n\n",Wh,"S2 = sum(n=n1,n2-1,a(n)/b(n)*prod(k=n1,n,p(k)/q(k))*sum(m=n1,n,c(m)/d(m)))\n\n",Gr,"Output: ",Wh," [P,Q,B,T,D,C,V]",Gr," integer valued algorithm computing parameters")); addhelp(BinSplit1,Str(Yw,"\n SERIES BINARY SPLITTING (TYPE 1)\n\n",Wh,"BinSplit(~F,n1,n2)",Gr," for ",Wh,"F = [a(n),b(n),p(n),q(n)]",Gr," a vector of ",Br,"t_CLOSUREs",Gr," whose components\n are typically polynomials, computes by binary splitting method sums of type\n\n",Wh,"S1 = sum(n=n1,n2-1,a(n)/b(n)*prod(k=n1,n,p(k)/q(k)))\n\n",Gr,"Output: ",Wh,"[P,Q,B,T]",Gr," integer valued algorithm computing parameters")); BinSplit2(~F, n1, n2) = { my( P = 1, Q = 1, B = 1, T = 0, D = 1, C = 0, V = 0, LP, LQ, LB, LT, LD, LC, LV, RP, RQ, RB, RT, RD, RC, RV, nm, tmp1 = 1, tmp2, tmp3 ); \\ \\ F = [a(n),b(n),p(n),q(n),c(n),d(n)] \\ if( n2 - n1 < 5, \\ \\ then \\ for ( j = n1, n2-1, LP = F[3](j); LQ = F[4](j); LB = F[2](j); LD = F[6](j); LC = F[5](j); \\ tmp2 = LB * LQ; tmp3 = LP * F[1](j) * tmp1; T = T * tmp2 + tmp3; C = C * LD + D * LC; V = V * tmp2 * LD + C * tmp3; P *= LP; Q *= LQ; B *= LB; D *= LD; tmp1 *= LP * LB; ), \\ \\ else \\ nm = (n1 + n2) >> 1; \\ [RP,RQ,RB,RT,RD,RC,RV] = BinSplit2(~F, nm, n2); [LP,LQ,LB,LT,LD,LC,LV] = BinSplit2(~F, n1, nm); \\ tmp1 = RB * RQ; tmp2 = LB * LP; tmp3 = LC * RD; \\ P = LP * RP; Q = RQ * LQ; B = LB * RB; T = LT * tmp1 + RT * tmp2; D = LD * RD; C = RC * LD + tmp3; V = RD * LV * tmp1 + ( RT * tmp3 + LD * RV ) * tmp2; \\ \\ end if ); return([P,Q,B,T,D,C,V]); } BinSplit1(~F, n1, n2) = { my( P = 1, Q = 1, B = 1, T = 0, LP, LQ, LB, LT, RP, RQ, RB, RT, tmp1 = 1, nm ); \\ \\ F = [a(n),b(n),p(n),q(n)] \\ if( n2 - n1 < 5, \\ \\ then \\ for ( j = n1, n2-1, LP = F[3](j); LQ = F[4](j); LB = F[2](j); \\ T = T * LB * LQ + LP * F[1](j) * tmp1; P *= LP; Q *= LQ; B *= LB; \\ tmp1 *= LP * LB; ), \\ \\ else \\ nm = (n1 + n2) >> 1; \\ [RP,RQ,RB,RT] = BinSplit1(~F, nm, n2); [LP,LQ,LB,LT] = BinSplit1(~F, n1, nm); \\ P = LP * RP; Q = RQ * LQ; B = LB * RB; T = LT * RB * RQ + RT * LB * LP; \\ \\ end if ); return([P,Q,B,T]); } sumbinsplit(~F, n1 = 1, dgs = getlocalprec()) = { my( n = #F, P, Q, B, T, D, C, V, [a,b] = F[3..4] ); my( n2 = 1 + ceil(dgs*log(10)/log(abs(pollead(Pol(b(x),x))/pollead(Pol(a(x),x))))) ); \\ if ( n > 4, [P, Q, B, T, D, C, V] = BinSplit2(~F,n1,n2); return(1.*([V/D,T]/B/Q)),\ [P, Q, B, T] = BinSplit1(~F,n1,n2); return(1.*(T/B/Q))); } addhelp(sumbinsplit,Str(Yw,"\n LINEARLY CONVERGENT SERIES BINARY SPLITTING SUMMATION\n\n",Wh,"sumbinsplit( ~F, {n1 = 1}, {dgs = getlocalprec()} )\n\n",Gr,"for either ",Wh,"F = [a(n),b(n),p(n),q(n)] ",Gr,"or",Wh," F = [a(n),b(n),p(n),q(n),c(n),d(n)]",Gr," vectors of ",Br,"t_CLOSUREs",Gr," whose\n components are typically polynomials. It computes sums of type 1 or type 2 by binary splitting method\n\n (See BinSplit1, BinSplit2 help)\n\n",Wh,"n1",Gr," starting index (default 1),",Wh," dgs",Gr," result's floating precision\n\n",Yw,"OUTPUT:",Gr," either",Wh," S1",Gr," series value (Type 1) or ",Wh," [S2, S1]",Gr," series values [Type 2, Type1]")); /* TESTINGS */ /* Digits(100000); a = n->1; b = n->n; p = n->n*(n<<1-1); q = n->3*(3*n-1)*(3*n-2); c = n->1; d = n->n*(n<<1-1)<<1; s = log(2)*(3*log(2)+Pi/2)/10-Pi^2/60; F = [a,b,p,q,c,d]; */ /* Digits(100000); s = -Pi*Catalan/2+33/32*zeta(3)+log(2)*Pi^2/24; F = [n->1,n->n^2,n->n*(n<<1-1),n->3*(3*n-1)*(3*n-2),n->1,n->n*(n<<1-1)<<1]; \\ precision(-log10(abs(sumbinsplit(~F)[1]/s-1)),ceil(log10(Digits()))); */ /* Digits(10000); a = n->1; b = n->n<<1+1; p = n->n<<1-1; q = n->n<<3; c = n->1; d = n->(n<<1-1)^2; s = Pi^3/648; F = [a,b,p,q,c,d]; */ /* Digits(10000); a = n->-1; b = n->n^3; p = n->-n; q = n->(n<<1-1)<<1; c = n->20*n-9; d = n->n*(n<<1-1)<<1; s = 2*Pi^4/75; F = [a,b,p,q,c,d]; */ /* Digits(10000); a = n->2; b = n->n^2; p = n->n; q = n->(n<<1-1); c = n->1; d = n->n<<1-1; s = 7*zeta(3)-2*Pi*Catalan; F = [a,b,p,q,c,d]; */ /* Digits(10000); a = n->1; b = n->n^4; p = n->n; q = n->(n<<1-1)<<1; c = n->36*n-17; d = n->n*(n<<1-1)<<1; s = 14*zeta(5)/9+5/18*Pi^2*zeta(3); F = [a,b,p,q,c,d]; */ /* Digits(10000); a = n->1; b = n->n^2; p = n->n; q = n->(n<<1-1)<<1; c = n->12*n-5; d = n->n*(n<<1-1)<<1; s = 5*zeta(3)/3; F = [a,b,p,q,c,d]; */
Making a close analysis of the nested hypergeometric series W and partial sums W(n1,n2) I have found the binary splitting relationships, Write the inner hypergeometric sum in W(n1,n2) as Z(n1,n2) = SUM(m=n1,n2-1,c(m)/d(m) * PROD(i=n1,m,f(i)/g(i))) we have W(n1,n2) = = SUM(n=n1,n2-1,a(n)/b(n) * PROD(k=n1,n,p(k)/q(k)) * Z(n1,n+1)) The algorithm is a deeper variation of the previous one. We have now 8 polynomial functions a(n), b(n), p(n), q(n), c(n), d(n), f(n), g(n). Set these products and sums to be computed by binary splitting P = p(n1) ... p(n2-1) Q = q(n1) ... q(n2−1) B = b(n1) ... b(n2-1) T = B Q S D = d(n1) ... d(n2-1) F = f(n1) ... f(n2-1) G = g(n1) ... g(n2-1) C = D G Z V = D B Q G W If n2 - n1 =< 4 these values are computed directly. If n2 - n1 > 4 they are computed recursively by binary splitting. Choose an index nm in the middle of n1 and n2, compute the components Pl, Ql, Bl , Tl, Dl, Cl, Vl, Fl, Gl belonging to the interval n1 =< n < nm, compute the components Pr, Qr , Br, Tr, Dr, Cr, Vr, Fr, Gr belonging to the interval nm =< n < n2 and set these products and sums P = Pl Pr Q = Ql Qr B = Bl Br T = Br Qr Tl + Bl Pl Tr D = Dl Dr F = Fl Fr G = Gl Gr C = Cl Dr Gr + Cr Dl Fl V = Dr Br Qr Gr Vl + Dr Cl Bl Pl Gr Tr + Dl Bl Pl Fl Vr Using auxiliary variables and factorizing, these 27 big integer products can be reduced to just 19. Finally, this algorithm is applied to n1 = 0 and n2 = nmax = O(N), and final floating point divisions are performed. Algorithm provides all 3 sums S = T / (B Q) Z = C / (D G) W = V / (B Q D G) I will code and test this algorithm to complement this answer. Many convergence acceleration methods (CAM) applied to some slowly convergent series have the structure of series W (for example, some classical CAMs like Salzer's, Gustavson's, sumalt() from Pari GP -Cohen, Rodriguez, Zagier-, Weniger's transformations and several Levin-type CAMs). I believe that the merge of BinSplit and Levin-type sequence transformations should provide a strong boost to this topic. We will see.
Mathematica Code with Module and If statement
Can I simply ask the logical flow of the below Mathematica code? What are the variables arg and abs doing? I have been searching for answers online and used ToMatlab but still cannot get the answer. Thank you. Code: PositiveCubicRoot[p_, q_, r_] := Module[{po3 = p/3, a, b, det, abs, arg}, b = ( po3^3 - po3 q/2 + r/2); a = (-po3^2 + q/3); det = a^3 + b^2; If[det >= 0, det = Power[Sqrt[det] - b, 1/3]; -po3 - a/det + det , (* evaluate real part, imaginary parts cancel anyway *) abs = Sqrt[-a^3]; arg = ArcCos[-b/abs]; abs = Power[abs, 1/3]; abs = (abs - a/abs); arg = -po3 + abs*Cos[arg/3] ] ]
abs and arg are being reused multiple times in the algorithm. In a case where det > 0 the steps are po3 = p/3; b = (po3^3 - po3 q/2 + r/2); a = (-po3^2 + q/3); abs1 = Sqrt[-a^3]; arg1 = ArcCos[-b/abs1]; abs2 = Power[abs1, 1/3]; abs3 = (abs2 - a/abs2); arg2 = -po3 + abs3*Cos[arg1/3] abs3 can be identified as A in this answer: Using trig identity to a solve cubic equation That is the most salient point of this answer. Evaluating symbolically and numerically may provide some other insights. Using demo inputs {p, q, r} = {-2.52111798, -71.424692, -129.51520}; Copyable version of trig identity notes - NB a, b, p & q are used differently in this post Plot[x^3 - 2.52111798 x^2 - 71.424692 x - 129.51520, {x, 0, 15}] a = 1; b = -2.52111798; c = -71.424692; d = -129.51520; p = (3 a c - b^2)/3 a^2; q = (2 b^3 - 9 a b c + 27 a^2 d)/27 a^3; A = 2 Sqrt[-p/3] A == abs3 -(b/3) + A Cos[1/3 ArcCos[ -((b/3)^3 - (b/3) c/2 + d/2)/Sqrt[-(-(b^2/9) + c/3)^3]]] Edit There is also a solution shown here TRIGONOMETRIC SOLUTION TO THE CUBIC EQUATION, by Alvaro H. Salas Clear[a, b, c] 1/3 (-a + 2 Sqrt[a^2 - 3 b] Cos[1/3 ArcCos[ (-2 a^3 + 9 a b - 27 c)/(2 (a^2 - 3 b)^(3/2))]]) /. {a -> -2.52111798, b -> -71.424692, c -> -129.51520} 10.499
Running Time of Algorithm - If statements inside While loop
I have this example A = 2,1,8,4,3,6 // c1, n n = 6 // c2, n i = 1 // c3, n H = 2 // c4, n inv = 0 // c5, n while H <= n // c6, n(n+1)/2-1 if A[i] > A[H] && !H = n // c7, n(n-1)/2 inv = inv + 1 H = H + 1 else if A[i] > A[H] && H = n // c10, n(n-1)/2 inv = inv + 1 i = i + 1 H = i + 1 else if A[i] < A[H] && !H = n // c14, n(n-1)/2 H = H + 1 else if A[i] < A[H] && H = n // c16, n(n-1)/2 i = i + 1 H = i + 1 print inv // c19, n My question is how many n times will the code inside the if statements run in this example?
First, to understand this code, some assumptions must be made: The array A is 1-indexed based, i.e. the first element is accessed as A[1]. The elements in A are unique - duplicate values are not allowed. The expression !H = n means H is not equal to n The loop condition is H <= n, so let's see when this could become false. We can see that as long as H < n, an iteration will increment H with one (either in the first if block, or in the third). When H reaches n, i is incremented (and only then), and H becomes i+1 (in the second or last if block). At one point i will become n, and then H will be set to i+1 again, which is the only way H can get a value that is greater than n, at which point the loop stops. So, in other words, this loop makes i go from 1 to n, and for each of those values of i, H runs from n+1 to n. This really means the tuple (i,H) takes all possible pairs from the range 1...n where i < H. This number of pairs is thus n(n-1)/2 (also noted C(n,2)). In the example n = 6, so the number of pairs (iterations) is 6(6-1)/2 = 15. The following JavaScript implementation demonstrates that a loop counter indeed reaches the count of 15: // Must add an element at index 0, since the // original code assumes 1-based indexing A = [null,2,1,8,4,3,6] // c1, n n = 6 // c2, n i = 1 // c3, n H = 2 // c4, n inv = 0 // c5, n loopCounter = 0 while (H <= n) { // c6, n(n+1)/2-1 loopCounter++; // count it!! if (A[i] > A[H] && H != n) { // c7, n(n-1)/2 inv = inv + 1 H = H + 1 } else if (A[i] > A[H] && H == n) { // c10, n(n-1)/2 inv = inv + 1 i = i + 1 H = i + 1 } else if (A[i] < A[H] && H != n) { // c14, n(n-1)/2 H = H + 1 } else if (A[i] < A[H] && H == n) { // c16, n(n-1)/2 i = i + 1 H = i + 1 } } console.log('inv = ', inv) // c19, n console.log('iterations = ', loopCounter)
Can anyone explain how this division algorithm works?
I saw this in an algorithm textbook. I am confused about the middle recursive function. If you can explain it with an example, such as 4/2, that would be great! function divide(x, y) Input: Two n-bit integers x and y, where y ≥ 1 Output: The quotient and remainder of x divided by y if x = 0: return (q, r) = (0, 0) (q, r) = divide(floor(x/2), y) q = 2 · q, r = 2 · r if x is odd: r = r + 1 if r ≥ y: r = r − y, q = q + 1 return (q, r)
You're seeing how many times it's divisible by 2. This is essentially performing bit shifts and operating on the binary digits. A more interesting case would be 13/3 (13 is 1101 in binary). divide(13, 3) // initial binary value - 1101 divide(6, 3) // shift right - 110 divide(3, 3) // shift right - 11 divide(1, 3) // shift right - 1 (this is the most significant bit) divide(0, 3) // shift right - 0 (no more significant bits) return(0, 0) // roll it back up return(0, 1) // since x is odd (1) return(1, 0) // r = r * 2 = 2; x is odd (3) so r = 3 and the r > y condition is true return(2, 0) // q = 2 * 1; r = 2 * 1 - so r >= y and q = 2 + 1 return(4, 1) // q = 2 * 2; x is odd to r = 0 + 1
Rounding of double to nearest member of an arithmetical progression?
I have a formula of a sequence of double numbers k = a + d * n, where a and d are constant double values, n is an integer number, k >= 0, a >= 0. For example: ..., 300, 301.6, 303.2, 304.8, 306.4, ... I want to round a given number c to a nearest value from this sequence which is lower than c. Currently I use something like this: double someFunc(double c) { static double a = 1; static double d = 2; int n = 0; double a1 = a; if (c >= a) { while (a1 < c) { a1 += d; } a1 -= d; } else { while (a1 > c) { a1 -= d; } } return a1; } Is it possible to do the same without these awful cycles? I ask because the following situation may appear: abs(a - c) >> abs(d) (the first number is much more then the second one and so a lot of iterations possible) My question is similar to the following one. But in my case I also have a a variable which has influence on the final result. It means that a sequence may haven't number 0.
Suppose c is a number in your sequence. Then you have n = (c - a) / d. Since you want an integer <= c, then take n = floor((c - a) / d). Then you can round c to: a + d * floor((c - a) / d) Suppose k = 3 + 5 * n and you round c=21. And 3 + 5 * floor((21 - 3) / 5) = 3 + 5 * 3 = 18