'https://www.freebasic.net/forum/viewtopic.php?f=7&t=25684 'by frisian ≫ May 18, 2017 20:33 'Last edited by frisian on May 22, 2017 21:09 #Include Once "gmp_int.bi" Dim As gmp_int i, j, two = 2 '数字が小さい場合 ' 数値が FB の integer より大きい場合は、こちらを使います: two = gmp_int("2") Dim As Integer k ' 2の累乗 Print "2 の累乗を幾つか表示します。" Print "(以降何度か中断します。何かキー入力でデモを継続します。)" Sleep For i = 0 To 128 Print "2 ^ " & i & " = " & two ^ i Next i Print Sleep Print "gmp_int を FreeBASIC Integer に型変換することは" Print "gmp_int が Integer に収まることがわかっている場合にだけ、使えます" k = two Print "k = two ->";k Print i = "1" + String(35, "0") i = i + 1 Print i; " / 3 = "; i / 3 Print Print Print "19 shr 1 = " ; 19 shr 1 Print "gmp_int_2_base(19,2) " ; gmp_int_2_base(19,2) Print "gmp_int_2_base(9,2) " ; gmp_int_2_base(9,2) Print Print "19 shl 1 = " ; 19 shl 1 Print "gmp_int_2_base(19,2) " ; gmp_int_2_base(19,2) Print "gmp_int_2_base(38,2) " ; gmp_int_2_base(38,2) Print i = gmp_int(String(40,"1"), 2) Print "&B" + String(40,"1") + " = ";i Print i; " shr 39 = "; i Shr 39 Print i = 1 Print i; " shl 128 = "; i Shl 128 Print Print "gmp_int_2_base を使って、gmp_int 数を、文字列として出力する" i = "1234567890" Print i; " in base 62 = "; gmp_int_2_base(i, 62) Print i; " in base 16 = "; gmp_int_2_base(i, 16) Print i; " in base 8 = "; gmp_int_2_base(i, 8) Print i; " in base 2 = "; gmp_int_2_base(i, 2) Print i = gmp_int("09azAZ", 62) Print "09azAZ(62) = "; i Sleep '********************************* ' 平方根 n乗根 Print i = 10000 Print i; " の平方根(小数切り捨て) ";" = "; root(i) Print "残余 = "; rootrem(i) Print Print i; " の5乗根(小数切り捨て)";" = "; root(i, 5) Print "残余 = "; rootrem(i, 5) Print root(i, 5); " ^ 5 = "; root(i, 5) ^ 5 Print root(i, 5) ^ 5; " + "; rootrem(i, 5); " = "; Print root(i, 5) ^ 5 + rootrem(i ,5); ", i = "; i Print Print "62の3乗根 " , "root(62, 3) = "; root(62, 3) Print i = 40 Print " 開始値 "; gmp_int_2_base(i, 2) setbit (i, 0) Print " set bit 0 "; gmp_int_2_base(i, 2) clrbit (i, 0) Print "clear bit 0 "; gmp_int_2_base(i, 2) combit (i, 1) Print " 補数 bit 1 "; gmp_int_2_base(i, 2) combit (i, 1) Print " 補数 bit 1 "; gmp_int_2_base(i, 2) Print For k = 0 To 5 Print "bit"; k; If tstbit(i, k) = 0 Then Print " is 0" If tstbit(i, k) = 1 Then Print " is 1" Next Print Sleep ' 素数 i = 10 Print i; " ^ 2 mod 49 = "; powm(i, 2, 49) Print Print i; k = isprime(i) If k = 2 Then Print " 素数" ElseIf k = 1 Then Print " おそらく素数(特定されていない)" ElseIf k = 0 Then Print " 素数でない" End If Print i = 2 : i = i ^ 61 -1 ' メルセンヌ数、2の冪よりも 1 小さい自然数 Print i; " , 15 回テスト (既定)"; k = isprime(i) If k = 2 Then Print " 素数" ElseIf k = 1 Then Print " おそらく素数(特定されていない)" ElseIf k = 0 Then Print " 素数でない" End If Print i; " , 50 回テスト,"; k = isprime(i , 50) If k = 2 Then Print " 素数" ElseIf k = 1 Then Print " おそらく素数(特定されていない)" ElseIf k = 0 Then Print " 素数でない" End If Print Print i; ", 次の素数 = "; nextprime(i) Print i = "11111111111111111111111" Print i; " , 1000 回テスト,"; k = isprime(i , 1000) If k = 2 Then Print " 素数" ElseIf k = 1 Then Print " おそらく素数(特定されていない)" ElseIf k = 0 Then Print " 素数でない" End If Print i = "111111111111111111131111111111111111111" Print i; " , 1000 回テスト,"; k = isprime(i , 1000) If k = 2 Then Print " 素数" ElseIf k = 1 Then Print " おそらく素数(特定されていない)" ElseIf k = 0 Then Print " 素数でない" End If Sleep Print '********************************* ' 加算、減算 Print "変数に整数を入力する方法" Dim As gmp_int c Print Dim As gmp_int a = "123456789123456789123456789123456789123456789123456789" Dim As gmp_int b = "987654321987654321987654321987654321987654321987654321" c = a + b +1 Print c Print gmp_int_2_base(c, 62); " (base 62)" Print c = a c += b +1 Print c Print c = 2 c ^= 128 Print c Print Print "整数を直接計算する方法" Print Print gmp_int("123456789012345678901234567890123456789012345678901234567890")-gmp_int("123456789012345678901234567890")+1 Print Print ' 最大公約数、最小公倍数 i = 20 : j = 100 Print "最大公約数 gcd("; i; ", "; j; ") = "; gcd(i, j) Print "最小公倍数 lcm("; i; ", "; j; ") = "; lcm(i, j) Print i = "1234567890123456789" : j = "2345612345623456123456" Print "最大公約数 gcd("; i; ", "; j; ") = "; gcd(i, j) Print "最小公倍数 lcm("; i; ", "; j; ") = "; lcm(i, j) Print Print "123456789012345678901234567890123456789012345678901234567890 と 123456789012345678901234567890 の最大公約数は " Print gcd(gmp_int("123456789012345678901234567890123456789012345678901234567890"), gmp_int("123456789012345678901234567890")) Print ' 階乗 Print "階乗 fac(10) = "; fac(10) Print "多重階乗 mfac(n, m) = n!^(m) = n*(n-m)*(n-2m)*... " Print "多重階乗、7 飛ばしの積 mfac(10, 7) = "; mfac(10, 7) ' 10 * 3 Print Print "素数積、10 以下のすべての正の素数の積 primorial(10) = "; primorial(10) ' 2 * 3 * 5 * 7 Print Print "100 番目のフィボナッチ数 = "; fib(100) Print Sleep ' 乱数 Print "乱数" Dim As gmp_int array(1 To 2, 1 To 10) For k = 1 To 10 array(1, k) = gmp_rnd(10) array(2, k) = gmp_rnd ' 0 〜 2^32-1 の間の数を返す Next For k = 1 To 10 Print array(1, k), array(2, k) Next Print '整形して出力するために GMP 表示ルーチンを使う 'Gmp_printf( !"%Zd\n", c.num ) Gmp_printf( !"%70Zd\n", c.num ) ' 右詰め70文字。 幅は空白で埋める Gmp_printf( !"%070Zd\n", c.num ) ' 右詰め70文字。 幅はゼロで埋める Print : Print "デモ終了" Sleep End
' version 22/05/2017 'by frisian on May 22, 2017 21:09 'https://www.freebasic.net/forum/viewtopic.php?f=7&t=25684 ' オリジナル by yetifoot 'https://www.freebasic.net/forum/viewtopic.php?t=7173 ' May 2017: srvaldez ' ループコードを修正 ' May 2017: frisian ' 自己責任でお使い下さい ' 注意: このファイルを動かすためには GMP 6.0 32bit が必要です(テスト済み)。 ' GMP 4.0 では動作しません(一部の関数は後で追加された) ' GMP 5.0 ではテストしていません ' ' mpz_mod を mpz_tdiv_r に変更して、mod がデフォルトの FB動作を模倣するようにしました。 ' \(整数除算)と mod の両方で tdiv(切り捨て) ' この動作は、あなたが FB の float 扱いを integer 変換に変更しても、変わりません ' 「ceil 天井」は切り上げ、「floor 床」は切捨て、「round」は四捨五入した結果を返します ' 結果を切捨て(floor) にしたい場合は、mpz_fdiv を使います ' 結果を切り上げ(ceil) にしたい場合は、mpz_cdiv を使います ' ' 浮動小数点の除算(/)から余りを得るには、学校で習った算術が必要です ' remainder = number - (number / divisor) * divisor ' ' 配列と型を作成できます ' swap も機能します ' ' 浮動小数点除算(/)を修正・改良 ' 追加演算子 Shr(SHift Right 右ビットシフト) と Shl(Shift Left 左ビットシフト) を追加 ' コメントのいくつかの誤りを修正し、リストを整理 ' 関数 gmp_int_2_base(gmp_int、n = 2)を追加。基数 2 〜 62 (既定は 10、10進数) の gmp_int 数の文字列を返す ' setbit(gmp_int、n)を追加 (n番目のビットを1に設定) ' clrbit(gmp_int、n)を追加 (n番目のビットを0に設定) ' combit (gmp_int、n) を追加 (n番目のビットを反転 (1 -> 0, 0 -> 1)) ' tstbit (gmp_int, n) を追加 (n番目のビットをテストし、そのビット (0 または 1) を返す) ' root (gmp_int, n = 2) を追加 (default = 2, 平方根) (n次元 root の小数を切り捨てた整数部分を返す) ' root (gmp_int, 3) は立方根 ' rootrem (gmp_int, n = 2) を追加 (gmp_int - root(gmp_int, n) ^ n を返す) ' powm (gmp_int1, n, gmp_int2) を追加 ((gmp_int1 ^ n) mod gmp_int2 を返す) ' isprime (gmp_int, reps) を追加 ' (n が確実に素数なら 2 を返す ' n がおそらく素数なら 1 を返す(特定されていない場合) ' n が確実に素数でないなら 0 を返す ' reps の妥当な値は 15〜50 です(デフォルト= 15)) ' nextprime (gmp_int) を追加 (gmp_int より大きい次の素数を見つける) ' legendre (gmp_int1, gmp_int2) を追加 (ルジャンドル記号 (-1、0、1)を返す) ' ルジャンドル記号とは、a が p の平方剰余か否かを簡潔に表す記号 ' gcd (gmp_int1, gmp_int2) を追加 (最大公約数を返す) ' lcm (gmp_int1, gmp_int2) を追加 (最小公倍数を返す) ' fac (n) を追加 (階乗 n! を返す) ' mfac (n, m) を追加 (m 多重階乗を返す。m 飛ばしの積、n!^(m) = n*(n-m)*(n-2m)*...) ' primorial (n) を追加 (素数積、<= n のすべての正の素数の積を返す) ' fib (n) を追加 (n 番目のフィボナッチ数を返す) ' ' rnd (gmp_int) を追加 (擬似乱数列生成器メルセンヌ・ツイスタ、0 と gmp_int - 1 の間の乱数を返す) ' 数を指定ししないか、数 <= 0 の場合は、数は 2 ^ 32 に設定されます。 ' ルーチンが最初に呼び出されたとき、乱数生成器は種設定されます。 ' タイマーを無作為化すると、毎回種が変わります ' 無作為化を使わないか、または無作為化「数」を実行すると、連続して起こる結果は同じになります(FB rnd と同じ) ' ' setbit, clrbit, combit は値を返しません ' tstbit, gmp_sgn, isprime, legendre は long を返します ' root, rootrem, powm, nextprime, gcd, lcm, fac, mfac, primorial, fib, gmp_rnd は、gmp_int を返す ' ' 多重定義演算子 +=, -=, *=, \=, /=, ^=, Mod=, And=, Or=, Xor=, Shl= ans Shr= to は、gmp_int で動作します ' ' 多重定義 abs(), sgn() は gmp_int で動作します #Ifndef __GMP_INT_BI__ #Define __GMP_INT_BI__ #Include Once "gmp.bi" Type gmp_int Declare Constructor ( ) Declare Constructor ( ByVal i As Long ) Declare Constructor ( ByRef s As String, ByVal _base As Long= 10 ) Declare Constructor ( ByRef g As gmp_int ) Declare Destructor ( ) Declare Operator Let ( ByRef g As gmp_int ) Declare Operator Let ( ByVal i As Long) Declare Operator Let ( ByRef s As String ) Declare Operator Cast ( ) As Long Declare Operator Cast ( ) As String ' For Next Implicit step = +1 Declare Operator For ( ) Declare Operator Step( ) Declare Operator For ( ByRef stp As gmp_int ) Declare Operator Step ( ByRef stp As gmp_int ) Declare Operator Next ( ByRef end_cond As gmp_int ) As Integer Declare Operator Next ( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer Declare Function getString ( ByVal _base As Long = 10 ) As String num As mpz_ptr = 0 Declare Operator += (ByRef rhs As gmp_int) Declare Operator -= (ByRef rhs As gmp_int) Declare Operator *= (ByRef rhs As gmp_int) Declare Operator \= (ByRef rhs As gmp_int) Declare Operator /= (ByRef rhs As gmp_int) Declare Operator ^= (ByVal rhs As Long) Declare Operator Mod= (ByRef rhs As gmp_int) Declare Operator And= (ByRef rhs As gmp_int) Declare Operator Or= (ByRef rhs As gmp_int) Declare Operator Xor= (ByRef rhs As gmp_int) Declare Operator Shl= (ByVal rhs As Long) Declare Operator Shr= (ByVal rhs As Long) End Type Declare Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Function root ( ByRef op As gmp_int, ByVal n As Long = 2 ) As gmp_int Declare Function rootrem ( ByRef op As gmp_int, ByVal n As Long = 2 ) As gmp_int Declare Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As Long ) As gmp_int Declare Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Function powm (ByRef op As gmp_int, ByRef power As gmp_int, ByRef modulus As gmp_int ) As gmp_int Declare Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Declare Operator Shl ( ByRef lhs As gmp_int, ByVal rhs As Long ) As gmp_int Declare Operator Shr ( ByRef lhs As gmp_int, ByVal rhs As Long ) As gmp_int Declare Operator Sgn ( ByRef rhs As gmp_int ) As Long Declare Operator Abs ( ByRef rhs As gmp_int ) As gmp_int Declare Sub setbit ( ByRef op As gmp_int, ByVal n As Long ) Declare Sub clrbit ( ByRef op As gmp_int, ByVal n As Long ) Declare Sub combit ( ByRef op As gmp_int, ByVal n As Long ) Declare Function tstbit ( ByRef op As gmp_int, ByVal n As Long ) As Long Declare Operator - ( ByRef rhs As gmp_int ) As gmp_int Declare Operator Not ( ByRef rhs As gmp_int ) As gmp_int Declare Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Declare Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Declare Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Declare Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Declare Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Declare Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Declare Function gmp_int_2_base (ByRef bigint As gmp_int, ByVal _base As Long = 10 ) As String Declare Function isprime ( ByRef op As gmp_int, ByVal reps As Long = 15 ) As Long Declare Function nextprime ( ByRef op As gmp_int ) As gmp_int Declare Function legendre ( ByRef a As gmp_int , ByRef p As gmp_int ) As Long Declare Function gcd ( ByRef a As gmp_int, ByRef b As gmp_int ) As gmp_int Declare Function lcm ( ByRef a As gmp_int, ByRef b As gmp_int ) As gmp_int Declare Function fac (ByVal n As Long ) As gmp_int Declare Function mfac (ByVal n As Long, ByVal m As Long ) As gmp_int ' result = n!^(m) = n*(n-m)*(n-2m)*... Declare Function primorial (ByVal n As Long ) As gmp_int Declare Function fib ( ByVal n As Long ) As gmp_int Declare Function gmp_rnd ( ByRef max As gmp_int = 0) As gmp_int #EndIf '__GMP_INT_BI__ ':::::::: Constructor gmp_int ( ) num = Callocate( SizeOf( __mpz_struct ) ) mpz_init( num ) End Constructor ':::::::: Constructor gmp_int ( ByVal i As Long ) num = Callocate( SizeOf( __mpz_struct ) ) mpz_init_set_si( num, i ) End Constructor ':::::::: Constructor gmp_int ( ByRef s As String, ByVal _base As Long = 10 ) num = Callocate( SizeOf( __mpz_struct ) ) mpz_init_set_str( num, StrPtr( s ), _base ) End Constructor ':::::::: Constructor gmp_int ( ByRef g As gmp_int ) num = Callocate( SizeOf( __mpz_struct ) ) mpz_init_set( num, g.num ) End Constructor ':::::::: Destructor gmp_int ( ) mpz_clear( num ) DeAllocate( num ) End Destructor ':::::::: Operator gmp_int.let ( ByRef g As gmp_int ) mpz_set( num, g.num ) End Operator ':::::::: Operator gmp_int.let ( ByVal i As Long ) mpz_set_si( num, i ) End Operator ':::::::: Operator gmp_int.let ( ByRef s As String ) mpz_set_str( num, StrPtr(s), 10 ) End Operator Operator gmp_int.cast ( ) As Long Operator = mpz_get_si(num) End Operator ':::::::: Operator gmp_int.cast ( ) As String Operator = getString( 10 ) End Operator '===================================================================== ' Implicit step gmp_int.For gmp_int.Next gmp_int.Step is +1 Operator gmp_int.for ( ) End Operator Operator gmp_int.step ( ) This += 1 'this = this+1 ' End Operator Operator gmp_int.next ( ByRef end_cond As gmp_int ) As Integer Return This <= end_cond End Operator '' explicit step versions '' Operator gmp_int.for ( ByRef step_var As gmp_int ) End Operator Operator gmp_int.step ( ByRef step_var As gmp_int ) This += step_var 'this = this + step_var ' End Operator Operator gmp_int.next ( ByRef end_cond As gmp_int, ByRef step_var As gmp_int ) As Integer If step_var < 0 Then Return This >= end_cond Else Return This <= end_cond End If End Operator ':::::::: Function gmp_int.getString ( ByVal _base As Long = 10 ) As String Dim As ZString Ptr s = mpz_get_str( 0, _base, num ) If s Then Function = *s DeAllocate( s ) End If End Function ':::::::: Operator + ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_add( result.num, lhs.num, rhs.num ) Operator = result End Operator ':::::::: Operator - ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_sub( result.num, lhs.num, rhs.num ) Operator = result End Operator ':::::::: Operator * ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_mul( result.num, lhs.num, rhs.num ) Operator = result End Operator ':::::::: Operator \ ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_tdiv_q( result.num, lhs.num, rhs.num ) Operator = result End Operator ':::::::: Operator / ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int ' これは実際に非常に厄介ですが、浮動小数割り算で思いつくことができる最善の方法です、 ' 丸めは人々が期待する結果をもたらします。 ' 0.5 は 1 に、0.4 は 0 に、-0.5 は -1 に、-0.4 は 0 になります。 ' temp が必要な 100% ではありませんが、それを安全のために使いました。 ' 一部の GMP 関数では、mpz を dest として、また source のひとつとして渡すことは、悪い考えです。 Dim As mpf_ptr l, r, q, half, temp Dim As gmp_int result 'gmp 浮動小数点のサイズが固定されていると、精度が低下する可能性があります 'サイズは mpf_set_default_prec によって、または mpf_init2('var'、size) を使って設定されます 'lhs と rhs のサイズを見つけ、最長のサイズをとり、32ビット(9桁)加えます Dim As UInteger l1 = mpz_sizeinbase ( lhs.num, 2 ) Dim As UInteger r1 = mpz_sizeinbase ( rhs.num, 2 ) If r1 > l1 Then l1 = r1 l1 = l1 +32 l = Callocate( SizeOf( __mpf_struct ) ) r = Callocate( SizeOf( __mpf_struct ) ) q = Callocate( SizeOf( __mpf_struct ) ) half = Callocate( SizeOf( __mpf_struct ) ) temp = Callocate( SizeOf( __mpf_struct ) ) mpf_init2( l, l1 ) ' set the size for l to l1 mpf_init2( r, l1 ) ' set the size for r to l1 mpf_init2( q, l1 ) ' set the size for q to l1 mpf_init_set_d( half, .5 ) mpf_init2( temp, l1 ) ' set the size for temp to l1 mpf_set_z( l, lhs.num ) mpf_set_z( r, rhs.num ) mpf_div( q, l, r ) Dim As Long cmp_val = mpf_cmp_d( q, 0 ) If cmp_val > 0 Then mpf_add( temp, q, half ) ElseIf cmp_val < 0 Then mpf_sub( temp, q, half ) Else mpf_set( temp, q ) End If mpz_set_f( result.num, temp) mpf_clear( l ) mpf_clear( r ) mpf_clear( q ) mpf_clear( half ) mpf_clear( temp ) DeAllocate( l ) DeAllocate( r ) DeAllocate( q ) DeAllocate( half ) DeAllocate( temp ) Operator = result End Operator Function root ( ByRef op As gmp_int, ByVal n As Long = 2 ) As gmp_int Dim As gmp_int result mpz_root( result.num, op.num, n ) Function = result End Function Function rootrem ( ByRef op As gmp_int, ByVal n As Long = 2 ) As gmp_int Dim As gmp_int result, tmp mpz_rootrem( tmp.num, result.num, op.num, n ) Function = result End Function ':::::::: Operator ^ ( ByRef lhs As gmp_int, ByVal rhs As Long ) As gmp_int Dim As gmp_int result mpz_pow_ui( result.num, lhs.num, rhs ) Operator = result End Operator Operator Mod ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_tdiv_r( result.num, lhs.num, rhs.num ) Operator = result End Operator Function powm ( ByRef _base As gmp_int, ByRef power As gmp_int, ByRef modulus As gmp_int ) As gmp_int Dim As gmp_int result mpz_powm( result.num, _base.num, power.num, modulus.num ) Return result End Function ':::::::: Operator And ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_and( result.num, lhs.num, rhs.num ) Operator = result End Operator ':::::::: Operator Or ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_ior( result.num, lhs.num, rhs.num ) Operator = result End Operator ':::::::: Operator Xor ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_xor( result.num, lhs.num, rhs.num ) Operator = result End Operator Operator Shl ( ByRef lhs As gmp_int, ByVal rhs As Long ) As gmp_int Dim As gmp_int result mpz_mul_2exp( result.num, lhs.num, rhs ) Operator = result End Operator Operator Shr ( ByRef lhs As gmp_int, ByVal rhs As Long ) As gmp_int Dim As gmp_int result mpz_tdiv_q_2exp( result.num, lhs.num, rhs ) Operator = result End Operator Operator Sgn ( ByRef rhs As gmp_int ) As Long Return mpz_sgn( rhs.num ) End Operator Operator Abs ( ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_abs(result.num, rhs.num ) Return result End Operator Sub setbit ( ByRef op As gmp_int, ByVal n As Long) mpz_setbit( op.num, n ) End Sub Sub clrbit ( ByRef op As gmp_int, ByVal n As Long) mpz_clrbit( op.num, n ) End Sub Sub combit ( ByRef op As gmp_int, ByVal n As Long) mpz_combit( op.num, n ) End Sub Function tstbit ( ByRef op As gmp_int, ByVal n As Long) As Long ' return 0 if the bit is 0 and 1 if the bit is 1 Return mpz_tstbit( op.num, n ) End Function ':::::::: Operator - ( ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_neg( result.num, rhs.num ) Operator = result End Operator ':::::::: Operator Not ( ByRef rhs As gmp_int ) As gmp_int Dim As gmp_int result mpz_com( result.num, rhs.num ) Operator = result End Operator ':::::::: Operator = ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Operator = (mpz_cmp( lhs.num, rhs.num ) = 0) End Operator ':::::::: Operator < ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Operator = (mpz_cmp( lhs.num, rhs.num ) < 0) End Operator ':::::::: Operator > ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Operator = (mpz_cmp( lhs.num, rhs.num ) > 0) End Operator ':::::::: Operator <= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Operator = (mpz_cmp( lhs.num, rhs.num ) <= 0) End Operator ':::::::: Operator >= ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Operator = (mpz_cmp( lhs.num, rhs.num ) >= 0) End Operator ':::::::: Operator <> ( ByRef lhs As gmp_int, ByRef rhs As gmp_int ) As Long Operator = (mpz_cmp( lhs.num, rhs.num ) <> 0) End Operator Operator gmp_int.+= (ByRef rhs As gmp_int) mpz_add(This.num, this.num, rhs.num) End Operator Operator gmp_int.-= (ByRef rhs As gmp_int) mpz_sub(This.num, this.num, rhs.num) End Operator Operator gmp_int.*= (ByRef rhs As gmp_int) mpz_mul(This.num, this.num, rhs.num) End Operator Operator gmp_int.\= (ByRef rhs As gmp_int) mpz_tdiv_q(This.num, this.num, rhs.num) End Operator Operator gmp_int./= (ByRef rhs As gmp_int) This = This / rhs End Operator Operator gmp_int.^= (ByVal rhs As Long) mpz_pow_ui(This.num, this.num, rhs) End Operator Operator gmp_int.mod= (ByRef rhs As gmp_int) mpz_tdiv_r( this.num, this.num, rhs.num ) End Operator Operator gmp_int.And= (ByRef rhs As gmp_int) mpz_and(This.num, this.num, rhs.num) End Operator Operator gmp_int.Or= (ByRef rhs As gmp_int) mpz_ior(This.num, this.num, rhs.num) End Operator Operator gmp_int.Xor= (ByRef rhs As gmp_int) mpz_xor(This.num, this.num, rhs.num) End Operator Operator gmp_int.shl= (ByVal rhs As Long) mpz_mul_2exp(This.num, this.num, rhs) End Operator Operator gmp_int.Shr= (ByVal rhs As Long) mpz_tdiv_q_2exp(This.num, this.num, rhs) End Operator ' 基数 2 〜 62(デフォルト10、10進数)の gmp_int 数の文字列を返します。 Function gmp_int_2_base (ByRef bigint As gmp_int, ByVal _base As Long = 10 ) As String Dim As ZString Ptr s = mpz_get_str( 0, _base, bigint.num ) If s Then Function = *s DeAllocate( s ) End If End Function Function isprime ( ByRef op As gmp_int, ByVal reps As Long = 15 ) As Long ' n が確実に素数なら 2 を返す ' n がおそらく素数なら 1 を返す(特定されていない場合) ' n が確実に素数でないなら 0 を返す ' reps の妥当な値は 15〜50 です(デフォルト= 15)) If reps < 15 Then reps = 15 Function = mpz_probab_prime_p ( op.num, reps ) End Function Function nextprime ( ByRef op As gmp_int ) As gmp_int Dim As gmp_int result mpz_nextprime( result.num , op.num) Function = result End Function Function legendre (ByRef a As gmp_int , ByRef p As gmp_int ) As Long ' p needs to be a odd positive prime Function = mpz_legendre ( a.num, p.num) End Function Function gcd ( ByRef a As gmp_int, ByRef b As gmp_int ) As gmp_int Dim As gmp_int result mpz_gcd( result.num, a.num, b.num ) Function = result End Function Function lcm ( ByRef a As gmp_int, ByRef b As gmp_int ) As gmp_int Dim As gmp_int result mpz_lcm( result.num, a.num, b.num ) Function = result End Function Function fac (ByVal n As Long ) As gmp_int Dim As gmp_int result mpz_fac_ui( result.num , n ) Function = result End Function Function mfac (ByVal n As Long, ByVal m As Long ) As gmp_int ' result = n!^(m) = n*(n-m)*(n-2m)*... Dim As gmp_int result mpz_mfac_uiui ( result.num, n, m ) Function = result End Function Function primorial (ByVal n As Long ) As gmp_int Dim As gmp_int result mpz_primorial_ui (result.num, n ) Function = result End Function Function fib ( ByVal n As Long ) As gmp_int Dim As gmp_int result mpz_fib_ui ( result.num, n) Function = result End Function ' -= Random number generator stuff (integer) =- Type gmp_random Declare Constructor ( ) Declare Destructor ( ) g_rnd As Any Ptr End Type Constructor gmp_random ( ) g_rnd = Callocate( SizeOf ( __gmp_randstate_struct ) ) gmp_randinit_mt ( g_rnd ) ' Mersenne Twister End Constructor Destructor gmp_random ( ) gmp_randclear ( g_rnd ) DeAllocate ( g_rnd ) End Destructor Function gmp_rnd ( ByRef max As gmp_int = 0 ) As gmp_int Static state As gmp_random Static flag As Long If flag = 0 Then Dim As String seed_str Dim As gmp_int seed For i As Long = 0 To 200 ' create seed seed_str += Str( Int( Rnd * 10 ) ) Next seed = seed_str Gmp_randseed ( state.g_rnd, seed.num ) ' seed the random generator flag = 1 End If If max <= 0 Then max = 2 max ^= 32 ' 2 ^ 32 End If Dim As gmp_int result Mpz_urandomm ( result.num , state.g_rnd, max.num ) Function = result End Function