Skip to content

Commit cee7ef6

Browse files
committed
Add support for broadcasting scalar arguments
1 parent 53cbb44 commit cee7ef6

7 files changed

Lines changed: 302 additions & 72 deletions

File tree

lib/node_modules/@stdlib/math/iter/divide/README.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,26 @@ The returned [iterator][mdn-iterator-protocol] protocol-compliant object has the
6868
- **next**: function which returns an [iterator][mdn-iterator-protocol] protocol-compliant object containing the next iterated value (if one exists) assigned to a `value` property and a `done` property having a `boolean` value indicating whether the [iterator][mdn-iterator-protocol] is finished.
6969
- **return**: function which closes an [iterator][mdn-iterator-protocol] and returns a single (optional) argument in an [iterator][mdn-iterator-protocol] protocol-compliant object.
7070

71+
If provided a numeric value as an [`iterator`][mdn-iterator-protocol] argument, the value is broadcast as an **infinite** [iterator][mdn-iterator-protocol] which **always** returns the provided value.
72+
73+
```javascript
74+
var array2iterator = require( '@stdlib/array/to-iterator' );
75+
76+
var arr = array2iterator( [ 1.0, 2.0 ] );
77+
78+
var it = iterDivide( arr, 4.0 );
79+
// returns <Object>
80+
81+
var v = it.next().value;
82+
// returns 0.25
83+
84+
v = it.next().value;
85+
// returns 0.5
86+
87+
var bool = it.next().done;
88+
// returns true
89+
```
90+
7191
</section>
7292

7393
<!-- /.usage -->
@@ -96,7 +116,6 @@ The returned [iterator][mdn-iterator-protocol] protocol-compliant object has the
96116

