1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
|
# This documents all the optimizations that are done to bytecode
# by fparser.cc directly while parsing the input function
# (excluding powi).
# identifiers: lowercase=cImmeds, uppercase=opcodes
# [bracketed expression in condition]: constraints to input immeds or opcodes
# [bracketed expression in replacement]: function that produces an immed
# {braceted expression in replacement}: function that produces an opcode
#
# The comment tag "#TEST pathlet" indicates the test(s) that apply
# to this particular rule. Note that the tests only test that this
# rule does not _break_ anything (they try to invoke the rule),
# but they don't test whether the rule is actually applied
# and that the rule has the intended effect.
#
#y [isEvenInteger(y)&&!isEvenInteger(x*y)] cExp x cPow -> cAbs [y*x] cExp
#y [isEvenInteger(y)&&!isEvenInteger(x*y)] cExp2 x cPow -> cAbs [y*x] cExp2
# ^ y cExp never occurs (already optimized to literal)
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [isEvenInteger(y)&&!isEvenInteger(x*y)] cPow x cPow -> cAbs [y*x] cPow #TEST 10/absyxpow_neg, 10/absyxpow_pos
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr x [!isEvenInteger(x+x)] cPow -> cAbs [x+x] cPow
IF(FP_FLOAT_VERSION) cSqr cSqrt -> cAbs # TEST 10/sqrsqrt
#IF(FP_FLOAT_VERSION) cSqr cRSqrt -> cAbs cInv
# (x^y)^1.5 is unacceptable,
# for y might be 2, resulting in x^3
# f(-2) = 8
# f'(-2) = -8
# (x^y)^5 is okay
# for y might be 1.2, resulting in x^6
# f(-2) = nan
# f'(-2) = 64
# (x^y)^2 is okay,
# for y might be 1.5, resulting in x^3
# f(-2) = nan <- ok because of this
# f'(-2) = -8
#
#y [!isInteger(y)] cExp x [isInteger(x)] cPow -> [y*x] cExp
#y [!isInteger(y)] cExp2 x [isInteger(x)] cPow -> [y*x] cExp2
# ^ y cExp never occurs (already optimized to literal)
IF(FP_FLOAT_VERSION) y [!isInteger(y)] cPow x [isInteger(x)] cPow -> [y*x] cPow # TEST 10/ypowxpow
IF(FP_FLOAT_VERSION) cExp x [isInteger(x)] cPow -> [x] cMul cExp # TEST 10/expxpow
IF(FP_FLOAT_VERSION) cExp2 x [isInteger(x)] cPow -> [x] cMul cExp2 # TEST 10/exp2xpow
IF(FP_FLOAT_VERSION) cPow x [isInteger(x)] cPow -> [x] cMul cPow # TEST 10/powxpow
IF(FP_FLOAT_VERSION) cSqr x cPow -> [x+x] cPow #TEST 10/sqrxpow, 10/sqrxpow_nonint
# This rule does not speed up evaluation at all, but
# it greatly simplifies the optimization rule set, when
# we don't need to check for sequences of an immed and cSub.
x cSub -> [-x] cAdd # TEST 10/immsub
###### REMOVING IDLE OPERATIONS :
x [x==Value_t(1)] cMul -> # TEST 10/mul1
x [x==Value_t(1)] cDiv -> # TEST 10/div1
x [x==Value_t()] cAdd -> # TEST 10/add0
x [x==Value_t()] cSub -> # TEST 10/sub0
cDup cMin -> # TEST 10/dupminmax
cDup cMax -> # TEST 10/dupminmax
cNeg cNeg -> # TEST 10/negneg
IF(FP_FLOAT_VERSION) cInv cInv -> # TEST 10/invinv
IF(FP_COMPLEX_VERSION) cConj cConj ->
B [B==A] cDup A [IsVarOpcode(A)] cMin -> B cDup # TEST 10/dupminmax2
B [B==A] cDup A [IsVarOpcode(A)] cMax -> B cDup # TEST 10/dupminmax2
B [B==A] cMin A [IsVarOpcode(A)] cMin -> B cMin # TEST 10/dupminmax3
B [B==A] cMax A [IsVarOpcode(A)] cMax -> B cMax # TEST 10/dupminmax3
y [y*x==Value_t(1)] cMul x cMul -> # TEST 10/mul1b
###### OPERATIONS WHICH PRODUCE A CONSTANT VALUE:
###### An expression is turned into a constant value
###### by multiplying it with zero and adding the constant.
cDup cSub -> [Value_t()] cMul # TEST 10/subxx
cDup cRSub -> [Value_t()] cMul # TEST 10/subxx
cDup cDiv -> [Value_t()] cMul [Value_t(1)] cAdd # TEST 10/divxx
IF(FP_COMPLEX_VERSION) cReal cImag -> [Value_t()] cMul
IF(FP_COMPLEX_VERSION) cAbs cImag -> [Value_t()] cMul
IF(FP_FLOAT_VERSION) x [x==Value_t()] cPow -> [Value_t()] cMul [Value_t(1)] cAdd
IF(FP_FLOAT_VERSION) cSinCos cHypot -> [Value_t()] cMul [Value_t(1)] cAdd # TEST 99/59
# Multiplications by zero: Undo as many operands as possible by peeling.
# Some of these optimimizations can be disabled due to law of diminishing returns.
A [IsVarOpcode(A)] x [x==Value_t()] cMul -> [x] # TEST 10/mul_zero VERIFY
A [IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
B [IsVarOpcode(B)] A [IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
B [IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A [IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> A [x] cMul # TEST 10/mul_zero VERIFY
y A [IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
A [IsVarOpcode(A)] cMul x [x==Value_t()] cMul -> [x] cMul # TEST 10/mul_zero VERIFY
C [IsVarOpcode(C)] B [IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> A [x] cMul # TEST 10/mul_zero VERIFY
C [IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] B [IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> B A [x] cMul # TEST 10/mul_zero VERIFY
y B [IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] x [x==Value_t()] cMul -> A [x] cMul # TEST 10/mul_zero VERIFY
###### INLINE EXPANSION OF BASIC OPERATORS :
x cNeg -> [-x] # TEST 10/neg
x [x!=Value_t()] cInv -> [Value_t(1)/x]
y x cMul -> [y*x] # TEST 10/mul
y x [x!=Value_t()] cDiv -> [y/x] # TEST 10/div
y x [x!=Value_t()] cMod -> [fp_mod(y,x)] # TEST 10/mod
y x cAdd -> [y+x] # TEST 10/add
y x cSub -> [y-x] # TEST 10/sub
x cNot -> [fp_not(x)] # TEST 10/not
#y [y!=Value_t()] x cRDiv -> [x/y]
#y x cRSub -> [x-y]
y x cLess -> [fp_less(y,x)] # TEST 10/cmplt
y x cLessOrEq -> [fp_lessOrEq(y,x)] # TEST 10/cmple
y x cGreater -> [fp_less(x,y)] # TEST 10/cmpgt
y x cGreaterOrEq -> [fp_lessOrEq(x,y)] # TEST 10/cmpge
y x cEqual -> [fp_equal(y,x)] # TEST 10/cmpeq
y x cNEqual -> [fp_nequal(y,x)] # TEST 10/cmpne
y x cAnd -> [fp_and(x,y)] # TEST 10/and
y x cOr -> [fp_or(x,y)] # TEST 10/or
#y x cAbsAnd -> [fp_absAnd(x,y)]
#y x cAbsOr -> [fp_absOr(x,y)]
cNeg x cMul -> [-x] cMul # TEST 10/negmul
x cMul cNeg -> [-x] cMul # TEST 10/mulneg
x [x==Value_t(-1)] cMul -> cNeg # TEST 10/mulminus1
cNeg x [x!=Value_t()] cDiv -> [-x] cDiv # TEST 10/negdiv
y cAdd x cAdd -> [y+x] cAdd # TEST 11/42
y cMul x cMul -> [y*x] cMul # TEST 11/43
###### INLINE EXPANSION OF BASIC FUNCTIONS :
x cAbs -> [fp_abs(x)] # TEST 10/abs
IF(FP_FLOAT_VERSION) x cDeg -> [RadiansToDegrees(x)] # TEST 10/deg
IF(FP_FLOAT_VERSION) x cRad -> [DegreesToRadians(x)] # TEST 10/rad
IF(FP_FLOAT_VERSION) x cCeil -> [fp_ceil(x)] # TEST 10/ceil*
IF(FP_FLOAT_VERSION) x cFloor -> [fp_floor(x)] # TEST 10/floor*
IF(FP_FLOAT_VERSION) x cInt -> [fp_int(x)] # TEST 10/int
IF(FP_FLOAT_VERSION) x cTrunc -> [fp_trunc(x)] # TEST 10/runc*
IF(FP_FLOAT_VERSION) y x cAtan2 -> [fp_atan2(y,x)] # TEST 10/atan2*
y x cMin -> [fp_min(x,y)] # TEST 10/min
y x cMax -> [fp_max(x,y)] # TEST 10/max
##### REAL VERSIONS:
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x>=Value_t(1)] cAcosh -> [fp_acosh(x)] # TEST 10/acosh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAsinh -> [fp_asinh(x)] # TEST 10/asinh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [fp_abs(x)< Value_t(1)] cAtanh -> [fp_atanh(x)] # TEST 10/atanh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [fp_abs(x)<=Value_t(1)] cAcos -> [fp_acos(x)] # TEST 10/acos*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [fp_abs(x)<=Value_t(1)] cAsin -> [fp_asin(x)] # TEST 10/asin*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAtan -> [fp_atan(x)] # TEST 10/atan*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCbrt -> [fp_cbrt(x)] # TEST 10/cbrt*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCos -> [fp_cos(x)] # TEST 10/cos*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCosh -> [fp_cosh(x)] # TEST 10/cosh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp -> [fp_exp(x)] # TEST 10/exp*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp2 -> [fp_exp2(x)] # TEST 10/exp2*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x> Value_t(0)] cLog -> [fp_log(x)] # TEST 10/log*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x> Value_t(0)] cLog10 -> [fp_log10(x)] # TEST 10/log10*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x> Value_t(0)] cLog2 -> [fp_log2(x)] # TEST 10/log2*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSin -> [fp_sin(x)] # TEST 10/sin*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSinh -> [fp_sinh(x)] # TEST 10/sinh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x>=Value_t(0)] cSqrt -> [fp_sqrt(x)] # TEST 10/sqr*
#IF(FP_FLOAT_VERSION) x [x> Value_t()] cRSqrt -> [Value_t(1)/fp_sqrt(x)]
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTan -> [fp_tan(x)] # TEST 10/tan*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTanh -> [fp_tanh(x)] # TEST 10/tanh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [ y!=Value_t(0) || x>=Value_t(0)] x cPow -> [fp_pow(y,x)] # TEST 10/pow*
##### COMPLEX VERSIONS:
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAcosh -> [fp_acosh(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAsinh -> [fp_asinh(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [Value_t(fp_abs(x.real()),x.imag())!=Value_t(1,0)] cAtanh -> [fp_atanh(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAcos -> [fp_acos(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cAsin -> [fp_asin(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [Value_t(x.real(),fp_abs(x.imag()))!=Value_t(0,1)] cAtan -> [fp_atan(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCbrt -> [fp_cbrt(x)] # TEST 10/cbrt*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCos -> [fp_cos(x)] # TEST 10/cos*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cCosh -> [fp_cosh(x)] # TEST 10/cosh*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp -> [fp_exp(x)] # TEST 10/exp*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cExp2 -> [fp_exp2(x)] # TEST 10/exp2*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x!=Value_t(0)] cLog -> [fp_log(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x!=Value_t(0)] cLog10 -> [fp_log10(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x!=Value_t(0)] cLog2 -> [fp_log2(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSin -> [fp_sin(x)] # TEST 10/sin*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSinh -> [fp_sinh(x)] # TEST 10/sinh*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cSqrt -> [fp_sqrt(x)]
#IF(FP_FLOAT_VERSION) x [x> Value_t(0)] cRSqrt -> [Value_t(1)/fp_sqrt(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTan -> [fp_tan(x)] # TEST 10/tan*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cTanh -> [fp_tanh(x)] # TEST 10/tanh*
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y x cPow -> [fp_pow(y,x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x cArg -> [fp_arg(x)]
IF(FP_COMPLEX_VERSION) x cReal -> [fp_real(x)]
IF(FP_COMPLEX_VERSION) x cImag -> [fp_imag(x)]
IF(FP_COMPLEX_VERSION) x cConj -> [fp_conj(x)]
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x y cPolar -> [fp_polar(x,y)]
###### SIMPLIFYING SOME OPCODE SEQUENCES :
x [x==Value_t(2)] cMul -> cDup cAdd # TEST 10/mul2
cNeg cAdd -> cSub # TEST 10/negadd
cNeg cSub -> cAdd # TEST 10/negsub
cNeg cAbs -> cAbs # TEST 10/negabs
cDup cMul -> cSqr # TEST 10/sqr_xx
cNeg cSqr -> cSqr # TEST 10/negsqr
cAbs cSqr -> cSqr # TEST 10/abssqr
IF(FP_FLOAT_VERSION) cSqrt cInv -> cRSqrt # TEST 10/rsqrt
IF(FP_FLOAT_VERSION) x [x==fp_const_rad_to_deg<Value_t>()] cMul -> cDeg #TEST 10/deg
IF(FP_FLOAT_VERSION) x [x==fp_const_deg_to_rad<Value_t>()] cMul -> cRad #TEST 10/rad
IF(FP_FLOAT_VERSION) cDeg x cMul -> [RadiansToDegrees(x)] cMul # TEST 10/degxmul
IF(FP_FLOAT_VERSION) cRad x cMul -> [DegreesToRadians(x)] cMul # TEST 10/radxmul VERIFY
IF(FP_FLOAT_VERSION) x cMul cRad -> [DegreesToRadians(x)] cMul # TEST 10/xmulrad
IF(FP_FLOAT_VERSION) cInv cDiv -> cMul # TEST 10/invdiv
IF(FP_FLOAT_VERSION) cInv cMul -> cDiv # TEST 10/invmul (float-only, because: y*(1/x) vs y/x)
cLess cNot -> cGreaterOrEq # TEST 10/not_lt
cLessOrEq cNot -> cGreater # TEST 10/not_le
cGreater cNot -> cLessOrEq # TEST 10/not_gt
cGreaterOrEq cNot -> cLess # TEST 10/not_ge
cEqual cNot -> cNEqual # TEST 10/not_eq
cNEqual cNot -> cEqual # TEST 10/not_ne
cDup cOr -> cNotNot # TEST 99/3
cDup cAnd -> cNotNot # TEST 99/3
IF(!FP_COMPLEX_VERSION) cNeg cNot -> cNot # TEST 10/negnot
IF(!FP_COMPLEX_VERSION) cAbs cNot -> cNot # TEST 10/absnot
cNot cNot -> cNotNot # TEST 10/notnot
cNotNot cNot -> cNot # TEST 10/notnotnot
cAbsNotNot cNot -> cAbsNot # TEST 10/absnotnotnot
cNot cNotNot -> cNot # TEST 10/notnotnot2
# ^ Impossible as it seems, it is triggered by (!x & !x) -> !!(!x)
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs cCos -> cCos # TEST 10/abscos
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs cCosh -> cCosh # TEST 10/abscosh
IF(FP_FLOAT_VERSION) cNeg cCos -> cCos # TEST 10/negcos
IF(FP_FLOAT_VERSION) cNeg cCosh -> cCosh # TEST 10/negcosh
IF(FP_FLOAT_VERSION) cNeg cSin -> cSin cNeg # TEST 10/negsin
IF(FP_FLOAT_VERSION) cNeg cSinh -> cSinh cNeg # TEST 10/negsinh
IF(FP_FLOAT_VERSION) cNeg cTan -> cTan cNeg # TEST 10/negtan
IF(FP_FLOAT_VERSION) cNeg cTanh -> cTanh cNeg # TEST 10/negtanh
IF(FP_FLOAT_VERSION) x cMul cSin cNeg -> [-x] cMul cSin # TEST 10/xmulsinneg
IF(FP_FLOAT_VERSION) x cMul cSinh cNeg -> [-x] cMul cSinh # TEST 10/xmulsinhneg
IF(FP_FLOAT_VERSION) x cMul cTan cNeg -> [-x] cMul cTan # TEST 10/xmultanneg
IF(FP_FLOAT_VERSION) x cMul cTanh cNeg -> [-x] cMul cTanh # TEST 10/xmultanhneg
IF(FP_FLOAT_VERSION) cSin cDiv -> cCsc cMul # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cCos cDiv -> cSec cMul # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cTan cDiv -> cCot cMul # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cCsc cDiv -> cSin cMul # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cSec cDiv -> cCos cMul # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cCot cDiv -> cTan cMul # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cSin cInv -> cCsc # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cCos cInv -> cSec # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cTan cInv -> cCot # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cCsc cInv -> cSin # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cSec cInv -> cCos # TEST 10/invsincostan
IF(FP_FLOAT_VERSION) cCot cInv -> cTan # TEST 10/invsincostan
###################
# rdiv(x,y)/z --> rdiv(x*z,y) (y/x/z = y/(x*z))
IF(FP_FLOAT_VERSION) B [IsVarOpcode(B)] cRDiv A [IsVarOpcode(A)] cDiv -> A cMul B cRDiv #TEST 11/23
IF(FP_FLOAT_VERSION) x cRDiv A [IsVarOpcode(A)] cDiv -> A cMul [x] cRDiv #TEST 11/24
IF(FP_FLOAT_VERSION) x cRDiv A [IsVarOpcode(A)] cMul -> [DO_STACKPLUS1] A [x] cMul cRDiv #TEST 11/25
x [x==Value_t(1)] cRDiv -> cInv
# a/b/c = a/(b*c)
IF(FP_FLOAT_VERSION) B [IsVarOpcode(B)] cDiv A [IsVarOpcode(A)] cDiv -> [DO_STACKPLUS1] B A cMul cDiv #TEST 11/26
# a/b*c = a*b/c (increases chances of doing the div grouping if more divs come later)
IF(FP_FLOAT_VERSION) B [IsVarOpcode(B)] cDiv A [IsVarOpcode(A)] cMul -> [DO_STACKPLUS1] A cMul B cDiv #TEST 11/27
# The three rules below: same as above, but with immed instead of var A
# (do only when there is an explicit optimization; otherwise we get an infinite loop)
IF(FP_FLOAT_VERSION) y B [IsVarOpcode(B)] cDiv x cMul -> [y*x] B cDiv
IF(FP_FLOAT_VERSION) y cMul B [IsVarOpcode(B)] cDiv x cMul -> [y*x] cMul B cDiv
IF(FP_FLOAT_VERSION) cNeg B [IsVarOpcode(B)] cDiv x cMul -> [-x] cMul B cDiv #TEST 11/28
IF(FP_FLOAT_VERSION) cRDiv A [IsVarOpcode(A)] cMul -> [DO_STACKPLUS1] A cMul cRDiv #TEST 11/29
# The three rules below: same as above, but with immed instead of var A
# (do only when there is an explicit optimization; otherwise we get an infinite loop)
IF(FP_FLOAT_VERSION) y cRDiv x cMul -> [y*x] cRDiv #TEST 11/30
IF(FP_FLOAT_VERSION) y cMul cRDiv x cMul -> [y*x] cMul cRDiv
IF(FP_FLOAT_VERSION) cNeg cRDiv x cMul -> [-x] cMul cRDiv #TEST 11/31
# These below are just Add/Sub analogies of the above rules.
x cRSub A [IsVarOpcode(A)] cSub -> A cAdd [x] cRSub #TEST 11/32
x cRSub A [IsVarOpcode(A)] cAdd -> [DO_STACKPLUS1] A [x] cAdd cRSub #TEST 11/33
y B [IsVarOpcode(B)] cSub x cAdd -> [ y+x] B cSub
y cAdd B [IsVarOpcode(B)] cSub x cAdd -> [ y+x] cAdd B cSub #TEST 11/34
cNeg B [IsVarOpcode(B)] cSub x cAdd -> [-x] cAdd B cSub #TEST 11/35
cRSub A [IsVarOpcode(A)] cAdd -> [DO_STACKPLUS1] A cAdd cRSub #TEST 11/32 (DUP)
cRSub A [IsVarOpcode(A)] cSub -> [DO_STACKPLUS1] A cSub cRSub #TEST 11/33 (DUP)
y cRSub x cAdd -> [ y+x] cRSub #TEST 11/36
y cAdd cRSub x cAdd -> [ y+x] cAdd cRSub #TEST 11/37
cNeg cRSub x cAdd -> [-x] cAdd cRSub
A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(0)] cLess -> A [x] cMul # TEST 10/lt0
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr cLog -> cAbs cLog cDup cAdd # TEST 10/sqrlog
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr cLog2 -> cAbs cLog2 cDup cAdd # TEST 10/sqrlog2
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr cLog10 -> cAbs cLog10 cDup cAdd # TEST 10/sqrlog10
IF(FP_FLOAT_VERSION) y [(y*x)==fp_const_rad_to_deg<Value_t>()] cMul x cMul -> cDeg
IF(FP_FLOAT_VERSION) y [(y*x)==fp_const_deg_to_rad<Value_t>()] cMul x cMul -> cRad
cDup cAdd cDup cAdd -> [Value_t(4)] cMul # TEST 10/mul4
cDup cAdd cMul cDup cAdd -> cMul [Value_t(4)] cMul # TEST 10/mul4
cDup x cMul cAdd -> [x+Value_t(1)] cMul # TEST 10/dupxmuladd
cDup x cPow cMul -> [x+Value_t(1)] cPow # TEST 10/dupxpowmul
IF(FP_FLOAT_VERSION) cDup [x+x==Value_t(1)] cAdd x cMul -> # TEST 10/dupaddmulh
cDup cAdd x cMul -> [x+x] cMul # TEST 10/dupaddmul7
IF(FP_FLOAT_VERSION) cDup [x+x==Value_t(1)] cAdd cMul x cMul -> cMul # TEST 10/dupaddmulmulh
cDup cAdd cMul x cMul -> cMul [x+x] cMul # TEST 10/dupaddmulmul7
IF(FP_FLOAT_VERSION) y [(y/x)==fp_const_rad_to_deg<Value_t>()] cMul x [x!=Value_t(0)] cDiv -> cDeg
IF(FP_FLOAT_VERSION) y [(y/x)==fp_const_deg_to_rad<Value_t>()] cMul x [x!=Value_t(0)] cDiv -> cRad
IF(FP_FLOAT_VERSION) y cMul x [x!=Value_t(0)] cDiv -> [y/x] cMul
IF(FP_FLOAT_VERSION) x [x!=Value_t(0)] cDiv -> [Value_t(1)/x] cMul # TEST 10/multodiv
#IF(FP_FLOAT_VERSION) y cExp x cPow -> [y*x] cExp
#IF(FP_FLOAT_VERSION) y cExp2 x cPow -> [y*x] cExp2
# ^ y cExp never occurs (already optimized to literal)
IF(FP_FLOAT_VERSION) y cPow x cPow -> [y*x] cPow # TEST 10/ypowxpow (maybe?)
IF(FP_FLOAT_VERSION) x [x==Value_t(0.5)] cPow -> cSqrt # TEST 10/powhalf
IF(FP_FLOAT_VERSION) x [x==Value_t(1)/Value_t(3)] cPow -> cCbrt # TEST 10/powthird
IF(FP_FLOAT_VERSION) x [x==Value_t(1)/Value_t(-3)] cPow -> cCbrt cInv # TEST 10/powminusthird
IF(FP_FLOAT_VERSION) x [x==Value_t(-0.5)] cPow -> cRSqrt # TEST 10/powminushalf
IF(FP_FLOAT_VERSION) x [x==Value_t(-1)] cPow -> cInv # TEST 10/powminusone
IF(FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] cSqrt cSqr -> A # TEST 10/sqrtsqr1, 10/sqrtsqr2
# ^ Doable only if lhs > 0.
IF(FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] cLog cExp -> A # TEST 10/logexp1, 10/logexp2
IF(FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] cLog2 cExp2 -> A # TEST 10/log2exp1, 10/log2exp2
# ^ Doable only if lhs > 0.
IF(FP_FLOAT_VERSION) cExp cLog -> # TEST 10/explog
IF(FP_FLOAT_VERSION) cExp2 cLog2 -> # TEST 12/exp2log2
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAsin cSin ->
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAcos cCos ->
# ^ For real values, doable only if abs(x) <= 1
#IF(FP_FLOAT_VERSION) cAtan cTan ->
IF(FP_FLOAT_VERSION) cAsinh cSinh -> # TEST 10/asinhsinh
#IF(FP_FLOAT_VERSION) cAcosh cCosh -> # TEST 10/acoshcosh
# ^ Doable only if x >= 1
IF(FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAtanh cTanh ->
# ^ For real values, doable only if abs(x) < 1
IF(FP_FLOAT_VERSION) cAtan2 cTan -> cDiv # TEST 10/atan2tan
IF(FP_FLOAT_VERSION) cPow cInv -> cNeg cPow # TEST 10/powinv
#IF(FP_FLOAT_VERSION) x [x<0] cPow cMul -> [-x] cPow cDiv
cAbs x [x==Value_t(0)] cEqual -> [x] cEqual # TEST 10/abseq0
cAbs x [x==Value_t(0)] cNEqual -> [x] cNEqual # TEST 10/absneq0
cSqr x [x==Value_t(0)] cEqual -> [x] cEqual # TEST 10/sqreq0
cSqr x [x==Value_t(0)] cNEqual -> [x] cNEqual # TEST 10/sqrneq0
IF(!FP_COMPLEX_VERSION) y cAdd x A [IsComparisonOpcode(A)] -> [x-y] A # TEST 10/cmp_add
IF(!FP_COMPLEX_VERSION) cNeg x A [IsComparisonOpcode(A)] -> [-x] {OppositeComparisonOpcode(A)} # TEST 10/cmp_neg
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [y>Value_t(0)] cMul x A [IsComparisonOpcode(A)] -> [x/y] A # TEST 10/cmp_mulpos
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [y<Value_t(0)] cMul x A [IsComparisonOpcode(A)] -> [x/y] {OppositeComparisonOpcode(A)} # TEST 10/cmp_mulneg
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) y [y>Value_t(0)] cPow [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> [fp_pow(x,Value_t(1)/y)] A # TEST 10/cmp_powy_*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSqr [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> cAbs [fp_sqrt(x)] A # TEST 10/cmp_sqr, 10/cmp_sqr_neg
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cExp [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> [fp_log(x)] A # TEST 10/cmp_exp, 10/cmp_exp_neg
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cExp2 [x>Value_t(0)] x A [IsComparisonOpcode(A)] -> [fp_log2(x)] A # TEST 10/cmp_exp2, 10/cmp_exp2_neg
# ^ Always doable
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) B [IsNeverNegativeValueOpcode(B)] cLog x A [IsComparisonOpcode(A)] -> B [fp_exp(x)] A # TEST 10/cmp_log_*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) B [IsNeverNegativeValueOpcode(B)] cLog2 x A [IsComparisonOpcode(A)] -> B [fp_exp2(x)] A # TEST 10/cmp_log2_*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) B [IsNeverNegativeValueOpcode(B)] cLog10 x A [IsComparisonOpcode(A)] -> B [fp_pow(Value_t(10),x)] A # TEST 10/cmp_log10_*
# ^ Doable only if lhs > 0.
#IF(FP_FLOAT_VERSION) cAsin [fp_abs(x)<fp_const_pi<Value_t>()*Value_t(0.5)] x A [IsComparisonOpcode(A)] -> [fp_sin(x)] A # TEST 10/cmp_asin*
#IF(FP_FLOAT_VERSION) cAcos [x>=Value_t(0)&&fp_abs(x)<fp_const_pi<Value_t>()] x A [IsComparisonOpcode(A)] -> [fp_cos(x)] {OppositeComparisonOpcode(A)} # TEST 10/cmp_acos*
# ^ Doable only if abs(x) <= 1
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAtan [fp_abs(x)<fp_const_pi<Value_t>()*Value_t(0.5)] x A [IsComparisonOpcode(A)] -> [fp_tan(x)] A # TEST 10/cmp_atan*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cSinh x A [IsComparisonOpcode(A)] -> [fp_asinh(x)] A # TEST 10/cmp_sinh*
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cTanh [fp_abs(x)<Value_t(1)] x A [IsComparisonOpcode(A)] -> [fp_atanh(x)] A # TEST 10/cmp_tanh*
# (x+3)*4 -> x*4 + 12
y cAdd x cMul -> [x] cMul [y*x] cAdd #TEST 11/39
A [IsVarOpcode(A)] y cMul cAdd x cMul -> [x] cMul A [y*x] cMul cAdd #TEST 11/40
A [IsVarOpcode(A)] y cMul cSub x cMul -> [x] cMul A [y*x] cMul cSub #TEST 11/41
IF(!FP_COMPLEX_VERSION) A [IsLogicalOpcode(A)] cAbsNot cNot -> A # TEST 10/absnot3
IF(!FP_COMPLEX_VERSION) A [A!=cImmed] cAbsNot cNot -> A cAbsNotNot # TEST 10/absnot4
IF(!FP_COMPLEX_VERSION) A [IsNeverNegativeValueOpcode(A)] cNot -> A cAbsNot # TEST 10/absnot2
IF(!FP_COMPLEX_VERSION) A [IsNeverNegativeValueOpcode(A)] cAbs -> A # TEST 10/absneverneg
IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cTrunc-> A # TEST 10/inttrunc
IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cFloor-> A # TEST 10/intfloor
IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cCeil -> A # TEST 10/intceil
IF(FP_FLOAT_VERSION) A [IsAlwaysIntegerOpcode(A)] cInt -> A # TEST 10/intint
#IF(FP_FLOAT_VERSION) x cMul cFloor cNeg -> [-x] cMul cCeil
#IF(FP_FLOAT_VERSION) x cMul cCeil cNeg -> [-x] cMul cFloor
IF(FP_FLOAT_VERSION) cNeg cFloor -> cCeil cNeg # TEST 10/negfloor, 10/floorneg
IF(FP_FLOAT_VERSION) cNeg cCeil -> cFloor cNeg # TEST 10/negceil, 10/ceilneg
IF(FP_FLOAT_VERSION) x cAdd cExp -> cExp [fp_exp(x)] cMul # TEST 10/addexp
IF(FP_FLOAT_VERSION) x cAdd cExp2 -> cExp2 [fp_exp2(x)] cMul # TEST 10/addexp2
IF(FP_FLOAT_VERSION) cPow cDiv -> cNeg cPow cMul # TEST 10/powdiv
IF(FP_FLOAT_VERSION) cExp cDiv -> cNeg cExp cMul # TEST 10/expdiv
IF(FP_FLOAT_VERSION) cExp2 cDiv -> cNeg cExp2 cMul # TEST 10/exp2div
IF(!FP_FLOAT_VERSION) x [x==Value_t(0)] cEqual -> cNot # TEST 10/eq0
IF(!FP_FLOAT_VERSION) x [x==Value_t(0)] cNEqual -> cNotNot # TEST 10/neq0
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(0)] cGreater -> cNotNot # TEST 10/gt0_abs
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(1)] cGreaterOrEq -> cNotNot # TEST 10/ge1_abs
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(1)] cLess -> cNot # TEST 10/gt1_abs
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) cAbs x [x==Value_t(0)] cLessOrEq -> cNot # TEST 10/ge0_abs
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(0)] cGreater -> A cNotNot # TEST 10/gt0_pos, 10/gt0_neg
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(1)] cGreaterOrEq -> A cNotNot # TEST 10/ge1_pos, 10/ge1_neg
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(1)] cLess -> A cNot # TEST 10/gt1_pos, 10/gt1_neg
IF(!FP_COMPLEX_VERSION && !FP_FLOAT_VERSION) A [IsNeverNegativeValueOpcode(A)] x [x==Value_t(0)] cLessOrEq -> A cNot # TEST 10/ge0_pos, 10/ge0_neg
IF(!FP_FLOAT_VERSION) A [IsLogicalOpcode(A)] x [x==Value_t(1)] cEqual -> A # TEST 10/eq1
IF(!FP_FLOAT_VERSION) A [IsLogicalOpcode(A)] x [x==Value_t(1)] cNEqual -> A cNot # TEST 10/neq1
IF(!FP_FLOAT_VERSION) x cAdd cNotNot -> [-x] cNEqual # TEST 10/xaddnotnot
IF(!FP_FLOAT_VERSION) x cAdd cNot -> [-x] cEqual # TEST 10/xaddnot
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs x [x!=Value_t(0)] cLess -> [Value_t(0.5)/x] cMul cNot # TEST 10/absnzlt
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs x [x!=Value_t(0)] cGreaterOrEq -> [Value_t(0.5)/x] cMul cNotNot # TEST 10/absnzge
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(0.5)] cLess -> cAbsNot # TEST 10/lthalf
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(0.5)] cGreaterOrEq -> cAbsNotNot # TEST 10/gehalf
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(-0.5)] cGreater -> cNeg cAbsNot # TEST 10/gtminushalf
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) x [x==Value_t(-0.5)] cLessOrEq -> cNeg cAbsNotNot # TEST 10/leminushalf
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs x [isEvenInteger(x)] cPow -> [x] cPow # TEST 10/absevenconstpow
IF(!FP_COMPLEX_VERSION && FP_FLOAT_VERSION) cAbs cMul x [isEvenInteger(x)] cPow -> cMul [x] cPow # TEST 10/absmulevenconstpow
IF(FP_FLOAT_VERSION) cAcosh cSinh -> [DO_STACKPLUS1] cSqr [Value_t(-1)] cAdd cSqrt # TEST 10/acoshsinh
# sinh(x) = 0.5 * (exp(x) - exp(-x))
# acosh(x) = log(x + sqrt(x*x - 1))
# Thus,
# sinh(acosh(x)) = 0.5 * (exp(log(x + sqrt(x*x - 1))) - exp(-log(x + sqrt(x*x - 1))))
# sinh(acosh(x)) = 0.5 * ( ( (x + sqrt(x*x - 1))) - 1 / (x + sqrt(x*x - 1)) )
# sinh(acosh(x)) = 0.5 * (x + sqrt(x*x - 1) - 1 / (x + sqrt(x*x - 1)))
# sinh(acosh(x)) = 0.5*x + 0.5*sqrt(x*x - 1) - 0.5/(x + sqrt(x*x - 1))
# Maxima gets a step further and says that:
# sinh(acosh(x)) = sqrt(x-1)*sqrt(x+1)
# Furthermore, Wikipedia gives us this:
# sinh(acosh(x)) = sqrt(x*x-1) IF abs(x) > 1 or complex version
IF(FP_FLOAT_VERSION) cAsinh cCosh -> [DO_STACKPLUS1] cSqr [Value_t(1)] cAdd cSqrt # TEST 10/asinhcosh
# cosh(asinh(x)) = sqrt(x^2+1)
# Hardcoded optimizations that are too complex or
# impossible to convey using this rule file:
IF(FP_FLOAT_VERSION) x cPow -> [DO_POWI]
# x*x = x^2
B [B==A] A [IsVarOpcode(A)] cMul -> B cSqr # TEST 10/sqr_xx
# ...*x*x = ...*x^2
B [B==A] cMul A [IsVarOpcode(A)] cMul -> B cSqr cMul # TEST 10/sqr_yxx
# -x*x = -(x^2)
B [B==A] cNeg A [IsVarOpcode(A)] cMul -> B cSqr cNeg # TEST 10/sqr_nxx
# x*-x = -(x^2)
cDup cNeg cMul -> cSqr cNeg # TEST 10/sqr_xnx
# ...*-x*x = ...*-(x^2)
B [B==A] cNeg cMul A [IsVarOpcode(A)] cMul -> B cSqr cMul cNeg # TEST 10/sqr_ynxx
# ...*x*-x = ...*-(x^2)
B [B==A] cMul A [IsVarOpcode(A)] cNeg cMul -> B cSqr cMul cNeg # TEST 10/sqr_yxnx
B [B==A] A [IsVarOpcode(A) && mData->mByteCode.size() > 0] -> B cDup # TEST 10/xxdup
D [D==B] C [C==A] B [IsVarOpcode(B) && mData->mByteCode.size() > 1] A [IsUnaryOpcode(A)] -> D C cDup # TEST 10/xxfdup
D [D==B] C [C==A] cMul B [IsVarOpcode(B) && mData->mByteCode.size() > 1] A [IsUnaryOpcode(A)] cMul -> D C cSqr cMul # TEST 10/xxsqrdup
IF(FP_FLOAT_VERSION) cExp2 -> [DO_STACKPLUS1] [fp_log(Value_t(2))] cMul cExp # TEST 02/exp2
IF(FP_FLOAT_VERSION) cExp cLog2 -> [DO_STACKPLUS1] [fp_log2(fp_const_e<Value_t>())] cMul # TEST 10/explog2
IF(FP_FLOAT_VERSION) cExp cLog10 -> [DO_STACKPLUS1] [fp_log10(fp_const_e<Value_t>())] cMul # TEST 10/explog10
# expr0 expr1 cExp cMul cLog
# -> expr0 cLog expr1 cAdd
# could be done if expr1 is a var. Too special case. Not doing...
# expr0 cLog expr1 cLog
# -> expr0 expr1 cMul cLog
# similar.
IF(FP_FLOAT_VERSION) x [x>Value_t(0)] cMul cLog2 -> cLog2 [fp_log2(x)] cAdd # TEST 10/logmul2
IF(FP_FLOAT_VERSION) x [x>Value_t(0)] cMul cLog -> cLog [fp_log(x)] cAdd # TEST 10/logmul
IF(FP_FLOAT_VERSION) x [x>Value_t(0)] cMul cLog10 -> cLog10 [fp_log10(x)] cAdd # TEST 10/logmul10
IF(FP_FLOAT_VERSION) B [B==A] cSin A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCos -> B cSinCos # TEST 10/sincos_sc
IF(FP_FLOAT_VERSION) B [B==A] cSin A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cSec -> B cSinCos cInv # TEST 10/sincos_sci
IF(FP_FLOAT_VERSION) B [B==A] cSin A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCsc -> B cSin cDup cInv # TEST 10/sincos_ssi
IF(FP_FLOAT_VERSION) B [B==A] cCos A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cSec -> B cCos cDup cInv # TEST 10/sincos_cci
IF(FP_FLOAT_VERSION) B [B==A] cTan A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCot -> B cTan cDup cInv # TEST 10/sincos_tti
IF(FP_FLOAT_VERSION) B [B==A] cCsc A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cSin -> B cCsc cDup cInv # TEST 10/sincos_sis
IF(FP_FLOAT_VERSION) B [B==A] cSec A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCos -> B cSec cDup cInv # TEST 10/sincos_cic
IF(FP_FLOAT_VERSION) B [B==A] cCot A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cTan -> B cCot cDup cInv # TEST 10/sincos_tit
IF(FP_FLOAT_VERSION) cSinCos cDiv -> cTan # TEST 10/sincos_tan
IF(FP_FLOAT_VERSION) cSinCos cRDiv -> cCot
IF(FP_FLOAT_VERSION) B [B==A] cCos A [IsVarOpcode(A) && mData->mByteCode.size() > 3] cSin C [IsCommutativeOrParamSwappableBinaryOpcode(C)] -> B cSinCos {GetParamSwappedBinaryOpcode(C)} # TEST 99/59
IF(FP_FLOAT_VERSION) B [B==A] cCosh A [IsVarOpcode(A) && mData->mByteCode.size() > 3] cSinh C [IsCommutativeOrParamSwappableBinaryOpcode(C)] -> B cSinhCosh {GetParamSwappedBinaryOpcode(C)} # TEST 99/59
IF(FP_FLOAT_VERSION) B [B==A] cSinh A [IsVarOpcode(A) && mData->mByteCode.size() > 2] cCosh -> B cSinhCosh
IF(FP_FLOAT_VERSION) B [B==A] cCos A [IsVarOpcode(A) && mData->mByteCode.size() > 3] cCsc cMul -> B cCot
IF(FP_FLOAT_VERSION) cSinhCosh cDiv -> cTanh
IF(FP_FLOAT_VERSION) cSinhCosh cRDiv -> cTanh cInv
IF(FP_FLOAT_VERSION) cSqr A [IsVarOpcode(A)] cSqr cAdd cSqrt -> A cHypot # TEST 10/xsqrysqrhypot
IF(FP_FLOAT_VERSION) cSqr A [IsVarOpcode(A)] B [IsUnaryOpcode(B)] cSqr cAdd cSqrt -> A B cHypot # TEST 10/xsqryfsqrhypot
|