1 /*
  2  * Copyright (C) 2012-2013 たかはしのんき. All rights reserved.
  3  *
  4  * History:
  5  *  0.6 2013-06-15 JsDoc Toolkit対応。
  6  *  0.5 2013-03-16 行ベクトルを  BMatrix としてサポート。
  7  *  0.4 2012-05-17 メソッド  getValue, cross の性能改善。
  8  *  0.3 2012-05-15 初期値の設定方法 2.を追加。prototype 設定の記法を変更。
  9  *  0.2 2012-05-10 メソッド  abs, inv, equals, diff, xor, mul, dot, cross, toTeX の追加。
 10  *  0.1 2012-05-10 新規作成。Java 版より移植。
 11  */
 12 
 13 /**
 14  * @fileOverview BVector - 2進ベクトルオブジェクトの定義
 15  * @version 0.6
 16  * @author たかはしのんき
 17  * 
 18  */
 19 
 20 // ビット操作のためのマスクを定義します。
 21 var mask = [
 22 	0x80000000, 0x40000000, 0x20000000, 0x10000000,
 23 	0x08000000, 0x04000000, 0x02000000, 0x01000000,
 24 	0x00800000, 0x00400000, 0x00200000, 0x00100000,
 25 	0x00080000, 0x00040000, 0x00020000, 0x00010000,
 26 	0x00008000, 0x00004000, 0x00002000, 0x00001000,
 27 	0x00000800, 0x00000400, 0x00000200, 0x00000100,
 28 	0x00000080, 0x00000040, 0x00000020, 0x00000010,
 29 	0x00000008, 0x00000004, 0x00000002, 0x00000001
 30 	];
 31 
 32 /**
 33  * 2進ベクトルオブジェクト BVector を定義します。
 34  * 1. bv = new BVector(4);				// 次数 4 の2進ベクトル、初期値は (0, 0, 0, 0)
 35  * 2. bv = new BVector(4, 1);			// 次数 4 の2進ベクトル、初期値は (1, 1, 1, 1)
 36  * 3. bv = new BVector(1, 0, 1, 0);		// 次数 4 の2進ベクトル、初期値は (1, 0, 1, 0)
 37  * @constructor
 38  * @this {BVector}
 39  * @since 0.1
 40  */
 41 BVector = function() {
 42 	this.order = arguments.length;
 43 	if (arguments.length == 1)
 44 		this.order = arguments[0];
 45 	if (arguments.length == 2 && arguments[0] > 1)
 46 		this.order = arguments[0];
 47 	this.bits = new Array(Math.ceil(this.order / 32.0));
 48 	if (arguments.length == 1)
 49 		this.clear();
 50 	else if (arguments.length == 2 && arguments[0] > 1 && arguments[1] == 1)
 51 		for (var i = 1; i <= this.order; i++)
 52 			this.setValue(i, 1);
 53 	else
 54 		for (var i = 1; i <= this.order; i++)
 55 			if (arguments[i - 1])
 56 				this.setValue(i, 1);
 57 };
 58 
 59 BVector.prototype = {
 60 
 61 	/**
 62 	 * 2進ベクトルをゼロクリアします。
 63 	 * @since 0.2
 64 	 */
 65 	clear : function() {
 66 		for (var i = 0; i < this.bits.length; i++)
 67 			this.bits[i] = 0;
 68 	},
 69 
 70 	/**
 71 	 * 2進ベクトルオブジェクト BVector の要素 i に 0 か 1 の value を設定するメソッド
 72 	 * BVector.setValue(i, value) を定義します。
 73 	 * @param i 要素番号
 74 	 * @param value 設定する値
 75 	 * @since 0.1
 76 	 */
 77 	setValue : function(i, value) {
 78 		var i0 = i - 1;		// 0 originに変換
 79 		var i1 = i0 & 0x1F;	// 32 の剰余
 80 		var i2 = i0 >> 5;	// 32 の商
 81 		if (value == 1)
 82 			this.bits[i2] |= mask[i1];
 83 		else if (value == 0)
 84 			this.bits[i2] &= ~mask[i1];
 85 	},
 86 
 87 	/**
 88 	 * 2進ベクトルオブジェクト BVector の要素 i の値を取り出すメソッド
 89 	 * BVector.getValue(i) を定義します。
 90 	 * @param i 要素番号
 91 	 * @return 値
 92 	 * @since 0.1
 93 	 */
 94 	getValue : function(i) {
 95 		var i0 = i - 1;		// 0 originに変換
 96 		// i0 & 0x1F は 32 の剰余
 97 		// i0 >> 5 は 32 の商
 98 		return (this.bits[i0 >> 5] & mask[i0 & 0x1F]) ? 1 : 0;
 99 	},
100 
101 	/**
102 	 * 2進ベクトルオブジェクト BVector をコピーするメソッド
103 	 * BVector.clone() を定義します。
104 	 * @return 2進ベクトルのコピーを返します。
105 	 * @since 0.1
106 	 */
107 	clone : function() {
108 		var bv = new BVector(this.order);
109 		for (var i = 0; i < this.bits.length; i++)
110 			bv.bits[i] = this.bits[i];
111 		return bv;
112 	},
113 
114 	/**
115 	 * 2進ベクトルの値が1の要素を数え上げます。
116 	 * @return 値が1の要素を数え上げた数を返します。
117 	 * @since 0.2
118 	 */
119 	abs : function() {
120 		var n = 0;
121 		for (var i = 1; i <= this.order; i++)
122 			if (this.getValue(i) == 1)
123 				n++;
124 		return n;
125 	},
126 
127 	/**
128 	 * 2進ベクトルを反転して(invert)返します。
129 	 * @return ベクトルの反転を返します。
130 	 * @since 0.2
131 	 */
132 	inv : function() {
133 		var bv = new BVector(this.order);
134 		var m1 = (this.order - 1) % 32;			// 剰余
135 		var mask1 = mask[m1];
136 		for (var mask2 = 0; mask1 != 0; mask1 <<= 1) {
137 			mask2 |= mask1;
138 			for (var i = 0; i < this.bits.length - 1; i++)
139 				bv.bits[i] = ~this.bits[i];
140 			bv.bits[i] = ~this.bits[i] & mask2;
141 		}
142 		return bv;
143 	},
144 
145 	/**
146 	 * 2進ベクトルを転置して(transpose)2進行列として返します。
147 	 * @return ベクトルの転置を返します。
148 	 * @since 0.5
149 	 */
150 	tran : function() {
151 		var bm = new BMatrix(1, this.order);
152 		for (var j = 1; j <= this.order; j++)
153 			bm.setValue(1, j, this.getValue(j));
154 		return bm;
155 	},
156 
157 	/**
158 	 * 2つの2進ベクトルが等しければtrueを返します。同じでないかエラーの場合はfalseを返します。
159 	 * @param bv2 比較対象のベクトル
160 	 * @return 2つのベクトルが等しければtrueを返します。
161 	 * @since 0.2
162 	 */
163 	equals : function(bv2) {
164 		if (this.order != bv2.order)
165 			return false;				// 次元が異なる
166 		for (var i = 0; i < this.bits.length; i++)
167 			if (this.bits[i] != bv2.bits[i])
168 				return false;			// 値が異なる
169 		return true;
170 	},
171 
172 	/**
173 	 * 2進ベクトルオブジェクト bv2 との論理和をとるメソッド
174 	 * BVector.or(bv2) を定義します。
175 	 * @param bv2 論理和の第2オペランドを指定します。
176 	 * @return bv2 との論理和を返します。
177 	 * @since 0.1
178 	 */
179 	or : function(bv2) {
180 		if (this.order != bv2.order)
181 			return null;
182 		var bv = this.clone();
183 		for (var i = 0; i < this.bits.length; i++)
184 			bv.bits[i] |= bv2.bits[i];
185 		return bv;
186 	},	
187 
188 	/**
189 	 * 2進ベクトルオブジェクト bv2 との論理積をとるメソッド
190 	 * BVector.and(bv2) を定義します。
191 	 * @param bv2 論理積の第2オペランドを指定します。
192 	 * @return bv2 との論理積を返します。
193 	 * @since 0.1
194 	 */
195 	and : function(bv2) {
196 		if (this.order != bv2.order)
197 			return null;
198 		var bv = this.clone();
199 		for (var i = 0; i < this.bits.length; i++)
200 			bv.bits[i] &= bv2.bits[i];
201 		return bv;
202 	},	
203 
204 	/**
205 	 * 2進ベクトル同士の論理差を返します。エラーの場合はnullを返します。
206 	 * @param bv2 論理差の第2オペランド
207 	 * @return 2つのベクトルの論理差を返します。
208 	 * @since 0.2
209 	 */
210 	diff : function(bv2) {
211 		if (this.order != bv2.order)
212 			return null;
213 		var bv = this.clone();
214 		for (var i = 0; i < this.bits.length; i++)
215 			bv.bits[i] &= ~bv2.bits[i];
216 		return bv;
217 	},
218 
219 	/**
220 	 * 2進行列同士の排他的論理和を返します。エラーの場合はnullを返します。
221 	 * @param bv2 排他的論理和の第2オペランド
222 	 * @return 2つの行列の排他的論理和を返します。
223 	 * @since 0.2
224 	 */
225 	xor : function(bv2) {
226 		if (this.order != bv2.order)
227 			return null;
228 		var bv = this.clone();
229 		for (var i = 0; i < this.bits.length; i++)
230 			bv.bits[i] ^= bv2.bits[i];
231 		return bv;
232 	},
233 
234 	/**
235 	 * ベクトルとスカラ(0か1)の積を返します。エラーの場合はnullを返します。
236 	 * @param b2 積の第2オペランド
237 	 * @return ベクトルとスカラの積を返します。
238 	 * @since 0.2
239 	 */
240 	mul : function(b2) {
241 		if (b2 != 0 && b2 != 1)
242 			return null;
243 		var bv = new BVector(this.order);
244 		if (b2 == 0)
245 			return bv;	// 0 ベクトル
246 		else
247 			return this.clone();
248 	},
249 
250 	/**
251 	 * 2進ベクトル同士の積(ドット積)を返します。エラーの場合は-1を返します。
252 	 * @param bv2 積の第2オペランド
253 	 * @return 2つのベクトルのドット積を返します。
254 	 * @since 0.2
255 	 */
256 	dot : function(bv2) {
257 		if (this.order != bv2.order)
258 			return -1;
259 		var b = 0;
260 		for (var i = 1; i <= this.order; i++)
261 			b |= (this.getValue(i) & bv2.getValue(i));
262 		return b;
263 	},
264 
265 	/**
266 	 * 2進ベクトルと2進ベクトルの転置との積(クロス積)を返します。エラーの場合はnullを返します。
267 	 * @param bv2 積の第2オペランド
268 	 * @return 2つのベクトルのクロス積を返します。
269 	 * @since 0.2
270 	 */
271 	cross : function(bv2) {
272 		if (this.order != bv2.order)
273 			return null;
274 		var bm = new BMatrix(this.order, this.order);
275 		for (var j = 0; j < this.order; j++)
276 			if (bv2.getValue(j + 1) == 1)
277 				bm.colv[j] = this.clone();
278 		return bm;
279 	},
280 
281 	/**
282 	 * 2進ベクトルオブジェクト BVector を文字列に変換するメソッド
283 	 * BVector.toString() を定義します。
284 	 * @return 文字列を返します。
285 	 * @since 0.1
286 	 */
287 	toString : function() {
288 		var str = "(";
289 		for (var i = 0; i < this.order; i++) {
290 			str = str + this.getValue(i + 1);	// 1 origin に変換
291 			if (i < this.order - 1)
292 				str = str + ",";
293 		}
294 		str = str + ")";
295 		return str;
296 	},
297 
298 	/**
299 	 * 2進ベクトルオブジェクト BVector を TeX 形式に変換します。
300 	 * @since 0.2
301 	 */
302 	toTeX : function() {
303 		var str = "\\begin{pmatrix}";
304 		for (var i = 0; i < this.order; i++) {
305 			str = str + this.getValue(i + 1);	// 1 origin に変換
306 			if (i < this.order - 1)
307 				str = str + "\\\\";
308 		}
309 		str = str + "\\end{pmatrix}";
310 		return str;
311 	},
312 };
313