97117
```javascript
98118
var iterSineWave = require( '@stdlib/simulate/iter/sine-wave' );
99-
var iterConstant = require( '@stdlib/iter/constant' );
100119
var iterDivide = require( '@stdlib/math/iter/divide' );
101120

102121
// Create an iterator which generates a sine wave:
@@ -106,11 +125,8 @@ var sine = iterSineWave({
106125
'iter': 100
107126
});
108127

109-
// Create an iterator which always returns the same value:
110-
var scalar = iterConstant( 10.0 );
111-
112128
// Create an iterator which scales the sine wave amplitude:
113-
var it = iterDivide( sine, scalar );
129+
var it = iterDivide( sine, 10.0 );
114130

115131
// Perform manual iteration...
116132
var v;

lib/node_modules/@stdlib/math/iter/divide/docs/repl.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
provided iterator. In other words, the returned iterator ends once *one* of
88
the provided iterators ends.
99

10+
If provided a numeric value as an iterator argument, the value is broadcast
11+
as an infinite iterator which always returns the provided value.
12+
1013
If an environment supports Symbol.iterator and provided iterators are
1114
iterable, the returned iterator is iterable.
1215

lib/node_modules/@stdlib/math/iter/divide/docs/types/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Iterator = Iter | IterableIterator;
3030
*
3131
* ## Notes
3232
*
33+
* - If provided a numeric value as an iterator argument, the value is broadcast as an **infinite** iterator which **always** returns the provided value.
3334
* - If an iterated value is non-numeric (including `NaN`), the function returns `NaN`. If non-numeric iterated values are possible, you are advised to provide an iterator which type checks and handles non-numeric values accordingly.
3435
* - The length of the returned iterator is equal to the length of the shortest provided iterator. In other words, the returned iterator ends once **one** of the provided iterators ends.
3536
* - If an environment supports `Symbol.iterator` and all provided iterators are iterable, the returned iterator is iterable.
@@ -56,7 +57,7 @@ type Iterator = Iter | IterableIterator;
5657
* var bool = iter.next().done;
5758
* // returns true
5859
*/
59-
declare function iterDivide( iter0: Iterator, iter1: Iterator, ...iterN: Array<Iterator> ): Iterator; // tslint:disable-line:max-line-length
60+
declare function iterDivide( iter0: Iterator | number, iter1: Iterator | number, ...iterN: Array<Iterator | number> ): Iterator; // tslint:disable-line:max-line-length
6061

6162

6263
// EXPORTS //

lib/node_modules/@stdlib/math/iter/divide/docs/types/test.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,28 @@ function iterator() {
5050
iterDivide( iterator(), iterator(), iterator() ); // $ExpectType Iterator
5151
iterDivide( iterator(), iterator(), iterator(), iterator() ); // $ExpectType Iterator
5252
iterDivide( iterator(), iterator(), iterator(), iterator(), iterator() ); // $ExpectType Iterator
53+
54+
iterDivide( iterator(), 4.0 ); // $ExpectType Iterator
55+
iterDivide( iterator(), 4.0, iterator() ); // $ExpectType Iterator
56+
iterDivide( iterator(), 4.0, iterator(), iterator() ); // $ExpectType Iterator
57+
iterDivide( iterator(), 4.0, iterator(), iterator(), iterator() ); // $ExpectType Iterator
58+
59+
iterDivide( 4.0, iterator() ); // $ExpectType Iterator
60+
iterDivide( 4.0, iterator(), iterator() ); // $ExpectType Iterator
61+
iterDivide( 4.0, iterator(), iterator(), iterator() ); // $ExpectType Iterator
62+
iterDivide( 4.0, iterator(), iterator(), iterator(), iterator() ); // $ExpectType Iterator
63+
64+
iterDivide( 4.0, 4.0 ); // $ExpectType Iterator
65+
iterDivide( 4.0, 4.0, 4.0 ); // $ExpectType Iterator
66+
iterDivide( 4.0, 4.0, 4.0, 4.0 ); // $ExpectType Iterator
67+
iterDivide( 4.0, 4.0, 4.0, 4.0, 4.0 ); // $ExpectType Iterator
5368
}
5469

55-
// The compiler throws an error if the function is provided a first argument which is not an iterator protocol-compliant object...
70+
// The compiler throws an error if the function is provided a first argument which is not an iterator protocol-compliant object or a number...
5671
{
5772
iterDivide( '5', iterator() ); // $ExpectError
5873
iterDivide( '5', iterator(), iterator() ); // $ExpectError
5974

60-
iterDivide( 5, iterator() ); // $ExpectError
61-
iterDivide( 5, iterator(), iterator() ); // $ExpectError
62-
6375
iterDivide( true, iterator() ); // $ExpectError
6476
iterDivide( true, iterator(), iterator() ); // $ExpectError
6577

@@ -82,14 +94,11 @@ function iterator() {
8294
iterDivide( ( x: number ): number => x, iterator(), iterator() ); // $ExpectError
8395
}
8496

85-
// The compiler throws an error if the function is provided a second argument which is not an iterator protocol-compliant object...
97+
// The compiler throws an error if the function is provided a second argument which is not an iterator protocol-compliant object or a number...
8698
{
8799
iterDivide( iterator(), '5' ); // $ExpectError
88100
iterDivide( iterator(), '5', iterator() ); // $ExpectError
89101

90-
iterDivide( iterator(), 5 ); // $ExpectError
91-
iterDivide( iterator(), 5, iterator() ); // $ExpectError
92-
93102
iterDivide( iterator(), true ); // $ExpectError
94103
iterDivide( iterator(), true, iterator() ); // $ExpectError
95104

@@ -112,14 +121,11 @@ function iterator() {
112121
iterDivide( iterator(), ( x: number ): number => x, iterator() ); // $ExpectError
113122
}
114123

115-
// The compiler throws an error if the function is provided a third argument which is not an iterator protocol-compliant object...
124+
// The compiler throws an error if the function is provided a third argument which is not an iterator protocol-compliant object or a number...
116125
{
117126
iterDivide( iterator(), iterator(), '5' ); // $ExpectError
118127
iterDivide( iterator(), iterator(), '5', iterator() ); // $ExpectError
119128

120-
iterDivide( iterator(), iterator(), 5 ); // $ExpectError
121-
iterDivide( iterator(), iterator(), 5, iterator() ); // $ExpectError
122-
123129
iterDivide( iterator(), iterator(), true ); // $ExpectError
124130
iterDivide( iterator(), iterator(), true, iterator() ); // $ExpectError
125131

@@ -146,4 +152,5 @@ function iterator() {
146152
{
147153
iterDivide(); // $ExpectError
148154
iterDivide( iterator() ); // $ExpectError
155+
iterDivide( 4.0 ); // $ExpectError
149156
}

lib/node_modules/@stdlib/math/iter/divide/examples/index.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
'use strict';
2020

2121
var iterSineWave = require( '@stdlib/simulate/iter/sine-wave' );
22-
var iterConstant = require( '@stdlib/iter/constant' );
2322
var iterDivide = require( './../lib' );
2423

2524
// Create an iterator which generates a sine wave:
@@ -29,11 +28,8 @@ var sine = iterSineWave({
2928
'iter': 100
3029
});
3130

32-
// Create an iterator which always returns the same value:
33-
var scalar = iterConstant( 10.0 );
34-
3531
// Create an iterator which scales the sine wave amplitude:
36-
var it = iterDivide( sine, scalar );
32+
var it = iterDivide( sine, 10.0 );
3733

3834
// Perform manual iteration...
3935
var v;

lib/node_modules/@stdlib/math/iter/divide/lib/main.js

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
2424
var isFunction = require( '@stdlib/assert/is-function' );
25+
var isNumber = require( '@stdlib/assert/is-number' ).isPrimitive;
2526
var isIteratorLike = require( '@stdlib/assert/is-iterator-like' );
2627
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
2728
var iteratorSymbol = require( '@stdlib/symbol/iterator' );
@@ -33,7 +34,7 @@ var iteratorSymbol = require( '@stdlib/symbol/iterator' );
3334
* Returns an iterator which performs element-wise division of two or more iterators.
3435
*
3536
* @param {Iterator} iter0 - first input iterator
36-
* @param {...Iterator} iterator - subsequent iterators
37+
* @param {...(Iterator|number)} iterator - subsequent iterators
3738
* @throws {Error} must provide two or more iterators
3839
* @throws {TypeError} must provide iterator protocol-compliant objects
3940
* @returns {Iterator} iterator
@@ -57,6 +58,7 @@ var iteratorSymbol = require( '@stdlib/symbol/iterator' );
5758
*/
5859
function iterDivide() {
5960
var iterators;
61+
var types;
6062
var niter;
6163
var iter;
6264
var FLG;
@@ -67,21 +69,25 @@ function iterDivide() {
6769
throw new Error( 'insufficient input arguments. Must provide two or more iterators.' );
6870
}
6971
iterators = [];
72+
types = [];
7073
for ( i = 0; i < niter; i++ ) {
71-
if ( !isIteratorLike( arguments[ i ] ) ) {
72-
throw new TypeError( 'invalid argument. Must provide an iterator protocol-compliant object. Argument: `' + i + '`. Value: `' + arguments[ i ] + '`.' );
73-
}
7474
iterators.push( arguments[ i ] );
75-
}
76-
// Create an iterator protocol-compliant object:
75+
if ( isIteratorLike( arguments[ i ] ) ) {
76+
types.push( 1 );
77+
} else if ( isNumber( arguments[ i ] ) ) {
78+
types.push( 0 );
79+
} else {
80+
throw new TypeError( 'invalid argument. Must provide an iterator protocol-compliant object or a number. Argument: `' + i + '`. Value: `' + arguments[ i ] + '`.' );
81+
}
82+
}// Create an iterator protocol-compliant object:
7783
iter = {};
7884
setReadOnly( iter, 'next', next );
7985
setReadOnly( iter, 'return', end );
8086

8187
// If an environment supports `Symbol.iterator` and all provided iterators are iterable, make the iterator iterable:
8288
if ( iteratorSymbol ) {
8389
for ( i = 0; i < niter; i++ ) {
84-
if ( !isFunction( iterators[ i ][ iteratorSymbol ] ) ) {
90+
if ( types[ i ] && !isFunction( iterators[ i ][ iteratorSymbol ] ) ) { // eslint-disable-line max-len
8591
FLG = true;
8692
break;
8793
}
@@ -110,46 +116,54 @@ function iterDivide() {
110116
};
111117
}
112118
FLG = 0;
113-
v = iterators[ 0 ].next();
114-
if ( v.done ) {
115-
FLG += 1;
116-
if ( hasOwnProp( v, 'value' ) ) {
117-
if ( typeof v.value === 'number' ) {
118-
s = v.value;
119-
} else {
120-
s = NaN;
121-
}
122-
} else {
123-
return {
124-
'done': true
125-
};
126-
}
127-
} else if ( typeof v.value === 'number' ) {
128-
s = v.value;
129-
} else {
130-
s = NaN;
131-
}
132-
for ( i = 1; i < niter; i++ ) {
133-
v = iterators[ i ].next();
119+
if ( types[ 0 ] ) {
120+
v = iterators[ 0 ].next();
134121
if ( v.done ) {
135122
FLG += 1;
136123
if ( hasOwnProp( v, 'value' ) ) {
137124
if ( typeof v.value === 'number' ) {
138-
s /= v.value;
125+
s = v.value;
139126
} else {
140127
s = NaN;
141128
}
142-
continue;
129+
} else {
130+
return {
131+
'done': true
132+
};
143133
}
144-
return {
145-
'done': true
146-
};
147-
}
148-
if ( typeof v.value === 'number' ) {
149-
s /= v.value;
134+
} else if ( typeof v.value === 'number' ) {
135+
s = v.value;
150136
} else {
151137
s = NaN;
152138
}
139+
} else {
140+
s = iterators[ 0 ];
141+
}
142+
for ( i = 1; i < niter; i++ ) {
143+
if ( types[ i ] ) {
144+
v = iterators[ i ].next();
145+
if ( v.done ) {
146+
FLG += 1;
147+
if ( hasOwnProp( v, 'value' ) ) {
148+
if ( typeof v.value === 'number' ) {
149+
s /= v.value;
150+
} else {
151+
s = NaN;
152+
}
153+
continue;
154+
}
155+
return {
156+
'done': true
157+
};
158+
}
159+
if ( typeof v.value === 'number' ) {
160+
s /= v.value;
161+
} else {
162+
s = NaN;
163+
}
164+
} else {
165+
s /= iterators[ i ];
166+
}
153167
}
154168
return {
155169
'value': s,
@@ -189,7 +203,11 @@ function iterDivide() {
189203

190204
args = [];
191205
for ( i = 0; i < niter; i++ ) {
192-
args.push( iterators[ i ][ iteratorSymbol ]() );
206+
if ( types[ i ] ) {
207+
args.push( iterators[ i ][ iteratorSymbol ]() );
208+
} else {
209+
args.push( iterators[ i ] );
210+
}
193211
}
194212
return iterDivide.apply( null, args );
195213
}

0 commit comments

Comments
 (0)