Skip to content

Commit a562a58

Browse files
committed
Update start and end based on clarified definitions
1 parent 06d7db6 commit a562a58

8 files changed

Lines changed: 465 additions & 87 deletions

File tree

examples/browser/cql4browsers.js

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,25 +2289,31 @@ class Interval {
22892289
}
22902290
start() {
22912291
if (this.low == null) {
2292-
if (this.lowClosed) {
2293-
return (0, math_1.minValueForInstance)(this.high);
2292+
const quantityInstance = this.high && this.pointType == elmTypes_1.ELM_QUANTITY_TYPE ? this.high : undefined;
2293+
const minValue = (0, math_1.minValueForType)(this.pointType, quantityInstance);
2294+
if (this.lowClosed || minValue == null) {
2295+
return minValue;
22942296
}
22952297
else {
2296-
return this.low;
2298+
const end = ((end) => (end.isUncertainty ? end.high : end))(this.high == null ? (0, math_1.maxValueForType)(this.pointType) : this.end());
2299+
return new uncertainty_1.Uncertainty(minValue, end);
22972300
}
22982301
}
2299-
return this.toClosed().low;
2302+
return this.lowClosed ? this.low : (0, math_1.successor)(this.low, this.pointType);
23002303
}
23012304
end() {
23022305
if (this.high == null) {
2303-
if (this.highClosed) {
2304-
return (0, math_1.maxValueForInstance)(this.low);
2306+
const quantityInstance = this.low && this.pointType == elmTypes_1.ELM_QUANTITY_TYPE ? this.low : undefined;
2307+
const maxValue = (0, math_1.maxValueForType)(this.pointType, quantityInstance);
2308+
if (this.highClosed || maxValue == null) {
2309+
return maxValue;
23052310
}
23062311
else {
2307-
return this.high;
2312+
const start = ((start) => (start.isUncertainty ? start.low : start))(this.low == null ? (0, math_1.minValueForType)(this.pointType) : this.start());
2313+
return new uncertainty_1.Uncertainty(start, maxValue);
23082314
}
23092315
}
2310-
return this.toClosed().high;
2316+
return this.highClosed ? this.high : (0, math_1.predecessor)(this.high, this.pointType);
23112317
}
23122318
starts(other, precision) {
23132319
if (this.isBoundlessInterval) {
@@ -2576,7 +2582,7 @@ exports.ThreeValuedLogic = ThreeValuedLogic;
25762582
},{}],12:[function(require,module,exports){
25772583
"use strict";
25782584
Object.defineProperty(exports, "__esModule", { value: true });
2579-
exports.Quantity = void 0;
2585+
exports.MAX_QUANTITY_VALUE = exports.MIN_QUANTITY_VALUE = exports.Quantity = void 0;
25802586
exports.parseQuantity = parseQuantity;
25812587
exports.doAddition = doAddition;
25822588
exports.doSubtraction = doSubtraction;
@@ -2716,6 +2722,10 @@ class Quantity {
27162722
}
27172723
}
27182724
exports.Quantity = Quantity;
2725+
// Require MIN/MAX here because math.js requires this file, and when we make this file require
2726+
// math.js before it exports DateTime and Date, it errors due to the circular dependency...
2727+
exports.MIN_QUANTITY_VALUE = new Quantity(math_1.MIN_FLOAT_VALUE, '1');
2728+
exports.MAX_QUANTITY_VALUE = new Quantity(math_1.MAX_FLOAT_VALUE, '1');
27192729
function parseQuantity(str) {
27202730
const components = /([+|-]?\d+\.?\d*)\s*('(.+)')?/.exec(str);
27212731
if (components != null && components[1] != null) {
@@ -9261,7 +9271,7 @@ exports.greaterThan = greaterThan;
92619271
exports.greaterThanOrEquals = greaterThanOrEquals;
92629272
exports.equivalent = equivalent;
92639273
exports.equals = equals;
9264-
const datatypes_1 = require("../datatypes/datatypes");
9274+
const uncertainty_1 = require("../datatypes/uncertainty");
92659275
function areNumbers(a, b) {
92669276
return typeof a === 'number' && typeof b === 'number';
92679277
}
@@ -9277,7 +9287,7 @@ function areDateTimesOrQuantities(a, b) {
92779287
(a && a.isQuantity && b && b.isQuantity));
92789288
}
92799289
function isUncertainty(x) {
9280-
return x instanceof datatypes_1.Uncertainty;
9290+
return x instanceof uncertainty_1.Uncertainty;
92819291
}
92829292
function lessThan(a, b, precision) {
92839293
if (areNumbers(a, b) || areBigInts(a, b) || areStrings(a, b)) {
@@ -9290,7 +9300,7 @@ function lessThan(a, b, precision) {
92909300
return a.lessThan(b);
92919301
}
92929302
else if (isUncertainty(b)) {
9293-
return datatypes_1.Uncertainty.from(a).lessThan(b);
9303+
return uncertainty_1.Uncertainty.from(a).lessThan(b);
92949304
}
92959305
else {
92969306
return null;
@@ -9307,7 +9317,7 @@ function lessThanOrEquals(a, b, precision) {
93079317
return a.lessThanOrEquals(b);
93089318
}
93099319
else if (isUncertainty(b)) {
9310-
return datatypes_1.Uncertainty.from(a).lessThanOrEquals(b);
9320+
return uncertainty_1.Uncertainty.from(a).lessThanOrEquals(b);
93119321
}
93129322
else {
93139323
return null;
@@ -9324,7 +9334,7 @@ function greaterThan(a, b, precision) {
93249334
return a.greaterThan(b);
93259335
}
93269336
else if (isUncertainty(b)) {
9327-
return datatypes_1.Uncertainty.from(a).greaterThan(b);
9337+
return uncertainty_1.Uncertainty.from(a).greaterThan(b);
93289338
}
93299339
else {
93309340
return null;
@@ -9341,7 +9351,7 @@ function greaterThanOrEquals(a, b, precision) {
93419351
return a.greaterThanOrEquals(b);
93429352
}
93439353
else if (isUncertainty(b)) {
9344-
return datatypes_1.Uncertainty.from(a).greaterThanOrEquals(b);
9354+
return uncertainty_1.Uncertainty.from(a).greaterThanOrEquals(b);
93459355
}
93469356
else {
93479357
return null;
@@ -9454,11 +9464,11 @@ function equals(a, b) {
94549464
return a.equals(b);
94559465
}
94569466
// If one is an Uncertainty, convert the other to an Uncertainty
9457-
if (a instanceof datatypes_1.Uncertainty) {
9458-
b = datatypes_1.Uncertainty.from(b);
9467+
if (a instanceof uncertainty_1.Uncertainty) {
9468+
b = uncertainty_1.Uncertainty.from(b);
94599469
}
9460-
else if (b instanceof datatypes_1.Uncertainty) {
9461-
a = datatypes_1.Uncertainty.from(a);
9470+
else if (b instanceof uncertainty_1.Uncertainty) {
9471+
a = uncertainty_1.Uncertainty.from(a);
94629472
}
94639473
// Use overloaded 'equals' function if it is available
94649474
if (typeof a.equals === 'function') {
@@ -9500,7 +9510,7 @@ function equals(a, b) {
95009510
return false;
95019511
}
95029512

9503-
},{"../datatypes/datatypes":7}],54:[function(require,module,exports){
9513+
},{"../datatypes/uncertainty":14}],54:[function(require,module,exports){
95049514
"use strict";
95059515
Object.defineProperty(exports, "__esModule", { value: true });
95069516
exports.AnnotatedError = void 0;
@@ -9727,6 +9737,7 @@ exports.decimalAdjust = decimalAdjust;
97279737
exports.decimalOrNull = decimalOrNull;
97289738
exports.decimalLongOrNull = decimalLongOrNull;
97299739
const exception_1 = require("../datatypes/exception");
9740+
const quantity_1 = require("../datatypes/quantity");
97309741
const datetime_1 = require("../datatypes/datetime");
97319742
const uncertainty_1 = require("../datatypes/uncertainty");
97329743
const elmTypes_1 = require("./elmTypes");
@@ -10025,9 +10036,14 @@ function maxValueForInstance(val) {
1002510036
return exports.MAX_DATE_VALUE?.copy();
1002610037
}
1002710038
else if (val && val.isQuantity) {
10028-
const val2 = val.clone();
10029-
val2.value = maxValueForInstance(val2.value);
10030-
return val2;
10039+
// Although the spec says max Quantity has unit '1', it doesn't make sense to change the unit,
10040+
// especially if this is being used in the context of an interval or uncertainty since the
10041+
// left and right sides need to be comparable in those cases.
10042+
const maxQuantity = quantity_1.MAX_QUANTITY_VALUE.clone();
10043+
if (val.unit) {
10044+
maxQuantity.unit = val.unit;
10045+
}
10046+
return maxQuantity;
1003110047
}
1003210048
else {
1003310049
return null;
@@ -10048,13 +10064,17 @@ function maxValueForType(type, quantityInstance) {
1004810064
case elmTypes_1.ELM_TIME_TYPE:
1004910065
return exports.MAX_TIME_VALUE?.copy();
1005010066
case elmTypes_1.ELM_QUANTITY_TYPE: {
10067+
// Although the spec says max Quantity has unit '1', it doesn't make sense to change the unit,
10068+
// especially if this is being used in the context of an interval or uncertainty since the
10069+
// left and right sides need to be comparable in those cases.
10070+
const maxQuantity = quantity_1.MAX_QUANTITY_VALUE.clone();
1005110071
if (quantityInstance == null) {
10052-
// can't infer a quantity unit type from nothing]
10053-
return null;
10072+
return maxQuantity;
10073+
}
10074+
if (quantityInstance.unit) {
10075+
maxQuantity.unit = quantityInstance.unit;
1005410076
}
10055-
const maxQty = quantityInstance.clone();
10056-
maxQty.value = exports.MAX_FLOAT_VALUE;
10057-
return maxQty;
10077+
return maxQuantity;
1005810078
}
1005910079
}
1006010080
return null;
@@ -10081,9 +10101,14 @@ function minValueForInstance(val) {
1008110101
return exports.MIN_DATE_VALUE?.copy();
1008210102
}
1008310103
else if (val && val.isQuantity) {
10084-
const val2 = val.clone();
10085-
val2.value = minValueForInstance(val2.value);
10086-
return val2;
10104+
// Although the spec says max Quantity has unit '1', it doesn't make sense to change the unit,
10105+
// especially if this is being used in the context of an interval or uncertainty since the
10106+
// left and right sides need to be comparable in those cases.
10107+
const minQuantity = quantity_1.MIN_QUANTITY_VALUE.clone();
10108+
if (val.unit) {
10109+
minQuantity.unit = val.unit;
10110+
}
10111+
return minQuantity;
1008710112
}
1008810113
else {
1008910114
return null;
@@ -10104,13 +10129,17 @@ function minValueForType(type, quantityInstance) {
1010410129
case elmTypes_1.ELM_TIME_TYPE:
1010510130
return exports.MIN_TIME_VALUE?.copy();
1010610131
case elmTypes_1.ELM_QUANTITY_TYPE: {
10132+
// Although the spec says max Quantity has unit '1', it doesn't make sense to change the unit,
10133+
// especially if this is being used in the context of an interval or uncertainty since the
10134+
// left and right sides need to be comparable in those cases.
10135+
const minQuantity = quantity_1.MIN_QUANTITY_VALUE.clone();
1010710136
if (quantityInstance == null) {
10108-
// can't infer a quantity unit type from nothing]
10109-
return null;
10137+
return minQuantity;
10138+
}
10139+
if (quantityInstance.unit) {
10140+
minQuantity.unit = quantityInstance.unit;
1011010141
}
10111-
const minQty = quantityInstance.clone();
10112-
minQty.value = exports.MIN_FLOAT_VALUE;
10113-
return minQty;
10142+
return minQuantity;
1011410143
}
1011510144
}
1011610145
return null;
@@ -10145,7 +10174,7 @@ function decimalLongOrNull(value) {
1014510174
: null;
1014610175
}
1014710176

10148-
},{"../datatypes/datetime":8,"../datatypes/exception":9,"../datatypes/uncertainty":14,"./elmTypes":55}],58:[function(require,module,exports){
10177+
},{"../datatypes/datetime":8,"../datatypes/exception":9,"../datatypes/quantity":12,"../datatypes/uncertainty":14,"./elmTypes":55}],58:[function(require,module,exports){
1014910178
"use strict";
1015010179
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
1015110180
if (k2 === undefined) k2 = k;

src/datatypes/interval.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -526,24 +526,36 @@ export class Interval {
526526

527527
start() {
528528
if (this.low == null) {
529-
if (this.lowClosed) {
530-
return minValueForInstance(this.high);
529+
const quantityInstance =
530+
this.high && this.pointType == ELM_QUANTITY_TYPE ? this.high : undefined;
531+
const minValue = minValueForType(this.pointType, quantityInstance);
532+
if (this.lowClosed || minValue == null) {
533+
return minValue;
531534
} else {
532-
return this.low;
535+
const end = ((end: any) => (end.isUncertainty ? end.high : end))(
536+
this.high == null ? maxValueForType(this.pointType) : this.end()
537+
);
538+
return new Uncertainty(minValue, end);
533539
}
534540
}
535-
return this.toClosed().low;
541+
return this.lowClosed ? this.low : successor(this.low, this.pointType);
536542
}
537543

538544
end() {
539545
if (this.high == null) {
540-
if (this.highClosed) {
541-
return maxValueForInstance(this.low);
546+
const quantityInstance =
547+
this.low && this.pointType == ELM_QUANTITY_TYPE ? this.low : undefined;
548+
const maxValue = maxValueForType(this.pointType, quantityInstance);
549+
if (this.highClosed || maxValue == null) {
550+
return maxValue;
542551
} else {
543-
return this.high;
552+
const start = ((start: any) => (start.isUncertainty ? start.low : start))(
553+
this.low == null ? minValueForType(this.pointType) : this.start()
554+
);
555+
return new Uncertainty(start, maxValue);
544556
}
545557
}
546-
return this.toClosed().high;
558+
return this.highClosed ? this.high : predecessor(this.high, this.pointType);
547559
}
548560

549561
starts(other: any, precision?: any) {

src/datatypes/quantity.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { ELM_DECIMAL_TYPE } from '../util/elmTypes';
2-
import { decimalAdjust, isValidDecimal, overflowsOrUnderflows } from '../util/math';
2+
import {
3+
decimalAdjust,
4+
isValidDecimal,
5+
MIN_FLOAT_VALUE,
6+
MAX_FLOAT_VALUE,
7+
overflowsOrUnderflows
8+
} from '../util/math';
39
import {
410
checkUnit,
511
convertUnit,
@@ -157,6 +163,11 @@ export class Quantity {
157163
}
158164
}
159165

166+
// Require MIN/MAX here because math.js requires this file, and when we make this file require
167+
// math.js before it exports DateTime and Date, it errors due to the circular dependency...
168+
export const MIN_QUANTITY_VALUE = new Quantity(MIN_FLOAT_VALUE, '1');
169+
export const MAX_QUANTITY_VALUE = new Quantity(MAX_FLOAT_VALUE, '1');
170+
160171
export function parseQuantity(str: string) {
161172
const components = /([+|-]?\d+\.?\d*)\s*('(.+)')?/.exec(str);
162173
if (components != null && components[1] != null) {

src/util/comparison.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Uncertainty } from '../datatypes/datatypes';
1+
import { Uncertainty } from '../datatypes/uncertainty';
22

33
function areNumbers(a: any, b: any) {
44
return typeof a === 'number' && typeof b === 'number';

0 commit comments

Comments
 (0)