Prjalp コーディング要点

  alpasm.h             ヘッダファイル（四則演算、数値編集、比較）
  alpinc.h             ヘッダファイル（組込み関数）

下記内容と、上記のヘッダファイルに書かれていることを合わせて参照してください。

1.多倍長数値の計算エリア
 クワード単位(1クワード=8バイト)で確保したエリアを利用して多倍長演算を行います。

   1) Prjalp内部に8192クワードを用意しているので初期化して利用します。

 __int64 iii;

 iii = _mm_arini99(1024);

   長さ1024のエリアを初期化して利用する。iii には 初期化したエリア個数が設定される。
   エリアを参照するには、_mm_adr99(n)で取得したアドレスを利用します。(0 ≦ n ≦ iii -1)

    __int64 *adr0, *adr1, *adr2, *adr3, *adr4, *adr5, *adr6, *adr7;
    ,,,
    
    adr0 = _mm_adr99(0);
    adr1 = _mm_adr99(1);
    ,,,
    adr7 = _mm_adr99(7);
    
    _a_struztor(adr0, 0, (char*)"123.45678901234567890");   /* アドレスadr0に123.45678901234567890を設定する) */

    adr0を利用することなく_mm_adr99(0)を直接記述しても結果は同じです。

    _a_struztor(_mm_adr99(0), 0, (char*)"123.45678901234567890");

   2) Prjalpを利用する側で用意したエリアを利用する場合は
 
    __int64 bigarea[32767];   /* 長さ 32767 の多倍長数値の計算エリア */
    __int64 iii;
    __int64 *tadr;
    
    ,,,
   iii = _mm_aruini(bigarea, 32767, 100); /* 単位長 100 の多倍長数値の計算エリアを初期化 */

   tadr = mm_adru(bigarea, iii - 1);      /* bigareaに初期化した最後のエリアのアドレスをtadrに設定する */

2.多倍長数値の計算精度と必要な長さ

   1)固定小数点位置での演算

   計算精度は京＾ｎで指定します。京=10000000000000000=10^16
   ｎ＝-1のときの最小値は1/10000000000000000なので小数点以下16桁での演算です。
   ,,,
   ｎ＝-100のときは小数点以下1600桁での演算です。
 
   多倍長演算で必要となるエリアの単位長は計算精度によってある程度決まりますが、
   計算精度を高めるときはできるだけ大きくとってください。

   整数部の桁数＋小数点以下の桁数＋演算時のワークエリア
   ・小数点以下の桁数       ｎ×0.844 + 1           京＾|ｎ|のクワード数
   ・整数部の桁数           １クワード              ※2(整数部の最大値 18446744073709551615)
   ・演算時のワークエリア   ４クワード              ※3(最小)
 
   ｎ＝-100のときは
     100 × 0.844 + 1 + 1 + 4 = 90(最小)
   余裕を持って
     100 × 2 = 200 (推奨)

   演算結果が確保したエリアの大きさを超えた場合はエラーとなります。

2)格納するエリアの最大長での演算
 乗算、除算で数値が格納できる大きさを超えた場合は格納エリアに収まる様に丸めて演算します。
 


3.多倍長数値の四則演算
  多倍長数値は「指数値×整数」の形式で格納しています。

3-1.多倍長数値と多倍長数値の四則演算
  1)加算、減算は指数値が一致している数値同士のみで可能です。

__int64	_b_sub(__int64* p1, __int64* p2);
//
//	多倍長形式数値の減算
//
//   p1(rcx) 減算される多倍長形式数値のアドレス
//   p2(rdx) 減算する多倍長形式数値のアドレス
//
//   戻り
//       0   正常終了
//		-1	処理できない(エリア不足、指数値が不一致))
//
__int64	_b_add(__int64* p1, __int64* p2);
//
//	多倍長形式数値の加算
//
//   p1(rcx) 加算される多倍長形式数値のアドレス
//   p2(rdx) 加算する多倍長形式数値のアドレス
//
//   戻り
//       0   正常終了
//		-1	処理できない(エリア不足、指数値が不一致)
//

    →指数値が不一致の場合は一方の多倍長数値の指数値を調整して演算します。
__int64	_a_adjnums(__int64* p1, __int64 p2);
//
//   多倍長形式の数値の指数値を調整する
//
//   p1(rcx) 数値のアドレス
//   p2(rdx) 調整後の指数値
//
//   戻り
//       0   正常終了
//       -1  数値部の確保サイズが足りない
//

   2)乗算は２数の整数の積と２数の指数を加算して指数または桁数調整します。

