UNPKG

phpjs

Version:

php.js offers community built php functions in javascript

297 lines (258 loc) 7.17 kB
/** * BC Math Library for Javascript * Ported from the PHP5 bcmath extension source code, * which uses the libbcmath package... * Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc. * Copyright (C) 2000 Philip A. Nelson * The Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA. * e-mail: philnelson@acm.org * us-mail: Philip A. Nelson * Computer Science Department, 9062 * Western Washington University * Bellingham, WA 98226-9062 * * bcmath-js homepage: * * This code is covered under the LGPL licence, and can be used however you want :) * Be kind and share any decent code changes. */ var libbcmath = { PLUS: '+', MINUS: '-', BASE: 10, // must be 10 (for now) scale: 0, // default scale /** * Basic number structure */ bc_num: function() { this.n_sign = null; // sign this.n_len = null; /* (int) The number of digits before the decimal point. */ this.n_scale = null; /* (int) The number of digits after the decimal point. */ //this.n_refs = null; /* (int) The number of pointers to this number. */ //this.n_text = null; /* ?? Linked list for available list. */ this.n_value = null; /* array as value, where 1.23 = [1,2,3] */ this.toString = function() { var r, tmp; tmp = this.n_value.join(''); // add minus sign (if applicable) then add the integer part r = ((this.n_sign == libbcmath.PLUS) ? '' : this.n_sign) + tmp.substr(0, this.n_len); // if decimal places, add a . and the decimal part if (this.n_scale > 0) { r += '.' + tmp.substr(this.n_len, this.n_scale); } return r; }; }, /** * @param int length * @param int scale * @return bc_num */ bc_new_num: function(length, scale) { var temp; // bc_num temp = new libbcmath.bc_num(); temp.n_sign = libbcmath.PLUS; temp.n_len = length; temp.n_scale = scale; temp.n_value = libbcmath.safe_emalloc(1, length + scale, 0); libbcmath.memset(temp.n_value, 0, 0, length + scale); return temp; }, safe_emalloc: function(size, len, extra) { return Array((size * len) + extra); }, /** * Create a new number */ bc_init_num: function() { return new libbcmath.bc_new_num(1, 0); }, _bc_rm_leading_zeros: function(num) { /* We can move n_value to point to the first non zero digit! */ while ((num.n_value[0] === 0) && (num.n_len > 1)) { num.n_value.shift(); num.n_len--; } }, /** * Convert to bc_num detecting scale */ php_str2num: function(str) { var p; p = str.indexOf('.'); if (p == -1) { return libbcmath.bc_str2num(str, 0); } else { return libbcmath.bc_str2num(str, (str.length - p)); } }, CH_VAL: function(c) { return c - '0'; //?? }, BCD_CHAR: function(d) { return d + '0'; // ?? }, isdigit: function(c) { return (isNaN(parseInt(c, 10)) ? false : true); }, bc_str2num: function(str_in, scale) { var str, num, ptr, digits, strscale, zero_int, nptr; // remove any non-expected characters /* Check for valid number and count digits. */ str = str_in.split(''); // convert to array ptr = 0; // str digits = 0; strscale = 0; zero_int = false; if ((str[ptr] === '+') || (str[ptr] === '-')) { ptr++; /* Sign */ } while (str[ptr] === '0') { ptr++; /* Skip leading zeros. */ } //while (libbcmath.isdigit(str[ptr])) { while ((str[ptr]) % 1 === 0) { //libbcmath.isdigit(str[ptr])) { ptr++; digits++; /* digits */ } if (str[ptr] === '.') { ptr++; /* decimal point */ } //while (libbcmath.isdigit(str[ptr])) { while ((str[ptr]) % 1 === 0) { //libbcmath.isdigit(str[ptr])) { ptr++; strscale++; /* digits */ } if ((str[ptr]) || (digits + strscale === 0)) { // invalid number, return 0 return libbcmath.bc_init_num(); //*num = bc_copy_num (BCG(_zero_)); } /* Adjust numbers and allocate storage and initialize fields. */ strscale = libbcmath.MIN(strscale, scale); if (digits === 0) { zero_int = true; digits = 1; } num = libbcmath.bc_new_num(digits, strscale); /* Build the whole number. */ ptr = 0; // str if (str[ptr] === '-') { num.n_sign = libbcmath.MINUS; //(*num)->n_sign = MINUS; ptr++; } else { num.n_sign = libbcmath.PLUS; //(*num)->n_sign = PLUS; if (str[ptr] === '+') { ptr++; } } while (str[ptr] === '0') { ptr++; /* Skip leading zeros. */ } nptr = 0; //(*num)->n_value; if (zero_int) { num.n_value[nptr++] = 0; digits = 0; } for (; digits > 0; digits--) { num.n_value[nptr++] = libbcmath.CH_VAL(str[ptr++]); //*nptr++ = CH_VAL(*ptr++); } /* Build the fractional part. */ if (strscale > 0) { ptr++; /* skip the decimal point! */ for (; strscale > 0; strscale--) { num.n_value[nptr++] = libbcmath.CH_VAL(str[ptr++]); } } return num; }, cint: function(v) { if (typeof(v) == 'undefined') { v = 0; } var x = parseInt(v, 10); if (isNaN(x)) { x = 0; } return x; }, /** * Basic min function * @param int * @param int */ MIN: function(a, b) { return ((a > b) ? b : a); }, /** * Basic max function * @param int * @param int */ MAX: function(a, b) { return ((a > b) ? a : b); }, /** * Basic odd function * @param int * @param int */ ODD: function(a) { return (a & 1); }, /** * replicate c function * @param array return (by reference) * @param string char to fill * @param int length to fill */ memset: function(r, ptr, chr, len) { var i; for (i = 0; i < len; i++) { r[ptr + i] = chr; } }, /** * Replacement c function * Obviously can't work like c does, so we've added an "offset" param so you could do memcpy(dest+1, src, len) as memcpy(dest, 1, src, len) * Also only works on arrays */ memcpy: function(dest, ptr, src, srcptr, len) { var i; for (i = 0; i < len; i++) { dest[ptr + i] = src[srcptr + i]; } return true; }, /** * Determine if the number specified is zero or not * @param bc_num num number to check * @return boolean true when zero, false when not zero. */ bc_is_zero: function(num) { var count; // int var nptr; // int /* Quick check. */ //if (num == BCG(_zero_)) return TRUE; /* Initialize */ count = num.n_len + num.n_scale; nptr = 0; //num->n_value; /* The check */ while ((count > 0) && (num.n_value[nptr++] === 0)) { count--; } if (count !== 0) { return false; } else { return true; } }, bc_out_of_memory: function() { throw new Error('(BC) Out of memory'); } };