@@ -23,6 +23,42 @@ function IsZero(d: f64): boolean {
2323 return Math . abs ( d ) < 1e-9 ;
2424}
2525
26+ @inline
27+ function sort4 ( ) : void {
28+ // sort 4 value via sorting networks
29+ let t0 : f64 , t1 : f64 ;
30+ t0 = unchecked ( output [ 0 ] ) ;
31+ t1 = unchecked ( output [ 1 ] ) ;
32+ if ( t0 > t1 ) { // swap(0, 1)
33+ unchecked ( output [ 0 ] = t1 ) ;
34+ unchecked ( output [ 1 ] = t0 ) ;
35+ }
36+ t0 = unchecked ( output [ 2 ] ) ;
37+ t1 = unchecked ( output [ 3 ] ) ;
38+ if ( t0 > t1 ) { // swap(2, 3)
39+ unchecked ( output [ 2 ] = t1 ) ;
40+ unchecked ( output [ 3 ] = t0 ) ;
41+ }
42+ t0 = unchecked ( output [ 0 ] ) ;
43+ t1 = unchecked ( output [ 2 ] ) ;
44+ if ( t0 > t1 ) { // swap(0, 2)
45+ unchecked ( output [ 0 ] = t1 ) ;
46+ unchecked ( output [ 2 ] = t0 ) ;
47+ }
48+ t0 = unchecked ( output [ 1 ] ) ;
49+ t1 = unchecked ( output [ 3 ] ) ;
50+ if ( t0 > t1 ) { // swap(1, 3)
51+ unchecked ( output [ 1 ] = t1 ) ;
52+ unchecked ( output [ 3 ] = t0 ) ;
53+ }
54+ t0 = unchecked ( output [ 1 ] ) ;
55+ t1 = unchecked ( output [ 2 ] ) ;
56+ if ( t0 > t1 ) { // swap(1, 2)
57+ unchecked ( output [ 1 ] = t1 ) ;
58+ unchecked ( output [ 2 ] = t0 ) ;
59+ }
60+ }
61+
2662/* normal form: a^2 + bx + c = 0 */
2763// Returns number of solutions.
2864export function SolveQuadric ( index1 : i32 = 0 , index2 : i32 = 1 ) : i32 {
@@ -79,28 +115,28 @@ export function SolveCubic(): i32 {
79115 D = q * q + cb_p ;
80116
81117 if ( IsZero ( D ) ) {
82- if ( IsZero ( q ) ) { // one triple solution
118+ if ( IsZero ( q ) ) { // one triple solution
83119 unchecked ( output [ 0 ] = 0 ) ;
84120 num = 1 ;
85- } else { // one single and one double solution
86- const u : f64 = Math . cbrt ( - q ) ;
121+ } else { // one single and one double solution
122+ const u = Math . cbrt ( - q ) ;
87123 unchecked ( output [ 0 ] = 2 * u ) ;
88124 unchecked ( output [ 1 ] = - u ) ;
89- num = 2 ;
125+ num = 2 ;
90126 }
91127 } else if ( D < 0 ) { // Casus irreducibilis: three real solutions
92- const phi = 1.0 / 3 * Math . acos ( - q / Math . sqrt ( - cb_p ) ) ;
128+ const phi = 1.0 / 3 * Math . acos ( - q / Math . sqrt ( - cb_p ) ) ;
93129 const t = 2 * Math . sqrt ( - p ) ;
94130 unchecked ( output [ 0 ] = t * Math . cos ( phi ) ) ;
95131 unchecked ( output [ 1 ] = - t * Math . cos ( phi + Math . PI / 3 ) ) ;
96132 unchecked ( output [ 2 ] = - t * Math . cos ( phi - Math . PI / 3 ) ) ;
97133 num = 3 ;
98134 } else { // one real solution
99- const sqrt_D = Math . sqrt ( D ) ;
135+ const sqrt_D = Math . sqrt ( D ) ;
100136 const u = Math . cbrt ( sqrt_D - q ) ;
101137 const v = - Math . cbrt ( sqrt_D + q ) ;
102138 unchecked ( output [ 0 ] = u + v ) ;
103- num = 1 ;
139+ num = 1 ;
104140 }
105141
106142 /* resubstitute */
@@ -140,7 +176,7 @@ export function SolveQuartic(): i32 {
140176 D = unchecked ( input [ 4 ] * t ) ;
141177
142178 // substitute x = y - A/4 to eliminate cubic term:
143- // x^4 + px^2 + qx + r = 0
179+ // x^4 + px^2 + qx + r = 0
144180
145181 sq_A = A * A ;
146182 p = - 3.0 / 8 * sq_A + B ;
@@ -157,7 +193,7 @@ export function SolveQuartic(): i32 {
157193
158194 num = SolveCubic ( ) ;
159195 } else {
160- // solve the resolvent cubic ...
196+ // solve the resolvent cubic ...
161197
162198 unchecked ( input [ 3 ] = 1.0 / 2 * r * p - 1.0 / 8 * q * q ) ;
163199 unchecked ( input [ 2 ] = - r ) ;
@@ -166,11 +202,11 @@ export function SolveQuartic(): i32 {
166202
167203 SolveCubic ( ) ;
168204
169- // ... and take the one real solution ...
205+ // ... and take the one real solution ...
170206
171207 z = unchecked ( output [ 0 ] ) ;
172208
173- // ... to build two quadric equations
209+ // ... to build two quadric equations
174210
175211 u = z * z - r ;
176212 v = 2 * z - p ;
@@ -254,8 +290,9 @@ export function range(): i32 {
254290 // (3) via quadratic: t = (speed*sin O)/gravity + sqrt(speed*speed*sin O + 2*gravity*initialHeight)/gravity [ignore smaller root]
255291 // (4) solution: range = x = (speed*cos O)/gravity * sqrt(speed*speed*sin O + 2*gravity*initialHeight) [plug t back into x=speed*time*cos O]
256292 const angle = 45 * ( Math . PI * 2 ) / 360 ; // no air resistence, so 45 degrees provides maximum range
257- const cos = Math . cos ( angle ) ;
258- const sin = Math . sin ( angle ) ;
293+ NativeMath . sincos ( angle ) ;
294+ const sin = NativeMath . sincos_sin ;
295+ const cos = NativeMath . sincos_cos ;
259296
260297 unchecked ( output [ outOffset ] = ( s * cos / g ) * ( s * sin + Math . sqrt ( s * s * sin * sin + 2 * g * h ) ) ) ;
261298
@@ -362,17 +399,19 @@ export function solveArcStatic(): i32 {
362399
363400 // solution 1
364401 // groundDir*Mathf.Cos(lowAng)*proj_speed + Vector3.up*Mathf.Sin(lowAng)*proj_speed;
365- let clo = Math . cos ( lowAng ) * s ;
366- let slo = Math . sin ( lowAng ) * s ;
402+ NativeMath . sincos ( lowAng ) ;
403+ let clo = NativeMath . sincos_cos * s ;
404+ let slo = NativeMath . sincos_sin * s ;
367405 unchecked ( output [ outOffset ++ ] = dx * clo ) ;
368406 unchecked ( output [ outOffset ++ ] = dy * clo + slo ) ;
369407 unchecked ( output [ outOffset ++ ] = dz * clo ) ;
370408
371409 // solution 2
372410 // s1 = groundDir*Mathf.Cos(highAng)*proj_speed + Vector3.up*Mathf.Sin(highAng)*proj_speed;
373411 if ( numSolutions > 1 ) {
374- let chi = Math . cos ( highAng ) * s ;
375- let shi = Math . sin ( highAng ) * s ;
412+ NativeMath . sincos ( highAng ) ;
413+ let chi = NativeMath . sincos_cos * s ;
414+ let shi = NativeMath . sincos_sin * s ;
376415 unchecked ( output [ outOffset ++ ] = dx * chi ) ;
377416 unchecked ( output [ outOffset ++ ] = dy * chi + shi ) ;
378417 unchecked ( output [ outOffset ++ ] = dz * chi ) ;
@@ -494,8 +533,7 @@ export function solveArcMoving(): i32 {
494533 const numTimes = SolveQuartic ( ) ;
495534
496535 // Sort so faster collision is found first
497- const sub = output . subarray ( 0 , 4 ) ;
498- sub . sort ( ) ;
536+ sort4 ( ) ;
499537
500538 // Plug quartic solutions into base equations
501539 // There should never be more than 2 positive, real roots.
@@ -514,8 +552,18 @@ export function solveArcMoving(): i32 {
514552 }
515553
516554 // Write out solutions
517- if ( numSolutions > 0 ) output . copyWithin ( outOffset + 6 , outOffset + 0 , outOffset + 3 ) ;
518- if ( numSolutions > 1 ) output . copyWithin ( outOffset + 9 , outOffset + 3 , outOffset + 6 ) ;
555+ if ( numSolutions > 0 ) {
556+ // output.copyWithin(outOffset + 6, outOffset + 0, outOffset + 3);
557+ unchecked ( output [ outOffset + 6 ] = output [ outOffset + 0 ] ) ;
558+ unchecked ( output [ outOffset + 7 ] = output [ outOffset + 1 ] ) ;
559+ unchecked ( output [ outOffset + 8 ] = output [ outOffset + 2 ] ) ;
560+ }
561+ if ( numSolutions > 1 ) {
562+ // output.copyWithin(outOffset + 9, outOffset + 3, outOffset + 6);
563+ unchecked ( output [ outOffset + 9 ] = output [ outOffset + 3 ] ) ;
564+ unchecked ( output [ outOffset + 10 ] = output [ outOffset + 4 ] ) ;
565+ unchecked ( output [ outOffset + 11 ] = output [ outOffset + 5 ] ) ;
566+ }
519567
520568 // clean up
521569 input . fill ( 0 ) ;
@@ -592,7 +640,7 @@ export function solveLateralStatic(): i32 {
592640 // normalize diff
593641 const ls = dx * dx + dz * dz ;
594642 if ( ls > 0 ) {
595- const il = 1 / Math . sqrt ( ls ) ;
643+ const il = 1.0 / Math . sqrt ( ls ) ;
596644 dx *= il ;
597645 dz *= il ;
598646 }
@@ -612,11 +660,11 @@ export function solveLateralStatic(): i32 {
612660
613661 // fire_velocity
614662 unchecked ( output [ outOffset ++ ] = dx ) ;
615- unchecked ( output [ outOffset ++ ] = - ( 3 * py - 4 * h + ty ) / t ) ;
663+ unchecked ( output [ outOffset ++ ] = ( - 3 * py + 4 * h - ty ) / t ) ;
616664 unchecked ( output [ outOffset ++ ] = dz ) ;
617665
618666 // gravity
619- unchecked ( output [ outOffset ++ ] = - 4 * ( py - 2 * h + ty ) / ( t * t ) ) ;
667+ unchecked ( output [ outOffset ++ ] = - 4 * ( py - 2 * h + ty ) / ( t * t ) ) ;
620668
621669 // clean up
622670 input . fill ( 0 ) ;
@@ -710,17 +758,20 @@ export function solveLateralMoving(): i32 {
710758
711759 const n = SolveQuadric ( ) ;
712760
761+ const o0 = unchecked ( output [ 0 ] ) ;
762+ const o1 = unchecked ( output [ 1 ] ) ;
763+
713764 // pick smallest, positive time
714- const valid0 = n > 0 && unchecked ( output [ 0 ] ) > 0 ;
715- const valid1 = n > 1 && unchecked ( output [ 1 ] ) > 0 ;
765+ const valid0 = n > 0 && o0 > 0 ;
766+ const valid1 = n > 1 && o1 > 0 ;
716767
717768 let t : f64 ;
718769 if ( ! valid0 && ! valid1 )
719770 return 0 ;
720771 else if ( valid0 && valid1 )
721- t = Math . min ( unchecked ( output [ 0 ] ) , unchecked ( output [ 1 ] ) ) ;
772+ t = Math . min ( o0 , o1 ) ;
722773 else
723- t = valid0 ? unchecked ( output [ 0 ] ) : unchecked ( output [ 1 ] ) ;
774+ t = valid0 ? o0 : o1 ;
724775
725776 // Calculate impact point
726777 const ipx = tx + ( tvx * t ) ;
@@ -753,7 +804,7 @@ export function solveLateralMoving(): i32 {
753804
754805 // fire_velocity
755806 unchecked ( output [ outOffset ++ ] = dirx ) ;
756- unchecked ( output [ outOffset ++ ] = - ( 3 * py - 4 * b + ipy ) / t ) ;
807+ unchecked ( output [ outOffset ++ ] = ( - 3 * py + 4 * b - ipy ) / t ) ;
757808 unchecked ( output [ outOffset ++ ] = dirz ) ;
758809
759810 // impact_point
0 commit comments