@@ -271,28 +271,84 @@ public void geluInPlace() {
271271 }
272272 }
273273
274- public void geluInPlaceHighSpeed () {
275- int len = rows * cols , idx = 0 ;
276- if (HAS_VECTOR && isContiguous ()) {
274+ /**
275+ * GeGLU in-place: output = inputs[0] ⊙ GELU(inputs[1])
276+ *
277+ * @param gate
278+ */
279+ public void gegluInPlaceOld (FlatMatrixF gate ) { // gate is inputs[1]
280+ if (rows != gate .rows || cols != gate .cols ) {
281+ throw new IllegalArgumentException ("Shape mismatch for GeGLU" );
282+ }
283+
284+ int len = rows * cols ;
285+ int idx = 0 ;
286+
287+ if (HAS_VECTOR && isContiguous () && gate .isContiguous ()) {
277288 for (; idx < F_SPECIES .loopBound (len ); idx += VF_LEN ) {
278- var v = FloatVector .fromArray (F_SPECIES , data , offset + idx );
289+ var value = FloatVector .fromArray (F_SPECIES , this .data , this .offset + idx );
290+ var g = FloatVector .fromArray (F_SPECIES , gate .data , gate .offset + idx );
279291
280- // x + 0.044715 * x^3
281- var x2 = v .mul (v );
282- var x3 = x2 .mul (v );
283- var inner = v .add (x3 .mul (V_GELU_C2 )).mul (V_GELU_C1 );
292+ // GELU on gate
293+ var g2 = g .mul (g );
294+ var g3 = g2 .mul (g );
295+ var inner = g .add (g3 .mul (V_GELU_C2 )).mul (V_GELU_C1 );
296+ var t = inner .lanewise (VectorOperators .TANH );
297+ var geluGate = g .mul (V_HALF ).mul (t .add (V_ONE ));
284298
285- // tanh_poly(inner) = inner * (27 + inner^2) / (27 + 9*inner^2)
286- var t = tanh256 (inner ); // <- No scalar calls here
299+ // value * GELU(gate)
300+ value .mul (geluGate ).intoArray (this .data , this .offset + idx );
301+ }
302+ }
287303
288- v .mul (V_HALF ).mul (t .add (V_ONE )).intoArray (data , offset + idx );
304+ // Scalar fallback
305+ for (; idx < len ; idx ++) {
306+ float value = this .data [this .offset + idx ];
307+ float g = gate .data [gate .offset + idx ];
308+
309+ float g3 = g * g * g ;
310+ float t = (float ) Math .tanh (GELU_C1 * (g + GELU_C2 * g3 ));
311+ float geluGate = 0.5f * g * (1.0f + t );
312+
313+ this .data [this .offset + idx ] = value * geluGate ;
314+ }
315+ }
316+
317+ public void gegluInPlace (FlatMatrixF gate ) {
318+ if (rows != gate .rows || cols != gate .cols ) {
319+ throw new IllegalArgumentException ("Shape mismatch for GeGLU" );
320+ }
321+
322+ int len = rows * cols ;
323+ int idx = 0 ;
324+
325+ if (HAS_VECTOR && isContiguous () && gate .isContiguous ()) {
326+ for (; idx < F_SPECIES .loopBound (len ); idx += VF_LEN ) {
327+ var value = FloatVector .fromArray (F_SPECIES , this .data , this .offset + idx );
328+ var g = FloatVector .fromArray (F_SPECIES , gate .data , gate .offset + idx );
329+
330+ // GELU(gate)
331+ var g2 = g .mul (g );
332+ var g3 = g2 .mul (g );
333+ var inner = g .add (g3 .mul (V_GELU_C2 )).mul (V_GELU_C1 );
334+ var t = inner .lanewise (VectorOperators .TANH );
335+ var geluGate = g .mul (V_HALF ).mul (t .add (V_ONE ));
336+
337+ // value * GELU(gate)
338+ value .mul (geluGate ).intoArray (this .data , this .offset + idx );
289339 }
290340 }
341+
342+ // Scalar fallback
291343 for (; idx < len ; idx ++) {
292- float x = data [offset + idx ];
293- float x3 = x * x * x ;
294- float t = (float ) Math .tanh (GELU_C1 * (x + GELU_C2 * x3 ));
295- data [offset + idx ] = 0.5f * x * (1.0f + t );
344+ float value = this .data [this .offset + idx ];
345+ float g = gate .data [gate .offset + idx ];
346+
347+ float g3 = g * g * g ;
348+ float t = (float ) Math .tanh (GELU_C1 * (g + GELU_C2 * g3 ));
349+ float geluGate = 0.5f * g * (1.0f + t );
350+
351+ this .data [this .offset + idx ] = value * geluGate ;
296352 }
297353 }
298354
@@ -658,9 +714,13 @@ private static void matmulInPlaceScalar(FlatMatrixF A, FlatMatrixF B, FlatMatrix
658714 }
659715
660716 public static void randomFill (FlatMatrixF A ) {
717+ randomFill (A , 101 );
718+ }//end method randomFill
719+
720+ public static void randomFill (FlatMatrixF A , int max ) {
661721 ThreadLocalRandom ran = ThreadLocalRandom .current ();
662722 for (int i = 0 ; i < A .data .length ; i ++) {
663- A .data [i ] = 1 + ran .nextFloat (101 );
723+ A .data [i ] = 1 + ran .nextFloat (max );
664724 }
665725 }//end method randomFill
666726
@@ -1009,66 +1069,77 @@ private static void weightedSum(float[] scores, FlatMatrixF V, FlatMatrixF out,
10091069 }
10101070 }
10111071
1012- // 100% Vector ops. Compiles to vmulpd vaddpd vdivpd only
1013- private static FloatVector tanh256 (FloatVector x ) {
1014- var x2 = x .mul (x );
1015- var num = x2 .add (27.0f ); // 27 + x^2
1016- var den = x2 .mul (9.0f ).add (27.0f ); // 27 + 9*x^2
1017- return x .mul (num ).div (den ); // x * num / den
1018- }
1019-
1020- /**
1021- * Fast sigmoid: 1 / (1 + exp(-x)) Max error ~1e-3. ~3x faster than Math.exp
1022- * scalar. Uses expm1 + rational approx to stay stable.
1023- *
1024- * @param x
1025- * @return
1026- */
1027- public static FloatVector sigmoid (FloatVector x ) {
1028- // 1. Clamp: sig(-inf)=0, sig(+inf)=1
1029- x = x .max (MIN_X ).min (MAX_X );
1030-
1031- // 2. Use 1 / (1 + exp(-x)) = exp(x) / (1 + exp(x))
1032- // For x>=0: exp(-x) is small, more stable
1033- var negX = x .neg ();
1034- var expNegX = fastExp (negX ); // exp(-x)
1035- return ONE .div (ONE .add (expNegX ));
1036- }
1037-
10381072 /**
10391073 * Fast exp approx. Max error ~2e-3 on [-10, 10] Based on Pade approx:
10401074 * exp(x) = 2^(x * log2e)
1075+ *
1076+ * @param x
10411077 */
10421078 public static FloatVector fastExp (FloatVector x ) {
1079+ // Clamp input to avoid float underflow/overflow bounds [-88.0f, 88.0f]
1080+ x = x .lanewise (VectorOperators .MAX , -88.0f )
1081+ .lanewise (VectorOperators .MIN , 88.0f );
1082+
10431083 final FloatVector LOG2E = FloatVector .broadcast (F_SPECIES , 1.44269504f );
10441084 final FloatVector LN2 = FloatVector .broadcast (F_SPECIES , 0.69314718f );
1085+ final FloatVector ONE = FloatVector .broadcast (F_SPECIES , 1.0f );
10451086
1087+ // x * log2(e)
10461088 var fx = x .mul (LOG2E );
10471089
1048- // float -> int, truncate toward 0
1090+ // STEP 1: Perform manual floor via F2I truncation toward zero
10491091 IntVector ni = (IntVector ) fx .convertShape (VectorOperators .F2I , I_SPECIES , 0 );
1050-
1051- // F2I truncates, we need floor. Correct if fx < int(fx)
10521092 FloatVector ni_f = (FloatVector ) ni .convertShape (VectorOperators .I2F , F_SPECIES , 0 );
1093+
1094+ // For negative values, truncation goes the wrong way.
1095+ // If fx < ni_f, we must subtract 1 from the integer vector.
10531096 var needsDec = fx .compare (VectorOperators .LT , ni_f );
1054- ni = ni .sub (needsDec .toVector ().reinterpretAsInts ().lanewise (VectorOperators .ASHR , 31 )); // mask->int, subtract 1 where true
1097+ var oneInt = IntVector .broadcast (I_SPECIES , 1 );
1098+
1099+ // CORRECT FIX: Cast the Float mask to an Integer mask matching I_SPECIES
1100+ VectorMask <Integer > intMask = needsDec .cast (I_SPECIES );
1101+ ni = ni .sub (oneInt , intMask );
10551102
1056- var f = fx .sub (ni_f ); // fractional part in [0,1)
1103+ // STEP 2: Recompute the corrected float representation of the floor
1104+ ni_f = (FloatVector ) ni .convertShape (VectorOperators .I2F , F_SPECIES , 0 );
10571105
1058- // 2^f poly: 1 + y + y^2/2 + y^3/6, y = f*ln2
1106+ // Fractional part is now guaranteed to be in [0, 1)
1107+ var f = fx .sub (ni_f );
1108+
1109+ // STEP 3: 4th-order Polynomial approximation for 2^f
10591110 var y = f .mul (LN2 );
10601111 var y2 = y .mul (y );
10611112 var y3 = y2 .mul (y );
1062- var poly = ONE .add (y ).add (y2 .mul (0.5f )).add (y3 .mul (0.16666667f ));
1113+ var y4 = y3 .mul (y );
1114+
1115+ var poly = ONE .add (y )
1116+ .add (y2 .mul (0.5f ))
1117+ .add (y3 .mul (0.16666667f ))
1118+ .add (y4 .mul (0.041666668f ));
10631119
1064- // 2^n via bit cast: (n+127)<<23
1065- IntVector biasedExp = ni .add (127 );
1066- IntVector expBits = biasedExp .lanewise (VectorOperators .LSHL , 23 );
1067- FloatVector pow2n = (FloatVector ) expBits .convertShape (VectorOperators .I2F , F_SPECIES , 0 );
1120+ // STEP 4: 2^ni via raw bit manipulation: (ni + 127) << 23
1121+ var biased = ni .add (127 );
1122+ var bits = biased .lanewise (VectorOperators .LSHL , 23 );
1123+
1124+ // Pure bit-cast from integer registers to float registers
1125+ FloatVector pow2n = bits .reinterpretAsFloats ();
10681126
10691127 return poly .mul (pow2n );
10701128 }
10711129
1130+ /**
1131+ * Fast sigmoid: 1 / (1 + exp(-x)) Max error ~1e-3. ~3x faster than Math.exp
1132+ * scalar. Uses expm1 + rational approx to stay stable.
1133+ *
1134+ * @param x
1135+ * @return
1136+ */
1137+ public static FloatVector sigmoid (FloatVector x ) {
1138+ final FloatVector ONE = FloatVector .broadcast (F_SPECIES , 1.0f );
1139+ var negX = x .neg ();
1140+ return ONE .div (ONE .add (fastExp (negX )));
1141+ }
1142+
10721143
10731144//////////////////////////////MHA-ATTENTION-DONE/////////////////////////////////////////////
10741145}
0 commit comments