diff options
Diffstat (limited to 'lib/compiler/test/inline_SUITE_data/barnes2.erl')
-rw-r--r-- | lib/compiler/test/inline_SUITE_data/barnes2.erl | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/lib/compiler/test/inline_SUITE_data/barnes2.erl b/lib/compiler/test/inline_SUITE_data/barnes2.erl new file mode 100644 index 0000000000..a986331060 --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/barnes2.erl @@ -0,0 +1,160 @@ +% file: "barnes.erl" + +-module(barnes2). +-export([?MODULE/0]). + +?MODULE() -> + Stars = create_scenario(1000, 1.0), + R = hd(loop(10,1000.0,Stars,0)), + Str = lists:flatten(io:lib_format("~s", [R])), + {R,Str =:= {1.00000,-1.92269e+4,-1.92269e+4,2.86459e-2,2.86459e-2}}. + +create_scenario(N, M) -> + create_scenario0(0, 0, trunc(math:sqrt(N)), M). + +create_scenario0(_X, _SN, _SN, _M) -> + []; +create_scenario0(SN, Y, SN, M) -> + create_scenario0(0, Y+1, SN, M); +create_scenario0(X, Y, SN, M) -> + XPos0 = (((20000.0 * 2) / SN) * X) - 20000.0, + YPos0 = (((20000.0 * 2) / SN) * Y) - 20000.0, + Calibrate = ((20000.0 * 2) / SN) / 2, + XPos = XPos0 + Calibrate, + YPos = YPos0 + Calibrate, + [{M, XPos, YPos, 0.0, 0.0} | create_scenario0(X+1, Y, SN, M)]. + +relpos_to_quadrant(DX, DY) when DX >= 0 -> + if + DY >= 0 -> 0; + true -> 3 + end; +relpos_to_quadrant(_, DY) -> + if + DY >= 0 -> 1; + true -> 2 + end. + +quadrant_to_dx(0, D) -> D; +quadrant_to_dx(1, D) -> -D; +quadrant_to_dx(2, D) -> -D; +quadrant_to_dx(3, D) -> D. + +quadrant_to_dy(Q,D) -> + if + Q < 2 -> D; + true -> -D + end. + +create_tree(Stars) -> + create_tree0(Stars, empty). + +create_tree0([],Tree) -> + Tree; +create_tree0([{M,X,Y,_,_} | Stars], Tree) -> + create_tree0(Stars, insert_tree_element(Tree, M, X, Y, 0.0, 0.0, 20000.0)). + +insert_tree_element(empty, M, X, Y, _OX, _OY, _D) -> + {body,M,X,Y}; +insert_tree_element({branch,M0,SubTree}, M, X, Y, OX, OY, D) -> + Q = relpos_to_quadrant(X-OX,Y-OY), + D2 = D / 2, + DX = quadrant_to_dx(Q,D2), + DY = quadrant_to_dy(Q,D2), + {branch,M0+M,setelement(Q+1,SubTree, + insert_tree_element(element(Q+1,SubTree), + M, X, Y, OX+DX, OY+DY,D2))}; +insert_tree_element({body,M0,X0,Y0},M,X,Y,OX,OY,D) -> + resolve_body_conflict(M,X,Y,M0,X0,Y0,OX,OY,D). + +resolve_body_conflict(M0, X0, Y0, M1, X1, Y1, OX, OY, D) -> + T = {empty,empty,empty,empty}, + Q0 = relpos_to_quadrant(X0-OX,Y0-OY), + Q1 = relpos_to_quadrant(X1-OX,Y1-OY), + D2 = D / 2, + if + Q0 == Q1 -> DX = quadrant_to_dx(Q0,D2), + DY = quadrant_to_dy(Q1,D2), + {branch,M0+M1,setelement(Q0+1,T, + resolve_body_conflict(M0,X0,Y0, + M1,X1,Y1, + OX+DX,OY+DY, + D2))} ; + true -> {branch,M0+M1, setelement(Q1+1, + setelement(Q0+1,T,{body,M0,X0,Y0}), + {body,M1,X1,Y1})} + end. + +compute_acceleration(empty, _, _, _, _, _,L) -> + {{0.0, 0.0},L+1}; +compute_acceleration({body,BM,BX,BY}, _D, _OX, _OY, X, Y,L) -> + DX = BX - X, + DY = BY - Y, + R2 = (DX * DX) + (DY * DY), + Divisor = R2 * math:sqrt(R2), + if + Divisor < 0.000001 -> % was: Divisor < ?EPSILON -> + {{0.0, 0.0},L+1}; + true -> + Expr = BM / Divisor, + {{DX * Expr, DY * Expr},L+1} + end; +compute_acceleration({branch,M,SubTree}, D, OX, OY, X, Y,L) -> + DX = OX - X, + DY = OY - Y, + R2 = (DX * DX) + (DY * DY), + DD = D*D, + R2_THETA2 = 0.09 * R2, % TRY 2.0 *R2, !!! was: R2_THETA2 = ?THETA2*R2, + if + % Ok to approximate? + DD < R2_THETA2 -> + Divisor = R2 * math:sqrt(R2), + if + Divisor < 0.000001 -> + {{0.0,0.0},L}; + true -> + Expr = M / Divisor, + {{DX*Expr, DY*Expr},L+1} + end; + % Not ok to approximate... + true -> + D2 = D / 2, + {{AX0, AY0},L1} = compute_acceleration(element(1,SubTree), + D2, OX + quadrant_to_dx(0,D2), + OY + quadrant_to_dy(0,D2),X,Y,L), + {{AX1, AY1},L2} = compute_acceleration(element(2,SubTree), + D2, OX + quadrant_to_dx(1,D2), + OY + quadrant_to_dy(1,D2),X,Y,L1), + {{AX2, AY2},L3} = compute_acceleration(element(3,SubTree), + D2,OX + quadrant_to_dx(2,D2), + OY + quadrant_to_dy(2,D2),X,Y,L2), + {{AX3, AY3},L4} = compute_acceleration(element(4,SubTree), + D2, OX + quadrant_to_dx(3,D2), + OY + quadrant_to_dy(3,D2),X,Y,L3), + {{AX0+AX1+AX2+AX3, AY0+AY1+AY2+AY3},L4+1} + end. + +compute_star_accelerations(_Tree,[],L) -> + {[],L}; +compute_star_accelerations(Tree,[{_,X, Y,_,_}|Stars],L) -> + {A,AL} = compute_acceleration(Tree, 20000.0, 0.0, 0.0, X, Y,L), + {B,BL} = compute_star_accelerations(Tree, Stars,AL), + {[A | B],BL}. + +compute_next_state([],_,_) -> + []; +compute_next_state([{M,X,Y,VX,VY}|Stars],[{AX,AY}|Accs],Time) -> + VX0 = VX + (AX * Time), + VY0 = VY + (AY * Time), + [{M,X+(VX*Time),Y+(VY*Time),VX0,VY0} | compute_next_state(Stars,Accs,Time)]. + +advance_time(Time,Stars,L) -> + Tree = create_tree(Stars), + {Acc,NL} = compute_star_accelerations(Tree, Stars,L), + {compute_next_state(Stars, Acc, Time),NL}. + +loop(0,_Time,Stars,_L) -> + Stars; +loop(N,Time,Stars,L) -> + {NS,NL} = advance_time(Time,Stars,L), + loop(N-1,Time,NS,NL). |