__int64	_b_mulrnd(__int64* p1, __int64* p2, __int64 p3);
//
//	多倍長形式の数値を乗算して指定の計算精度に丸める
//
//   p1(rcx) 乗算される多倍長形式数値のアドレス
//   p2(rdx) 乗算する多倍長形式数値のアドレス
//   p3(r8)  計算精度(指数値)
//
//   戻り
//       0   正常終了
//       -1  計算出来ない、エリア不足
//
__int64	_b_mulrndsz(__int64* p1, __int64* p2);
//
//	多倍長形式の数値を乗算する
//	エリア不足のときは格納可能なサイズに丸める(指数値を増加させる)
//
//   p1(rcx) 乗算される多倍長形式数値のアドレス
//   p2(rdx) 乗算する多倍長形式数値のアドレス
//
//	戻り
//		1～	丸めた桁数
//		-1	処理できない、エリア不足（スタックエリアを確保できない）
//

   3)除算は割られる数の整数の指数調整をまたは桁数調整して商を求めます。

__int64	_b_divrnd(__int64* p1, __int64* p2,  __int64 p3);
//
//	多倍長形式の数値を指定の計算精度で除算する
//
//   p1(rcx) 除算される多倍長形式数値のアドレス
//   p2(rdx) 除算する多倍長形式数値のアドレス
//	p3(r8)	計算制度(指数値)
//
//   戻り
//       0   正常終了
//       -1  計算できない、ゼロ割、エリア不足
//
__int64	_b_divrndsz(__int64* p1, __int64* p2);
//
//	多倍長形式の数値を格納可能な計算精度で除算する
//
//   p1(rcx) 除算される多倍長形式数値のアドレス
//   p2(rdx) 除算する多倍長形式数値のアドレス
//
//	戻り
//		0	正常終了
//		-1	処理できない、エリア不足（スタックエリアを確保できない）
//

3-2.多倍長数値と６４ビット数値の四則演算
   四則演算される側の「整数」に対して四則演算します。

__int64	_b_mulnum(__int64* p1, __int64 p2);
//
//   多倍長形式の数値に符号なし６４ビット数値を乗ずる
//
//   p1(rcx) 多倍長形式数値のアドレス
//   p2(rdx) ６４ビット数値
//
//   戻り
//       0   正常終了
//       1   指数調整をした
//       -1  計算出来ない
//
__int64	_b_divnum(__int64* p1, __int64 p2);
//
//	多倍長形式の数値を符号なし６４ビット数値で除算する
//
//   p1(rcx) 多倍長形式数値のアドレス
//   p2(rdx) ６４ビット数値
//
//   戻り
//       0   正常終了
//       -1  計算出来ない、ゼロ割
//
__int64	_b_addnum(__int64* p1, __int64 p2);
//
//
//	多倍長形式の数値に６４ビット数値を加算する
//
//   p1(rcx) 多倍長形式数値のアドレス
//   p2(rdx) ６４ビット数値
//
//   戻り
//       0   正常終了
//       1   桁上がりが発生
//
__int64	_b_subnum(__int64* p1, __int64 p2);
//
//	多倍長形式の数値から６４ビット数値を減算する
//
//   p1(rcx) 多倍長形式数値のアドレス
//   p2(rdx) ６４ビット数値
//
//   戻り
//       0   正常終了
//       -1  処理できない(エリア不足)
//

3-3.多倍長数値の代入

__int64	_a_numovnum(__int64* p1, __int64* p2);
//
//   多倍長形式の数値を複写先のエリアに上書きする
//
//   p1(rcx) 複写先
//   p2(rdx) 複写元
//
//   戻り
//       0   正常終了
//       -1  複写先の確保サイズが足りない
//

__int64	_a_numtonum(__int64* p1, __int64 *p2, __int64 p3);
//
//   多倍長形式の数値を複写する
//
//   p1(rcx) 複写先
//   p2(rdx) 複写元
//   p3(r8)  複写先の確保サイズ
//
//   戻り
//       0   正常終了
//       -1  複写先の確保サイズが足りない
//


3-4.多倍長数値の大小判定

   1)多倍長数値 ⇔ 多倍長数値

__int64	_c_cmprnum(__int64* p1, __int64* p2);
//
//	数値の大小比較
//
//	p1(rcx)	数値１
//	p2(rdx)	数値２
//
//	戻り
//		-1	数値１ ＜ 数値２
//		0	数値１ ＝ 数値２
//		1	数値１ ＞ 数値２
//
__int64	_c_cmpabs(__int64* p1, __int64* p2);
//
//	数値の絶対値の大小比較
//
//	p1(rcx)	数値１
//	p2(rdx)	数値２
//
//	戻り
//		-1	数値１ ＜ 数値２
//		0	数値１ ＝ 数値２
//		1	数値１ ＞ 数値２
//

   2)多倍長数値 ⇔京＾ｎの比較 （主に収束の判定に利用）

