UNPKG

ni-data-types

Version:

Non-standard data types used by the webcharts team.

242 lines (199 loc) 9.53 kB
//**************************************** // NIComplex data type // National Instruments Copyright 2016 //**************************************** (function () { 'use strict'; // Constructor Function window.NIComplex = function (value, imag) { if (typeof value === 'string') { var complexNumber = this.parseFromString(value); this.realPart = complexNumber[0]; this.imaginaryPart = complexNumber[1]; } else if (typeof value === 'number') { this.realPart = value; if (typeof imag === 'number') { this.imaginaryPart = imag; } else if (typeof imag === 'undefined') { this.imaginaryPart = 0; } else { throw new Error('Can\'t create complex number: invalid imaginary part'); } } else { throw new Error('Can\'t create complex number'); } }; // Static Private Variables var spaceRemovalRegex = /\s+/g; var middleSignRegex = /([^eE][-+])|([eE][-+][iInN])/; var testRealRegex = /^[-+]?([0-9]+|[0-9]+\.|[0-9]*\.[0-9]+)$/; var testImagRegex = /^[-+]?([0-9]*|[0-9]+\.|[0-9]*\.[0-9]+)i$/; var testRealScientificNotationRegex = /^[-+]?([0-9]+|[0-9]+\.|[0-9]+\.|[0-9]*\.[0-9]+)[eE][-+]?[0-9]+$/; var testImagScientificNotationRegex = /^[-+]?([0-9]+|[0-9]+\.|[0-9]+\.|[0-9]*\.[0-9]+)[eE][-+]?[0-9]+i$/; var checkRealInfinityRegex = /^[-+]?Infinity$/; var checkImagInfinityRegex = /^[-+]?Infinityi$/; var transformInfinityRegex = /[iI]nf(inity)?/g; var checkOnlyI = /^[-+]?i$/; var checkNaN = /^[-+]?NaNi?$/; var fastPathComplexRegex = /^[-+]?([0-9]+|[0-9]+\.[0-9]+)([eE][-+]?[0-9]+)?[-+]([0-9]+|[0-9]+\.[0-9]+)([eE][-+]?[0-9]+)?i$/; var realPartOnlyRegex = /^[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?$/; var imaginaryPartOnlyRegex = /^[+\-]?((?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?i$/; var realPartSIRegex = /^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)(Y|Z|E|P|T|G|M|k|c|m|u|n|p|f|a|z|y){1}(?!i)$/; var imaginaryPartSIRegex = /^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)(Y|Z|E|P|T|G|M|k|c|m|u|n|p|f|a|z|y){1}i$/; var scientificAndSINotationRegex = /^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?E)(?!i)([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?E)i$/; var scientificAndSINotationReversedRegex = /^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?E)i([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?E)$/; // Static Public Functions // None // Prototype creation var proto = window.NIComplex.prototype; // Static Private Functions var getRealPart = function (value) { var result; if (value === '') { return 0; } else if (checkNaN.test(value)) { return NaN; } if (value.search(/[eE]/) === -1) { if (!(testRealRegex.test(value) || checkRealInfinityRegex.test(value))) { throw new Error('Invalid real part format'); } result = parseFloat(value); } else { if (!testRealScientificNotationRegex.test(value)) { throw new Error('Invalid real part scientific notation'); } result = parseFloat(value); } return result; }; var getImaginaryPart = function (value) { var result; if (value === '') { return 0; } else if (checkNaN.test(value)) { return NaN; } var valueWithoutI = value.slice(0, -1); //removes the i at the end if (value.search(/[eE]/) === -1) { if (!(testImagRegex.test(value) || checkImagInfinityRegex.test(value))) { throw new Error('Invalid imaginary part format'); } if (checkOnlyI.test(value)) { return parseFloat(valueWithoutI + '1'); } result = parseFloat(valueWithoutI); } else { if (!testImagScientificNotationRegex.test(value)) { throw new Error('Invalid imaginary part scientific notation'); } result = parseFloat(valueWithoutI); } return result; }; var fastParseFromString = function (complexString) { var middleSignIndex = complexString.search(middleSignRegex); var real = parseFloat(complexString.substring(0, middleSignIndex + 1)); var imag = parseFloat(complexString.substring(middleSignIndex + 1, complexString.length - 1)); return [real, imag]; }; var thoroughParseFromString = function (complexString) { var realSubString, imagSubString; if (complexString === '' || typeof complexString === 'undefined' || complexString === null) { throw new Error('Invalid number format'); } complexString = complexString.replace(transformInfinityRegex, 'Infinity'); if (scientificAndSINotationRegex.test(complexString)) { var parts = scientificAndSINotationRegex.exec(complexString), realPartCoefficient = parts[1], imaginaryPartCoefficient = parts[2]; return [scientificToDecimal(realPartCoefficient), scientificToDecimal(imaginaryPartCoefficient)]; } else if (scientificAndSINotationReversedRegex.test(complexString)) { var parts = scientificAndSINotationReversedRegex.exec(complexString), realPartCoefficient = parts[2], imaginaryPartCoefficient = parts[1]; return [scientificToDecimal(realPartCoefficient), scientificToDecimal(imaginaryPartCoefficient)]; } var middleSignIndex = complexString.search(middleSignRegex); var imagIndex = complexString.search(/i[-+]|i$/); if (middleSignIndex < imagIndex) { realSubString = complexString.substring(0, middleSignIndex + 1); imagSubString = complexString.substring(middleSignIndex + 1); } else { imagSubString = complexString.substring(0, middleSignIndex + 1); realSubString = complexString.substring(middleSignIndex + 1); } // Checks if real and/or imaginary parts have SI prefixes var realPartSITest = realPartSIRegex.test(realSubString), imaginaryPartSITest = imaginaryPartSIRegex.test(imagSubString), realPart, imaginaryPart; if (realPartSITest) { realPart = scientificToDecimal(realSubString); if (isNaN(realPart)) { throw new Error('Invalid real part format'); } } if (imaginaryPartSITest) { imaginaryPart = scientificToDecimal(imagSubString.slice(0, imagSubString.length - 1)); if (isNaN(imaginaryPart)) { throw new Error('Invalid imaginary part format'); } } if (realPart !== undefined && imaginaryPart !== undefined) { return [realPart, imaginaryPart]; } else if (realPart !== undefined) { return [realPart, getImaginaryPart(imagSubString)]; } else if (imaginaryPart !== undefined) { return [getRealPart(realSubString), imaginaryPart]; } return [getRealPart(realSubString), getImaginaryPart(imagSubString)]; }; var scientificToDecimal = function (scientificValue) { var prefixesToPowers = { 'Y': 24, 'Z': 21, 'E': 18, 'P': 15, 'T': 12, 'G': 9, 'M': 6, 'k': 3, 'c': -2, 'm': -3, 'u': -6, 'n': -9, 'p': -12, 'f': -15, 'a': -18, 'z': -21, 'y': -24 }, parts = realPartSIRegex.exec(scientificValue), numericPart = parts[1], prefix = parts[2], number = parseFloat(numericPart) * parseFloat('1e' + prefixesToPowers[prefix]); return number; }; // Public Prototype Methods proto.parseFromString = function (complexString) { complexString = complexString.replace(spaceRemovalRegex, ''); if (realPartOnlyRegex.test(complexString)) { // if only real part has been passed in the string return [parseFloat(complexString), 0]; } else if (imaginaryPartOnlyRegex.test(complexString)) { // if only imaginary part has been passed in the string var numericPartOfImaginary = complexString.slice(0, -1); if (checkOnlyI.test(complexString)) { numericPartOfImaginary += '1'; } return [0, parseFloat(numericPartOfImaginary)]; } else if (fastPathComplexRegex.test(complexString)) { return fastParseFromString(complexString); } else { return thoroughParseFromString(complexString); } }; proto.compare = function (complexNumb) { var complexNumbMagnitute = Math.sqrt(Math.pow(complexNumb.realPart, 2) + Math.pow(complexNumb.imaginaryPart, 2)); var thisMagnitute = Math.sqrt(Math.pow(this.realPart, 2) + Math.pow(this.imaginaryPart, 2)); if (thisMagnitute > complexNumbMagnitute) { return 1; } else if (thisMagnitute < complexNumbMagnitute) { return -1; } else { return 0; } }; proto.toString = function () { if (this.imaginaryPart >= 0) { return this.realPart + ' + ' + this.imaginaryPart + 'i'; } else { return this.realPart + ' - ' + Math.abs(this.imaginaryPart) + 'i'; } }; }());