• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16interface HelpUtil{
17    TextEncoder : Object;
18    TextDecoder : Object;
19    Base64 : Object;
20    Types : Object;
21    dealwithformatstring(formatString : string | Array<string | number | Fn>) : string;
22    printf(formatString : string | Array<string | number | Fn>,
23           ...valueString : Array<Object>) : string;
24    getErrorString(errnum : number) : string;
25    createExternalType() : Object;
26}
27
28interface Fn{
29    () : void;
30}
31declare function requireInternal(s : string) : HelpUtil;
32const helpUtil = requireInternal('util');
33var TextEncoder = helpUtil.TextEncoder;
34var TextDecoder = helpUtil.TextDecoder;
35var Base64 = helpUtil.Base64;
36var Types = helpUtil.Types;
37function switchLittleObject(enter : string, obj : Object, count : number) : string | Object
38{
39    let str : string = '';
40    if (obj === null) {
41        str += obj;
42    } else if (obj instanceof Array) {
43        str += '[ ' + arrayToString(enter, obj, count) + '[length]: ' + obj.length + ' ]';
44    } else if (typeof obj === 'function') {
45        str += '{ [Function: ' + obj.name + ']' + enter
46            + '[length]: ' + obj.length + ',' + enter
47            + '[name] :\'' + obj.name + '\',' + enter
48            + '[prototype]: ' + obj.name + ' { [constructor]: [Circular] } }';
49    } else if (typeof obj === 'object') {
50        str += '{ ';
51        let i : string;
52        let flag : boolean = false;
53        for (i in obj) {
54            flag = true;
55            str += switchLittleValue(enter, i, obj, count);
56        }
57        if (!flag) {
58            return obj;
59        }
60        str = str.substr(0, str.length - enter.length - 1);
61        str += ' }';
62    } else if (typeof obj === 'string') {
63        str += '\'' + obj + '\'';
64    } else {
65        str += obj;
66    }
67    return str;
68}
69
70function switchLittleValue(enter : string, protoName : string, obj : Object, count : number) : string
71{
72    let str : string = '';
73    if (obj[protoName] === null) {
74        str += protoName + ': null,' + enter;
75    } else if (obj[protoName] instanceof Array) {
76        str += protoName + ':' + enter
77            + '[ ' + arrayToString(enter + '  ', obj[protoName], count) + '[length]: '
78            + obj[protoName].length + ' ],' + enter;
79    } else if (typeof obj[protoName] === 'object') {
80        if (obj[protoName] === obj) {
81            str += protoName + ': [Circular]' + enter;
82        } else {
83            str += protoName + ':' + enter;
84            str += switchLittleObject(enter + '  ', obj[protoName], count + 1) + ',' + enter;
85        }
86    } else if (typeof obj[protoName] === 'function') {
87        let space : string= enter;
88        if (obj[protoName].name !== '') {
89            str += obj[protoName].name + ':' + space;
90        }
91        space += '  ';
92        str += '{ [Function: ' + obj[protoName].name + ']' + space
93            + '[length]: ' + obj[protoName].length + ',' + space
94            + '[name] :\'' + obj[protoName].name + '\',' + space
95            + '[prototype]: ' + obj[protoName].name
96            + ' { [constructor]: [Circular] } },' + enter;
97    } else {
98        if (typeof obj[protoName] === 'string') {
99            str += protoName + ': \'' + obj[protoName] + '\',' + enter;
100        } else {
101            str += protoName + ': ' + obj[protoName] + ',' + enter;
102        }
103    }
104    return str;
105}
106
107function arrayToString(enter : string, arr : Array<string | number | Fn>, count : number) : string
108{
109    let str : string = '';
110    if (!arr.length) {
111        return '';
112    }
113    let arrayEnter : string = ', ';
114    for (let k in arr) {
115        if (arr[k] !== null && (typeof arr[k] === 'function' || typeof arr[k] === 'object') && count <= 2) {
116            arrayEnter += enter;
117            break;
118        }
119    }
120    for (let i of arr) {
121        if (typeof i === 'string') {
122            str += '\'' + i.toString() + '\'' + arrayEnter;
123        } else if (typeof i === 'object') {
124            str += switchLittleObject(enter + '  ', i, count + 1);
125            str += arrayEnter;
126        } else if (typeof i === 'function') {
127            let space : string = enter;
128            space += '  ';
129            let end : string = '';
130            if (i.name !== '') {
131                str += '{ [Function: ' + i.name + ']' + space;
132                end = i.name + ' { [constructor]: [Circular] } }' + arrayEnter;
133            } else {
134                str += '{ [Function]' + space;
135                end = '{ [constructor]: [Circular] } }' + arrayEnter;
136            }
137            str += '[length]: '
138                + i.length + ',' + space
139                + '[name] :\'' + i.name + '\',' + space
140                + '[prototype]: ' + end;
141        } else {
142            str += i + arrayEnter;
143        }
144    }
145    return str;
146}
147
148function switchBigObject(enter : string, obj : Object, count : number) : string | Object
149{
150    let str : string = '';
151    if (obj === null) {
152        str += obj;
153    } else if (obj instanceof Array) {
154        str += '[ ' + arrayToBigString(enter, obj, count) + ' ]';
155    } else if (typeof obj === 'function') {
156        str += '{ [Function: ' + obj.name + '] }';
157    } else if (typeof obj === 'object') {
158        str += '{ ';
159        let i : string;
160        let flag : boolean = false;
161        for (i in obj) {
162            flag = true;
163            str += switchBigValue(enter, i, obj, count);
164        }
165        if (!flag) {
166            return obj;
167        }
168        str = str.substr(0, str.length - enter.length - 1);
169        str += ' }';
170    } else if (typeof obj === 'string') {
171        str += '\'' + obj + '\'';
172    } else {
173        str += obj;
174    }
175    return str;
176}
177
178function switchBigValue(enter : string, protoName : string, obj : Object, count : number) : string
179{
180    let str : string = '';
181    if (obj[protoName] === null) {
182        str += protoName + ': null,' + enter;
183    } else if (obj[protoName] instanceof Array) {
184        str += protoName + ':' + enter
185            + '[ ' + arrayToBigString(enter + '  ', obj[protoName], count) + ' ],' + enter;
186    } else if (typeof obj[protoName] === 'object') {
187        if (obj[protoName] === obj) {
188            str += protoName + ': [Circular]' + enter;
189        } else {
190            str += protoName + ':' + enter;
191            str += switchBigObject(enter + '  ', obj[protoName], count + 1) + ',' + enter;
192        }
193    } else if (typeof obj[protoName] === 'function') {
194        if (obj[protoName].name !== '') {
195            str += obj[protoName].name + ': ';
196        }
197        str += '[Function: ' + obj[protoName].name + '],' + enter;
198    } else {
199        if (typeof obj[protoName] === 'string') {
200            str += protoName + ': \'' + obj[protoName] + '\',' + enter;
201        } else {
202            str += protoName + ': ' + obj[protoName] + ',' + enter;
203        }
204    }
205    return str;
206}
207function arrayToBigString(enter : string, arr : Array<string | number | Fn>, count : number) : string
208{
209    let str : string = '';
210    if (!arr.length) {
211        return '';
212    }
213
214    let arrayEnter = ', ';
215    for (let i of arr) {
216        if (i !== null && (typeof i === 'object') && count <= 2) {
217            arrayEnter += enter;
218            break;
219        }
220    }
221    for (let j of arr) {
222        if (typeof j === 'string') {
223            str += '\'' + j + '\'' + arrayEnter;
224        } else if (typeof j === 'object') {
225            str += switchBigObject(enter + '  ', j, count + 1);
226            str += arrayEnter;
227        } else if (typeof j === 'function') {
228            if (j.name !== '') {
229                str += '[Function: ' + j.name + ']' + arrayEnter;
230            } else {
231                str += '[Function]' + arrayEnter;
232            }
233        } else {
234            str += j + arrayEnter;
235        }
236    }
237    str = str.substr(0, str.length - arrayEnter.length);
238    return str;
239}
240function switchIntValue(value : Object | symbol) : string
241{
242    let str : string = '';
243    if (value === '') {
244        str += 'NaN';
245    } else if (typeof value === 'bigint') {
246        str += value + 'n';
247    } else if (typeof value === 'symbol') {
248        str += 'NaN';
249    } else if (typeof value === 'number') {
250        str += parseInt(value.toString(), 10); // 10:The function uses decimal.
251    } else if (value instanceof Array) {
252        if (typeof value[0] === 'number') {
253            str += parseInt(value[0].toString(), 10); // 10:The function uses decimal.
254        } else if (typeof value[0] === 'string') {
255            if (isNaN(Number(value[0]))) {
256                str += 'NaN';
257            } else {
258                str += parseInt(value[0], 10); // 10:The function uses decimal.
259            }
260        }
261    } else if (typeof value === 'string') {
262        if (isNaN(Number(value))) {
263            str += 'NaN';
264        } else {
265            str += parseInt(value, 10); // 10:The function uses decimal.
266        }
267    } else {
268        str += 'NaN';
269    }
270    return str;
271}
272function switchFloatValue(value : Object | symbol) : string
273{
274    let str : string = '';
275    if (value === '') {
276        str += 'NaN';
277    } else if (typeof value === 'symbol') {
278        str += 'NaN';
279    } else if (typeof value === 'number') {
280        str += value;
281    } else if (value instanceof Array) {
282        if (typeof value[0] === 'number') {
283            str += parseFloat(value.toString());
284        } else if (typeof value[0] === 'string') {
285            if (isNaN(Number(value[0]))) {
286                str += 'NaN';
287            } else {
288                str += parseFloat(value[0]);
289            }
290        }
291    } else if (typeof value === 'string') {
292        if (isNaN(Number(value))) {
293            str += 'NaN';
294        } else {
295            str += parseFloat(value);
296        }
297    } else if (typeof value === 'bigint') {
298        str += value;
299    } else {
300        str += 'NaN';
301    }
302    return str;
303}
304
305function switchNumberValue(value : Object | symbol) : string
306{
307    let str : string = '';
308    if (value === '') {
309        str += '0';
310    } else if (typeof value === 'symbol') {
311        str += 'NaN';
312    } else if (typeof value === 'number') {
313        str += value;
314    } else if (value instanceof Array) {
315        str += 'NaN';
316    } else if (typeof value === 'string') {
317        if (isNaN(Number(value))) {
318            str += 'NaN';
319        } else {
320            str += Number(value);
321        }
322    } else if (typeof value === 'bigint') {
323        str += value.toString() + 'n';
324    } else {
325        str += 'NaN';
326    }
327    return str;
328}
329
330function switchStringValue(value : Object | symbol) : string
331{
332    let str : string = '';
333    if (typeof value === 'undefined') {
334        str += 'undefined';
335    } else if (typeof value === 'object') {
336        if (value === null) {
337            str += 'null';
338        } else {
339            str += value;
340        }
341    } else if (typeof value === 'symbol') {
342        str += value.toString();
343    } else {
344        str += value;
345    }
346    return str;
347}
348//    printf(formatString : string | Array<string | number | Fn>,
349//           ...valueString : Array<string | number | Fn | object>) : string;
350function printf(formatString : Array<string | number | Fn>, ...valueString : Array<Object>) : string
351{
352    let formats : string = helpUtil.dealwithformatstring(formatString);
353    let arr : Array<Object>= [];
354    arr = formats.split(' ');
355    let switchString : Array<Object>= [];
356    let valueLength : number = valueString.length;
357    let arrLength : number = arr.length;
358    let i : number= 0;
359    for (let sub of valueString) {
360        if (i >= arrLength) {
361            break;
362        }
363        if (arr[i] === 'o') {
364            switchString.push(switchLittleObject('\n  ', sub, 1));
365        } else if (arr[i] === 'O') {
366            switchString.push(switchBigObject('\n  ', sub, 1));
367        } else if (arr[i] === 'i') {
368            switchString.push(switchIntValue(sub));
369        } else if (arr[i] === 'j') {
370            switchString.push(JSON.stringify(sub));
371        } else if (arr[i] === 'd') {
372            switchString.push(switchNumberValue(sub));
373        } else if (arr[i] === 's') {
374            switchString.push(switchStringValue(sub));
375        } else if (arr[i] === 'f') {
376            switchString.push(switchFloatValue(sub));
377        } else if (arr[i] === 'c') {
378            switchString.push(sub.toString());
379        }
380        ++i;
381    }
382    while (i < valueLength) {
383        switchString.push(valueString[i].toString());
384        i++;
385    }
386    let helpUtilString : string = helpUtil.printf(formatString, ...switchString);
387    return helpUtilString;
388}
389
390function getErrorString(errnum : number) : string
391{
392    let errorString : string = helpUtil.getErrorString(errnum);
393    return errorString;
394}
395
396function createExternalType() : Object
397{
398    let externalType : Object = helpUtil.createExternalType();
399    return externalType;
400}
401
402function callbackified(original : Fn, ...args : Array<string | number | Fn>) : void
403{
404    const maybeCb = args.pop();
405    if (typeof maybeCb !== 'function') {
406        throw new Error('maybe is not function');
407    }
408    const cb = (...args : Array<null>) => {
409        Reflect.apply(maybeCb, this, args);
410    };
411    Reflect.apply(original, this, args).then((ret : null) => cb(null, ret), (rej : null) => cb(rej));
412}
413
414function getOwnPropertyDescriptors(obj : Fn) : PropertyDescriptorMap
415{
416    const result : PropertyDescriptorMap = {};
417    for (let key of Reflect.ownKeys(obj)) {
418        if (typeof key === 'string') {
419            result[key] = Object.getOwnPropertyDescriptor(obj, key);
420        }
421    }
422    return result;
423}
424
425function callbackWrapper(original : Fn) : void
426{
427    if (typeof original !== 'function') {
428        throw new Error('original is not function');
429    }
430    const descriptors = getOwnPropertyDescriptors(original);
431    if (typeof descriptors.length.value === 'number') {
432        descriptors.length.value++;
433    }
434    if (typeof descriptors.name.value === 'string') {
435        descriptors.name.value += 'callbackified';
436    }
437
438    function cb(...args : Array<string | number | Fn>) {
439        callbackified(original, ...args);
440    }
441    Object.defineProperties(cb, descriptors);
442}
443
444function promiseWrapper(func : Function) : Object
445{
446    return function (...args : Array<Object>) {
447        return new Promise((resolve, reject) => {
448            let callback : Function = function (err : Object | string, ...values : Array<Object>) {
449                if (err) {
450                    reject(err);
451                } else {
452                    resolve(values);
453                }
454            };
455            func.apply(null, [...args, callback]);
456        });
457    };
458}
459
460class LruBuffer
461{
462    private cache: Map<Object | undefined, Object | undefined>;
463    private maxSize : number = 64;
464    private maxNumber : number = 2147483647;
465    private putCount : number = 0;
466    private createCount : number = 0;
467    private evictionCount : number = 0;
468    private hitCount : number = 0;
469    private missCount : number = 0;
470    public length : number = 0;
471
472    public constructor(capacity?: number)
473    {
474        if (capacity !== undefined) {
475            if (capacity <= 0 || capacity % 1 !== 0 || capacity > this.maxNumber) {
476                throw new Error('data error');
477            }
478            this.maxSize = capacity;
479        }
480        this.cache = new Map();
481    }
482
483    public updateCapacity(newCapacity : number) : void
484    {
485        if (newCapacity <= 0 || newCapacity % 1 !== 0 || newCapacity > this.maxNumber) {
486            throw new Error('data error');
487        } else if (this.cache.size >newCapacity) {
488            this.changeCapacity(newCapacity);
489        }
490        this.length = this.cache.size;
491        this.maxSize = newCapacity;
492    }
493
494    public get(key : Object) : Object
495    {
496        if (key === null) {
497            throw new Error('key not be null');
498        }
499        let value : Object;
500        if (this.cache.has(key)) {
501            value = this.cache.get(key);
502            this.hitCount++;
503            this.cache.delete(key);
504            this.cache.set(key, value);
505            return value;
506        }
507
508        this.missCount++;
509        let createValue : Object = this.createDefault(key);
510        if (createValue === undefined) {
511            return undefined;
512        } else {
513            value = this.put(key, createValue);
514            this.createCount++;
515            if (value !== undefined) {
516                this.put(key, value);
517                this.afterRemoval(false, key, createValue, value);
518                return value;
519            }
520            return createValue;
521        }
522    }
523
524    public put(key : Object, value : Object) : Object
525    {
526        if (key === null || value === null) {
527            throw new Error('key or value not be null');
528        }
529        let former : Object;
530        this.putCount++;
531        if (this.cache.has(key)) {
532            former = this.cache.get(key);
533            this.cache.delete(key);
534            this.afterRemoval(false, key, former, value);
535        } else if (this.cache.size >= this.maxSize) {
536            this.cache.delete(this.cache.keys().next().value);
537            this.evictionCount++;
538        }
539        this.cache.set(key, value);
540        this.length = this.cache.size;
541        return former;
542    }
543
544    public getCreateCount() : number
545    {
546        return this.createCount;
547    }
548
549    public getMissCount() : number
550    {
551        return this.missCount;
552    }
553
554    public getRemovalCount() : number
555    {
556        return this.evictionCount;
557    }
558
559    public getMatchCount() : number
560    {
561        return this.hitCount;
562    }
563
564    public getPutCount() : number
565    {
566        return this.putCount;
567    }
568
569    public getCapacity() : number
570    {
571         return this.maxSize;
572    }
573
574    public clear() : void
575    {
576        this.cache.clear();
577        this.afterRemoval(false, this.cache.keys(), this.cache.values(), null);
578        this.length = this.cache.size;
579    }
580
581    public isEmpty() :boolean
582    {
583        let temp : boolean = false;
584        if (this.cache.size === 0) {
585            temp = true;
586        }
587        return temp;
588    }
589
590    public contains(key : Object) : boolean
591    {
592        let flag : boolean = false;
593        if (this.cache.has(key)) {
594            flag = true;
595            let value : Object;
596            this.hitCount++;
597            value = this.cache.get(key);
598            this.cache.delete(key);
599            this.cache.set(key, value);
600            this.length = this.cache.size;
601            return flag;
602        }
603        this.missCount++;
604        return flag;
605    }
606
607    public remove(key : Object) : Object
608    {
609        if (key === null) {
610            throw new Error('key not be null');
611        } else if (this.cache.has(key)) {
612            let former : Object;
613            former = this.cache.get(key);
614            this.cache.delete(key);
615            if (former !== null) {
616                this.afterRemoval(false, key, former, null);
617                this.length = this.cache.size;
618                return former;
619            }
620        }
621        this.length = this.cache.size;
622        return undefined;
623    }
624
625    public toString() : string
626    {
627        let peek : number = 0;
628        let hitRate : number = 0;
629        peek = this.hitCount + this.missCount;
630        if (peek !== 0) {
631            hitRate = 100 * this.hitCount / peek;
632        } else {
633            hitRate = 0;
634        }
635        let str : string = '';
636        str = 'Lrubuffer[ maxSize = ' + this.maxSize + ', hits = ' + this.hitCount + ', misses = ' + this.missCount
637            + ', hitRate = ' + hitRate + '% ]';
638        return str;
639    }
640
641    public values() : Object[]
642    {
643        let arr : Array<Object> = [];
644        for(let value of this.cache.values()) {
645            arr.push(value);
646        }
647        return arr;
648    }
649
650    public keys() : Object[]
651    {
652        let arr : Array<Object> = [];
653        for(let key of this.cache.keys()) {
654            arr.push(key);
655        }
656        return arr;
657    }
658
659    protected afterRemoval(isEvict : boolean, key : Object | undefined | null, value : Object | undefined | null,
660                           newValue : Object | undefined | null) : void
661    {
662
663    }
664
665    protected createDefault(key : Object) : Object
666    {
667        return undefined;
668    }
669
670    public entries() : IterableIterator<[Object, Object]>
671    {
672        return this.cache.entries();
673    }
674
675    public [Symbol.iterator] () : IterableIterator<[Object, Object]>
676    {
677        return this.cache.entries();
678    }
679
680    private changeCapacity(newCapacity : number) : void
681    {
682        while(this.cache.size >newCapacity) {
683            this.cache.delete(this.cache.keys().next().value);
684            this.evictionCount++;
685            this.afterRemoval(true, this.cache.keys(), this.cache.values(), null);
686        }
687    }
688}
689
690class RationalNumber
691{
692    private mnum : number = 0;
693    private mden : number = 0;
694    public constructor(num : number, den : number)
695    {
696        num = den < 0 ?  num * (-1) : num;
697        den = den < 0 ?  den * (-1) : den;
698        if (den === 0) {
699            if (num > 0) {
700                this.mnum = 1;
701                this.mden = 0;
702            } else if (num < 0) {
703                this.mnum = -1;
704                this.mden = 0;
705            } else {
706                this.mnum = 0;
707                this.mden = 0;
708            }
709        } else if (num === 0) {
710            this.mnum = 0;
711            this.mden = 1;
712        } else {
713            let gnum : number = 0;
714            gnum = this.getCommonDivisor(num, den);
715            if (gnum !== 0) {
716                this.mnum = num / gnum;
717                this.mden = den / gnum;
718            }
719        }
720    }
721
722    public createRationalFromString(str : string): RationalNumber
723    {
724        if (str === null) {
725            throw new Error('string invalid!');
726        }
727        if (str === 'NaN') {
728            return new RationalNumber(0, 0);
729        }
730        let colon : number = str.indexOf(':');
731        let semicolon : number = str.indexOf('/');
732        if ((colon < 0 && semicolon < 0) || (colon > 0 && semicolon > 0)) {
733            throw new Error('string invalid!');
734        }
735        let index : number = (colon > 0) ? colon : semicolon;
736        let s1 : string = str.substr(0, index);
737        let s2 : string = str.substr(index + 1, str.length);
738        let num1 : number = Number(s1);
739        let num2 : number = Number(s2);
740        return new RationalNumber(num1, num2);
741    }
742
743    public compareTo(other : RationalNumber) : number
744    {
745        if (this.mnum === other.mnum && this.mden === other.mden) {
746            return 0;
747        } else if (this.mnum === 0 && this.mden === 0) {
748            return 1;
749        } else if ((other.mnum === 0) && (other.mden === 0)) {
750            return -1;
751        } else if ((this.mden === 0 && this.mnum > 0) || (other.mden === 0 && other.mnum < 0)) {
752            return 1;
753        } else if ((this.mden === 0 && this.mnum < 0) || (other.mden === 0 && other.mnum > 0)) {
754            return -1;
755        }
756        let thisnum : number = this.mnum * other.mden;
757        let othernum : number = other.mnum * this.mden;
758        if (thisnum < othernum) {
759            return -1;
760        } else if (thisnum > othernum) {
761            return 1;
762        } else {
763            return 0;
764        }
765    }
766
767    public equals(obj : object) :boolean
768    {
769        if (!(obj instanceof RationalNumber)) {
770            return false;
771        }
772        let thisnum : number = this.mnum * obj.mden;
773        let objnum : number = obj.mnum * this.mden;
774        if (this.mnum === obj.mnum && this.mden === obj.mden) {
775            return true;
776        } else if ((thisnum === objnum) && (this.mnum !== 0 && this.mden !== 0) && (obj.mnum !== 0 && obj.mden !== 0)) {
777            return true;
778        } else if ((this.mnum === 0 && this.mden !== 0) && (obj.mnum === 0 && obj.mden !== 0)) {
779            return true;
780        } else if ((this.mnum > 0 && this.mden === 0) && (obj.mnum > 0 && obj.mden === 0)) {
781            return true;
782        } else if ((this.mnum < 0 && this.mden === 0) && (obj.mnum < 0 && obj.mden === 0)) {
783            return true;
784        } else {
785            return false;
786        }
787    }
788
789    public valueOf() : number
790    {
791        if (this.mnum > 0 && this.mden === 0) {
792            return Number.POSITIVE_INFINITY;
793        } else if (this.mnum < 0 && this.mden === 0) {
794            return Number.NEGATIVE_INFINITY;
795        } else if ((this.mnum === 0) && (this.mden === 0)) {
796            return Number.NaN;
797        } else {
798            return this.mnum / this.mden;
799        }
800    }
801
802    public getCommonDivisor(number1 : number, number2 : number) : number
803    {
804        if (number1 === 0 || number2 === 0) {
805            throw new Error('Parameter cannot be zero!');
806        }
807        let temp : number = 0;
808        if (number1 < number2) {
809            temp = number1;
810            number1 = number2;
811            number2 = temp;
812        }
813        while (number1 % number2 !== 0) {
814            temp = number1 % number2;
815            number1 = number2;
816            number2 = temp;
817        }
818        return number2;
819    }
820
821    public getDenominator() :number
822    {
823        return this.mden;
824    }
825
826    public getNumerator() : number
827    {
828        return this.mnum;
829    }
830
831    public isFinite() : boolean
832    {
833        return this.mden !== 0;
834    }
835
836    public isNaN() : boolean
837    {
838        return this.mnum === 0 && this.mden === 0;
839    }
840
841    public isZero() : boolean
842    {
843        return this.mnum === 0 && this.mden !== 0;
844    }
845
846    public toString() : string
847    {
848        let buf : string;
849        if (this.mnum === 0 && this.mden === 0) {
850            buf = 'NaN';
851        } else if (this.mnum > 0 && this.mden === 0) {
852            buf = 'Infinity';
853        } else if (this.mnum < 0 && this.mden === 0) {
854            buf = '-Infinity';
855        } else {
856            buf = String(this.mnum) + '/' + String(this.mden);
857        }
858        return buf;
859    }
860}
861
862interface ScopeComparable {
863    compareTo(other: ScopeComparable): boolean;
864}
865
866type ScopeType = ScopeComparable;
867
868class Scope {
869    private readonly _lowerLimit: ScopeType;
870    private readonly _upperLimit: ScopeType;
871
872    public constructor(readonly lowerObj: ScopeType, readonly upperObj: ScopeType) {
873        this.checkNull(lowerObj, 'lower limit not be null');
874        this.checkNull(upperObj, 'upper limit not be null');
875
876        if(lowerObj.compareTo(upperObj)) {
877            throw new Error('lower limit must be less than or equal to upper limit');
878        }
879        this._lowerLimit = lowerObj;
880        this._upperLimit = upperObj;
881    }
882
883    public getLower(): ScopeType {
884        return this._lowerLimit;
885    }
886
887    public getUpper(): ScopeType {
888        return this._upperLimit;
889    }
890
891    public compareTo(): boolean {
892        return false;
893    }
894
895    public contains(value: ScopeType): boolean;
896    public contains(scope: Scope): boolean;
897    public contains(x: Scope|ScopeType): boolean {
898        let resLower: boolean;
899        let resUpper: boolean;
900        this.checkNull(x, 'value must not be null');
901        if (x instanceof Scope) {
902            resLower= x._lowerLimit.compareTo(this._lowerLimit);
903            resUpper= this._upperLimit.compareTo(x._upperLimit);
904        } else {
905            resLower= x.compareTo(this._lowerLimit);
906            resUpper= this._upperLimit.compareTo(x);
907        }
908        return resLower && resUpper;
909    }
910
911    public clamp(value: ScopeType): ScopeType {
912        this.checkNull(value, 'value must not be null');
913
914        if (!value.compareTo(this._lowerLimit)) {
915            return this._lowerLimit;
916        } else if (value.compareTo(this._upperLimit)) {
917            return this._upperLimit;
918        } else {
919            return value;
920        }
921    }
922
923    public intersect(scope: Scope): Scope;
924    public intersect(lowerObj: ScopeType, upperObj: ScopeType): Scope;
925    public intersect(x: Scope, y?: Scope|ScopeType): Scope {
926        let reLower: boolean;
927        let reUpper: boolean;
928        let mLower: ScopeType;
929        let mUpper: ScopeType;
930        if (y) {
931            this.checkNull(x, 'lower limit must not be null');
932            this.checkNull(y, 'upper limit must not be null');
933            reLower = this._lowerLimit.compareTo(x);
934            reUpper = y.compareTo(this._upperLimit);
935            if (reLower && reUpper) {
936                return this;
937            } else {
938            mLower = reLower ? this._lowerLimit : x;
939            mUpper = reUpper ? this._upperLimit : y;
940            return new Scope(mLower, mUpper);
941            }
942        } else {
943            this.checkNull(x, 'scope must not be null');
944            reLower = this._lowerLimit.compareTo(x._lowerLimit);
945            reUpper = x._upperLimit.compareTo(this._upperLimit);
946            if (!reLower && !reUpper) {
947                return x;
948            } else if (reLower && reUpper) {
949                return this;
950            } else {
951                mLower = reLower ? this._lowerLimit : x._lowerLimit;
952                mUpper = reUpper ? this._upperLimit : x._upperLimit;
953                return new Scope(mLower, mUpper);
954           }
955        }
956    }
957
958    public expand(obj: ScopeType): Scope;
959    public expand(scope: Scope): Scope;
960    public expand(lowerObj: ScopeType, upperObj: ScopeType): Scope;
961    public expand(x: ScopeType, y?: ScopeType): Scope {
962        let reLower: boolean;
963        let reUpper: boolean;
964        let mLower: ScopeType;
965        let mUpper: ScopeType;
966        if (!y) {
967            this.checkNull(x, 'value must not be null');
968            if (!(x instanceof Scope)) {
969                this.checkNull(x, 'value must not be null');
970                return this.expand(x, x);
971            }
972            reLower = x._lowerLimit.compareTo(this._lowerLimit);
973            reUpper = this._upperLimit.compareTo(x._upperLimit);
974            if (reLower && reUpper) {
975                 return this;
976            } else if (!reLower && !reUpper) {
977                 return x;
978            } else {
979                mLower = reLower ? this._lowerLimit : x._lowerLimit;
980                mUpper = reUpper ? this._upperLimit : x._upperLimit;
981                return new Scope(mLower, mUpper);
982            }
983
984        } else {
985            this.checkNull(x, 'lower limit must not be null');
986            this.checkNull(y, 'upper limit must not be null');
987            reLower = x.compareTo(this._lowerLimit);
988            reUpper = this._upperLimit.compareTo(y);
989            if (reLower && reUpper) {
990                return this;
991            }
992            mLower = reLower ? this._lowerLimit : x;
993            mUpper = reUpper ? this._upperLimit : y;
994            return new Scope(mLower, mUpper);
995        }
996    }
997
998    public toString(): string {
999        let strLower : string = this._lowerLimit.toString();
1000        let strUpper : string = this._upperLimit.toString();
1001        return `[${strLower}, ${strUpper}]`;
1002    }
1003
1004    public checkNull(o: ScopeType, str: string): void {
1005        if (o === null) {
1006            throw new Error(str);
1007        }
1008    }
1009}
1010
1011export default {
1012    printf: printf,
1013    getErrorString: getErrorString,
1014    callbackWrapper: callbackWrapper,
1015    promiseWrapper: promiseWrapper,
1016    createExternalType: createExternalType,
1017    TextEncoder: TextEncoder,
1018    TextDecoder: TextDecoder,
1019    Base64: Base64,
1020    types: Types,
1021    LruBuffer: LruBuffer,
1022    RationalNumber : RationalNumber,
1023    Scope : Scope,
1024};
1025