1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.internal.widget.remotecompose.core.operations.utilities; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 21 import com.android.internal.widget.remotecompose.core.operations.utilities.easing.MonotonicSpline; 22 23 import java.util.Random; 24 25 /** high performance floating point expression evaluator used in animation */ 26 public class AnimatedFloatExpression { 27 @NonNull static IntMap<String> sNames = new IntMap<>(); 28 29 /** The START POINT in the float NaN space for operators */ 30 public static final int OFFSET = 0x310_000; 31 32 /** ADD operator */ 33 public static final float ADD = asNan(OFFSET + 1); 34 35 /** SUB operator */ 36 public static final float SUB = asNan(OFFSET + 2); 37 38 /** MUL operator */ 39 public static final float MUL = asNan(OFFSET + 3); 40 41 /** DIV operator */ 42 public static final float DIV = asNan(OFFSET + 4); 43 44 /** MOD operator */ 45 public static final float MOD = asNan(OFFSET + 5); 46 47 /** MIN operator */ 48 public static final float MIN = asNan(OFFSET + 6); 49 50 /** MAX operator */ 51 public static final float MAX = asNan(OFFSET + 7); 52 53 /** POW operator */ 54 public static final float POW = asNan(OFFSET + 8); 55 56 /** SQRT operator */ 57 public static final float SQRT = asNan(OFFSET + 9); 58 59 /** ABS operator */ 60 public static final float ABS = asNan(OFFSET + 10); 61 62 /** SIGN operator */ 63 public static final float SIGN = asNan(OFFSET + 11); 64 65 /** COPY_SIGN operator */ 66 public static final float COPY_SIGN = asNan(OFFSET + 12); 67 68 /** EXP operator */ 69 public static final float EXP = asNan(OFFSET + 13); 70 71 /** FLOOR operator */ 72 public static final float FLOOR = asNan(OFFSET + 14); 73 74 /** LOG operator */ 75 public static final float LOG = asNan(OFFSET + 15); 76 77 /** LN operator */ 78 public static final float LN = asNan(OFFSET + 16); 79 80 /** ROUND operator */ 81 public static final float ROUND = asNan(OFFSET + 17); 82 83 /** SIN operator */ 84 public static final float SIN = asNan(OFFSET + 18); 85 86 /** COS operator */ 87 public static final float COS = asNan(OFFSET + 19); 88 89 /** TAN operator */ 90 public static final float TAN = asNan(OFFSET + 20); 91 92 /** ASIN operator */ 93 public static final float ASIN = asNan(OFFSET + 21); 94 95 /** ACOS operator */ 96 public static final float ACOS = asNan(OFFSET + 22); 97 98 /** ATAN operator */ 99 public static final float ATAN = asNan(OFFSET + 23); 100 101 /** ATAN2 operator */ 102 public static final float ATAN2 = asNan(OFFSET + 24); 103 104 /** MAD operator */ 105 public static final float MAD = asNan(OFFSET + 25); 106 107 /** IFELSE operator */ 108 public static final float IFELSE = asNan(OFFSET + 26); 109 110 /** CLAMP operator */ 111 public static final float CLAMP = asNan(OFFSET + 27); 112 113 /** CBRT operator */ 114 public static final float CBRT = asNan(OFFSET + 28); 115 116 /** DEG operator */ 117 public static final float DEG = asNan(OFFSET + 29); 118 119 /** RAD operator */ 120 public static final float RAD = asNan(OFFSET + 30); 121 122 /** CEIL operator */ 123 public static final float CEIL = asNan(OFFSET + 31); 124 125 // Array ops 126 /** A DEREF operator */ 127 public static final float A_DEREF = asNan(OFFSET + 32); 128 129 /** Array MAX operator */ 130 public static final float A_MAX = asNan(OFFSET + 33); 131 132 /** Array MIN operator */ 133 public static final float A_MIN = asNan(OFFSET + 34); 134 135 /** A_SUM operator */ 136 public static final float A_SUM = asNan(OFFSET + 35); 137 138 /** A_AVG operator */ 139 public static final float A_AVG = asNan(OFFSET + 36); 140 141 /** A_LEN operator */ 142 public static final float A_LEN = asNan(OFFSET + 37); 143 144 /** A_SPLINE operator */ 145 public static final float A_SPLINE = asNan(OFFSET + 38); 146 147 /** RAND Random number 0..1 */ 148 public static final float RAND = asNan(OFFSET + 39); 149 150 /** RAND_SEED operator */ 151 public static final float RAND_SEED = asNan(OFFSET + 40); 152 153 /** NOISE_FROM operator calculate a random 0..1 number based on a seed */ 154 public static final float NOISE_FROM = asNan(OFFSET + 41); 155 156 /** RANDOM_IN_RANGE random number in range */ 157 public static final float RAND_IN_RANGE = asNan(OFFSET + 42); 158 159 /** SQUARE_SUM the sum of the square of two numbers */ 160 public static final float SQUARE_SUM = asNan(OFFSET + 43); 161 162 /** STEP x > edge ? 1 : 0; */ 163 public static final float STEP = asNan(OFFSET + 44); 164 165 /** SQUARE x*x; */ 166 public static final float SQUARE = asNan(OFFSET + 45); 167 168 /** DUP x,x; */ 169 public static final float DUP = asNan(OFFSET + 46); 170 171 /** HYPOT sqrt(x*x+y*y); */ 172 public static final float HYPOT = asNan(OFFSET + 47); 173 174 /** SWAP y,x; */ 175 public static final float SWAP = asNan(OFFSET + 48); 176 177 /** LERP (1-t)*x+t*y; */ 178 public static final float LERP = asNan(OFFSET + 49); 179 180 /** SMOOTH_STEP (1-smoothstep(edge0,edge1,x)); */ 181 public static final float SMOOTH_STEP = asNan(OFFSET + 50); 182 183 /** LAST valid operator */ 184 public static final int LAST_OP = OFFSET + 50; 185 186 /** VAR1 operator */ 187 public static final float VAR1 = asNan(OFFSET + 51); 188 189 /** VAR2 operator */ 190 public static final float VAR2 = asNan(OFFSET + 52); 191 192 /** VAR2 operator */ 193 public static final float VAR3 = asNan(OFFSET + 53); 194 195 // TODO SQUARE, DUP, HYPOT, SWAP 196 // private static final float FP_PI = (float) Math.PI; 197 private static final float FP_TO_RAD = 57.29578f; // 180/PI 198 private static final float FP_TO_DEG = 0.017453292f; // 180/PI 199 200 @NonNull float[] mStack = new float[0]; 201 @NonNull float[] mLocalStack = new float[128]; 202 @NonNull float[] mVar = new float[0]; 203 @Nullable CollectionsAccess mCollectionsAccess; 204 IntMap<MonotonicSpline> mSplineMap = new IntMap<>(); 205 private static Random sRandom; 206 getSplineValue(int arrayId, float pos)207 private float getSplineValue(int arrayId, float pos) { 208 MonotonicSpline fit = mSplineMap.get(arrayId); 209 float[] f = mCollectionsAccess.getFloats(arrayId); 210 if (fit != null) { 211 if (fit.getArray() == f) { // the array has not changed. 212 return fit.getPos(pos); 213 } 214 } 215 216 fit = new MonotonicSpline(null, f); 217 mSplineMap.put(arrayId, fit); 218 return fit.getPos(pos); 219 } 220 221 /** 222 * is float a math operator 223 * 224 * @param v 225 * @return 226 */ isMathOperator(float v)227 public static boolean isMathOperator(float v) { 228 if (Float.isNaN(v)) { 229 int pos = fromNaN(v); 230 // a data variable is a type of math operator for expressions 231 // it dereference to a value 232 if (NanMap.isDataVariable(v)) { 233 return false; 234 } 235 return pos > OFFSET && pos <= LAST_OP; 236 } 237 return false; 238 } 239 240 interface Op { eval(int sp)241 int eval(int sp); 242 } 243 244 /** 245 * Evaluate a float expression This system works by processing an Array of float (float[]) in 246 * reverse polish notation (rpn) Within that array some floats are commands they are encoded 247 * within an NaN. After processing the array the last item on the array is returned. The system 248 * supports variables allowing expressions like. sin(sqrt(x*x+y*y))/sqrt(x*x+y*y) Where x & y 249 * are passe as parameters Examples: (1+2) (1, 2, ADD) adds two numbers returns 3 eval(new 250 * float[]{ Var1, Var * } 251 * 252 * @param exp 253 * @param var 254 * @return 255 */ eval(@onNull float[] exp, @NonNull float... var)256 public float eval(@NonNull float[] exp, @NonNull float... var) { 257 mStack = exp; 258 mVar = var; 259 int sp = -1; 260 for (int i = 0; i < mStack.length; i++) { 261 float v = mStack[i]; 262 if (Float.isNaN(v)) { 263 sp = opEval(sp, fromNaN(v)); 264 } else { 265 mStack[++sp] = v; 266 } 267 } 268 return mStack[sp]; 269 } 270 271 /** 272 * Evaluate a float expression 273 * 274 * @param ca Access to float array collections 275 * @param exp the expressions 276 * @param len the length of the expression array 277 * @param var variables if the expression contains VAR tags 278 * @return the value the expression evaluated to 279 */ eval( @onNull CollectionsAccess ca, @NonNull float[] exp, int len, @NonNull float... var)280 public float eval( 281 @NonNull CollectionsAccess ca, @NonNull float[] exp, int len, @NonNull float... var) { 282 System.arraycopy(exp, 0, mLocalStack, 0, len); 283 mStack = mLocalStack; 284 mVar = var; 285 mCollectionsAccess = ca; 286 int sp = -1; 287 288 for (int i = 0; i < mStack.length; i++) { 289 float v = mStack[i]; 290 if (Float.isNaN(v)) { 291 int id = fromNaN(v); 292 if ((id & NanMap.ID_REGION_MASK) != NanMap.ID_REGION_ARRAY) { 293 sp = opEval(sp, id); 294 } else { 295 mStack[++sp] = v; 296 } 297 } else { 298 mStack[++sp] = v; 299 } 300 } 301 return mStack[sp]; 302 } 303 304 /** 305 * Evaluate a float expression 306 * 307 * @param ca The access to float arrays 308 * @param exp the expression 309 * @param len the length of the expression sections 310 * @return the value the expression evaluated to 311 */ eval(@onNull CollectionsAccess ca, @NonNull float[] exp, int len)312 public float eval(@NonNull CollectionsAccess ca, @NonNull float[] exp, int len) { 313 System.arraycopy(exp, 0, mLocalStack, 0, len); 314 mStack = mLocalStack; 315 mCollectionsAccess = ca; 316 int sp = -1; 317 318 for (int i = 0; i < len; i++) { 319 float v = mStack[i]; 320 if (Float.isNaN(v)) { 321 int id = fromNaN(v); 322 if ((id & NanMap.ID_REGION_MASK) != NanMap.ID_REGION_ARRAY) { 323 sp = opEval(sp, id); 324 } else { 325 mStack[++sp] = v; 326 } 327 } else { 328 mStack[++sp] = v; 329 } 330 } 331 return mStack[sp]; 332 } 333 dereference(@onNull CollectionsAccess ca, int id, int sp)334 private int dereference(@NonNull CollectionsAccess ca, int id, int sp) { 335 mStack[sp] = ca.getFloatValue(id, (int) (mStack[sp])); 336 return sp; 337 } 338 339 /** 340 * Evaluate a float expression 341 * 342 * @param exp 343 * @param len 344 * @param var 345 * @return 346 */ eval(@onNull float[] exp, int len, @NonNull float... var)347 public float eval(@NonNull float[] exp, int len, @NonNull float... var) { 348 System.arraycopy(exp, 0, mLocalStack, 0, len); 349 mStack = mLocalStack; 350 mVar = var; 351 int sp = -1; 352 353 for (int i = 0; i < len; i++) { 354 float v = mStack[i]; 355 if (Float.isNaN(v)) { 356 sp = opEval(sp, fromNaN(v)); 357 } else { 358 mStack[++sp] = v; 359 } 360 } 361 return mStack[sp]; 362 } 363 364 /** 365 * Evaluate a float expression 366 * 367 * @param exp 368 * @param var 369 * @return 370 */ evalDB(@onNull float[] exp, @NonNull float... var)371 public float evalDB(@NonNull float[] exp, @NonNull float... var) { 372 mStack = exp; 373 mVar = var; 374 int sp = -1; 375 376 for (float v : exp) { 377 if (Float.isNaN(v)) { 378 sp = opEval(sp, fromNaN(v)); 379 } else { 380 System.out.print(" " + v); 381 mStack[++sp] = v; 382 } 383 } 384 return mStack[sp]; 385 } 386 387 static { 388 int k = 0; 389 sNames.put(k++, "NOP"); 390 sNames.put(k++, "+"); 391 sNames.put(k++, "-"); 392 sNames.put(k++, "*"); 393 sNames.put(k++, "/"); 394 sNames.put(k++, "%"); 395 sNames.put(k++, "min"); 396 sNames.put(k++, "max"); 397 sNames.put(k++, "pow"); 398 sNames.put(k++, "sqrt"); 399 sNames.put(k++, "abs"); 400 sNames.put(k++, "sign"); 401 sNames.put(k++, "copySign"); 402 sNames.put(k++, "exp"); 403 sNames.put(k++, "floor"); 404 sNames.put(k++, "log"); 405 sNames.put(k++, "ln"); 406 sNames.put(k++, "round"); 407 sNames.put(k++, "sin"); 408 sNames.put(k++, "cos"); 409 sNames.put(k++, "tan"); 410 sNames.put(k++, "asin"); 411 sNames.put(k++, "acos"); 412 sNames.put(k++, "atan"); 413 sNames.put(k++, "atan2"); 414 sNames.put(k++, "mad"); 415 sNames.put(k++, "ifElse"); 416 sNames.put(k++, "clamp"); 417 sNames.put(k++, "cbrt"); 418 sNames.put(k++, "deg"); 419 sNames.put(k++, "rad"); 420 sNames.put(k++, "ceil"); 421 422 sNames.put(k++, "A_DEREF"); 423 sNames.put(k++, "A_MAX"); 424 sNames.put(k++, "A_MIN"); 425 sNames.put(k++, "A_SUM"); 426 sNames.put(k++, "A_AVG"); 427 sNames.put(k++, "A_LEN"); 428 sNames.put(k++, "A_SPLINE"); 429 sNames.put(k++, "RAND"); 430 sNames.put(k++, "RAND_SEED"); 431 432 sNames.put(k++, "noise_from"); 433 sNames.put(k++, "rand_in_range"); 434 sNames.put(k++, "square_sum"); 435 sNames.put(k++, "step"); 436 sNames.put(k++, "square"); 437 sNames.put(k++, "dup"); 438 sNames.put(k++, "hypot"); 439 sNames.put(k++, "swap"); 440 sNames.put(k++, "lerp"); 441 sNames.put(k++, "smooth_step"); 442 443 sNames.put(k++, "a[0]"); 444 sNames.put(k++, "a[1]"); 445 sNames.put(k++, "a[2]"); 446 } 447 448 /** 449 * given a float command return its math name (e.g sin, cos etc.) 450 * 451 * @param f 452 * @return 453 */ 454 @Nullable toMathName(float f)455 public static String toMathName(float f) { 456 int id = fromNaN(f) - OFFSET; 457 return sNames.get(id); 458 } 459 460 /** 461 * Convert an expression encoded as an array of floats int ot a string 462 * 463 * @param exp 464 * @param labels 465 * @return 466 */ 467 @NonNull toString(@onNull float[] exp, @Nullable String[] labels)468 public static String toString(@NonNull float[] exp, @Nullable String[] labels) { 469 StringBuilder s = new StringBuilder(); 470 for (int i = 0; i < exp.length; i++) { 471 float v = exp[i]; 472 if (Float.isNaN(v)) { 473 if (isMathOperator(v)) { 474 s.append(toMathName(v)); 475 } else { 476 int id = fromNaN(v); 477 String idString = 478 (id > NanMap.ID_REGION_ARRAY) ? ("A_" + (id & 0xFFFFF)) : "" + id; 479 s.append("["); 480 s.append(idString); 481 s.append("]"); 482 } 483 } else { 484 if (labels != null && labels[i] != null) { 485 s.append(labels[i]); 486 if (!labels[i].contains("_")) { 487 s.append(v); 488 } 489 } else { 490 s.append(v); 491 } 492 } 493 s.append(" "); 494 } 495 return s.toString(); 496 } 497 toString(@onNull float[] exp, int sp)498 static String toString(@NonNull float[] exp, int sp) { 499 // String[] str = new String[exp.length]; 500 if (Float.isNaN(exp[sp])) { 501 int id = fromNaN(exp[sp]) - OFFSET; 502 switch (NO_OF_OPS[id]) { 503 case -1: 504 return "nop"; 505 case 1: 506 return sNames.get(id) + "(" + toString(exp, sp + 1) + ") "; 507 case 2: 508 if (infix(id)) { 509 return "(" 510 + toString(exp, sp + 1) 511 + sNames.get(id) 512 + " " 513 + toString(exp, sp + 2) 514 + ") "; 515 } else { 516 return sNames.get(id) 517 + "(" 518 + toString(exp, sp + 1) 519 + ", " 520 + toString(exp, sp + 2) 521 + ")"; 522 } 523 case 3: 524 if (infix(id)) { 525 return "((" 526 + toString(exp, sp + 1) 527 + ") ? " 528 + toString(exp, sp + 2) 529 + ":" 530 + toString(exp, sp + 3) 531 + ")"; 532 } else { 533 return sNames.get(id) 534 + "(" 535 + toString(exp, sp + 1) 536 + ", " 537 + toString(exp, sp + 2) 538 + ", " 539 + toString(exp, sp + 3) 540 + ")"; 541 } 542 } 543 } 544 return Float.toString(exp[sp]); 545 } 546 547 static final int[] NO_OF_OPS = { 548 -1, // no op 549 2, 550 2, 551 2, 552 2, 553 2, // + - * / % 554 2, 555 2, 556 2, // min max, power 557 1, 558 1, 559 1, 560 1, 561 1, 562 1, 563 1, 564 1, // sqrt,abs,CopySign,exp,floor,log,ln 565 1, 566 1, 567 1, 568 1, 569 1, 570 1, 571 1, 572 2, // round,sin,cos,tan,asin,acos,atan,atan2 573 3, 574 3, 575 3, 576 1, 577 1, 578 1, 579 1, 580 0, 581 0, 582 0 // mad, ?:, 583 // a[0],a[1],a[2] 584 }; 585 586 /** 587 * to be used by parser to determine if command is infix 588 * 589 * @param n 590 * @return 591 */ infix(int n)592 static boolean infix(int n) { 593 return ((n < 6) || (n == 25) || (n == 26)); 594 } 595 596 /** 597 * Convert an id into a NaN object 598 * 599 * @param v 600 * @return 601 */ asNan(int v)602 public static float asNan(int v) { 603 return Float.intBitsToFloat(v | -0x800000); 604 } 605 606 /** 607 * Get ID from a NaN float 608 * 609 * @param v 610 * @return 611 */ fromNaN(float v)612 public static int fromNaN(float v) { 613 int b = Float.floatToRawIntBits(v); 614 return b & 0x7FFFFF; 615 } 616 617 // ================= New approach ======== 618 private static final int OP_ADD = OFFSET + 1; 619 private static final int OP_SUB = OFFSET + 2; 620 private static final int OP_MUL = OFFSET + 3; 621 private static final int OP_DIV = OFFSET + 4; 622 private static final int OP_MOD = OFFSET + 5; 623 private static final int OP_MIN = OFFSET + 6; 624 private static final int OP_MAX = OFFSET + 7; 625 private static final int OP_POW = OFFSET + 8; 626 private static final int OP_SQRT = OFFSET + 9; 627 private static final int OP_ABS = OFFSET + 10; 628 private static final int OP_SIGN = OFFSET + 11; 629 private static final int OP_COPY_SIGN = OFFSET + 12; 630 private static final int OP_EXP = OFFSET + 13; 631 private static final int OP_FLOOR = OFFSET + 14; 632 private static final int OP_LOG = OFFSET + 15; 633 private static final int OP_LN = OFFSET + 16; 634 private static final int OP_ROUND = OFFSET + 17; 635 private static final int OP_SIN = OFFSET + 18; 636 private static final int OP_COS = OFFSET + 19; 637 private static final int OP_TAN = OFFSET + 20; 638 private static final int OP_ASIN = OFFSET + 21; 639 private static final int OP_ACOS = OFFSET + 22; 640 private static final int OP_ATAN = OFFSET + 23; 641 private static final int OP_ATAN2 = OFFSET + 24; 642 private static final int OP_MAD = OFFSET + 25; 643 private static final int OP_TERNARY_CONDITIONAL = OFFSET + 26; 644 private static final int OP_CLAMP = OFFSET + 27; 645 private static final int OP_CBRT = OFFSET + 28; 646 private static final int OP_DEG = OFFSET + 29; 647 private static final int OP_RAD = OFFSET + 30; 648 private static final int OP_CEIL = OFFSET + 31; 649 private static final int OP_A_DEREF = OFFSET + 32; 650 private static final int OP_A_MAX = OFFSET + 33; 651 private static final int OP_A_MIN = OFFSET + 34; 652 private static final int OP_A_SUM = OFFSET + 35; 653 private static final int OP_A_AVG = OFFSET + 36; 654 private static final int OP_A_LEN = OFFSET + 37; 655 private static final int OP_A_SPLINE = OFFSET + 38; 656 private static final int OP_RAND = OFFSET + 39; 657 private static final int OP_RAND_SEED = OFFSET + 40; 658 659 private static final int OP_NOISE_FROM = OFFSET + 41; 660 private static final int OP_RAND_IN_RANGE = OFFSET + 42; 661 private static final int OP_SQUARE_SUM = OFFSET + 43; 662 private static final int OP_STEP = OFFSET + 44; 663 private static final int OP_SQUARE = OFFSET + 45; 664 private static final int OP_DUP = OFFSET + 46; 665 private static final int OP_HYPOT = OFFSET + 47; 666 private static final int OP_SWAP = OFFSET + 48; 667 private static final int OP_LERP = OFFSET + 49; 668 private static final int OP_SMOOTH_STEP = OFFSET + 50; 669 670 private static final int OP_FIRST_VAR = OFFSET + 51; 671 private static final int OP_SECOND_VAR = OFFSET + 52; 672 private static final int OP_THIRD_VAR = OFFSET + 53; 673 opEval(int sp, int id)674 int opEval(int sp, int id) { 675 float[] array; 676 677 switch (id) { 678 case OP_ADD: 679 mStack[sp - 1] = mStack[sp - 1] + mStack[sp]; 680 return sp - 1; 681 682 case OP_SUB: 683 mStack[sp - 1] = mStack[sp - 1] - mStack[sp]; 684 return sp - 1; 685 686 case OP_MUL: 687 mStack[sp - 1] = mStack[sp - 1] * mStack[sp]; 688 return sp - 1; 689 690 case OP_DIV: 691 mStack[sp - 1] = mStack[sp - 1] / mStack[sp]; 692 return sp - 1; 693 694 case OP_MOD: 695 mStack[sp - 1] = mStack[sp - 1] % mStack[sp]; 696 return sp - 1; 697 698 case OP_MIN: 699 mStack[sp - 1] = (float) Math.min(mStack[sp - 1], mStack[sp]); 700 return sp - 1; 701 702 case OP_MAX: 703 mStack[sp - 1] = (float) Math.max(mStack[sp - 1], mStack[sp]); 704 return sp - 1; 705 706 case OP_POW: 707 mStack[sp - 1] = (float) Math.pow(mStack[sp - 1], mStack[sp]); 708 return sp - 1; 709 710 case OP_SQRT: 711 mStack[sp] = (float) Math.sqrt(mStack[sp]); 712 return sp; 713 714 case OP_ABS: 715 mStack[sp] = (float) Math.abs(mStack[sp]); 716 return sp; 717 718 case OP_SIGN: 719 mStack[sp] = (float) Math.signum(mStack[sp]); 720 return sp; 721 722 case OP_COPY_SIGN: 723 mStack[sp - 1] = (float) Math.copySign(mStack[sp - 1], mStack[sp]); 724 return sp - 1; 725 726 case OP_EXP: 727 mStack[sp] = (float) Math.exp(mStack[sp]); 728 return sp; 729 730 case OP_FLOOR: 731 mStack[sp] = (float) Math.floor(mStack[sp]); 732 return sp; 733 734 case OP_LOG: 735 mStack[sp] = (float) Math.log10(mStack[sp]); 736 return sp; 737 738 case OP_LN: 739 mStack[sp] = (float) Math.log(mStack[sp]); 740 return sp; 741 742 case OP_ROUND: 743 mStack[sp] = (float) Math.round(mStack[sp]); 744 return sp; 745 746 case OP_SIN: 747 mStack[sp] = (float) Math.sin(mStack[sp]); 748 return sp; 749 750 case OP_COS: 751 mStack[sp] = (float) Math.cos(mStack[sp]); 752 return sp; 753 754 case OP_TAN: 755 mStack[sp] = (float) Math.tan(mStack[sp]); 756 return sp; 757 758 case OP_ASIN: 759 mStack[sp] = (float) Math.asin(mStack[sp]); 760 return sp; 761 762 case OP_ACOS: 763 mStack[sp] = (float) Math.acos(mStack[sp]); 764 return sp; 765 766 case OP_ATAN: 767 mStack[sp] = (float) Math.atan(mStack[sp]); 768 return sp; 769 770 case OP_ATAN2: 771 mStack[sp - 1] = (float) Math.atan2(mStack[sp - 1], mStack[sp]); 772 return sp - 1; 773 774 case OP_MAD: 775 mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2]; 776 return sp - 2; 777 778 case OP_TERNARY_CONDITIONAL: 779 mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2]; 780 return sp - 2; 781 782 case OP_CLAMP: 783 mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]); 784 return sp - 2; 785 786 case OP_CBRT: 787 mStack[sp] = (float) Math.pow(mStack[sp], 1 / 3.); 788 return sp; 789 790 case OP_DEG: 791 mStack[sp] = mStack[sp] * FP_TO_RAD; 792 return sp; 793 794 case OP_RAD: 795 mStack[sp] = mStack[sp] * FP_TO_DEG; 796 return sp; 797 798 case OP_CEIL: 799 mStack[sp] = (float) Math.ceil(mStack[sp]); 800 return sp; 801 802 case OP_A_DEREF: 803 id = fromNaN(mStack[sp - 1]); 804 mStack[sp - 1] = mCollectionsAccess.getFloatValue(id, (int) mStack[sp]); 805 return sp - 1; 806 807 case OP_A_MAX: 808 id = fromNaN(mStack[sp]); 809 array = mCollectionsAccess.getFloats(id); 810 float max = array[0]; 811 for (int i = 1; i < array.length; i++) { 812 max = Math.max(max, array[i]); 813 } 814 mStack[sp] = max; 815 return sp; 816 817 case OP_A_MIN: 818 id = fromNaN(mStack[sp]); 819 array = mCollectionsAccess.getFloats(id); 820 if (array.length == 0) { 821 return sp; 822 } 823 float min = array[0]; 824 for (int i = 1; i < array.length; i++) { 825 min = Math.min(min, array[i]); 826 } 827 mStack[sp] = min; 828 return sp; 829 830 case OP_A_SUM: 831 id = fromNaN(mStack[sp]); 832 array = mCollectionsAccess.getFloats(id); 833 float sum = 0; 834 for (int i = 0; i < array.length; i++) { 835 sum += array[i]; 836 } 837 mStack[sp] = sum; 838 return sp; 839 840 case OP_A_AVG: 841 id = fromNaN(mStack[sp]); 842 array = mCollectionsAccess.getFloats(id); 843 sum = 0; 844 for (int i = 0; i < array.length; i++) { 845 sum += array[i]; 846 } 847 mStack[sp] = sum / array.length; 848 return sp; 849 850 case OP_A_LEN: 851 id = fromNaN(mStack[sp]); 852 mStack[sp] = mCollectionsAccess.getListLength(id); 853 return sp; 854 855 case OP_A_SPLINE: 856 id = fromNaN(mStack[sp - 1]); 857 mStack[sp - 1] = getSplineValue(id, mStack[sp]); 858 return sp - 1; 859 860 case OP_RAND: 861 if (sRandom == null) { 862 sRandom = new Random(); 863 } 864 mStack[sp + 1] = sRandom.nextFloat(); 865 return sp + 1; 866 867 case OP_RAND_SEED: 868 float seed = mStack[sp]; 869 if (seed == 0) { 870 sRandom = new Random(); 871 } else { 872 if (sRandom == null) { 873 sRandom = new Random(Float.floatToRawIntBits(seed)); 874 } else { 875 sRandom.setSeed(Float.floatToRawIntBits(seed)); 876 } 877 } 878 return sp - 1; 879 case OP_NOISE_FROM: 880 int x = Float.floatToRawIntBits(mStack[sp]); 881 x = (x << 13) ^ x; // / Bitwise scrambling return 882 mStack[sp] = 883 (1.0f 884 - ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) 885 / 1073741824.0f); 886 return sp; 887 888 case OP_RAND_IN_RANGE: 889 if (sRandom == null) { 890 sRandom = new Random(); 891 } 892 mStack[sp] = sRandom.nextFloat() * (mStack[sp] - mStack[sp - 1]) + mStack[sp - 1]; 893 return sp; 894 case OP_SQUARE_SUM: 895 mStack[sp - 1] = mStack[sp - 1] * mStack[sp - 1] + mStack[sp] * mStack[sp]; 896 return sp - 1; 897 case OP_STEP: 898 System.out.println(mStack[sp] + " > " + mStack[sp - 1]); 899 mStack[sp - 1] = (mStack[sp - 1] > mStack[sp]) ? 1f : 0f; 900 return sp - 1; 901 case OP_SQUARE: 902 mStack[sp] = mStack[sp] * mStack[sp]; 903 return sp; 904 case OP_DUP: 905 mStack[sp + 1] = mStack[sp]; 906 return sp + 1; 907 case OP_HYPOT: 908 mStack[sp - 1] = (float) Math.hypot(mStack[sp - 1], mStack[sp]); 909 return sp - 1; 910 case OP_SWAP: 911 float swap = mStack[sp - 1]; 912 mStack[sp - 1] = mStack[sp]; 913 mStack[sp] = swap; 914 return sp; 915 case OP_LERP: 916 float tmp1 = mStack[sp - 2]; 917 float tmp2 = mStack[sp - 1]; 918 float tmp3 = mStack[sp]; 919 mStack[sp - 2] = tmp1 + (tmp2 - tmp1) * tmp3; 920 return sp - 2; 921 case OP_SMOOTH_STEP: 922 float val3 = mStack[sp - 2]; 923 float max2 = mStack[sp - 1]; 924 float min1 = mStack[sp]; 925 System.out.println("val3 = " + val3 + " min1 = " + min1 + " max2 = " + max2); 926 if (val3 < min1) { 927 mStack[sp - 2] = 0f; 928 System.out.println("below min "); 929 } else if (val3 > max2) { 930 mStack[sp - 2] = 1f; 931 System.out.println("above max "); 932 933 } else { 934 float v = (val3 - min1) / (max2 - min1); 935 System.out.println("v = " + v); 936 mStack[sp - 2] = v * v * (3 - 2 * v); 937 } 938 return sp - 2; 939 940 case OP_FIRST_VAR: 941 mStack[sp] = mVar[0]; 942 return sp; 943 944 case OP_SECOND_VAR: 945 mStack[sp] = mVar[1]; 946 return sp; 947 948 case OP_THIRD_VAR: 949 mStack[sp] = mVar[2]; 950 return sp; 951 } 952 return sp; 953 } 954 } 955