#!/usr/bin/env ruby
# encoding: utf-8

#パターン&ソースの登録
func = Hash.new()

func['| expr QUESTION expr COLON expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.iif(zdd2,zdd3) -> ZDD Object : 条件演算
 *
 *  zdd1,zdd2,zdd3,zdd4 : ZDD Object
 *
 * === 説明
 *  zdd1に含まれるアイテム集合については、zdd2の項を選択し、それ以外のアイテム集合についてはzdd3の項を選択する。
 *  (a+b).iif(2a+3b+4c+5d,3a+4b+5c+6d) -> 2a+3b+5c+6d # zdd1に含まれるアイテム集合a,bは、zdd2の項2a,3bを選択し、それ以外はzdd3の項5c,6dを選択する。
 *
 * 典型的には比較演算子と組み合わせて以下のように利用する。
 *  > x.show # -> 3a+2b+2c
 *  > y.show # -> 2a+2b+4c
 *  # (x,yが上記の通り定義されていたとする)
 *
 *  # xとyを比較し、yより大きい重みを持つ項をxから、それ以外をyから選ぶ。
 *  # x>yの結果はaであり、第1引数xから3aが選択され、その他のアイテム集合は第2引数yから2b,4cが選ばれる。
 *  > (x>y).iif(x,y) # -> 3a+2b+4c
 *
 *  # xとyを比較し、yより大きい重みを持つ項をxから選ぶ。
 *  # 上の例と同様であるが、第2引数が0なのでa以外のアイテム集合は何も選択されない。
 *  > (x>y).iif(x,0) # -> 3a
 *
 *  # xとyを比較し、yと同じ重みを持つ項をxから選ぶ。
 *  > (x==y).iif(x,0) # -> 2b
 * ----
 * ====== 上記の例において出力結果を示したコメントでは、アイテムをアルファベット小文字1文字で表し、項における重みとアイテム間のスペースおよびアイテム間のスペースを省略して表記している。
 */

VALUE vsop_iif(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v1;
	VALUE v2;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"20\",&v1,&v2);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v1);
	CtoI *ctoi_mode = value2ctoi(v2);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr MEET expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.meet(zdd2) -> ZDD Object : meet演算
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 *  zdd1に含まれるアイテム集合αとzdd2に含まれるアイテム集合βの共通集合α∩βを求める。
 *  例えば、アイテム集合abc と bcd の共通集合は以下の通り。
 *   abc.meet(bcd) = abc ∩ bcd = bc
 *  複数のアイテム集合間の演算では全組合せについて共通集合を求める。
 *  (abc + a).meet(bcd + b) = abc ∩ bcd + abc ∩ b + a ∩ bcd + a ∩ b
 *                          = bc        + b       + 1       + 1
 *                          = bc + b + 2
 *  重みについては、同じアイテム集合を複数に展開して計算すればよい。
 *  (2abc).meet(bcd) = (abc+abc).meet(bcd) = bc + bc = 2bc
 *
 * === 例
 *  > a=VSOP.itemset(\"a\")
 *  > b=VSOP.itemset(\"b\")
 *  > f=a+2*a*b+3*b
 *  
 *  # a + 2ab + 3b の各アイテム集合と引き数で指定されたアイテム集合 a との共通集合を求めると、
 *  # a + 2a + 3 = 3 a + 3となる。
 *  > f.meet(a).show
 *  3 a + 3
 *
 *  # アイテム集合bとの共通集合を求めると 1 + 2b + 3b = 5b + 1 となる。
 *  > f.meet(b).show
 *  5 b + 1
 *
 *  # アイテム集合 ab との共通集合を求めると a + 2ab + 3b となる。
 *  > f.meet(a*b).show
 *  2 a b + a + 3 b
 *
 *  # 定数1は空のアイテム集合なので、それとの共通集合を求めると係数だけが残り 1 + 2 + 3 = 6 となる。
 *  > f.meet(1).show
 *  6
 *  > exit
 *
 *  > a=VSOP.itemset(\"a\")
 *  > b=VSOP.itemset(\"b\")
 *  > c=VSOP.itemset(\"c\")
 *  >
 *  > f=((a*b*c)+2*(a*b)+(b*c)+1)
 *  > f.show
 *   a b c + 2 a b + b c + 1
 *
 *  > g=2*a*b + a
 *  > g.show
 *   a b + a
 *  # abc + 2ab + bc + 1 の各アイテム集合と引き数で指定された 2ab + a の各アイテム集合との共通集合を求めると、
 *  # 以下の通りとなる(アイテム間のスペースは省略)。
 *  # abc ∩ 2ab = 2ab
 *  # 2ab ∩ 2ab = 4ab
 *  # bc  ∩ 2ab = 2b
 *  # 1   ∩ 2ab = 2
 *  # abc ∩ a   = a
 *  # 2ab ∩ a   = 2a
 *  # bc  ∩ a   = 1
 *  # 1   ∩ a   = 1
 *  # 結果をまとめると 6ab + 3a + 2b + 4 となる。
 *  #
 *  > f.meet(g).show
 *   6 a b + 3 a + 2 b + 4
 * ----
 * ====== 上記の例において出力結果を示したコメントでは、アイテムをアルファベット小文字1文字で表し、項における重みとアイテム間のスペースおよびアイテム間のスペースを省略して表記している。
 */

VALUE vsop_meet(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr NE expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.ne?(zdd2) -> ZDD Object : 不等比較演算
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれるアイテム集合とzdd2に含まれるアイテム集合を比較し、重みが異なるアイテム集合を選択する。
 *  詳しくは==演算子を参照のこと。
 *
 * === 関連
 *  ==, >=, >, <=, <, iif
 */

VALUE vsop_ne(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| print QUOTIENT IDVAR expr'] =<<'SCP_EOF'
"
VALUE vsop_print_arg1(VALUE self,char *arg){
	Vsop_Ruby* rmod;
//	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_modd =new CtoI(*rmod->cmod);
	int len = strlen(arg);
	char *str_c;
	str_c = new char[len+1];
	strcpy(str_c,arg);		
	#{pgm_src}
	return self;
}

"
SCP_EOF


func['| print QUOTIENT IDVAR FNAME expr'] =<<'SCP_EOF'
"
VALUE vsop_print_arg2(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v1,v2;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_mode =new CtoI(*rmod->cmod);
	rb_scan_args(argc, argv,\"20\",&v1,&v2);
	if(TYPE(v1)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (1st argument must be STRING)\");
	}
	if(TYPE(v2)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (2nd argument must be STRING)\");
	}
	char *arg1=RSTRING_PTR(v1);
	char *arg2=RSTRING_PTR(v2);

	int len;
	len = strlen(arg1);
	char *str_c;
	if(*arg1=='/'){
		str_c = new char[len];
		strcpy(str_c,arg1+1);
	}
	else{
		str_c = new char[len+1];
		strcpy(str_c,arg1);		
	}

	len = strlen(arg2);
	char *str_d = new char[len+3];
	sprintf(str_d,\"\\\"%s\\\"\",arg2);
	int len_d = len+2;

	#{pgm_src}
	return self;
}
"
SCP_EOF


func['| IMPORT LPAREN FNAME RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * VSOP.import(fileName) -> ZDD Object : ZDDのインポート
 *
 *  fileName : Ruby String
 *
 * === 説明
 *  exportメソッドで出力されたZDDファイル(fileNameで指定)をインポートしZDDオブジェクトを復元する。
 *  exportする時のsymbolによるアイテムの宣言順序とimportする時の宣言順序は同じでなければならない。
 *
 * === 例
 *
 *  # まずZDDオブジェクトfをファイル\"dat.zdd\"にエキスポートする。
 *  > VSOP.symbol(\"a\")
 *  > VSOP.symbol(\"b\")
 *  > VSOP.symbol(\"c\")
 *  > f=5*a*b*c+3*a*b+2*b*c+c
 *  > f.show
 *   5 a b c + 3 a b + 2 b c + c
 *  > f.export(\"dat.zdd\")
 *  > exit
 *
 *  # エキスポートされたファイル内容は以下の通り。
 *  $ more xxa
 *   _i 3
 *   _o 3
 *   _n 7
 *   4 1 F T
 *   248 2 F 5
 *   276 3 4 248
 *   232 2 F 4
 *   2 2 F T
 *   272 3 232 2
 *   268 3 232 248
 *   276
 *   272
 *   268
 *
 *  # 以下のようにsymbolを宣言した後にimportすれば正しく復元される。
 *  > VSOP.symbol(\"a\")
 *  > VSOP.symbol(\"b\")
 *  > VSOP.symbol(\"c\")
 *  > f=VSOP.import(\"dat.zdd\")
 *  > f.show
 *   5 a b c + 3 a b + 2 b c + c
 *  > exit
 *
 *  # もしアイテムb,cの宣言順序を入れ替えると結果においてもbとcが入れ替わってしまう。
 *  > VSOP.symbol(\"a\")
 *  > VSOP.symbol(\"c\")
 *  > VSOP.symbol(\"b\")
 *  > f=VSOP.import(\"dat.zdd\")
 *  > f.show
 *   5 a c b + 3 a c + 2 c b + b
 *  > exit
 *
 *  # 宣言せずにインポートすると、x1,x2,x3のようなアイテム名が使われる。
 *  # この時、各アイテムの後ろに付いた数字は、アイテムの宣言の逆順による連番となる。
 *  # 以下の例では、x1=c, x2=b, x3=cである。
 *  > VSOP.import(\"dat.zdd\")
 *  > f.show
 *   5 x3 x2 x1 + 3 x3 x2 + 2 x2 x1 + x1
 *  > exit
 */

VALUE vsop_import(int argc, VALUE *argv, VALUE self){
	VALUE v;
	CtoI *ctoi_fin; 
/*
	VALUE vz = rb_cv_get(self,\"@@init_cnt\");
	int init_cnt_v =  NUM2INT(vz);
	if(init_cnt_v==0){ BDDV_Init(256, env_nmax);}
	init_cnt_v++;
	rb_cv_set(self,\"@@init_cnt\",INT2NUM(init_cnt_v));
*/
	if(init_cnt==0){ BDDV_Init(256, env_nmax);}
	init_cnt++;

	rb_scan_args(argc, argv,\"10\",&v);
	if(TYPE(v)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (1st argument must be STRING)\");
	}
	char *argtmp = RSTRING_PTR(v);
	int len;
	len = strlen(argtmp);
	char *str_c = new char[len+3];
	sprintf(str_c,\"\\\"%s\\\"\",argtmp);
	int len_c = len+2;
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF


func['| expr LE expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 <= zdd2 : 以下比較演算
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれるアイテム集合とzdd2に含まれるアイテム集合を比較し、重みがzdd2以下のアイテム集合を選択する。
 *  詳しくは==演算子を参照のこと。
 *
 * === 関連
 *  ==, >=, >, <, ne?, iif
 */

VALUE vsop_le(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr LT expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 < zdd2 -> ZDD Object : 小なり比較演算
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 *  zdd1に含まれるアイテム集合とzdd2に含まれるアイテム集合を比較し、重みがzdd2より小さいアイテム集合を選択する。
 *  詳しくは==演算子を参照のこと。
 *
 * === 関連
 *  ==, >=, >, <=, ne?, iif
 */

VALUE vsop_lt(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr GE expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 >= zdd2 -> ZDD Object : 以上比較演算
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれるアイテム集合とzdd2に含まれるアイテム集合を比較し、重みがzdd2以上のアイテム集合を選択する。
 *  詳しくは==演算子を参照のこと。
 *
 * === 関連
 *  ==, >, <=, <, ne?, iif
 */

VALUE vsop_ge(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr GT expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 > zdd2 -> ZDD Object : 大なり比較演算
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれるアイテム集合とzdd2に含まれるアイテム集合を比較し、重みがzdd2より大きいアイテム集合を選択する。
 *  詳しくは==演算子を参照のこと。
 *
 * === 関連
 *  ==, >=, <=, <, ne?, iif
 */

VALUE vsop_gt(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF


func['| expr EQ expr'] =<<'SCP_EOF'
"
/**//*
 * call-seq:
 * zdd1 == zdd2 -> ZDD Object : 等価比較演算子
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれるアイテム集合とzdd2に含まれるアイテム集合を比較し、重みが同じアイテム集合を選択する。アイテム集合のみを返し、重みは1となることに注意する。
 *
 * 本パッケージで扱える比較演算子(関数)は以下の通り。
 *  zdd1 == zdd2   : 等価演算子
 *  zdd1 >= zdd2   : 以上演算子
 *  zdd1 >  zdd2   : 大なり演算子
 *  zdd1 <= zdd2   : 以下演算子
 *  zdd1 <  zdd2   : 小なり演算子
 *  zdd1.ne?(zdd2) : 不等関数
 * 
 * === 例
 *  > x.show
 *   3 a + 2 b + 2 c
 *  > y.show
 *   2 a + 2 b + 4 c
 *  # (x,yが上記の通り定義されていたとする)
 *
 *  # xとyを比較し、同じ重みを持つアイテム集合を選択する。
 *  > (x==y).show
 *   b
 *
 *  # xとyを比較し、y以上の重みを持つアイテム集合を選択する。
 *  > (x>=y).show
 *   a + b
 *
 *  # xとyを比較し、異なる重みを持つアイテム集合を選択する。
 *  > (x.ne?(y)).show
 *   a + c
 *
 * zdd1にあってzdd2にない(もしくはその逆)アイテム集合の重みは0と考えればよい。
 *  x.show
 *   3 a + 2 b + 2 c
 *  y.show
 *   2 a + 2 b
 *  # (x,yが上記の通り定義されていたとする)
 *
 *  # アイテム集合cはyにないので項0cを考えればよい。
 *  > (x>y).show
 *   a + c
 *  > (x.ne?(y)).show
 *   a + c
 *  > (x==y).show
 *   b
 * ----
 * ====== 上記の例において出力結果を示したコメントでは、アイテムをアルファベット小文字1文字で表し、項における重みとアイテム間のスペースおよびアイテム間のスペースを省略して表記している。
 */

VALUE vsop_eq(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TLE LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.termsLE(zdd2) -> ZDD Object : 重み比較による項選択(以下比較)
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる項のうち、zdd2で与えられた定数以下の重みを持つ項(重み+アイテム集合)を選択する。
 *  詳しくはtermsEQ演算子を参照のこと。
 *
 * === 関連
 *  termsEQ, termsNE, termsGE, termsGT, termsLE, termsLT, terms
 */

VALUE vsop_termsLE(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TLT LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.termsLT(zdd2) -> ZDD Object : 重み比較による項選択(小なり比較)
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる項のうち、zdd2で与えられた定数より小さい重みを持つ項(重み+アイテム集合)を選択する。
 *  詳しくはtermsEQ演算子を参照のこと。
 *
 * === 関連
 *  termsEQ, termsNE, termsGE, termsGT, termsLE, termsLT, terms
 */

VALUE vsop_termsLT(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TGE LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.termsGE(zdd2) -> ZDD Object : 重み比較による項選択(以上比較)
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる項のうち、zdd2で与えられた定数以上の重みを持つ項(重み+アイテム集合)を選択する。
 *  詳しくはtermsEQ演算子を参照のこと。
 *
 * === 関連
 *  termsEQ, termsNE, termsGE, termsGT, termsLE, termsLT, terms
 */

VALUE vsop_termsGE(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TGT LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * 書式 zdd1.termsGT(zdd2) -> ZDD Object : 重み比較による項選択(大なり比較)
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる項のうち、zdd2で与えられた定数より大きい重みを持つ項(重み+アイテム集合)を選択する。
 *  詳しくはtermsEQ演算子を参照のこと。
 *
 * === 関連
 *  termsEQ, termsNE, termsGE, termsGT, termsLE, termsLT, terms
 */


VALUE vsop_termsGT(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TNE LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.termsNE(zdd2) -> ZDD Object : 重み比較による項選択(不等比較)
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる項のうち、zdd2で与えられた定数と異なる重みを持つ項(重み+アイテム集合)を選択する。
 *  詳しくはtermsEQ演算子を参照のこと。
 *
 * === 関連
 *  termsEQ, termsNE, termsGE, termsGT, termsLE, termsLT, terms
 */

VALUE vsop_termsNE(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TEQ LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.termsEQ(zdd2) -> ZDD Object : 重み比較による項選択(等価比較)
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる項のうち、zdd2で与えられた定数と同じ重みを持つ項(重み+アイテム集合)を選択する。
 * zdd2にはconstantメソッドにより生成されたVSOP定数オブジェクト、もしくはFixnum,Bignumのrubyオブジェクトで指定する。
 *
 * 本パッケージで扱える全ての項選択メソッドは以下の通り。
 *  zdd1.termsEQ(zdd2) : 等価比較
 *  zdd1.termsGE(zdd2) : 以上比較
 *  zdd1.termsGT(zdd2) : 大なり比較
 *  zdd1.termsLE(zdd2) : 以下比較
 *  zdd1.termsLT(zdd2) : 小なり比較
 *  zdd1.termsNE(zdd2) : 不等比較
 * 
 * === 例
 *  > x.show
 *   5 a + 3 b + c
 *  # xが上記の通り定義されていたとする。
 *
 *  # 3の重みを持つ項を選択する。
 *  > x.termsEQ(3).show
 *   3 b
 *
 *  # 3以上の重みを持つ項を選択する。
 *  > x.termsGE(3).show
 *   5 a + 3 b
 *
 *  # 3でない重みを持つ項を選択する。
 *  > x.termsNE(3).show
 *   5 a + c
 *
 *  # 条件に合う項がなければ0
 *  > x.termsGT(10).show
 *   0
 */

VALUE vsop_termsEQ(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr FPC LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.freqpatC(minsup) : 頻出飽和アイテム集合の列挙
 *
 *  zdd    : ZDD Object
 *  minsup : Ruby Integer
 *
 * === 説明
 *  zddから最小サポートminsup以上出現する頻出飽和アイテム集合を全て列挙し、そのZDDオブジェクトを返す。
 *
 * === 例
 * freqpatAを参照のこと。
 */
VALUE vsop_freqpatC(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr FPM LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/**//*
 * call-seq:
 * zdd.freqpatM(minsup) -> ZDD Object : 頻出極大アイテム集合の列挙
 *
 *  zdd    : ZDD Object
 *  minsup : Ruby Integer
 *
 * === 説明
 *  zddから最小サポートminsup以上出現する頻出極大アイテム集合を全て列挙し、そのZDDオブジェクトを返す。
 *
 * === 例
 * freqpatAを参照のこと。
 */
VALUE vsop_freqpatM(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr FPA LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.freqpatA(minsup) : 頻出アイテム集合の列挙
 *
 *  zdd    : ZDD Object
 *  minsup : Ruby Integer
 *
 * === 説明
 *  zddから最小サポートminsup以上出現する頻出アイテム集合を全て列挙し、そのZDDオブジェクトを返す。
 *
 * === 例
 *  > a=VSOP.itemset(\"a\")
 *  > b=VSOP.itemset(\"b\")
 *  > c=VSOP.itemset(\"c\")
 *  > d=VSOP.itemset(\"d\")
 *  > t=a*b + a + b*c*d + a*b*c + a 
 *  > t.show
 *   a b c + a b + 2 a + b c d
 * 
 *  > t.freqpatA(1).show
 *   a b c + a b + a c + a + b c d + b c + b d + b + c d + c + d + 1
 *  > t.freqpatM(1).show
 *   a b c + b c d
 *  > t.freqpatC(1).show
 *   a b c + a b + a + b c d + b c + b + 1
 *
 *  > t.freqpatA(2).show
 *   a b + a + b c + b + c + 1
 *  > t.freqpatM(2).show
 *   a b + b c
 *  > t.freqpatC(2).show
 *   a b + a + b c + b + 1
 *  > t.freqpatA(3).show
 *   a + b + 1
 *  > t.freqpatM(3).show
 *   a + b
 *  > t.freqpatC(3).show
 *   a + b + 1
 *
 * === 関連
 * freqpatM, freqpatC
 */
VALUE vsop_freqpatA(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr SYMGRP'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.symgrp : Generates symmetric item sets in zdd.
 *
 *  zdd : ZDD Object
 *
 * === 説明
 *
 */
VALUE vsop_symgrp(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| MINUS expr %prec UMINUS'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * - zdd -> ZDD Object : -単項演算子
 *
 *  zdd : ZDD Object
 *
 * === 説明
 * zddに含まれる全てのアイテム集合の重みの符合を変える。
 *
 * === 例
 *  > x.show
 *  3 a + 2 b
 *  > (-x).show
 *   -3 a - 2 b
 */

VALUE vsop_minus_op(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_modb =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| PLUS expr %prec UPLUS'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * + zdd -> ZDD Object : 単項演算子
 *
 *  zdd : ZDD Object
 *
 * === 説明
 * zddに含まれる全てのアイテム集合をそのまま返す(何もしない)。
 *
 * === 例
 *  > x.show
 *   3 a + 2 b
 *  > (+x).show
 *   3 a + 2 b
 */

VALUE vsop_plus_op(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_modb =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr PERMITSYM LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.permitsym(zdd2) : Filters terms in zdd1 each of which consists of zdd2 number of items.
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 *
 */

VALUE vsop_permitsym(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr RESTRICT LPAREN expr RPAREN'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.restrict(zdd2) : restrict
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1に含まれる組合せの中から、zdd2中の少なくとも1つの組合せを包含する要素だけを抽出する。
 *
 * === 例
 *  > x.show
 *   5 a + 3 b + c
 *  > y.show
 *   a + b
 *  # x,yが上記の通り定義されていたとする。
 *  > z.show
 *   a b
 *  > x.restrinct(y).show
 *   5 a + 3 b
 *  > x.restrinct(z).show
 *   0
 *  > x.restrinct(\"a\").show
 *   5 a
 */

VALUE vsop_restrict(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF


func['| u_expr ITEMS'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.items -> ZDD Object : ZDDを構成する全アイテムの列挙
 *
 *  zdd : ZDD Object
 *
 * === 説明
 *  zdd上の全アイテムとその重みについて、新しいZDDオブジェクトを生成し返す。
 *
 * === 例
 *  > a=VSOP.itemset(\"a\")
 *  > b=VSOP.itemset(\"b\")
 *  > c=VSOP.itemset(\"c\")
 *  > f=((a*b*c)+(a*b)+(b*c))
 *  > f.show
 *   a b c + 2 a b + b c
 *
 *  # ZDDオブジェクトfは3つのアイテムa,b,cから構成されており、それぞれのアイテムの重みを以下の通り計算する。
 *  # アイテムaを含む項は\"a b c\"と\"2 a b\"で、その重み合計は3となる。
 *  # アイテムbは全ての項に含まれ、その重み合計は4となる。
 *  # アイテムcを含む項は\"a b c\"と\"b c\"で、その重み合計は2となる。
 *  > f.items.show
 *   3 a + 4 b + 2 c
 */

VALUE vsop_items(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr TOTALVAL'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.totalval -> Ruby Integer : 重みの合計
 *
 *  zdd : ZDD Object
 *
 * === 説明
 * zddに含まれる項(定数項も含む)の重みの合計をruby整数で返す。
 *
 * === 例
 *  > x.show
 *   5 a + 3 b + c
 *  # xが上記の通り定義されていたとする。
 *
 *  > puts x.totalval
 *   9
 *
 *  # 定数項も含めて求められる。
 *  > x.show
 *   5 a + 3 b + c - 10
 *  # xが上記の通り定義されていたとする。
 *  > puts x.totalval
 *   -1
 * === 関連
 *  minval, maxval
 */

VALUE vsop_totalval(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
  int val = rmod->cmod->TotalVal().GetInt();
	return INT2NUM(val);
/*
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
*/
}
"
SCP_EOF

func['| u_expr MINVAL'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.minval -> ZDD Object : 重みの最小値
 *
 *  zdd : ZDD Object
 *
 * === 説明
 * zddに含まれる項(定数項も含む)のうち、最小の重みをVSOP定数オブジェクトで返す。
 *
 * === 例
 *  > x.show
 *   5 a - 3 b + c
 *  # xが上記の通り定義されていたとする。
 *
 *  > x.maxval.show
 *   -3
 *
 *  # 最小値は定数項も含めて求められる。
 *  > x.show
 *   5 a - 3 b + c - 10
 *  # xが上記の通り定義されていたとする。
 *  > x.maxval.show
 *   -10
 *
 *  # 最小の重みを持つ項を選択する。
 *  > x.show
 *   5 a - 3 b + 5 c - 3
 *  # xが上記の通り定義されていたとする。
 *  > x.termsEQ(x.maxval).show
 *   -3 b - 3
 *
 * === 関連
 *  maxval
 */

VALUE vsop_minval(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr MAXVAL'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd.maxval -> ZDD Object : 重みの最大値
 *
 *  zdd : ZDD Object
 *
 * === 説明
 * zddに含まれる項(定数項も含む)のうち、最大の重みをVSOP定数オブジェクトで返す。
 *
 * === 例
 *  > x.show
 *   5 a + 3 b + c
 *  # xが上記の通り定義されていたとする。
 *  > x.maxval.show
 *   5
 *
 *  # 最大値は定数項も含めて求められる。
 *  > x.show
 *   5 a + 3 b + c + 10
 *  # xが上記の通り定義されていたとする。
 *  > x.maxval.show
 *   10
 *
 *  # 最大の重みを持つ項を選択する。
 *  > x.show
 *   5 a + 3 b + 5 c + 2
 *  # xが上記の通り定義されていたとする。
 *  > x.termsEQ(x.maxval).show
 *   5 a + 5 c
 *
 * === 関連
 *  minval
 */

VALUE vsop_maxval(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr REMAINDER expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 % zdd2 -> ZDD Object : 剰余演算子
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * ===説明
 *  剰余演算を行う。詳しくは / 演算子を参照。
 */

VALUE vsop_remainder(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr QUOTIENT expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 / zdd2 -> ZDD Object : 除算演算子
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * ==== a. 定数除算
 *  重み付き積和集合xの定数cによる除算x/cは、
 *  xの各項(アイテム集合)の重み(頻度)をcで整数除算した商を重みに持つアイテム集合が計算される。
 *  通常の多項式と同様に考えれば良い。
 *  x.show # -> 13a+3b (xが左記の通り定義されていたとする)
 *  x/5 -> 2a    # aの項:13/5の商は2であるから2a。bの項:3/5の商は0であるから0bとなり表示されない。
 *  x%5 -> 3a+3b # aの項:13/5の余りは3であるから3a。bの項:3/5の余りは3であるから3bとなる。
 *
 * ==== b. 1つのアイテム集合による除算
 *  重み付き積和集合xのアイテム集合vによる除算x/vは、xの各項をvで除する演算である。
 *  通常の多項式と同様に考えれば良い。
 *  x.show # -> 7ab+5bc
 *  y.show # -> 7ab+5bc+2c
 *  # (x,yが上記の通り定義されていたとする)
 *  x/'b'  # -> 7a+5c     # 7ab/bの商は7a。5bc/bの商は5c。
 *  y/'3b' # -> 2a+c      # 7ab/3bの商は2a。5bc/3bの商は1c。2c/3bの商は0となり表示されない。
 *  x%'b'  # -> 0         # 7ab/bの余りは0。5bc/bの余り0。
 *  y%'3b' # -> ab+2bc+2c # 7ab/3bの余りはab。5bc/3bの余りは2bc。2c/3bの余りは2c。
 *
 * ==== c. 2つ以上のアイテム集合による除算
 *  2つの重み付き積和集合x,yの除算x/yは次のように計算される。
 *  除数yの各項をT_iとしたときQ_i=x/T_iを全てのT_iについて得られたQ_i全て共通に含まれるアイテム集合(項)について、重みの絶対値が最小の項を商Qと定義する。
 *  通常の多項式とは異なることに注意する。
 *  x.show # -> 2ab+4ac+ad-2bc+3bd
 *  y.show # -> a+b
 *  # (x,yが上記の通り定義されていたとする)
 *  # Q_1=(x/'a')=2b +4c +d +0  +0  = 0  +2b +4c +d
 *  # Q_2=(x/'b')=2a +0  +0 -2c +3d = 2a +0  -2c +3d
 *  # Q_1,Q_2で共通のアイテム集合はcとdであり、それぞれで絶対値が最小の項は-2cとdである。よって求める商は以下の通りとなる。
 *  (x/y).show # -> -2c+d
 *  # x%yについてはx-(y*Q)を計算すればよい。
 *  (x%y).show # -> 2ab+6ac+2bd
 * ----
 * ====== 上記の例において出力結果を示したコメントでは、アイテムをアルファベット小文字1文字で表し、項における重みとアイテム間のスペースおよびアイテム間のスペースを省略して表記している。
 */

VALUE vsop_quotiment(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr MULTIPLY expr'] =<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 * zdd2 -> ZDD Object : 乗算演算子
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * ==== a. 定数乗算
 *  重み付き積和集合xに定数cを掛けるx*cでは、xの各項の重みをc倍する。
 *  通常の多項式と同様に考えれば良い。
 *  a=VSOP.itemset('a'); b=VSOP.itemset('b'); c=VSOP.itemset('c');
 *  (a*3).show           # -> 3a
 *  (-2*a).show          # -> -2a
 *  ((a+2*b+3*c)*4).show # -> 4a+8b+12c
 *
 * ==== b. 1つのアイテム集合の乗算
 *  重み付き積和集合xに1つのアイテム集合yを掛けるx*yでは、xの各項目にアイテム集合yを加える。
 *  ただし、同じアイテム同士の掛け算 a*a=a となることに注意する。
 *  x.show  # -> a+2ab+3c (xが左記の通り定義されていたとする)
 *  x*'d'   # -> ad+2abd+3cd
 *  x*'b'   # -> ab+2ab+3bc
 *  4*x*'a' # -> 4a+8ab+12ac
 *
 * ==== c. 2つ以上のアイテム集合の乗算
 *  2つの重み付き積和集合x,yの乗算x*yでは、xとyそれぞれの各項から一つずつ選ぶ組み合わせ全てについて上記a,bの乗算を付す。
 *  乗算の結果同じアイテム集合の項は加減算される。
 *  a=VSOP.itemset('a'); b=VSOP.itemset('b');
 *  c=VSOP.itemset('c'); d=VSOP.itemset('d');
 *  ((a+b)*(c+d)).show # -> ac+ad+bc+bd
 *  ((a+b)*(b+c)).show # -> ab+ac+b+bc
 *  ((a+b)*(a+b)).show # -> a+2ab+b
 *  ((a+b)*(a-b)).show # -> a-b
 * ----
 * ====== 上記の例において出力結果を示したコメントでは、アイテムをアルファベット小文字1文字で表し、項における重みとアイテム間のスペースおよびアイテム間のスペースを省略して表記している。
 */

VALUE vsop_multiply(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| LCM LPAREN FNAME FNAME NUMBER FNAME RPAREN'] =<<'SCP_EOF'
"
VALUE vsop_lcm_order(int argc, VALUE *argv, VALUE self){
	if(init_cnt==0){ BDDV_Init(256, env_nmax);}
	init_cnt++;

	VALUE v1,v2,v3,v4;
	CtoI *ctoi_fin; 
	rb_scan_args(argc, argv,\"40\",&v1,&v2,&v3,&v4);
	if(TYPE(v1)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (1st argument must be STRING)\");
	}
	if(TYPE(v2)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (1st argument must be STRING)\");
	}
	if(TYPE(v3)!=T_FIXNUM){
		rb_raise(rb_eRuntimeError,\"argument type error (3rd argument must be FIXNUM)\");
	}
	if(TYPE(v4)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (4th argument must be STRING)\");
	}
	char *arg1 = RSTRING_PTR(v1);
	char *arg2 = RSTRING_PTR(v2);
	int arg3_fix = FIX2INT(v3);
	char *arg4 = RSTRING_PTR(v4);

	int len;

	len = strlen(arg1);
	char *str_c = new char[len+3];
	sprintf(str_c,\"\\\"%s\\\"\",arg1);
	int len_c = len+2;

	len = strlen(arg2);
	char *str_d = new char[len+3];
	sprintf(str_d,\"\\\"%s\\\"\",arg2);
	int len_d = len+2;

	char *str_e = new char[64];
	sprintf(str_e,\"%d\",arg3_fix);

	len = strlen(arg4);
	char *str_f = new char[len+3];
	sprintf(str_f,\"\\\"%s\\\"\",arg4);
	int len_f = len+2;

	#{pgm_src}

	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF



func['| LCM LPAREN FNAME FNAME NUMBER RPAREN'] =<<'SCP_EOF'
"
VALUE vsop_lcm_nomal(int argc, VALUE *argv, VALUE self){
	if(init_cnt==0){ BDDV_Init(256, env_nmax);}
	init_cnt++;

	VALUE v1,v2,v3;
	CtoI *ctoi_fin; 
	rb_scan_args(argc, argv,\"30\",&v1,&v2,&v3);
	if(TYPE(v1)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (1st argument must be STRING)\");
	}
	if(TYPE(v2)!=T_STRING){
		rb_raise(rb_eRuntimeError,\"argument type error (1st argument must be STRING)\");
	}
	if(TYPE(v3)!=T_FIXNUM){
		rb_raise(rb_eRuntimeError,\"argument type error (3rd argument must be FIXNUM)\");
	}
	char *arg1 = RSTRING_PTR(v1);
	char *arg2 = RSTRING_PTR(v2);
	int arg3_fix = FIX2INT(v3);

	int len;

	len = strlen(arg1);
	char *str_c = new char[len+3];
	sprintf(str_c,\"\\\"%s\\\"\",arg1);
	int len_c = len+2;

	len = strlen(arg2);
	char *str_d = new char[len+3];
	sprintf(str_d,\"\\\"%s\\\"\",arg2);
	int len_d = len+2;

	char *str_e = new char[64];
	sprintf(str_e,\"%d\",arg3_fix);
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| u_expr PERMIT LPAREN expr RPAREN']=<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1.permit(zdd2) : permit演算子
 * 
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 *  zdd1に含まれる組合せの中から、zdd2中の少なくとも1つの組合せに包含される要素だけを抽出する。
 *
 * === 例
 *  > x.show
 *   5 a + 3 b + c
 *  > y.show
 *   a + b
 *  > z.show
 *   a b
 *  # x,y,zが上記の通り定義されていたとする。
 *
 *  > x.permit(y).show
 *   5 a + 3 b
 *  > x.permit(z).show
 *   0
 *  > x.permit(\"a\").show
 *   5 a
 */
VALUE vsop_permit(int argc, VALUE *argv, VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modd = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func[': print expr']=<<'SCP_EOF'
"
/*
 *  : print expr
 */

VALUE vsop_print(VALUE self){
	Vsop_Ruby* rmod;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	CtoI *ctoi_modb =new CtoI(*rmod->cmod);
	#{pgm_src}
	return self;
}
"
SCP_EOF

func['| expr PLUS expr']=<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 + zdd2 -> ZDD Object : 加算演算子
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1とzdd2の対応するアイテム集合同士の重みの加算を行う。
 *
 * === 例
 *  > x.show
 *   3 a + 2 b
 *  > y.show
 *   2 a + 2 b + 4 c
 *  # x,yが上記の通り定義されていたとする。
 *
 *  > (x+y).show
 *   5 a + 4 b + 4 c
 */

VALUE vsop_plus(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin;
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF

func['| expr MINUS expr']=<<'SCP_EOF'
"
/*
 * call-seq:
 * zdd1 - zdd2 -> ZDD Object : 減算演算子
 *
 *  zdd1,zdd2 : ZDD Object
 *
 * === 説明
 * zdd1とzdd2の対応するアイテム集合同士の重みの減算を行う。
 *
 * === 例
 *  > x.show
 *   3 a + 2 b
 *  > y.show
 *   2 a + 2 b + 4 c
 *  # x,yが上記の通り定義されていたとする。
 *
 *  > (x-y).show
 *   a - 4 c
 *  > (y-x).show
 *   -a + 4 c
 */

VALUE vsop_minus(int argc, VALUE *argv,VALUE self){
	Vsop_Ruby* rmod;
	VALUE v;
	Data_Get_Struct(self,Vsop_Ruby,rmod);
	rb_scan_args(argc, argv,\"10\",&v);
	CtoI *ctoi_moda =new CtoI(*rmod->cmod);
	CtoI *ctoi_modc = value2ctoi(v);
	CtoI *ctoi_fin; 
	#{pgm_src}
	Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
	rmod_rtn->cmod = ctoi_fin;
	return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
}
"
SCP_EOF




def extract_pgm(src)
	start_char =0
	end_char =0
	writeflg=1
	pgmsrc = ""

	src.each{|line|
		writeflg =1
		if "#{line}" =~ /\{/ then
			if(start_char==0) then 
				writeflg= 0
			end
			start_char= start_char + 1
		elsif "#{line}" =~ /\}/ then
			end_char = end_char + 1
			if(start_char==end_char) then
				pgmsrc =pgmsrc.gsub("$1.str", "str_a")
				pgmsrc =pgmsrc.gsub("$2.str", "str_b")
				pgmsrc =pgmsrc.gsub("$3.str", "str_c")
				pgmsrc =pgmsrc.gsub("$4.str", "str_d")
				pgmsrc =pgmsrc.gsub("$5.str", "str_e")
				pgmsrc =pgmsrc.gsub("$6.str", "str_f")
				pgmsrc =pgmsrc.gsub("$1.len", "len_a")
				pgmsrc =pgmsrc.gsub("$2.len", "len_b")
				pgmsrc =pgmsrc.gsub("$3.len", "len_c")
				pgmsrc =pgmsrc.gsub("$4.len", "len_d")
				pgmsrc =pgmsrc.gsub("$5.len", "len_e")
				pgmsrc =pgmsrc.gsub("$6.len", "len_f")
				pgmsrc =pgmsrc.gsub("$$", "ctoi_fin")
				pgmsrc =pgmsrc.gsub("$1", "ctoi_moda")
				pgmsrc =pgmsrc.gsub("$2", "ctoi_modb")
				pgmsrc =pgmsrc.gsub("$3", "ctoi_modc")
				pgmsrc =pgmsrc.gsub("$4", "ctoi_modd")
				pgmsrc =pgmsrc.gsub("$5", "ctoi_mode")
				pgmsrc =pgmsrc.gsub("$6", "ctoi_modf")
		 		return pgmsrc
			end
		end
		if(writeflg == 1)then
			pgmsrc = pgmsrc + "#{line}"
		end
	}
end

def func_set(func)
	##最初に%{から%}までint main以外をすべて抜き出す
	File.open("SAPPOROBDD/app/VSOP/vsopyacc.y++","r"){|src|
		writeflg=0
		mainflg=0
		main_s=0
		main_e=0
		src.each{|line| 
			if "#{line}" =~ /^%\{/ then
				writeflg=1
			elsif "#{line}" =~ /^%\}/ then
				break 
			elsif "#{line}" =~ /^int main/ then
				mainflg=1
				writeflg=0
			elsif "#{line}" =~ /\{|\}/ and mainflg == 1 then
				if "#{line}" =~ /\{/ then
					main_s = main_s+1
				end 
				if "#{line}" =~ /\}/ then
					main_e = main_e+1
					if main_s == main_e then
						writeflg =1
						mainflg = 0
					end 
				end 
			else
				if writeflg==1 then
					File.open("zdd_so.cpp","a"){|file|
						file.puts line
					}
				end				
			end
		}
	}
	#パターンごとの記述を抜き出す
	File.open("SAPPOROBDD/app/VSOP/vsopyacc.y++","r"){|src|
		src.each{|line| 
			if not func[line.squeeze(" ").chomp.lstrip.rstrip].nil?then
			key = line.squeeze(" ").chomp.lstrip.rstrip
			pgm_src = extract_pgm(src)
			File.open("zdd_so.cpp","a"){|file|
				eval "file.puts " + func[key]
			}
			end
		}
	}
end		


if(File.exist?("zdd_so.cpp"))then
	File.delete("zdd_so.cpp")
end


#zdd.cxxにsetfunc.cppを入れ込み、zdd_so.cppを作成
File.open("zdd_so.cxx","r"){|src|
	src.each{|line| 
		if "#{line}" =~ /^#include \"setfunc\.cpp\"/ then
			func_set(func)
		else
			File.open("zdd_so.cpp","a"){|file|
				file.puts line
			}
		end
	}
}










