      1 ﻿
      2 /**
      3  * @name	CeL function for math
      4  * @fileoverview
      5  * 本檔案包含了數學相關的 functions。
      6  * @since
      7  */
      8
      9 /*
     10 TODO:
     11 大數計算
     12 方程式圖形顯示 by SVG
     13 */
     14
     15
     16 if (typeof CeL === 'function'){
     17
     18 /**
     19  * 本 module 之 name(id)，<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。
     20  * @type	String
     21  * @constant
     22  * @inner
     23  * @ignore
     24  */
     25 var module_name = 'math';
     26
     27 //===================================================
     28 /**
     29  * 若欲 include 整個 module 時，需囊括之 code。
     30  * @type	Function
     31  * @param	{Function} library_namespace	namespace of library
     32  * @param	load_arguments	呼叫時之 argument(s)
     33  * @return
     34  * @name	CeL.math
     35  * @constant
     36  * @inner
     37  * @ignore
     38  */
     39 var code_for_including = function(library_namespace, load_arguments) {
     40
     41 //	requires
     42 if (eval(library_namespace.use_function(
     43 		'data.split_String_to_Object')))
     44 	return;
     45
     46
     47 /**
     48  * null module constructor
     49  * @class	數學相關的 functions
     50  */
     51 CeL.math
     52 = function() {
     53 	//	null module constructor
     54 };
     55
     56 /**
     57  * for JSDT: 有 prototype 才會將之當作 Class
     58  */
     59 CeL.math
     60 .prototype = {
     61 };
     62
     63
     64
     65
     66
     67 /*
     68 	Math	---------------------------------------------------------------
     69 */
     70
     71 /*
     72 //{var v=Math.LN2,d=mutual_division(v),q=to_rational_number(v);alert('值	'+v+'\n序列	'+d+'\n近似值	'+q[0]+' / '+q[1]+'\n約	'+(q=q[0]/q[1])+'\n值-近似	'+(q-=v)+'\n差'+(Math.abs(q=10000*q/v)>1?'萬分之'+q.to_fixed(2)+' ( '+q+' / 10000 )':'億分之'+(q*=10000).to_fixed(2)+' ( '+q+' / 100000000 )'),0,'近似值	'+v);}
     73
     74 //{var d=new Date,a=.142857,b=1000000,i=0,c;for(i=0;i<10000;i++)c=mutual_division(a);alert(c+'\n'+gDate(new Date-d));}
     75 */
     76
     77 CeL.math
     78 .
     79 /**
     80  * 輾轉相除 n1/n2 或 小數 n1/1 轉成 整數/整數
     81  * @param {Number} n1	number 1
     82  * @param {Number} [n2]	number 2
     83  * @param {Number} times	max 次數, 1,2,..
     84  * @return	{Array}	連分數序列 ** 負數視 _.mutual_division.done 而定!
     85  */
     86 mutual_division = function mutual_division(n1, n2, times) {
     87 	var q = [], c;
     88 	if (isNaN(times) || times <= 0)
     89 		times = 80;
     90 	if (!n2 || isNaN(n2))
     91 		n2 = 1;
     92
     93 	if (n1 != Math.floor(n1)) {
     94 		c = n1;
     95 		var i = 9, f = n2;
     96 		while (i--)
     97 			//	以整數運算比較快！這樣會造成整數多4%，浮點數多1/3倍的時間，但仍值得。
     98 			if (f *= 10, c *= 10, c === Math.floor(c)) {
     99 				n1 = c, n2 = f;
    100 				break;
    101 			}
    102 	}
    103
    104 	//	連分數負數之處理。更沒問題的: (n1 < 0?1:0) ^ (n2 < 0?1:0)
    105 	if (_.mutual_division.mode && ((n1 < 0) ^ (n2 < 0))) {
    106 		// 使兩數皆為正
    107 		if (n2 < 0)
    108 			n2 = -n2;
    109 		else
    110 			n1 = -n1;
    111
    112 		q.push(-(1 + (n1 - (c = n1 % n2)) / n2));
    113 		n1 = n2, n2 -= c;
    114 	}
    115
    116 	/* old:
    117 	 while(b&&n--)
    118 	  d.push((a-(c=a%b))/b),a=b,b=c;	//	2.08s@10000	可能因為少設定（=）一次c所以較快。但（若輸入不為整數）不確保d為整數？用Math.floor((a-(c=a%b))/b)可確保，速度與下式一樣快。
    119 	  //d.push(c=Math.floor(a/b)),c=a-b*c,a=b,b=c;	//	2.14s@10000:mutual_division(.142857)
    120 	  //d.push(Math.floor(a/b)),b=a%(c=b),a=c;	//	2.2s@10000
    121 	 //if(n)d.push(0);
    122 	*/
    123
    124 	//	2.4s@10000	可能因為少設定（=）一次c所以較快。但（若輸入不為整數）不確保d為整數？用Math.floor((a-(c=a%b))/b)可確保，速度與下式一樣快。
    125 	while (times--)
    126 		if (n2)
    127 			q.push((n1 - (c = n1 % n2)) / n2), n1 = n2, n2 = c;
    128 		else {
    129 			//	[ .. , done mark, (最後非零的餘數。若原 n1, n2 皆為整數，則此值為 GCD。但請注意:這邊是已經經過前面為了以整數運算，增加倍率過的數值!!) ]
    130 			q.push(_.mutual_division.done, n1);
    131 			//library_namespace.debug('done: ' + q);
    132 			break;
    133 		}
    134
    135 	//	2.26s@10000
    136 	//while(b&&n--)if(d.push((a-(c=a%b))/b),a=b,!(b=c)){d.push(0);break;}
    137
    138 	//var m=1;c=1;while(m&&n--)d.push(m=++c%2?b?(a-(a%=b))/b:0:a?(b-(b%=a))/a:0);//bug
    139
    140 	return q;
    141 };
    142 CeL.math
    143 .
    144 mutual_division.done = -7;//''
    145
    146 CeL.math
    147 .
    148 /**
    149  * !!mode:連分數處理，對負數僅有最初一數為負。
    150  */
    151 mutual_division.mode = 0;
    152
    153 CeL.math
    154 .
    155 /**
    156  * 取得連分數序列的數值
    157  * @param {Array} sequence	序列
    158  * @param {Number} [max_no]	取至第 max_no 個
    159  * @requires	mutual_division.done
    160  * @return
    161  * @see
    162  * var a=continued_fraction([1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]);
    163  * alert(a+'\n'+a[0]/a[1]+'\n'+Math.SQRT2+'\n'+(Math.SQRT2-a[0]/a[1])+'\n'+mutual_division(a[0],a[1]));
    164  */
    165 continued_fraction = function(sequence, max_no) {
    166 	if (!library_namespace.is_Array(sequence) || !sequence.length)
    167 		return sequence;
    168
    169 	if (sequence[sequence.length - 2] === _.mutual_division.done)
    170 		sequence.length -= 2;
    171
    172 	if (sequence.length < 1)
    173 		return sequence;
    174
    175 	if (!max_no/* ||max_no<2 */|| max_no > sequence.length)
    176 		max_no = sequence.length;
    177
    178 	var a, b;
    179 	if (max_no % 2)
    180 		b = 1, a = 0;
    181 	else
    182 		a = 1, b = 0;
    183 	//sequence[max_no++]=1;if(--max_no%2)b=sequence[max_no],a=s[--max_no];else a=sequence[max_no],b=sequence[--max_no];
    184
    185 	//library_namespace.debug('a=' + a + ', b=' + b + ', max_no=' + max_no);
    186 	while (max_no--)
    187 		if (max_no % 2)
    188 			b += a * sequence[max_no];
    189 		else
    190 			a += b * sequence[max_no];
    191 	//library_namespace.debug('a=' + a + ', b=' + b);
    192 	return [ a, b ];
    193 };
    194
    195
    196 CeL.math
    197 .
    198 /**
    199  * The best rational approximation. 取得值最接近之有理數 (use 連分數 continued fraction), 取近似值.
    200  * c.f., 調日法
    201  * 在分子或分母小於下一個漸進分數的分數中，其值是最接近精確值的近似值。
    202  * @example
    203  * to_rational_number(4088/783)
    204  * @param {Number} number	number
    205  * @param {Number} [rate]	比例在 rate 以上
    206  * @param {Number} [max_no]	最多取至序列第 max_no 個
    207  * 					TODO : 並小於 l: limit
    208  * @return	[分子, 分母, 誤差]
    209  * @requires	mutual_division,continued_fraction
    210  * @see
    211  * http://en.wikipedia.org/wiki/Continued_fraction#Best_to_rational_numbers
    212  */
    213 to_rational_number = function(number, rate, max_no) {
    214 	if (!rate)
    215 		//	This is a magic number: 我們無法準確得知其界限為何。
    216 		rate = 65536;
    217 	var d = _.mutual_division(number, 1, max_no && max_no > 0 ? max_no : 20),
    218 	i = 0, a, b = d[0], done = _.mutual_division.done;
    219
    220 	if (!b)
    221 		b = d[++i];
    222 	while (++i < d.length && (a = d[i]) !== done)
    223 		if (a / b < rate)
    224 			b = a;
    225 		else
    226 			break;
    227
    228 	if(0)
    229 		library_namespace.debug(
    230 			number + ' ' +
    231 			//	連分數表示
    232 			(d.length > 1 && d[d.length - 2] === _.mutual_division.done ?
    233 				'=' + ' [<em>' + d[0] + ';' + d.slice(1, i).join(', ') + '</em>'
    234 					+ (i < d.length - 2 ? ', ' + d.slice(i, -2).join(', ') : '')
    235 					+ '] .. ' + d.slice(-1) :
    236 				//	約等於的符號是≈或≒，不等於的符號是≠。
    237 				//	http://zh.wikipedia.org/wiki/%E7%AD%89%E4%BA%8E
    238 				'≈' + ' [<em>' + d[0] + ';' + d.slice(1, i).join(', ') + '</em>'
    239 					+ (i < d.length ? ', ' + d.slice(i).join(', ') : '') + ']: '
    240 					+ d.length + ',' + i + ',' + d[i]
    241 			)
    242 		);
    243 	d = _.continued_fraction(d, i);
    244 	//library_namespace.debug('→ ' + d[0] + '/' + d[1]);
    245 	if (d[1] < 0)
    246 		d[0] = -d[0], d[1] = -d[1];
    247
    248 	return [ d[0], d[1], d[0] / d[1] - number ];
    249 };
    250
    251
    252 /*	最大公因數/公約數	 Greatest Common Divisor
    253
    254 usage:
    255 	gcd(6,9)
    256 	GCD([5,3,8,2,6,9])
    257 */
    258 //_gcd[generateCode.dLK]='mutual_division,mutual_division_done';
    259 function _gcd(a,b){
    260  if(isNaN(a)||isNaN(b))
    261   return isNaN(b)?a:b;
    262
    263  var d=_.mutual_division(a,b);
    264  a=d.pop();
    265  if(d.pop()===_.mutual_division.done)
    266   return a;
    267 }
    268
    269 CeL.math
    270 .
    271 /**
    272  * Get GCD of 2 numbers
    273  * @param n1	number 1
    274  * @param n2	number 2
    275  * @return	GCD of the 2 numbers
    276  */
    277 gcd = function(n1, n2) {
    278 	/*
    279 	if (isNaN(a))
    280 		return b;
    281 	*/
    282 	//	必要!
    283 	if (!n2 || isNaN(n2))
    284 		return n1;
    285
    286 	//	也可最後再 Math.abs
    287 	/*
    288 	if (a < 0)
    289 		a = -a;
    290 	if (b < 0)
    291 		b = -b;
    292 	*/
    293
    294 	//	Euclidean algorithm
    295 	var r;
    296 	while (r = n1 % n2)
    297 		n1 = n2, n2 = r;
    298 	return n2 < 0 ? -n2 : n2;
    299 };
    300
    301 //GCD[generateCode.dLK]='gcd';
    302 function GCD(numA){
    303  var i=1,g=numA[0];
    304  for(;i<numA.length;i++)
    305   if(!isNaN(numA[i]))
    306    g=gcd(g,numA[i]);
    307  return g;
    308 }
    309 /*	最小公倍數	 Least Common Multiple
    310
    311 usage:
    312 	lcm(6,9)
    313 	lcm([5,3,8,2,6,9])
    314
    315 TODO:
    316 更快的方法：
    317 短除法
    318 一次算出 GCD, LCM
    319 */
    320 //lcm[generateCode.dLK]='gcd';
    321 function lcm(a,b){
    322  var l,g,i=1;
    323  if( typeof a=='object' && !isNaN(l=a[0]) ){
    324   while(i<a.length)
    325    l=lcm(l,a[i++]);
    326   return l;
    327  }
    328
    329  if( (g=gcd(a,b)) && !isNaN(g) )
    330   return a/g*b;
    331 }
    332
    333
    334 /*
    335 http://www.math.umbc.edu/~campbell/NumbThy/Class/Programming/JavaScript.html
    336 http://aoki2.si.gunma-u.ac.jp/JavaScript/
    337 */
    338
    339 CeL.math
    340 .
    341 /**
    342  * 得到平方數，相當於 Math.floor(Math.sqrt(number)).
    343  * get integer square root
    344  * @param {Number} positive number
    345  * @return	r, r^2 <= number < (r+1)^2
    346  * @example
    347  * var p = 20374345, q = CeL.math.floor_sqrt(p = p * p - 1); CeL.log(q + '<br/>' + (q * q) + '<br/>' + p + '<br/>' + (++q * q));
    348  * @see
    349  * <a href="http://www.azillionmonkeys.com/qed/sqroot.html" accessdate="2010/3/11 18:37">Paul Hsieh's Square Root page</a>
    350  * <a href="http://www.embeddedrelated.com/usenet/embedded/show/114789-1.php" accessdate="2010/3/11 18:34">Suitable Integer Square Root Algorithm for 32-64-Bit Integers on Inexpensive Microcontroller? | Comp.Arch.Embedded | EmbeddedRelated.com</a>
    351  */
    352 floor_sqrt = function(number){
    353 	if (isNaN(number = Math.floor(number)))
    354 		return;
    355 	var g = 0, v, h, t;
    356 	while ((t = g << 1) < (v = number - g * g)) {
    357 		//library_namespace.debug(t + ', ' + v);
    358 		h = 1;
    359 		while (h * (h + t) <= v)
    360 			// 因為型別轉關係，還是保留 << 而不用 *2
    361 			h <<= 1;//h *= 2;
    362 		g += h >> 1;//h / 2;//
    363 	}
    364 	//library_namespace.debug('end: ' + t + ', ' + v);
    365 	return g;
    366 };
    367
    368
    369 CeL.math
    370 .
    371 /**
    372  * 取得某數的質因數，因式分解/素因子分解, factorization, get floor factor.
    373  * 唯一分解定理(The Unique Factorization Theorem)告訴我們素因子分解是唯一的，這即是稱為算術基本定理 (The Fundamental Theorem of Arithmeric) 的數學金科玉律。
    374  * @param {Number} number
    375  * @return	{Array} [prime1,power1,prime2,power2,..]
    376  * @see
    377  * <a href="http://homepage2.nifty.com/m_kamada/math/10001.htm" accessdate="2010/3/11 18:7">Factorizations of 100...001</a>
    378  * @requires	floor_sqrt
    379  */
    380 factorization = function(number) {
    381 	var f = 2, p, a, l, r = [];
    382 	if (isNaN(number) || number < 1 || number >
    383 			/*
    384 			 * javascript 可以表示的最大整數值
    385 			 * 10^21-2^16-1 = 999999999999999934463
    386 			 * @see
    387 			 * http://www.highdots.com/forums/javascript/how-js-numbers-represented-internally-166538-4.html
    388 			 */
    389 			999999999999999934469)
    390 		return;
    391 	number = Math.floor(number);
    392
    393 	// 2,3
    394 	while (number > 1) {
    395 		if (number % f === 0) {
    396 			p = 0;
    397 			do
    398 				number /= f, p++;
    399 			while (number % f === 0); // do{n/=f,p++;}while(n%f==0);
    400 			r.push(f, p);
    401 		}
    402 		if (++f > 3)
    403 			break;
    404 	}
    405
    406 	a = 4, f = 5, l = _.floor_sqrt(number); // 5-初始化
    407 	while (number > 1) {
    408 		if (f > l) {
    409 			r.push(number, 1);
    410 			break;
    411 		}
    412 		// document.write('<br/>'+f+','+n);
    413 		if (number % f === 0) {
    414 			p = 0;
    415 			do {
    416 				number /= f, p++;
    417 			} while (number % f === 0);
    418 			l = _.floor_sqrt(number), r.push(f, p);
    419 		}
    420 		f += a = a === 2 ? 4 : 2;
    421 	}
    422 	return r;
    423 };
    424
    425 /*	test
    426 function count(n){
    427 var a=factorization(n),s='',v=1;
    428 if(a){
    429  for(var i=0;i<a.length;i+=2){s+='*'+a[i]+(a[i+1]>1?'^'+a[i+1]:'');v*=Math.pow(a[i],a[i+1]);}
    430  s=s.substr(1)+'='+v+'='+n;
    431 }else s='error! '+n;
    432 document.getElementById('result').value+=s+'\n-------------------------------------------\n';
    433 }
    434 */
    435
    436
    437 /*	猜測一個數可能的次方數。	2005/2/18 19:20未完成
    438 	type=0:整數,1:有理數
    439 	return [base分子,base分母,exponent分子,exponent分母]
    440 */
    441 function to_exponent(num,type){
    442  var bn,bd,en=1,ed,sq=[1,num],t,q,error=1e-9,g=function(n){q=_.to_rational_number(n,99999);if((!type||q[1]==1)&&!(q[0]>99999&&q[1]>99999)&&q[2]/n<error)bn=q[0],bd=q[1],ed=t;};//error:誤差
    443
    444  if(!ed)g(sq[t=1]);
    445  if(!ed)g(sq[t=2]=sq[1]*sq[1]);
    446  if(!ed)g(sq[t=3]=sq[1]*sq[2]);
    447  if(!ed)g(sq[t=4]=sq[2]*sq[2]);
    448  if(!ed)g(sq[t=5]=sq[2]*sq[3]);
    449  if(!ed)bn=num,bd=ed=1;
    450
    451  return [bn,bd,en,ed];
    452 }
    453 //var t=to_exponent(Math.pow(2/3,1/1));alert(t[0]+'/'+t[1]+'^'+t[2]+'/'+t[3]);
    454
    455
    456
    457
    458 /*
    459 for 出題
    460
    461 runCode.setR=0;
    462 for(var i=0,j,t,s,n_e;i<10;){
    463  t=2000+8000*Math.random();
    464  s=get_random_prime.get_different_number_set(3,t,t/8);
    465  if(s.LCM>9999)continue;
    466  n_e=[];
    467  n_e[s.GCD]=1;
    468  for(j=0;j<s.length;j++)
    469   if(n_e[s[j]])continue;
    470   else n_e[s[j]]=1;
    471  sl([s.GCD,s.LCM]+'<b style="color:#c4a">;</b> '+s);i++;
    472 }
    473
    474 */
    475
    476 //	求乘積
    477 function get_product(nums,till){	//	num array, 乘到比till小就回傳
    478  var p=1,i=0,l=nums.length;
    479  for(;i<l;i++){
    480   if(till&&p*nums[i]>till)break;
    481   p*=nums[i];
    482  }
    483  return p;
    484 }
    485
    486
    487 //	2009/10/21 11:57:47
    488 //get_random_prime[generateCode.dLK]='get_product';
    489 get_random_prime.primes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
    490 function get_random_prime(count,exclude,all_different){	//	個數, 排除
    491  var _f=arguments.callee,i,j,p=[],l;
    492  if(!count||count<1)count=1;
    493  if(!_f.excluded)
    494   _f.excluded=[];
    495  if(exclude)exclude=[];
    496
    497  for(j=0;j<count;j++){
    498   l=80;	//	timeout
    499   do{
    500    i=Math.round(10*Math.tan(Math.random()*1.5));
    501    if(!--l)return;	//	timeout
    502   }while(_f.excluded[i]);
    503   p.push(_f.primes[i]);
    504   if(exclude)exclude.push(i);
    505  }
    506
    507  //	選完才排除本次選的
    508  if(exclude)
    509   for(j=0,l=exclude.length;j<l;j++){
    510    i=exclude[j];
    511    if(_f.excluded[i])_f.excluded[i]++;
    512    else _f.excluded[i]=1;
    513   }
    514
    515  return count==1?p[0]:p;
    516 }
    517
    518 //	return [GCD, n1, n2, ..]
    519 get_random_prime.get_different_number_set=function(count,till,GCD_till){
    520  delete this.excluded;
    521  if(!GCD_till)GCD_till=1e5;
    522  if(!till)till=1e5;
    523
    524  var GCD=get_product(this(20,1),GCD_till),na=[],n_e=[],n,i=0,out;
    525  n_e[GCD]=1;
    526
    527  for(;i<count;i++){
    528   out=80;	//	timeout
    529   do{
    530    n=this(20);
    531    n.unshift(GCD);
    532    n=get_product(n,till);
    533   }while(n_e[n]&&--out);
    534   n_e[n]=1;
    535   na.push(n);
    536  }
    537
    538  if(typeof lcm=='function')
    539   na.LCM=lcm(na);
    540  na.GCD=GCD;
    541  return na;
    542 };
    543
    544
    545
    546 CeL.math
    547 .
    548 /**
    549  * VBScript has a Hex() function but JScript does not.
    550  * @param {Number} number
    551  * @return	{String} number in hex
    552  * @example
    553  * alert('0x'+CeL.hex(16725))
    554  */
    555 hex = function(number) {
    556 	return (number < 0 ? number + 0x100000000 : number - 0).toString(16);
    557 }
    558
    559 CeL.math
    560 .
    561 /**
    562  * 補數計算。
    563  * 正數的補數即為自身。若要求得互補之後的數字，請設成負數。
    564  * @param {Number} number
    565  * @return	{Number} base	1: 1's Complement, 2: 2's Complement, (TODO: 3, 4, ..)
    566  * @example
    567  * alert(complement())
    568  * @see
    569  * http://www.tomzap.com/notes/DigitalSystemsEngEE316/1sAnd2sComplement.pdf
    570  * http://en.wikipedia.org/wiki/Method_of_complements
    571  * http://en.wikipedia.org/wiki/Signed_number_representations
    572  * @since	2010/3/12 23:47:52
    573  */
    574 complement = function() {
    575 	return this.from.apply(this, arguments);
    576 };
    577
    578 _.complement.prototype = {
    579
    580 base : 2,
    581
    582 //	1,2,..
    583 bits : 8,
    584
    585 //	radix complement or diminished radix complement.
    586 //	http://en.wikipedia.org/wiki/Method_of_complements
    587 diminished : 0,
    588
    589 /**
    590  * 正負符號.
    591  * 正: 0/false,
    592  * 負 negative value:!=0 / true
    593  */
    594 sign : 0,
    595
    596 //	get the value
    597 valueOf : function() {
    598 	return this.sign ? -this.value : this.value;
    599 },
    600
    601 /**
    602  * set value
    603  */
    604 set : function(value) {
    605 	var m = Number(value), a = Math.abs(m);
    606 	if (isNaN(m) || m && a < 1e-8 || a > 1e12){
    607 		library_namespace.debug('complement.set: error number: ' + value);
    608 		return;
    609 	}
    610
    611 	this.sign = m < 0;
    612 	// this.value 僅有正值
    613 	this.value = a;
    614
    615 	return this;
    616 },
    617
    618
    619 /**
    620  * input
    621  */
    622 from : function(number, base, diminished) {
    623 	//	正規化
    624 	number = ('' + (number||0)).replace(/\s+$|^[\s0]+/g, '') || '0';
    625 	//library_namespace.debug(number + ':' + number.length + ',' + this.bits);
    626
    627 	//	整數部分位數
    628 	var value = number.indexOf('.'), tmp;
    629 	if (value == -1)
    630 		value = number.length;
    631 	//	TODO: not good
    632 	if (value > this.bits)
    633 		//throw 'overflow';
    634 		library_namespace.err('complement.from: overflow: ' + value);
    635
    636 	if (typeof diminished === 'undefined')
    637 		//	illegal setup
    638 		diminished = this.diminished;
    639 	else
    640 		this.diminished = diminished;
    641
    642 	if ((base = Math.floor(base)) && base > 0){
    643 		if (base === 1)
    644 			base = 2, this.diminished = 1;
    645 		this.base = base;
    646 	}else
    647 		//	illegal base
    648 		base = this.base;
    649 	//library_namespace.debug(base + "'s Complement");
    650
    651 	//	TODO: 僅對 integer 有效
    652 	value = parseInt(number, base);
    653 	tmp = Math.pow(base, this.bits - 1);
    654 	if (value >= tmp * base)
    655 		//throw 'overflow';
    656 		library_namespace.err('complement.from: overflow: ' + value);
    657
    658 	//library_namespace.debug('compare ' + value + ',' + tmp);
    659 	if (value < tmp)
    660 		this.sign = 0;
    661 	else
    662 		//library_namespace.debug('負數 ' + (tmp * base - (diminished ? 1 : 0)) + '-'+ value+'='+(tmp * base - (diminished ? 1 : 0) - value)),
    663 		this.sign = 1,
    664 		value = tmp * base - (diminished ? 1 : 0) - value;
    665
    666 	this.value = value;
    667 	//library_namespace.debug(number + ' → '+this.valueOf());
    668
    669 	return this;
    670 },
    671
    672 /**
    673  * output
    674  */
    675 to : function(base, diminished) {
    676 	if (!(base = Math.floor(base)) || base < 1)
    677 		base = this.base;
    678 	else if (base === 1)
    679 		base = 2, diminished = 1;
    680 	if (typeof diminished === 'undefined')
    681 		diminished = this.diminished;
    682
    683 	var value = this.value, tmp = Math.pow(base, this.bits - 1);
    684 	if (value > tmp || value === tmp && (diminished || !this.sign))
    685 		//throw 'overflow';
    686 		library_namespace.err('complement.to: overflow: ' + (this.sign ? '-' : '+') + value);
    687
    688 	if (this.sign){
    689 		tmp *= base;
    690 		if (diminished)
    691 			//	TODO: 僅對 integer 有效
    692 			tmp--;
    693 		//library_namespace.debug('負數 ' + value + '，sum=' + tmp);
    694 		// 負數，添上兩補數之和
    695 		value = tmp - value;
    696 	}
    697
    698 	//library_namespace.debug('value: ' + (this.sign ? '-' : '+') + value);
    699
    700 	value = value.toString(Math.max(2, this.base));
    701
    702 	return value;
    703 }
    704
    705 };
    706
    707 _.complement.prototype.toString = _.complement.prototype.to;
    708
    709
    710 /*
    711 	↑Math	---------------------------------------------------------------
    712 */
    713
    714
    715 return (
    716 	CeL.math
    717 );
    718 };
    719
    720 //============================================================================
    721
    722 CeL.setup_module(module_name, code_for_including);
    723
    724 };
    725