range.js (7779B)
1 import { factory } from '../../utils/factory.js'; 2 import { noBignumber, noMatrix } from '../../utils/noop.js'; 3 var name = 'range'; 4 var dependencies = ['typed', 'config', '?matrix', '?bignumber', 'smaller', 'smallerEq', 'larger', 'largerEq']; 5 export var createRange = /* #__PURE__ */factory(name, dependencies, _ref => { 6 var { 7 typed, 8 config, 9 matrix, 10 bignumber, 11 smaller, 12 smallerEq, 13 larger, 14 largerEq 15 } = _ref; 16 17 /** 18 * Create an array from a range. 19 * By default, the range end is excluded. This can be customized by providing 20 * an extra parameter `includeEnd`. 21 * 22 * Syntax: 23 * 24 * math.range(str [, includeEnd]) // Create a range from a string, 25 * // where the string contains the 26 * // start, optional step, and end, 27 * // separated by a colon. 28 * math.range(start, end [, includeEnd]) // Create a range with start and 29 * // end and a step size of 1. 30 * math.range(start, end, step [, includeEnd]) // Create a range with start, step, 31 * // and end. 32 * 33 * Where: 34 * 35 * - `str: string` 36 * A string 'start:end' or 'start:step:end' 37 * - `start: {number | BigNumber}` 38 * Start of the range 39 * - `end: number | BigNumber` 40 * End of the range, excluded by default, included when parameter includeEnd=true 41 * - `step: number | BigNumber` 42 * Step size. Default value is 1. 43 * - `includeEnd: boolean` 44 * Option to specify whether to include the end or not. False by default. 45 * 46 * Examples: 47 * 48 * math.range(2, 6) // [2, 3, 4, 5] 49 * math.range(2, -3, -1) // [2, 1, 0, -1, -2] 50 * math.range('2:1:6') // [2, 3, 4, 5] 51 * math.range(2, 6, true) // [2, 3, 4, 5, 6] 52 * 53 * See also: 54 * 55 * ones, zeros, size, subset 56 * 57 * @param {*} args Parameters describing the ranges `start`, `end`, and optional `step`. 58 * @return {Array | Matrix} range 59 */ 60 return typed(name, { 61 // TODO: simplify signatures when typed-function supports default values and optional arguments 62 // TODO: a number or boolean should not be converted to string here 63 string: _strRange, 64 'string, boolean': _strRange, 65 'number, number': function numberNumber(start, end) { 66 return _out(_rangeEx(start, end, 1)); 67 }, 68 'number, number, number': function numberNumberNumber(start, end, step) { 69 return _out(_rangeEx(start, end, step)); 70 }, 71 'number, number, boolean': function numberNumberBoolean(start, end, includeEnd) { 72 return includeEnd ? _out(_rangeInc(start, end, 1)) : _out(_rangeEx(start, end, 1)); 73 }, 74 'number, number, number, boolean': function numberNumberNumberBoolean(start, end, step, includeEnd) { 75 return includeEnd ? _out(_rangeInc(start, end, step)) : _out(_rangeEx(start, end, step)); 76 }, 77 'BigNumber, BigNumber': function BigNumberBigNumber(start, end) { 78 var BigNumber = start.constructor; 79 return _out(_bigRangeEx(start, end, new BigNumber(1))); 80 }, 81 'BigNumber, BigNumber, BigNumber': function BigNumberBigNumberBigNumber(start, end, step) { 82 return _out(_bigRangeEx(start, end, step)); 83 }, 84 'BigNumber, BigNumber, boolean': function BigNumberBigNumberBoolean(start, end, includeEnd) { 85 var BigNumber = start.constructor; 86 return includeEnd ? _out(_bigRangeInc(start, end, new BigNumber(1))) : _out(_bigRangeEx(start, end, new BigNumber(1))); 87 }, 88 'BigNumber, BigNumber, BigNumber, boolean': function BigNumberBigNumberBigNumberBoolean(start, end, step, includeEnd) { 89 return includeEnd ? _out(_bigRangeInc(start, end, step)) : _out(_bigRangeEx(start, end, step)); 90 } 91 }); 92 93 function _out(arr) { 94 if (config.matrix === 'Matrix') { 95 return matrix ? matrix(arr) : noMatrix(); 96 } 97 98 return arr; 99 } 100 101 function _strRange(str, includeEnd) { 102 var r = _parse(str); 103 104 if (!r) { 105 throw new SyntaxError('String "' + str + '" is no valid range'); 106 } 107 108 var fn; 109 110 if (config.number === 'BigNumber') { 111 if (bignumber === undefined) { 112 noBignumber(); 113 } 114 115 fn = includeEnd ? _bigRangeInc : _bigRangeEx; 116 return _out(fn(bignumber(r.start), bignumber(r.end), bignumber(r.step))); 117 } else { 118 fn = includeEnd ? _rangeInc : _rangeEx; 119 return _out(fn(r.start, r.end, r.step)); 120 } 121 } 122 /** 123 * Create a range with numbers. End is excluded 124 * @param {number} start 125 * @param {number} end 126 * @param {number} step 127 * @returns {Array} range 128 * @private 129 */ 130 131 132 function _rangeEx(start, end, step) { 133 var array = []; 134 var x = start; 135 136 if (step > 0) { 137 while (smaller(x, end)) { 138 array.push(x); 139 x += step; 140 } 141 } else if (step < 0) { 142 while (larger(x, end)) { 143 array.push(x); 144 x += step; 145 } 146 } 147 148 return array; 149 } 150 /** 151 * Create a range with numbers. End is included 152 * @param {number} start 153 * @param {number} end 154 * @param {number} step 155 * @returns {Array} range 156 * @private 157 */ 158 159 160 function _rangeInc(start, end, step) { 161 var array = []; 162 var x = start; 163 164 if (step > 0) { 165 while (smallerEq(x, end)) { 166 array.push(x); 167 x += step; 168 } 169 } else if (step < 0) { 170 while (largerEq(x, end)) { 171 array.push(x); 172 x += step; 173 } 174 } 175 176 return array; 177 } 178 /** 179 * Create a range with big numbers. End is excluded 180 * @param {BigNumber} start 181 * @param {BigNumber} end 182 * @param {BigNumber} step 183 * @returns {Array} range 184 * @private 185 */ 186 187 188 function _bigRangeEx(start, end, step) { 189 var zero = bignumber(0); 190 var array = []; 191 var x = start; 192 193 if (step.gt(zero)) { 194 while (smaller(x, end)) { 195 array.push(x); 196 x = x.plus(step); 197 } 198 } else if (step.lt(zero)) { 199 while (larger(x, end)) { 200 array.push(x); 201 x = x.plus(step); 202 } 203 } 204 205 return array; 206 } 207 /** 208 * Create a range with big numbers. End is included 209 * @param {BigNumber} start 210 * @param {BigNumber} end 211 * @param {BigNumber} step 212 * @returns {Array} range 213 * @private 214 */ 215 216 217 function _bigRangeInc(start, end, step) { 218 var zero = bignumber(0); 219 var array = []; 220 var x = start; 221 222 if (step.gt(zero)) { 223 while (smallerEq(x, end)) { 224 array.push(x); 225 x = x.plus(step); 226 } 227 } else if (step.lt(zero)) { 228 while (largerEq(x, end)) { 229 array.push(x); 230 x = x.plus(step); 231 } 232 } 233 234 return array; 235 } 236 /** 237 * Parse a string into a range, 238 * The string contains the start, optional step, and end, separated by a colon. 239 * If the string does not contain a valid range, null is returned. 240 * For example str='0:2:11'. 241 * @param {string} str 242 * @return {{start: number, end: number, step: number} | null} range Object containing properties start, end, step 243 * @private 244 */ 245 246 247 function _parse(str) { 248 var args = str.split(':'); // number 249 250 var nums = args.map(function (arg) { 251 // use Number and not parseFloat as Number returns NaN on invalid garbage in the string 252 return Number(arg); 253 }); 254 var invalid = nums.some(function (num) { 255 return isNaN(num); 256 }); 257 258 if (invalid) { 259 return null; 260 } 261 262 switch (nums.length) { 263 case 2: 264 return { 265 start: nums[0], 266 end: nums[1], 267 step: 1 268 }; 269 270 case 3: 271 return { 272 start: nums[0], 273 end: nums[2], 274 step: nums[1] 275 }; 276 277 default: 278 return null; 279 } 280 } 281 });