|
Lines 20-25
Link Here
|
| 20 |
|
20 |
|
| 21 |
package org.eclipse.ocl; |
21 |
package org.eclipse.ocl; |
| 22 |
|
22 |
|
|
|
23 |
import java.math.BigDecimal; |
| 24 |
import java.math.BigInteger; |
| 25 |
import java.math.RoundingMode; |
| 23 |
import java.util.AbstractList; |
26 |
import java.util.AbstractList; |
| 24 |
import java.util.ArrayList; |
27 |
import java.util.ArrayList; |
| 25 |
import java.util.Collection; |
28 |
import java.util.Collection; |
|
Lines 257-271
Link Here
|
| 257 |
OCLExpression<C> arg = args.get(0); |
260 |
OCLExpression<C> arg = args.get(0); |
| 258 |
Object argVal = arg.accept(getVisitor()); |
261 |
Object argVal = arg.accept(getVisitor()); |
| 259 |
|
262 |
|
| 260 |
if (sourceVal instanceof Number) { |
263 |
// normalise to BigInteger or BigDecimal for comparison |
| 261 |
// coerce to Long or Double, if possible, for comparison |
264 |
sourceVal = ObjectUtil.normalise(sourceVal); |
| 262 |
sourceVal = higherPrecisionNumber((Number) sourceVal); |
265 |
argVal = ObjectUtil.normalise(argVal); |
| 263 |
} |
|
|
| 264 |
|
| 265 |
if (argVal instanceof Number) { |
| 266 |
// coerce to Long or Double, if possible, for comparison |
| 267 |
argVal = higherPrecisionNumber((Number) argVal); |
| 268 |
} |
| 269 |
|
266 |
|
| 270 |
return Boolean.valueOf(ObjectUtil.equal(sourceVal, argVal)); |
267 |
return Boolean.valueOf(ObjectUtil.equal(sourceVal, argVal)); |
| 271 |
} |
268 |
} |
|
Lines 277-291
Link Here
|
| 277 |
OCLExpression<C> arg = args.get(0); |
274 |
OCLExpression<C> arg = args.get(0); |
| 278 |
Object argVal = arg.accept(getVisitor()); |
275 |
Object argVal = arg.accept(getVisitor()); |
| 279 |
|
276 |
|
| 280 |
if (sourceVal instanceof Number) { |
277 |
// normalise to BigInteger or BigDecimal for comparison |
| 281 |
// coerce to Long or Double, if possible, for comparison |
278 |
sourceVal = ObjectUtil.normalise(sourceVal); |
| 282 |
sourceVal = higherPrecisionNumber((Number) sourceVal); |
279 |
argVal = ObjectUtil.normalise(argVal); |
| 283 |
} |
|
|
| 284 |
|
| 285 |
if (argVal instanceof Number) { |
| 286 |
// coerce to Long or Double, if possible, for comparison |
| 287 |
argVal = higherPrecisionNumber((Number) argVal); |
| 288 |
} |
| 289 |
|
280 |
|
| 290 |
return Boolean.valueOf(!ObjectUtil.equal(sourceVal, argVal)); |
281 |
return Boolean.valueOf(!ObjectUtil.equal(sourceVal, argVal)); |
| 291 |
} |
282 |
} |
|
Lines 309-391
Link Here
|
| 309 |
return getInvalid(); |
300 |
return getInvalid(); |
| 310 |
} |
301 |
} |
| 311 |
|
302 |
|
|
|
303 |
// normalise to BigInteger or BigDecimal |
| 304 |
sourceVal = ObjectUtil.normalise(sourceVal); |
| 312 |
// evaluate this operation |
305 |
// evaluate this operation |
| 313 |
switch (opCode) { |
306 |
switch (opCode) { |
| 314 |
|
307 |
|
| 315 |
case PredefinedType.MINUS: |
308 |
case PredefinedType.MINUS: |
| 316 |
// Integer::minus() |
309 |
if (sourceVal instanceof UnlimitedNaturalLiteralExp<?>) { |
| 317 |
if (sourceVal instanceof Integer) { |
310 |
// the unlimited value has no negative |
| 318 |
return - (Integer) sourceVal; |
311 |
return getInvalid(); |
| 319 |
} else if (sourceVal instanceof Long) { |
|
|
| 320 |
return - (Long) sourceVal; |
| 321 |
} |
312 |
} |
| 322 |
|
313 |
if (sourceVal instanceof BigInteger) { |
| 323 |
// Double::minus() |
314 |
// Integer::minus() |
| 324 |
return - (Double) sourceVal; |
315 |
return ((BigInteger) sourceVal).negate(); |
|
|
316 |
} |
| 317 |
else { |
| 318 |
// Double::minus() |
| 319 |
return ((BigDecimal) sourceVal).negate(); |
| 320 |
} |
| 325 |
|
321 |
|
| 326 |
case PredefinedType.ABS: |
322 |
case PredefinedType.ABS: |
| 327 |
if (sourceVal instanceof Integer) { |
323 |
if (sourceVal instanceof UnlimitedNaturalLiteralExp<?>) { |
| 328 |
int sourceInt = (Integer) sourceVal; |
324 |
// the unlimited value has no absolute |
| 329 |
|
325 |
return getInvalid(); |
| 330 |
if (sourceType == getUnlimitedNatural()) { |
326 |
} |
| 331 |
// the unlimited value has no absolute |
327 |
if (sourceVal instanceof BigInteger) { |
| 332 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
|
|
| 333 |
return getInvalid(); |
| 334 |
} |
| 335 |
} |
| 336 |
|
| 337 |
// Integer::abs() |
| 338 |
return Math.abs(sourceInt); |
| 339 |
} else if (sourceVal instanceof Long) { |
| 340 |
long sourceInt = (Long) sourceVal; |
| 341 |
|
| 342 |
if (sourceType == getUnlimitedNatural()) { |
| 343 |
// the unlimited value has no absolute |
| 344 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
| 345 |
return getInvalid(); |
| 346 |
} |
| 347 |
} |
| 348 |
|
| 349 |
// Integer::abs() |
328 |
// Integer::abs() |
| 350 |
return Math.abs(sourceInt); |
329 |
return ((BigInteger)sourceVal).abs(); |
| 351 |
} |
330 |
} |
| 352 |
|
331 |
else { |
| 353 |
// Real::abs() |
332 |
// Real::abs() |
| 354 |
return Math.abs((Double) sourceVal); |
333 |
return ((BigDecimal)sourceVal).abs(); |
|
|
334 |
} |
| 355 |
|
335 |
|
| 356 |
case PredefinedType.FLOOR: |
336 |
case PredefinedType.FLOOR: |
| 357 |
if (sourceVal instanceof Double) { |
337 |
// the unlimited value has no floor |
|
|
338 |
if (sourceVal instanceof UnlimitedNaturalLiteralExp<?>) { |
| 339 |
return getInvalid(); |
| 340 |
} |
| 341 |
if (sourceVal instanceof BigDecimal) { |
| 358 |
// Real::floor() |
342 |
// Real::floor() |
| 359 |
return (int) Math.floor((Double) sourceVal); |
343 |
return ((BigDecimal)sourceVal).divideToIntegralValue(BigDecimal.ONE).toBigInteger(); |
| 360 |
} |
344 |
} |
| 361 |
|
|
|
| 362 |
if (sourceType == getUnlimitedNatural()) { |
| 363 |
long sourceInt = (Long) higherPrecisionNumber((Number) sourceVal); |
| 364 |
|
| 365 |
// the unlimited value has no floor |
| 366 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
| 367 |
return getInvalid(); |
| 368 |
} |
| 369 |
} |
| 370 |
|
| 371 |
// Integer::floor() |
345 |
// Integer::floor() |
| 372 |
return sourceVal; |
346 |
return sourceVal; |
| 373 |
|
347 |
|
| 374 |
case PredefinedType.ROUND: |
348 |
case PredefinedType.ROUND: |
| 375 |
if (sourceVal instanceof Double) { |
349 |
// the unlimited value can't be rounded |
|
|
350 |
if (sourceVal instanceof UnlimitedNaturalLiteralExp<?>) { |
| 351 |
return getInvalid(); |
| 352 |
} |
| 353 |
if (sourceVal instanceof BigDecimal) { |
| 376 |
// Real::round() |
354 |
// Real::round() |
| 377 |
return (int) Math.round((Double) sourceVal); |
355 |
return ((BigDecimal)sourceVal).add(new BigDecimal(0.5)).divideToIntegralValue(BigDecimal.ONE).toBigInteger(); |
| 378 |
} |
356 |
} |
| 379 |
|
|
|
| 380 |
if (sourceType == getUnlimitedNatural()) { |
| 381 |
long sourceInt = (Long) higherPrecisionNumber((Number) sourceVal); |
| 382 |
|
| 383 |
// the unlimited value can't be rounded |
| 384 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
| 385 |
return getInvalid(); |
| 386 |
} |
| 387 |
} |
| 388 |
|
| 389 |
// Integer::round() |
357 |
// Integer::round() |
| 390 |
return sourceVal; |
358 |
return sourceVal; |
| 391 |
|
359 |
|
|
Lines 524-529
Link Here
|
| 524 |
// Integer |
492 |
// Integer |
| 525 |
// and back (necessary since in OCL Integers extend |
493 |
// and back (necessary since in OCL Integers extend |
| 526 |
// Reals but this is not true of the java primtives). |
494 |
// Reals but this is not true of the java primtives). |
|
|
495 |
argType = ((TypeExp<C>)arg).getReferredType(); |
| 527 |
|
496 |
|
| 528 |
// if the source is undefined or the conversion to |
497 |
// if the source is undefined or the conversion to |
| 529 |
// OclVoid so is the result |
498 |
// OclVoid so is the result |
|
Lines 534-555
Link Here
|
| 534 |
return getInvalid(); |
503 |
return getInvalid(); |
| 535 |
} |
504 |
} |
| 536 |
|
505 |
|
| 537 |
if (sourceVal instanceof Double |
506 |
if (sourceVal instanceof BigDecimal |
| 538 |
&& (argType == getInteger())) { |
507 |
&& (argType == getInteger())) { |
| 539 |
return new Integer(((Double) sourceVal).intValue()); |
508 |
BigInteger bigInteger = ((BigDecimal) sourceVal).toBigInteger(); |
| 540 |
} else if (sourceVal instanceof Integer |
509 |
BigDecimal delta = ((BigDecimal) sourceVal).subtract(new BigDecimal(bigInteger)); |
|
|
510 |
return delta.signum() == 0 ? bigInteger : getInvalid(); |
| 511 |
} else if (sourceVal instanceof BigInteger |
| 541 |
&& (argType == getReal())) { |
512 |
&& (argType == getReal())) { |
| 542 |
|
513 |
|
| 543 |
if (sourceType == getUnlimitedNatural()) { |
514 |
/* if (sourceType == getUnlimitedNatural()) { |
| 544 |
int sourceInt = (Integer) sourceVal; |
515 |
int sourceInt = (Integer) sourceVal; |
| 545 |
|
516 |
|
| 546 |
// the unlimited value is positive infinity |
517 |
// the unlimited value is positive infinity |
| 547 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
518 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED.intValue()) { |
| 548 |
return Double.POSITIVE_INFINITY; |
519 |
return Double.POSITIVE_INFINITY; |
| 549 |
} |
520 |
} |
| 550 |
} |
521 |
} */ |
| 551 |
|
522 |
|
| 552 |
return new Double(((Integer) sourceVal).doubleValue()); |
523 |
return new BigDecimal((BigInteger) sourceVal); |
| 553 |
} |
524 |
} |
| 554 |
|
525 |
|
| 555 |
return sourceVal; |
526 |
return sourceVal; |
|
Lines 561-673
Link Here
|
| 561 |
argVal = arg.accept(getVisitor()); |
532 |
argVal = arg.accept(getVisitor()); |
| 562 |
} |
533 |
} |
| 563 |
|
534 |
|
| 564 |
if (sourceVal instanceof Number) { |
535 |
// we have a numeric operation. Promote to high precision |
| 565 |
// we have a numeric operation. Promote to high precision |
536 |
sourceVal = ObjectUtil.normalise(sourceVal); |
| 566 |
sourceVal = higherPrecisionNumber((Number) sourceVal); |
537 |
argVal = ObjectUtil.normalise(argVal); |
| 567 |
|
|
|
| 568 |
if (argVal instanceof Number) { |
| 569 |
argVal = higherPrecisionNumber((Number) argVal); |
| 570 |
} |
| 571 |
} |
| 572 |
|
538 |
|
| 573 |
if (sourceVal instanceof Long && argVal instanceof Long) { |
539 |
boolean sourceUnlimited = sourceVal instanceof UnlimitedNaturalLiteralExp<?>; |
| 574 |
// |
540 |
boolean argUnlimited = argVal instanceof UnlimitedNaturalLiteralExp<?>; |
| 575 |
// source and single arg are both integers |
541 |
if (sourceUnlimited && argUnlimited) { |
| 576 |
// |
542 |
switch (opCode) { |
| 577 |
|
|
|
| 578 |
long sourceInt = (Long) sourceVal; |
| 579 |
long argInt = (Long) argVal; |
| 580 |
|
| 581 |
boolean sourceUnlimited = |
| 582 |
sourceType == getUnlimitedNatural() |
| 583 |
&& sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED; |
| 584 |
boolean argUnlimited = |
| 585 |
argType == getUnlimitedNatural() |
| 586 |
&& argInt == UnlimitedNaturalLiteralExp.UNLIMITED; |
| 587 |
|
| 588 |
if (sourceUnlimited && argUnlimited) { |
| 589 |
switch (opCode) { |
| 590 |
case PredefinedType.LESS_THAN: |
| 591 |
case PredefinedType.LESS_THAN_EQUAL: |
| 592 |
case PredefinedType.GREATER_THAN: |
| 593 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 594 |
// two inifinte values cannot be compared. We |
| 595 |
// allow = and <> only to test for unbounded |
| 596 |
// multiplicities |
| 597 |
return Boolean.FALSE; |
| 598 |
default: |
| 599 |
// cannot do arithmetic on the unlimited value |
| 600 |
return getInvalid(); |
| 601 |
} |
| 602 |
} else if (sourceUnlimited || argUnlimited) { |
| 603 |
switch (opCode) { |
| 604 |
case PredefinedType.LESS_THAN: |
543 |
case PredefinedType.LESS_THAN: |
| 605 |
case PredefinedType.LESS_THAN_EQUAL: |
544 |
case PredefinedType.LESS_THAN_EQUAL: |
| 606 |
return argUnlimited; |
|
|
| 607 |
case PredefinedType.GREATER_THAN: |
545 |
case PredefinedType.GREATER_THAN: |
| 608 |
case PredefinedType.GREATER_THAN_EQUAL: |
546 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 609 |
return sourceUnlimited; |
547 |
// two inifinte values cannot be compared. We |
|
|
548 |
// allow = and <> only to test for unbounded |
| 549 |
// multiplicities |
| 550 |
return Boolean.FALSE; |
| 610 |
default: |
551 |
default: |
| 611 |
// cannot do arithmetic on the unlimited value |
552 |
// cannot do arithmetic on the unlimited value |
| 612 |
return getInvalid(); |
553 |
return getInvalid(); |
| 613 |
} |
554 |
} |
|
|
555 |
} else if (sourceUnlimited || argUnlimited) { |
| 556 |
switch (opCode) { |
| 557 |
case PredefinedType.LESS_THAN: |
| 558 |
case PredefinedType.LESS_THAN_EQUAL: |
| 559 |
return argUnlimited; |
| 560 |
case PredefinedType.GREATER_THAN: |
| 561 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 562 |
return sourceUnlimited; |
| 563 |
default: |
| 564 |
// cannot do arithmetic on the unlimited value |
| 565 |
return getInvalid(); |
| 614 |
} |
566 |
} |
|
|
567 |
} else if (sourceVal instanceof BigInteger && argVal instanceof BigInteger) { |
| 568 |
// |
| 569 |
// source and single arg are both integers |
| 570 |
// |
| 571 |
|
| 572 |
// long sourceInt = (Long) sourceVal; |
| 573 |
// long argInt = (Long) argVal; |
| 574 |
|
| 615 |
|
575 |
|
| 616 |
switch (opCode) { |
576 |
switch (opCode) { |
| 617 |
|
577 |
|
| 618 |
// Integer::plus(Integer) |
578 |
// Integer::plus(Integer) |
| 619 |
case PredefinedType.PLUS: |
579 |
case PredefinedType.PLUS: |
| 620 |
return coerceNumber(sourceInt + argInt); |
580 |
return ((BigInteger)sourceVal).add((BigInteger)argVal); |
| 621 |
|
581 |
|
| 622 |
// Integer::minus(Integer) |
582 |
// Integer::minus(Integer) |
| 623 |
case PredefinedType.MINUS: |
583 |
case PredefinedType.MINUS: |
| 624 |
return coerceNumber(sourceInt - argInt); |
584 |
return ((BigInteger)sourceVal).subtract((BigInteger)argVal); |
| 625 |
|
585 |
|
| 626 |
// Integer::times(Integer) |
586 |
// Integer::times(Integer) |
| 627 |
case PredefinedType.TIMES: |
587 |
case PredefinedType.TIMES: |
| 628 |
return coerceNumber(sourceInt * argInt); |
588 |
return ((BigInteger)sourceVal).multiply((BigInteger)argVal); |
| 629 |
|
589 |
|
| 630 |
// Integer::divide(Integer) |
590 |
// Integer::divide(Integer) |
| 631 |
case PredefinedType.DIVIDE: { |
591 |
case PredefinedType.DIVIDE: { |
| 632 |
// denominator of 0 means undefined |
592 |
// denominator of 0 means undefined |
| 633 |
double num = sourceInt; |
593 |
return (((BigInteger)argVal).signum() == 0) ? getInvalid() : |
| 634 |
double denom = argInt; |
594 |
new BigDecimal((BigInteger)sourceVal).divide(new BigDecimal((BigInteger)argVal), RoundingMode.HALF_EVEN); |
| 635 |
return (denom == 0.0) ? getInvalid() : num / denom; |
|
|
| 636 |
} |
595 |
} |
| 637 |
|
596 |
|
| 638 |
// Integer::div(Integer) |
597 |
// Integer::div(Integer) |
| 639 |
case PredefinedType.DIV: |
598 |
case PredefinedType.DIV: |
| 640 |
// denominator of 0 means undefined |
599 |
// denominator of 0 means undefined |
| 641 |
return (argInt == 0) ? getInvalid() : |
600 |
return (((BigInteger)argVal).signum() == 0) ? getInvalid() : |
| 642 |
coerceNumber(sourceInt / argInt); |
601 |
((BigInteger)sourceVal).divide((BigInteger)argVal); |
| 643 |
|
602 |
|
| 644 |
// Integer::mod(Integer) |
603 |
// Integer::mod(Integer) |
| 645 |
case PredefinedType.MOD: |
604 |
case PredefinedType.MOD: |
| 646 |
return coerceNumber(sourceInt % argInt); |
605 |
return ((BigInteger)sourceVal).mod((BigInteger)argVal); |
| 647 |
|
606 |
|
| 648 |
// Integer::max(Integer) |
607 |
// Integer::max(Integer) |
| 649 |
case PredefinedType.MAX: |
608 |
case PredefinedType.MAX: |
| 650 |
return coerceNumber(Math.max(sourceInt, argInt)); |
609 |
return ((BigInteger)sourceVal).max((BigInteger)argVal); |
| 651 |
|
610 |
|
| 652 |
// Integer::min(Integer) |
611 |
// Integer::min(Integer) |
| 653 |
case PredefinedType.MIN: |
612 |
case PredefinedType.MIN: |
| 654 |
return coerceNumber(Math.min(sourceInt, argInt)); |
613 |
return ((BigInteger)sourceVal).min((BigInteger)argVal); |
| 655 |
|
614 |
|
| 656 |
// Integer::lessThan(Integer) |
615 |
// Integer::lessThan(Integer) |
| 657 |
case PredefinedType.LESS_THAN: |
616 |
case PredefinedType.LESS_THAN: |
| 658 |
return sourceInt < argInt; |
617 |
return ((BigInteger)sourceVal).compareTo((BigInteger)argVal) < 0; |
| 659 |
|
618 |
|
| 660 |
// Integer::greaterThan(Integer) |
619 |
// Integer::greaterThan(Integer) |
| 661 |
case PredefinedType.GREATER_THAN: |
620 |
case PredefinedType.GREATER_THAN: |
| 662 |
return sourceInt > argInt; |
621 |
return ((BigInteger)sourceVal).compareTo((BigInteger)argVal) > 0; |
| 663 |
|
622 |
|
| 664 |
// Integer::lessThanEqual(Integer) |
623 |
// Integer::lessThanEqual(Integer) |
| 665 |
case PredefinedType.LESS_THAN_EQUAL: |
624 |
case PredefinedType.LESS_THAN_EQUAL: |
| 666 |
return sourceInt <= argInt; |
625 |
return ((BigInteger)sourceVal).compareTo((BigInteger)argVal) <= 0; |
| 667 |
|
626 |
|
| 668 |
// Integer::greaterThanEqual(Integer) |
627 |
// Integer::greaterThanEqual(Integer) |
| 669 |
case PredefinedType.GREATER_THAN_EQUAL: |
628 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 670 |
return sourceInt >= argInt; |
629 |
return ((BigInteger)sourceVal).compareTo((BigInteger)argVal) >= 0; |
| 671 |
|
630 |
|
| 672 |
default: { |
631 |
default: { |
| 673 |
String message = OCLMessages.bind( |
632 |
String message = OCLMessages.bind( |
|
Lines 679-859
Link Here
|
| 679 |
throw error; |
638 |
throw error; |
| 680 |
} |
639 |
} |
| 681 |
} |
640 |
} |
| 682 |
} else if (sourceVal instanceof Long |
641 |
} else if (sourceVal instanceof Number |
| 683 |
&& argVal instanceof Double) { |
642 |
&& argVal instanceof Number) { |
| 684 |
|
643 |
if (sourceVal instanceof BigInteger) { |
| 685 |
// |
644 |
sourceVal = new BigDecimal((BigInteger) sourceVal); |
| 686 |
// source is an integer and single arg is a real |
|
|
| 687 |
// |
| 688 |
|
| 689 |
long sourceInt = (Long) sourceVal; |
| 690 |
double argReal = (Double) argVal; |
| 691 |
|
| 692 |
if (sourceType == getUnlimitedNatural()) { |
| 693 |
if (sourceInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
| 694 |
switch (opCode) { |
| 695 |
case PredefinedType.LESS_THAN: |
| 696 |
// unlimited is not less than or equal to |
| 697 |
// any Real value |
| 698 |
return Boolean.FALSE; |
| 699 |
case PredefinedType.GREATER_THAN: |
| 700 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 701 |
// unlimited is greater than |
| 702 |
// every Real value |
| 703 |
return Boolean.TRUE; |
| 704 |
default: |
| 705 |
// cannot do arithmetic on the unlimited value |
| 706 |
return getInvalid(); |
| 707 |
} |
| 708 |
} |
| 709 |
} |
| 710 |
|
| 711 |
switch (opCode) { |
| 712 |
|
| 713 |
// Integer::plus(Real) |
| 714 |
case PredefinedType.PLUS: |
| 715 |
return coerceNumber(sourceInt + argReal); |
| 716 |
|
| 717 |
// Integer::minus(Real) |
| 718 |
case PredefinedType.MINUS: |
| 719 |
return coerceNumber(sourceInt - argReal); |
| 720 |
|
| 721 |
// Integer::times(Real) |
| 722 |
case PredefinedType.TIMES: |
| 723 |
return coerceNumber(sourceInt * argReal); |
| 724 |
|
| 725 |
// Integer::divide(Real) |
| 726 |
case PredefinedType.DIVIDE: |
| 727 |
// denominator of 0 results in undefined |
| 728 |
return (argReal == 0.0) ? getInvalid() : sourceInt / argReal; |
| 729 |
|
| 730 |
// Integer::max(Real) |
| 731 |
case PredefinedType.MAX: |
| 732 |
return coerceNumber(Math.max(sourceInt, argReal)); |
| 733 |
|
| 734 |
// Integer::min(Real) |
| 735 |
case PredefinedType.MIN: |
| 736 |
return coerceNumber(Math.min(sourceInt, argReal)); |
| 737 |
|
| 738 |
// Integer::lessThan(Real) |
| 739 |
case PredefinedType.LESS_THAN: |
| 740 |
return sourceInt < argReal; |
| 741 |
|
| 742 |
// Integer::greaterThan(Real) |
| 743 |
case PredefinedType.GREATER_THAN: |
| 744 |
return sourceInt > argReal; |
| 745 |
|
| 746 |
// Integer::lessThanEqual(Real) |
| 747 |
case PredefinedType.LESS_THAN_EQUAL: |
| 748 |
return sourceInt <= argReal; |
| 749 |
|
| 750 |
// Integer::greaterThanEqual(Real) |
| 751 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 752 |
return sourceInt >= argReal; |
| 753 |
|
| 754 |
default: { |
| 755 |
String message = OCLMessages.bind( |
| 756 |
OCLMessages.UnknownOperation_ERROR_, |
| 757 |
getName(oper)); |
| 758 |
RuntimeException error = new RuntimeException(message); |
| 759 |
OCLPlugin.throwing(getClass(), |
| 760 |
"visitOperationCallExp", error);//$NON-NLS-1$ |
| 761 |
throw error; |
| 762 |
} |
| 763 |
} |
645 |
} |
| 764 |
} |
646 |
if (argVal instanceof BigInteger) { |
| 765 |
|
647 |
argVal = new BigDecimal((BigInteger) argVal); |
| 766 |
else if (sourceVal instanceof Double |
|
|
| 767 |
&& argVal instanceof Long) { |
| 768 |
|
| 769 |
double sourceReal = (Double) sourceVal; |
| 770 |
long argInt = (Long) argVal; |
| 771 |
|
| 772 |
// |
| 773 |
// source is a real and single arg is an integer |
| 774 |
// |
| 775 |
|
| 776 |
if (argType == getUnlimitedNatural()) { |
| 777 |
if (argInt == UnlimitedNaturalLiteralExp.UNLIMITED) { |
| 778 |
switch (opCode) { |
| 779 |
case PredefinedType.LESS_THAN: |
| 780 |
// unlimited is greater than |
| 781 |
// every Real value |
| 782 |
return Boolean.TRUE; |
| 783 |
case PredefinedType.GREATER_THAN: |
| 784 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 785 |
// unlimited is not less than or equal to |
| 786 |
// any Real value |
| 787 |
return Boolean.FALSE; |
| 788 |
default: |
| 789 |
// cannot do arithmetic on the unlimited value |
| 790 |
return getInvalid(); |
| 791 |
} |
| 792 |
} |
| 793 |
} |
| 794 |
|
| 795 |
// for these arithmetic operations, don't need to coerce |
| 796 |
// the result to any other precision because OCL Reals are |
| 797 |
// represented as Doubles, anyway |
| 798 |
switch (opCode) { |
| 799 |
|
| 800 |
// Real::plus(Integer) |
| 801 |
case PredefinedType.PLUS: |
| 802 |
return sourceReal + argInt; |
| 803 |
|
| 804 |
// Real::minus(Integer) |
| 805 |
case PredefinedType.MINUS: |
| 806 |
return sourceReal - argInt; |
| 807 |
|
| 808 |
// Real::times(Integer) |
| 809 |
case PredefinedType.TIMES: |
| 810 |
return sourceReal * argInt; |
| 811 |
|
| 812 |
// Real::divide(Integer) |
| 813 |
case PredefinedType.DIVIDE: |
| 814 |
// denominator of 0 results in undefined |
| 815 |
return (argInt == 0) ? getInvalid() : sourceReal / argInt; |
| 816 |
|
| 817 |
// Real::max(Integer) |
| 818 |
case PredefinedType.MAX: |
| 819 |
return Math.max(sourceReal, argInt); |
| 820 |
|
| 821 |
// Real::min(Integer) |
| 822 |
case PredefinedType.MIN: |
| 823 |
return Math.min(sourceReal, argInt); |
| 824 |
|
| 825 |
// Real::lessThan(Integer) |
| 826 |
case PredefinedType.LESS_THAN: |
| 827 |
return sourceReal < argInt; |
| 828 |
|
| 829 |
// Real::greaterThan(Integer) |
| 830 |
case PredefinedType.GREATER_THAN: |
| 831 |
return sourceReal > argInt; |
| 832 |
|
| 833 |
// Real::lessThanEqual(Integer) |
| 834 |
case PredefinedType.LESS_THAN_EQUAL: |
| 835 |
return sourceReal <= argInt; |
| 836 |
|
| 837 |
// Real::greaterThanEqual(Integer) |
| 838 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 839 |
return sourceReal >= argInt; |
| 840 |
|
| 841 |
default: { |
| 842 |
String message = OCLMessages.bind( |
| 843 |
OCLMessages.UnknownOperation_ERROR_, |
| 844 |
getName(oper)); |
| 845 |
RuntimeException error = new RuntimeException(message); |
| 846 |
OCLPlugin.throwing(getClass(), |
| 847 |
"visitOperationCallExp", error);//$NON-NLS-1$ |
| 848 |
throw error; |
| 849 |
} |
| 850 |
} |
648 |
} |
| 851 |
} else if (sourceVal instanceof Double |
|
|
| 852 |
&& argVal instanceof Double) { |
| 853 |
|
| 854 |
double sourceReal = (Double) sourceVal; |
| 855 |
double argReal = (Double) argVal; |
| 856 |
|
| 857 |
// |
649 |
// |
| 858 |
// source is a real and single arg is a real |
650 |
// source is a real and single arg is a real |
| 859 |
// |
651 |
// |
|
Lines 862-905
Link Here
|
| 862 |
|
654 |
|
| 863 |
// Real::plus(Real) |
655 |
// Real::plus(Real) |
| 864 |
case PredefinedType.PLUS: |
656 |
case PredefinedType.PLUS: |
| 865 |
return sourceReal + argReal; |
657 |
return ((BigDecimal)sourceVal).add((BigDecimal)argVal); |
| 866 |
|
658 |
|
| 867 |
// Real::minus(Real) |
659 |
// Real::minus(Real) |
| 868 |
case PredefinedType.MINUS: |
660 |
case PredefinedType.MINUS: |
| 869 |
return sourceReal - argReal; |
661 |
return ((BigDecimal)sourceVal).subtract((BigDecimal)argVal); |
| 870 |
|
662 |
|
| 871 |
// Real::times(Real) |
663 |
// Real::times(Real) |
| 872 |
case PredefinedType.TIMES: |
664 |
case PredefinedType.TIMES: |
| 873 |
return sourceReal * argReal; |
665 |
return ((BigDecimal)sourceVal).multiply((BigDecimal)argVal); |
| 874 |
|
666 |
|
| 875 |
// Real::divide(Real) |
667 |
// Real::divide(Real) |
| 876 |
case PredefinedType.DIVIDE: |
668 |
case PredefinedType.DIVIDE: |
| 877 |
// denominator of 0 results in undefined |
669 |
// denominator of 0 results in undefined |
| 878 |
return (argReal == 0.0) ? getInvalid() : sourceReal / argReal; |
670 |
return (((BigDecimal)argVal).signum() == 0) ? getInvalid() : |
|
|
671 |
((BigDecimal)sourceVal).divide((BigDecimal)argVal); |
| 879 |
|
672 |
|
| 880 |
// Real::max(Real) |
673 |
// Real::max(Real) |
| 881 |
case PredefinedType.MAX: |
674 |
case PredefinedType.MAX: |
| 882 |
return Math.max(sourceReal, argReal); |
675 |
return ((BigDecimal)sourceVal).max((BigDecimal)argVal); |
| 883 |
|
676 |
|
| 884 |
// Real::min(Real) |
677 |
// Real::min(Real) |
| 885 |
case PredefinedType.MIN: |
678 |
case PredefinedType.MIN: |
| 886 |
return Math.min(sourceReal, argReal); |
679 |
return ((BigDecimal)sourceVal).min((BigDecimal)argVal); |
| 887 |
|
680 |
|
| 888 |
// Real::lessThan(Real) |
681 |
// Real::lessThan(Real) |
| 889 |
case PredefinedType.LESS_THAN: |
682 |
case PredefinedType.LESS_THAN: |
| 890 |
return sourceReal < argReal; |
683 |
return ((BigDecimal)sourceVal).compareTo((BigDecimal)argVal) < 0; |
| 891 |
|
684 |
|
| 892 |
// Real::greaterThan(Real) |
685 |
// Real::greaterThan(Real) |
| 893 |
case PredefinedType.GREATER_THAN: |
686 |
case PredefinedType.GREATER_THAN: |
| 894 |
return sourceReal > argReal; |
687 |
return ((BigDecimal)sourceVal).compareTo((BigDecimal)argVal) > 0; |
| 895 |
|
688 |
|
| 896 |
// Real::lessThanEqual(Real) |
689 |
// Real::lessThanEqual(Real) |
| 897 |
case PredefinedType.LESS_THAN_EQUAL: |
690 |
case PredefinedType.LESS_THAN_EQUAL: |
| 898 |
return sourceReal <= argReal; |
691 |
return ((BigDecimal)sourceVal).compareTo((BigDecimal)argVal) <= 0; |
| 899 |
|
692 |
|
| 900 |
// Real::greaterThanEqual(Real) |
693 |
// Real::greaterThanEqual(Real) |
| 901 |
case PredefinedType.GREATER_THAN_EQUAL: |
694 |
case PredefinedType.GREATER_THAN_EQUAL: |
| 902 |
return sourceReal >= argReal; |
695 |
return ((BigDecimal)sourceVal).compareTo((BigDecimal)argVal) >= 0; |
| 903 |
|
696 |
|
| 904 |
default: { |
697 |
default: { |
| 905 |
String message = OCLMessages.bind( |
698 |
String message = OCLMessages.bind( |
|
Lines 1101-1107
Link Here
|
| 1101 |
|
894 |
|
| 1102 |
case PredefinedType.AT: { |
895 |
case PredefinedType.AT: { |
| 1103 |
// OrderedSet, Sequence::at(Integer) |
896 |
// OrderedSet, Sequence::at(Integer) |
| 1104 |
int indexVal = ((Integer) argVal).intValue(); |
897 |
int indexVal = ((Number) argVal).intValue(); |
| 1105 |
return CollectionUtil.at(sourceColl, indexVal); |
898 |
return CollectionUtil.at(sourceColl, indexVal); |
| 1106 |
} |
899 |
} |
| 1107 |
|
900 |
|
|
Lines 1170-1196
Link Here
|
| 1170 |
// just one ternary string operation |
963 |
// just one ternary string operation |
| 1171 |
// String::substring(Integer, Integer) |
964 |
// String::substring(Integer, Integer) |
| 1172 |
// index orgin 1 for OCL |
965 |
// index orgin 1 for OCL |
| 1173 |
int lower = ((Integer) arg1).intValue() - 1; |
966 |
int lower = ((Number) arg1).intValue() - 1; |
| 1174 |
int upper = ((Integer) arg2).intValue(); |
967 |
int upper = ((Number) arg2).intValue(); |
| 1175 |
return ((String) sourceVal).substring(lower, upper); |
968 |
return ((String) sourceVal).substring(lower, upper); |
| 1176 |
} else if (sourceVal instanceof Collection<?>) { |
969 |
} else if (sourceVal instanceof Collection<?>) { |
| 1177 |
@SuppressWarnings("unchecked") |
970 |
@SuppressWarnings("unchecked") |
| 1178 |
Collection<Object> sourceColl = (Collection<Object>) sourceVal; |
971 |
Collection<Object> sourceColl = (Collection<Object>) sourceVal; |
| 1179 |
if (opCode == PredefinedType.INSERT_AT) { |
972 |
if (opCode == PredefinedType.INSERT_AT) { |
| 1180 |
// OrderedSet, Sequence::insertAt(Integer, T) |
973 |
// OrderedSet, Sequence::insertAt(Integer, T) |
| 1181 |
int index = ((Integer) arg1).intValue(); |
974 |
int index = ((Number) arg1).intValue(); |
| 1182 |
return CollectionUtil.insertAt(sourceColl, index, |
975 |
return CollectionUtil.insertAt(sourceColl, index, |
| 1183 |
arg2); |
976 |
arg2); |
| 1184 |
} else if (opCode == PredefinedType.SUB_ORDERED_SET) { |
977 |
} else if (opCode == PredefinedType.SUB_ORDERED_SET) { |
| 1185 |
// OrderedSet, Sequence::subOrderedSet(Integer, Integer) |
978 |
// OrderedSet, Sequence::subOrderedSet(Integer, Integer) |
| 1186 |
int lower = ((Integer) arg1).intValue(); |
979 |
int lower = ((Number) arg1).intValue(); |
| 1187 |
int upper = ((Integer) arg2).intValue(); |
980 |
int upper = ((Number) arg2).intValue(); |
| 1188 |
return CollectionUtil.subOrderedSet(sourceColl, |
981 |
return CollectionUtil.subOrderedSet(sourceColl, |
| 1189 |
lower, upper); |
982 |
lower, upper); |
| 1190 |
} else if (opCode == PredefinedType.SUB_SEQUENCE) { |
983 |
} else if (opCode == PredefinedType.SUB_SEQUENCE) { |
| 1191 |
// Sequence::subSequence(Integer, Integer) |
984 |
// Sequence::subSequence(Integer, Integer) |
| 1192 |
int lower = ((Integer) arg1).intValue(); |
985 |
int lower = ((Number) arg1).intValue(); |
| 1193 |
int upper = ((Integer) arg2).intValue(); |
986 |
int upper = ((Number) arg2).intValue(); |
| 1194 |
return CollectionUtil.subSequence(sourceColl, |
987 |
return CollectionUtil.subSequence(sourceColl, |
| 1195 |
lower, upper); |
988 |
lower, upper); |
| 1196 |
} |
989 |
} |
|
Lines 2044-2050
Link Here
|
| 2044 |
@Override |
1837 |
@Override |
| 2045 |
public Object visitUnlimitedNaturalLiteralExp( |
1838 |
public Object visitUnlimitedNaturalLiteralExp( |
| 2046 |
UnlimitedNaturalLiteralExp<C> literalExp) { |
1839 |
UnlimitedNaturalLiteralExp<C> literalExp) { |
| 2047 |
return literalExp.getIntegerSymbol(); |
1840 |
return literalExp.isUnlimited() ? literalExp : literalExp.getUnlimitedNaturalSymbol(); |
| 2048 |
} |
1841 |
} |
| 2049 |
|
1842 |
|
| 2050 |
/** |
1843 |
/** |
|
Lines 2129-2141
Link Here
|
| 2129 |
OCLExpression<C> last = collRange.getLast(); |
1922 |
OCLExpression<C> last = collRange.getLast(); |
| 2130 |
|
1923 |
|
| 2131 |
// evaluate first value |
1924 |
// evaluate first value |
| 2132 |
Integer firstVal = (Integer) first.accept(getVisitor()); |
1925 |
Number firstVal = (Number) first.accept(getVisitor()); |
| 2133 |
if (firstVal == null) { |
1926 |
if (firstVal == null) { |
| 2134 |
result.add(null); |
1927 |
result.add(null); |
| 2135 |
return result; |
1928 |
return result; |
| 2136 |
} |
1929 |
} |
| 2137 |
// evaluate last value |
1930 |
// evaluate last value |
| 2138 |
Integer lastVal = (Integer) last.accept(getVisitor()); |
1931 |
Number lastVal = (Number) last.accept(getVisitor()); |
| 2139 |
if (lastVal == null) { |
1932 |
if (lastVal == null) { |
| 2140 |
result.add(null); |
1933 |
result.add(null); |
| 2141 |
return result; |
1934 |
return result; |
|
Lines 2168-2182
Link Here
|
| 2168 |
OCLExpression<C> last = range.getLast(); |
1961 |
OCLExpression<C> last = range.getLast(); |
| 2169 |
|
1962 |
|
| 2170 |
// evaluate first value |
1963 |
// evaluate first value |
| 2171 |
Integer firstVal = (Integer) first.accept(getVisitor()); |
1964 |
Number firstVal = (Number) first.accept(getVisitor()); |
| 2172 |
Integer lastVal = (Integer) last.accept(getVisitor()); |
1965 |
Number lastVal = (Number) last.accept(getVisitor()); |
| 2173 |
if (!((firstVal == null) || (lastVal == null))) { |
1966 |
if (!((firstVal == null) || (lastVal == null))) { |
| 2174 |
// TODO: enhance IntegerRangeList to support multiple ranges |
1967 |
// TODO: enhance IntegerRangeList to support multiple ranges |
| 2175 |
// add values between first and last inclusive |
1968 |
// add values between first and last inclusive |
| 2176 |
int firstInt = firstVal.intValue(); |
1969 |
int firstInt = firstVal.intValue(); |
| 2177 |
int lastInt = lastVal.intValue(); |
1970 |
int lastInt = lastVal.intValue(); |
| 2178 |
for (int i = firstInt; i <= lastInt; i++) { |
1971 |
for (int i = firstInt; i <= lastInt; i++) { |
| 2179 |
result.add(new Integer(i)); |
1972 |
result.add(BigInteger.valueOf(i)); |
| 2180 |
} |
1973 |
} |
| 2181 |
} |
1974 |
} |
| 2182 |
} // end of collection range |
1975 |
} // end of collection range |
|
Lines 2190-2196
Link Here
|
| 2190 |
|
1983 |
|
| 2191 |
// private static inner class for lazy lists over an integer range |
1984 |
// private static inner class for lazy lists over an integer range |
| 2192 |
private static final class IntegerRangeList |
1985 |
private static final class IntegerRangeList |
| 2193 |
extends AbstractList<Integer> { |
1986 |
extends AbstractList<BigInteger> { |
| 2194 |
|
1987 |
|
| 2195 |
// public IntegerRangeList() { |
1988 |
// public IntegerRangeList() { |
| 2196 |
// super(); |
1989 |
// super(); |
|
Lines 2216-2222
Link Here
|
| 2216 |
} |
2009 |
} |
| 2217 |
|
2010 |
|
| 2218 |
@Override |
2011 |
@Override |
| 2219 |
public Integer get(int index) { |
2012 |
public BigInteger get(int index) { |
| 2220 |
if (index < 0 || index >= size()) { |
2013 |
if (index < 0 || index >= size()) { |
| 2221 |
String message = OCLMessages.bind( |
2014 |
String message = OCLMessages.bind( |
| 2222 |
OCLMessages.IndexOutOfRange_ERROR_, |
2015 |
OCLMessages.IndexOutOfRange_ERROR_, |
|
Lines 2229-2257
Link Here
|
| 2229 |
OCLPlugin.throwing(getClass(), "get", error);//$NON-NLS-1$ |
2022 |
OCLPlugin.throwing(getClass(), "get", error);//$NON-NLS-1$ |
| 2230 |
throw error; |
2023 |
throw error; |
| 2231 |
} |
2024 |
} |
| 2232 |
return new Integer(first + index); |
2025 |
return BigInteger.valueOf(first + index); |
| 2233 |
} |
2026 |
} |
| 2234 |
|
2027 |
|
| 2235 |
@Override |
2028 |
@Override |
| 2236 |
public Iterator<Integer> iterator() { |
2029 |
public Iterator<BigInteger> iterator() { |
| 2237 |
// local iterator class that provides |
2030 |
// local iterator class that provides |
| 2238 |
// hasNext() and next() methods appropriate |
2031 |
// hasNext() and next() methods appropriate |
| 2239 |
// for this range set |
2032 |
// for this range set |
| 2240 |
class IntegerRangeIterator |
2033 |
class IntegerRangeIterator |
| 2241 |
implements Iterator<Integer> { |
2034 |
implements Iterator<BigInteger> { |
| 2242 |
|
2035 |
|
| 2243 |
public IntegerRangeIterator() { |
2036 |
public IntegerRangeIterator() { |
| 2244 |
curr = first; |
2037 |
curr = first; |
| 2245 |
initialized = false; |
2038 |
initialized = false; |
| 2246 |
} |
2039 |
} |
| 2247 |
|
2040 |
|
| 2248 |
public Integer next() { |
2041 |
public BigInteger next() { |
| 2249 |
if (!initialized) { |
2042 |
if (!initialized) { |
| 2250 |
curr = first - 1; |
2043 |
curr = first - 1; |
| 2251 |
initialized = true; |
2044 |
initialized = true; |
| 2252 |
} |
2045 |
} |
| 2253 |
if (hasNext()) { |
2046 |
if (hasNext()) { |
| 2254 |
return new Integer(++curr); |
2047 |
return BigInteger.valueOf(++curr); |
| 2255 |
} |
2048 |
} |
| 2256 |
throw new NoSuchElementException(); |
2049 |
throw new NoSuchElementException(); |
| 2257 |
} |
2050 |
} |