Skip to content

Commit

Permalink
Use [1 1>@0.inf as the canonical not-a-number
Browse files Browse the repository at this point in the history
ref #320
  • Loading branch information
frostburn committed May 14, 2024
1 parent 7b4b701 commit 7ec0908
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 22 deletions.
8 changes: 4 additions & 4 deletions documentation/interchange.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,16 @@ To support tempering after interchanging data, the special `1°` basis element i
```

### Not-a-number
The special token `nan` indicates a value that can't be interpreted as an interval.
The special combination `[1 1>@0.inf` indicates a value that can't be interpreted as an interval.
```c
nan "asin(2)" niente
[1 1>@0.inf "asin(2)" niente
```

## Example
See [examples/interchange.sw](https://github.com/xenharmonic-devs/sonic-weave/blob/main/examples/interchange.sw) for various extreme values supported by the original SonicWeave runtime.

```c
// Created using SonicWeave 0.0.37
// Created using SonicWeave 0.1.0

"Various values to test the .swi interchange format"

Expand Down Expand Up @@ -151,5 +151,5 @@ See [examples/interchange.sw](https://github.com/xenharmonic-devs/sonic-weave/bl
[-5 1 5/2 1 1>@1°.Hz.2.3.37 "" niente
[1>@inf "infinity" niente
[1 1>@-1.inf "negative infinity" niente
nan "not-a-number" niente
[1 1>@0.inf "not-a-number" niente
```
4 changes: 2 additions & 2 deletions src/__tests__/cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Interchange format', () => {

it('has representation for nan', () => {
const result = toSonicWeaveInterchange('nan');
expect(result).toContain('nan');
expect(result).toContain('[1 1>@0.inf');
});

it('has representation for negative infinity Hz', () => {
Expand All @@ -24,6 +24,6 @@ describe('Interchange format', () => {

it('has representation for nan Hz (normalizes)', () => {
const result = toSonicWeaveInterchange('nan * 1 Hz');
expect(result).toContain('nan');
expect(result).toContain('[1 1>@0.inf');
});
});
14 changes: 3 additions & 11 deletions src/interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ export class Interval {
* @param interchange Boolean flag to format everything explicitly.
* @returns A virtual monzo literal.
*/
asMonzoLiteral(interchange = false): MonzoLiteral | undefined {
asMonzoLiteral(interchange = false): MonzoLiteral {
let node: MonzoLiteral;
if (
interchange &&
Expand All @@ -1089,11 +1089,7 @@ export class Interval {
clone.numberOfComponents = NUM_INTERCHANGE_COMPONENTS;
node = clone.asMonzoLiteral();
} else {
const maybeNode = this.value.asMonzoLiteral();
if (maybeNode === undefined) {
return undefined;
}
node = maybeNode;
node = this.value.asMonzoLiteral();
}
if (
interchange &&
Expand Down Expand Up @@ -1129,11 +1125,7 @@ export class Interval {
result = `${this.steps}°`;
} else {
const node = this.asMonzoLiteral();
if (node) {
result = literalToString(node);
} else {
result = this.value.toString();
}
result = literalToString(node);
}
if (this.domain === 'linear') {
return `linear(${result})`;
Expand Down
14 changes: 9 additions & 5 deletions src/monzo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -745,12 +745,16 @@ export class TimeReal {
* @param interchange Boolean flag to use Hz basis for the absolute echelon.
* @returns Monzo literal.
*/
asMonzoLiteral(interchange = false): MonzoLiteral | undefined {
if (isNaN(this.value)) {
return undefined;
}
asMonzoLiteral(interchange = false): MonzoLiteral {
const components: VectorComponent[] = [];
const basis: BasisElement[] = [];
if (isNaN(this.value)) {
basis.push({numerator: 0, denominator: null, radical: false});
components.push({sign: '', left: 1, right: '', exponent: null});
basis.push('inf');
components.push({sign: '', left: 1, right: '', exponent: null});
return {type: 'MonzoLiteral', components, ups: 0, lifts: 0, basis};
}
if (interchange) {
if (this.timeExponent) {
basis.push('Hz');
Expand Down Expand Up @@ -817,7 +821,7 @@ export class TimeReal {
* Obtain an AST node representing the time monzo as a monzo literal suitable for interchange between programs.
* @returns Monzo literal.
*/
asInterchangeLiteral(): MonzoLiteral | undefined {
asInterchangeLiteral(): MonzoLiteral {
return this.asMonzoLiteral(true);
}

Expand Down
6 changes: 6 additions & 0 deletions src/parser/__tests__/expression.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2410,4 +2410,10 @@ describe('Poor grammar / Fun with "<"', () => {
expect(interval.valueOf()).toBe(0);
expect(interval.value).toBeInstanceOf(TimeReal);
});

it('parses the universal not-a-number', () => {
const interval = evaluate('[1 1>@0.inf') as Interval;
expect(interval.valueOf()).toBeNaN();
expect(interval.value).toBeInstanceOf(TimeReal);
});
});

0 comments on commit 7ec0908

Please sign in to comment.