__int64	_c_cmpexp(__int64* p1, __int64 p2);
//
//	数値の絶対値と京＾ｎの比較
//
//	p1(rcx)	数値
//	p2(rdx)	ｎ
//
//	戻り
//		-1	数値 ＜ 京＾ｎ
//		0	数値 ＝ 京＾ｎ
//		1	数値 ＞ 京＾ｎ
//
__int64 _c_cmpdexp(__int64* p1, __int64 *p2, __int64 p3);
//
//	２つの数値の差分の絶対値と京＾ｎの比較
//
//	p1(rcx)	数値１
//	p2(rdx)	数値２
//	p3(r8)	ｎ
//
//	戻り
//		-1	｜数値１－数値２｜ ＜ 京＾ｎ
//		0	｜数値１－数値２｜ ＝ 京＾ｎ
//		1	｜数値１－数値２｜ ＞ 京＾ｎ
//

   3)多倍長数値の正負、ゼロ判定

__int64	_c_zero(__int64* p1);
//
//	数値のゼロを判定する
//
//	p1(rcx)	数値
//
//	戻り
//		-1	数値 ＜ 0
//		0	数値 ＝ 0
//		1	数値 ＞ 0
//
__int64	_c_valid(__int64* p1);
//
//	有効数値か否かの判定
//
//	p1(rcx)	数値
//
//	戻り
//		0	初期化された数値
//		1	有効値
//		-1	判定不能
//

4.多倍長数値の変換

4-1.文字列、６４ビット数値

   1)文字列で表現された数値

__int64	_a_struztor(__int64* p1, __int64 p2, char* p3);
//
//
//	文字列で表現された数値を多倍長形式に変換して取込む
//	【書式】
// [±] 数字 [[.]数字] [e[±]数字]
//
//	p1(rcx)	取込み先のアドレス
//	p2(rdx)	取込み先の大きさ(クワード数)(0,3～)
//          0のときは確保済みの大きさ
//	p3(r8)	文字列のアドレス('\0'までが対象)
//
//	戻り
//		0   正常終了
//       -1  変換できない
//

   2)６４ビット数値

__int64	_a_numbintor(__int64* p1, __int64 p2, __int64 p3, __int64 p4);
//
//	符号付き６４ビット数値を指定の計算精度で多倍長形式に変換して取込む
//   【計算精度】
//       計算精度 = -1のとき0.0000000000000001(1 / 10 ^ 16)が最小単位
//
//	p1(rcx)	取込み先のアドレス
//	p2(rdx)	取込み先の大きさ(クワード数)(0, 3～)
//           0のときは確保済のエリアに設定する
//	p3(r8)	６４ビット数値
//	p4(r9)	計算精度
//
//	戻り
//		0   正常終了
//       -1  変換できない(エリア不足)
//

4-2.多倍長数値を文字列に変換

char* _a_prtnum(__int64* p1);
//
//   多倍長形式の数値を編集して出力する(最高　約16000桁)
//
//   p1(rcx) 数値のアドレス
//
//   戻り
//       変換結果を格納したアドレス
//
char	*_a_prtenum(__int64* p1, __int64 p2);
//
//   多倍長形式の数値をｅ変換して指定の仮数桁数で出力する
//
//   p1(rcx) 数値のアドレス
//   p2(rdx) 仮数部の桁数
//
//   戻り
//       変換結果を格納したアドレス
//


5.組込関数
alpinc.h を参照


6.その他

1)サンプルプログラムは自由に改変してかまいません。
  また、ほとんどの関数で戻りコードの判定なして記述しています。
　必要に応じて戻りコードの判定を入れたロジックにしてください。

2)デバッグが必要な場合は 4-2, の _a_prtnum、_a_prtenum をロジックに挿入して確認してください。

3)Prjalpは西暦２０００年頃から趣味でＭＡＳＭのプログラミングを始めたのがきっかけで、仕事の合間に作成しました。
 当初は１６ビットの8086のＭＡＳＭでしたが３２ビットＭＡＳＭ、６４ビットＭＡＳＭに発展しました。

 開発は　ＭＡＳＭ６４ ９０％　ＣＰＰ（Ｃ＋＋）　１０％　です。
 

以上


2026.5.24(大安) by Boke-jisan