xeij/EFPBox.java (1/3)
1 2 3//========================================================================================
// EFPBox.java
// en:Floating-point number box -- Floating-point calculation and floating-point registers
// ja:浮動小数点数箱 -- 浮動小数点演算と浮動小数点レジスタ
// Copyright (C) 2003-2026 Makoto Kamada
//
// This file is part of the XEiJ (X68000 Emulator in Java).
// You can use, modify and redistribute the XEiJ if the conditions are met.
// Read the XEiJ License for more details.
// https://stdkmd.net/xeij/
//========================================================================================
package xeij;
import java.lang.*; //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
import java.util.*; //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,Timer,TimerTask,TreeMap
public class EFPBox {
//浮動小数点拡張命令
// 実験のみ。常用しないこと
// $xx70: FLGAMMA *m,FPn
// $xx71: FTGAMMA *m,FPn
// 三角関数
// sin 正弦 sine サイン
// cos 余弦 cosine コサイン
// tan 正接 tangent タンジェント
// cot 余接 cotangent コタンジェント
// sec 正割 secant セカント
// csc 余割 cosecant コセカント
// 逆三角関数
// asin 逆正弦 inverse sine インバースサイン
// acos 逆余弦 inverse cosine インバースコサイン
// atan 逆正接 inverse tangent インバースタンジェント
// acot 逆余接 inverse cotangent インバースコタンジェント
// asec 逆正割 inverse secant インバースセカント
// acsc 逆余割 inverse cosecant インバースコセカント
// 双曲線関数
// sinh 双曲線正弦 hyperbolic sine ハイパボリックサイン
// cosh 双曲線余弦 hyperbolic cosine ハイパボリックコサイン
// tanh 双曲線正接 hyperbolic tangent ハイパボリックタンジェント
// coth 双曲線余接 hyperbolic cotangent ハイパボリックコタンジェント
// sech 双曲線正割 hyperbolic secant ハイパボリックセカント
// csch 双曲線余割 hyperbolic cosecant ハイパボリックコセカント
// 逆双曲線関数
// asinh 逆双曲線正弦 inverse hyperbolic sine インバースハイパボリックサイン
// acosh 逆双曲線余弦 inverse hyperbolic cosine インバースハイパボリックコサイン
// atanh 逆双曲線正接 inverse hyperbolic tangent インバースハイパボリックタンジェント
// acoth 逆双曲線余接 inverse hyperbolic cotangent インバースハイパボリックコタンジェント
// asech 逆双曲線正割 inverse hyperbolic secant インバースハイパボリックセカント
// acsch 逆双曲線余割 inverse hyperbolic cosecant インバースハイパボリックコセカント
// その他
// lgamma ログガンマ関数
// tgamma ガンマ関数
public static final boolean EPB_EXTRA_OPERATION = true; //true=浮動小数点拡張命令を追加する
//------------------------------------------------------------------------
//モード
public static final int EPB_MODE_MC68881 = 1 << 1; //MC68881
public static final int EPB_MODE_MC68882 = 1 << 2; //MC68882
public static final int EPB_MODE_MC68060 = 1 << 6; //MC68060
public static final int EPB_MODE_FULLSPEC = EPB_MODE_MC68881 | EPB_MODE_MC68882 | EPB_MODE_MC68060;
public static final int EPB_MODE_EXTENDED = 1 << 8; //拡張精度
public static final int EPB_MODE_TRIPLE = 1 << 9; //三倍精度
public int epbMode;
//------------------------------------------------------------------------
//フラグ flg
public static final int P = 0 << 31; //+
public static final int M = 1 << 31; //-
public static final int Z = 1 << 30; //±0
public static final int I = 1 << 29; //±Inf
public static final int N = 1 << 28; //±NaN
//------------------------------------------------------------------------
//FPCR
// exception enable byte
public static final int EPB_FPCR_BS = 1 << 15; //BSUN branch/set on unordered
public static final int EPB_FPCR_SN = 1 << 14; //SNAN signaling not a number
public static final int EPB_FPCR_OE = 1 << 13; //OPERR operand error
public static final int EPB_FPCR_OF = 1 << 12; //OVFL overflow
public static final int EPB_FPCR_UF = 1 << 11; //UNFL underflow
public static final int EPB_FPCR_DZ = 1 << 10; //DZ divide by zero
public static final int EPB_FPCR_X2 = 1 << 9; //INEX2 inexact operation
public static final int EPB_FPCR_X1 = 1 << 8; //INEX1 inexact decimal input
// rounding precision
public static final int EPB_FPCR_PX = 0 << 6; //extended
public static final int EPB_FPCR_PS = 1 << 6; //single
public static final int EPB_FPCR_PD = 2 << 6; //double
// 3 << 6; //double
// rounding mode
public static final int EPB_FPCR_RN = 0 << 4; //to nearest
public static final int EPB_FPCR_RZ = 1 << 4; //toward zero
public static final int EPB_FPCR_RM = 2 << 4; //toward minus infinity
public static final int EPB_FPCR_RP = 3 << 4; //toward plus infinity
public static final int EPB_FPCR_ALL = 0x0000fff0;
public int epbFpcr;
//------------------------------------------------------------------------
//FPSR
// FPSRのEXCとAEXCを同時にセットする方法はAEXC_UNFL|=EXC_UNFL&EXC_INEX2の&を処理しにくいので、
// 命令実行後にテーブルを使ってEXCをAEXCに反映させる方法に変更した
// condition code byte
public static final int EPB_FPSR_M = 1 << 27; //N negative
public static final int EPB_FPSR_Z = 1 << 26; //Z zero
public static final int EPB_FPSR_I = 1 << 25; //INF infinity
public static final int EPB_FPSR_N = 1 << 24; //NAN not a number or unordered
// quotient byte
public static final int EPB_FPSR_S = 1 << 23; //sign of quotient
public static final int EPB_FPSR_Q = 127 << 16; //quotient
// exception status byte
public static final int EPB_FPSR_BS = 1 << 15; //BSUN branch/set on unordered
public static final int EPB_FPSR_SN = 1 << 14; //SNAN signaling not a number
public static final int EPB_FPSR_OE = 1 << 13; //OPERR operand error
public static final int EPB_FPSR_OF = 1 << 12; //OVFL overflow
public static final int EPB_FPSR_UF = 1 << 11; //UNFL underflow
public static final int EPB_FPSR_DZ = 1 << 10; //DZ divide by zero
public static final int EPB_FPSR_X2 = 1 << 9; //INEX2 inexact operation
public static final int EPB_FPSR_X1 = 1 << 8; //INEX1 inexact decimal input
// accrued exception byte
public static final int EPB_FPSR_AV = 1 << 7; //IOP invalid operation AV|=BS|SN|OE
public static final int EPB_FPSR_AO = 1 << 6; //OVFL overflow AO|=OF
public static final int EPB_FPSR_AU = 1 << 5; //UNFL underflow AU|=UF&X2
public static final int EPB_FPSR_AZ = 1 << 4; //DZ divide by zero AZ|=DZ
public static final int EPB_FPSR_AX = 1 << 3; //INEX inexact AX|=OF|X2|X1
public static final int EPB_FPSR_ALL = 0x0ffffff8;
public int epbFpsr;
//------------------------------------------------------------------------
//FPIAR instruction address register
public int epbFpiar;
//------------------------------------------------------------------------
//商
public int epbQuotient; //remの商の下位32bit
//------------------------------------------------------------------------
//丸め桁数
public static final int EPB_PREC_EXD = 0; //extended
public static final int EPB_PREC_SGL = 1; //single
public static final int EPB_PREC_DBL = 2; //double
public static final int EPB_PREC_DBL3 = 3; //double
//
public static final int EPB_PREC_TPL = 4; //triple
public static final int EPB_PREC_XSG = 5; //xsingle
public static final int EPB_PREC_EFP = 6; //efp
public int epbRoundingPrec; //丸め桁数
//------------------------------------------------------------------------
//丸めモード
public static final int EPB_MODE_RN = 0; //To nearest
public static final int EPB_MODE_RZ = 1; //Toward zero
public static final int EPB_MODE_RM = 2; //Toward minus infinity
public static final int EPB_MODE_RP = 3; //Toward plus infinity
public int epbRoundingMode; //丸めモード
//------------------------------------------------------------------------
//例外オペランド
// 例外発生時のオペランド
// MC68060のステートフレームに書き込まれる
// MC68060UM 6.7 FLOATING-POINT STATE FRAMESを参照
// BSUN
// 不定
// SNAN/OPERR/DZ
// ソースオペランド
// OVFL
// 中間結果。ただし指数部のバイアスが$3FFFではなくて$3FFF-$6000になる。それでも収まらなければ$0
// UNFL
// 中間結果。ただし指数部のバイアスが$3FFFではなくて$3FFF+$6000になる。それでも収まらなければ$0
// INEX
// INEX単独では不定。他の例外もあればそれに従う
public int epbExceptionOperandExponent; //extendedの指数部<<16
public long epbExceptionOperandMantissa; //extendedの仮数部
public int epbExceptionStatusWord; //MC68060の浮動小数点ステートフレームのステータスワード
//------------------------------------------------------------------------
//内部丸め
// 関数が内部で他の関数を複数回呼び出すとき、途中の計算を最大精度で行うため一時的に丸め桁数と丸めモードを変更する
// 同じEFPBoxのインスタンスを複数のスレッドで同時に使用すると誤動作する可能性がある
public int epbRoundingDepth; //深さ
public int epbRoundingOuterPrec; //epbRoundingDepth==0のときのepbRoundingPrec
public int epbRoundingOuterMode; //epbRoundingDepth==0のときのepbRoundingMode
//------------------------------------------------------------------------
//レジスタ
public static final int EPB_SRC_TMP = 8; //ソース用テンポラリレジスタ
public static final int EPB_DST_TMP = 9; //デスティネーション用テンポラリレジスタ
public static final int EPB_CONST_START = 10; //定数レジスタ0
public EFP[] epbFPn; //浮動小数点レジスタ
//------------------------------------------------------------------------
//定数
public static final HashMap<String,Integer> epbConstLongMap = new HashMap<String,Integer> (); //ロング定数
static {
//IOCSコール名(0x00~0xff)
for (int i = 0; i < Disassembler.DIS_IOCS_NAME.length; i++) {
String name = Disassembler.DIS_IOCS_NAME[i];
if (name.length () > 0) {
epbConstLongMap.put (name.toLowerCase (), i);
}
}
//SXコール名(0xa000~0xa7ff)
for (int i = 0; i < Disassembler.DIS_SXCALL_NAME.length; i++) {
String name = Disassembler.DIS_SXCALL_NAME[i];
if (name.length () > 0) {
epbConstLongMap.put (name.toLowerCase (), 0xa000 + i);
}
}
//FEファンクションコール名(0xfe00~0xfeff)
for (int i = 0; i < Disassembler.DIS_FPACK_NAME.length; i++) {
String name = Disassembler.DIS_FPACK_NAME[i];
if (name.length () > 0) {
epbConstLongMap.put (name.toLowerCase (), 0xfe00 + i);
}
}
//DOSコール名(0xff00~0xffff)
for (int i = 0; i < Disassembler.DIS_DOS_NAME.length; i++) {
String name = Disassembler.DIS_DOS_NAME[i];
if (name.length () > 0) {
epbConstLongMap.put (name.toLowerCase (), 0xff00 + i);
}
}
} //static
//------------------------------------------------------------------------
//コンストラクタ
public EFPBox () {
//モード
epbMode = EPB_MODE_EXTENDED | EPB_MODE_MC68882; //拡張精度、MC68882
//乱数
//epbRandSeed = 25214903917L; //乱数の種(48bit)
epbRandSeed = System.currentTimeMillis () & (1L << 48) - 1L; //乱数の種(48bit)
//浮動小数点レジスタ
epbFPn = new EFPBox.EFP[EPB_CONST_START + 128]; //FPn。[0]~[7]は汎用、[8]~[9]はテンポラリ、[10]~[137]は定数
for (int i = 0; i < epbFPn.length; i++) {
epbFPn[i] = new EFP ();
}
//定数
// FMOVECRはFPCRのrounding precisionとrounding modeの影響を受ける
// 使用時に丸める場合は定数を予めextendedに丸めた状態で格納してはならない
// rounding modeとrounding precisionのすべての組み合わせを展開しておいて定数の開始インデックスで区別する方法もある
// 060turboのROMはFMOVECR.X #$01,FP0の結果が0かどうかで68881と68882を見分けている
epbFPn[EPB_CONST_START + 0x00].sete (PI); //0x00 pi
epbSetROMSub (); //ROMオフセット0x01~0x0aを設定する
epbFPn[EPB_CONST_START + 0x0b].sete (LOG10_2); //0x0b log10(2) MC68882はRNの値が間違っている
epbFPn[EPB_CONST_START + 0x0c].sete (E); //0x0c e MC68882はRNの値が間違っている
epbFPn[EPB_CONST_START + 0x0d].sete (LOG2_E); //0x0d log2(e)
epbFPn[EPB_CONST_START + 0x0e].sete (LOG10_E); //0x0e log10(e) MC68882はRPの値が間違っている。MC68882はINEX2がセットされない
epbFPn[EPB_CONST_START + 0x0f].set0 (); //0x0f 0
epbFPn[EPB_CONST_START + 0x30].sete (LOG_2); //0x30 log(2)
epbFPn[EPB_CONST_START + 0x31].sete (LOG_10); //0x31 log(10)
epbFPn[EPB_CONST_START + 0x32].set1 (); //0x32 1
epbFPn[EPB_CONST_START + 0x33].sete (TEN); //0x33 10
epbFPn[EPB_CONST_START + 0x34].sete (TENXP1); //0x34 10^(2^1)=10^2=100
epbFPn[EPB_CONST_START + 0x35].sete (TENXP2); //0x35 10^(2^2)=10^4=10000
epbFPn[EPB_CONST_START + 0x36].sete (TENXP3); //0x36 10^(2^3)=10^8=100000000
epbFPn[EPB_CONST_START + 0x37].sete (TENXP4); //0x37 10^(2^4)=10^16
epbFPn[EPB_CONST_START + 0x38].sete (TENXP5); //0x38 10^(2^5)=10^32
epbFPn[EPB_CONST_START + 0x39].sete (TENXP6); //0x39 10^(2^6)=10^64
epbFPn[EPB_CONST_START + 0x3a].sete (TENXP7); //0x3a 10^(2^7)=10^128
epbFPn[EPB_CONST_START + 0x3b].sete (TENXP8); //0x3b 10^(2^8)=10^256
epbFPn[EPB_CONST_START + 0x3c].sete (TENXP9); //0x3c 10^(2^9)=10^512
epbFPn[EPB_CONST_START + 0x3d].sete (TENXP10); //0x3d 10^(2^10)=10^1024
epbFPn[EPB_CONST_START + 0x3e].sete (TENXP11); //0x3e 10^(2^11)=10^2048
epbFPn[EPB_CONST_START + 0x3f].sete (TENXP12); //0x3f 10^(2^12)=10^4096
//その他
epbReset ();
//コプロセッサインタフェイス
cirInit ();
}
//epbSetROMSub ()
// ROMオフセット0x01~0x0aを設定する
public final void epbSetROMSub () {
if ((epbMode & EPB_MODE_MC68882) != 0) { //MC68882、フルスペック
epbFPn[EPB_CONST_START + 0x01].setx012 (0x40010000, 0xfe00068200000000L); //0x01 (MC68882)
epbFPn[EPB_CONST_START + 0x02].setx012 (0x40010000, 0xffc0050380000000L); //0x02 (MC68882)
//epbFPn[EPB_CONST_START + 0x03].setx012 (0x20000000, 0x7fffffff00000000L); //0x03 (MC68882) Nがセットされる。表現できないのでNaNにする
epbFPn[EPB_CONST_START + 0x03].setnan ();
epbFPn[EPB_CONST_START + 0x04].setx012 (0x00000000, 0xffffffffffffffffL); //0x04 (MC68882)
epbFPn[EPB_CONST_START + 0x05].setx012 (0x3c000000, 0xfffffffffffff800L); //0x05 (MC68882)
epbFPn[EPB_CONST_START + 0x06].setx012 (0x3f800000, 0xffffff0000000000L); //0x06 (MC68882)
//epbFPn[EPB_CONST_START + 0x07].setx012 (0x00010000, 0xf65d8d9c00000000L); //0x07 (MC68882) Nがセットされる。表現できないのでNaNにする
epbFPn[EPB_CONST_START + 0x07].setnan ();
//epbFPn[EPB_CONST_START + 0x08].setx012 (0x7fff0000, 0x401e000000000000L); //0x08 (MC68882) Nがセットされる。表現できないのでNaNにする
epbFPn[EPB_CONST_START + 0x08].setnan ();
epbFPn[EPB_CONST_START + 0x09].setx012 (0x43f30000, 0xe000000000000000L); //0x09 (MC68882)
epbFPn[EPB_CONST_START + 0x0a].setx012 (0x40720000, 0xc000000000000000L); //0x0a (MC68882)
} else { //MC68881、MC68060
for (int offset = 0x01; offset <= 0x0a; offset++) {
epbFPn[EPB_CONST_START + offset].set0 ();
}
}
} //epbSetROMSub(int)
//epbFmovecr (x, offset)
// FMOVECRの下請け
// レジスタにROMの定数をコピーしてFPSRのコンディションコードバイトとエクセプションバイトを更新する
public void epbFmovecr (EFP x, int offset) {
//特別な場合を処理する
switch (offset) {
case 0x01:
if ((epbMode & EPB_MODE_MC68882) != 0) { //MC68882、フルスペック
if (epbRoundingPrec == EPB_PREC_SGL) {
if (epbRoundingMode == EPB_MODE_RN ||
epbRoundingMode == EPB_MODE_RZ ||
epbRoundingMode == EPB_MODE_RM) {
//x.setx012 (0x40010000, 0xfe00068000000000L);
x.flg = P;
x.epp = 0x4001 - 0x3fff;
x.dvl = 0xfe00068000000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_X2;
return;
}
}
}
break;
case 0x02:
if ((epbMode & EPB_MODE_MC68882) != 0) { //MC68882、フルスペック
if (epbRoundingPrec == EPB_PREC_SGL) {
if (epbRoundingMode == EPB_MODE_RP) {
//x.setx012 (0x40010000, 0xffc0058000000000L);
x.flg = P;
x.epp = 0x4001 - 0x3fff;
x.dvl = 0xffc0058000000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_X2;
return;
}
}
}
break;
case 0x03:
if ((epbMode & EPB_MODE_MC68882) != 0) { //MC68882、フルスペック
if (epbRoundingPrec == EPB_PREC_SGL) {
if (epbRoundingMode == EPB_MODE_RN ||
epbRoundingMode == EPB_MODE_RP) {
//x.setx012 (0x20000000, 0x8000000000000000L);
x.flg = P;
x.epp = 0x2000 - 0x3fff;
x.dvl = 0x8000000000000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_I | EPB_FPSR_X2;
} else {
//x.setx012 (0x20000000, 0x7fffff0000000000L);
x.flg = P;
x.epp = 0x2000 - 0x3fff;
x.dvl = 0x7fffff0000000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_N | EPB_FPSR_X2;
}
} else {
//x.setx012 (0x20000000, 0x7fffffff00000000L);
x.flg = P;
x.epp = 0x2000 - 0x3fff;
x.dvl = 0x7fffffff00000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_N;
}
return;
}
break;
case 0x07:
if ((epbMode & EPB_MODE_MC68882) != 0) { //MC68882、フルスペック
if (epbRoundingPrec == EPB_PREC_SGL) {
if (epbRoundingMode == EPB_MODE_RN ||
epbRoundingMode == EPB_MODE_RZ ||
epbRoundingMode == EPB_MODE_RM) {
//x.setx012 (0x00010000, 0xf65d8d8000000000L);
x.flg = P;
x.epp = 0x0001 - 0x3fff;
x.dvl = 0xf65d8d8000000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_N | EPB_FPSR_X2;
} else {
//x.setx012 (0x00010000, 0xf65d8e0000000000L);
x.flg = P;
x.epp = 0x0001 - 0x3fff;
x.dvl = 0xf65d8e0000000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_N | EPB_FPSR_X2;
}
} else {
//x.setx012 (0x00010000, 0xf65d8d9c00000000L);
x.flg = P;
x.epp = 0x0001 - 0x3fff;
x.dvl = 0xf65d8d9c00000000L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_N;
}
return;
}
break;
case 0x08:
if ((epbMode & EPB_MODE_MC68882) != 0) { //MC68882、フルスペック
//x.setx012 (0x7fff0000, 0x401e000000000000L);
x.flg = N;
x.epp = 0;
x.dvl = 0L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_N;
return;
}
break;
case 0x0b:
if (epbRoundingPrec == EPB_PREC_EXD) {
if (epbRoundingMode == EPB_MODE_RN) {
//x.setx012 (0x3ffd0000, 0x9a209a84fbcff798L);
x.flg = P;
x.epp = 0x3ffd - 0x3fff;
x.dvl = 0x9a209a84fbcff798L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_X2;
return;
}
}
break;
case 0x0c:
if (epbRoundingPrec == EPB_PREC_EXD) {
if (epbRoundingMode == EPB_MODE_RN) {
//x.setx012 (0x40000000, 0xadf85458a2bb4a9aL);
x.flg = P;
x.epp = 0x4000 - 0x3fff;
x.dvl = 0xadf85458a2bb4a9aL;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff | EPB_FPSR_X2;
return;
}
}
break;
case 0x0e:
if (epbRoundingPrec == EPB_PREC_EXD) {
//x.setx012 (0x3ffd0000, 0xde5bd8a937287195L);
x.flg = P;
x.epp = 0x3ffd - 0x3fff;
x.dvl = 0xde5bd8a937287195L;
x.cvl = 0L;
epbFpsr = epbFpsr & 0x00ff00ff;
return;
}
break;
}
//ROMからコピーする
x.sete (epbFPn[EPB_CONST_START + offset]);
//FPSRのコンディションコードバイトを設定してエクセプションバイトをクリアする
epbFpsr = epbFpsr & 0x00ff00ff | x.flg >>> 4;
//仮数部を丸める。X2がセットされる
if (epbRoundingPrec == EPB_PREC_EXD) {
x.roundmanx (epbRoundingMode);
} else if (epbRoundingPrec == EPB_PREC_SGL) {
x.roundmanf (epbRoundingMode);
} else if (epbRoundingPrec == EPB_PREC_DBL ||
epbRoundingPrec == EPB_PREC_DBL3) {
x.roundmand (epbRoundingMode);
} else if (epbRoundingPrec == EPB_PREC_TPL) {
x.roundmany (epbRoundingMode);
}
} //epbFmovecr(EFP,int)
//epbSetMC68881 ()
// MC68881モード
public void epbSetMC68881 () {
epbMode = epbMode & ~(EPB_MODE_MC68882 | EPB_MODE_MC68060) | EPB_MODE_MC68881;
epbSetROMSub ();
} //epbSetMC68881()
//epbSetMC68882 ()
// MC68882モード
public void epbSetMC68882 () {
epbMode = epbMode & ~(EPB_MODE_MC68881 | EPB_MODE_MC68060) | EPB_MODE_MC68882;
epbSetROMSub ();
} //epbSetMC68882()
//epbSetMC68060 ()
// MC68060モード
public void epbSetMC68060 () {
epbMode = epbMode & ~(EPB_MODE_MC68881 | EPB_MODE_MC68882) | EPB_MODE_MC68060;
epbSetROMSub ();
} //epbSetMC68060()
//epbSetFullSpec ()
// フルスペックモード
public void epbSetFullSpec () {
epbMode |= EPB_MODE_FULLSPEC;
epbSetROMSub ();
} //epbSetFullSpec()
//epbIsFullSpec ()
// フルスペックモードか
public boolean epbIsFullSpec () {
return (epbMode & EPB_MODE_FULLSPEC) == EPB_MODE_FULLSPEC;
} //epbIsFullSpec()
//epbSetExtended ()
// 拡張精度モード
public void epbSetExtended () {
epbMode = epbMode & ~EPB_MODE_TRIPLE | EPB_MODE_EXTENDED;
} //epbSetExtended()
//epbSetTriple ()
// 三倍精度モード
public void epbSetTriple () {
epbMode = epbMode & ~EPB_MODE_EXTENDED | EPB_MODE_TRIPLE;
} //epbSetTriple()
//epbIsTriple ()
// 三倍精度モードか
public boolean epbIsTriple () {
return (epbMode & EPB_MODE_TRIPLE) != 0;
} //epbIsTriple()
//epbReset ()
// リセット
public final void epbReset () {
//浮動小数点汎用レジスタ
for (int n = 0; n < 8; n++) {
epbFPn[n].setnan (); //ヌルステートをFRESTOREするとNon-signaling NaNになるのでそれに合わせる
}
//浮動小数点制御レジスタ
epbFpcr = 0;
epbFpsr = 0;
epbFpiar = 0;
epbQuotient = 0;
epbRoundingPrec = EPB_PREC_EFP;
epbRoundingMode = EPB_MODE_RN;
epbRoundingDepth = 0;
epbRoundingOuterPrec = EPB_PREC_EFP;
epbRoundingOuterMode = EPB_MODE_RN;
//浮動小数点例外
epbExceptionOperandExponent = 0;
epbExceptionOperandMantissa = 0x0000000000000000L;
epbExceptionStatusWord = 0;
//コプロセッサインタフェイス
cirReset ();
}
//epbSetRoundingPrec (prec)
// 丸め桁数を設定する
// precはEPB_PREC_EXD,EPB_PREC_SGL,EPB_PREC_DBL,EPB_PREC_DBL3,EPB_PREC_XSGのいずれか
// 三倍精度が選択されているときEPB_PREC_EXDをEPB_PREC_TPLに読み替える
public void epbSetRoundingPrec (int prec) {
epbRoundingPrec = prec == EPB_PREC_EXD && (epbMode & EPB_MODE_TRIPLE) != 0 ? EPB_PREC_TPL : prec;
} //epbSetRoundingPrec(int)
//epbSetRoundingMode (mode)
// 丸めモードを設定する
// modeはEPB_MODE_RN,EPB_MODE_RZ,EPB_MODE_RM,EPB_MODE_RPのいずれか
public void epbSetRoundingMode (int mode) {
epbRoundingMode = mode;
} //epbSetRoundingMode(int)
//------------------------------------------------------------------------
//乱数ジェネレータ
// java.util.Randomと同じ線形合同法を用いる
public long epbRandSeed;
//epbRandStart (n)
// 乱数列の初期化
public void epbRandStart (long n) {
epbRandSeed = (n ^ 25214903917L) & (1L << 48) - 1L;
} //epbRandStart(long)
//l = epbRand48 ()
// 48bit乱数の取得
public long epbRand48 () {
return epbRandSeed = epbRandSeed * 25214903917L + 11L & (1L << 48) - 1L;
} //epbRand48()
//i = epbRandInt ()
// int乱数の取得
public int epbRandInt () {
return (int) (epbRand48 () >>> 16);
} //epbRandInt()
//l = epbRandLong ()
// long乱数の取得
public long epbRandLong () {
return epbRand48 () >>> 16 << 32 | epbRand48 () >>> 16;
} //epbRandLong()
//------------------------------------------------------------------------
//epbMakeCmpTable ()
// cmp,compare,eq,ge,gt,le,lt,neで引数のどちらかが±0,±Inf,NaNの場合の結果を求めるためのテーブルを作る
public static void epbMakeCmpTable () {
int[] fa = new int[] {
P | Z,
M | Z,
P | I,
M | I,
N,
P,
M,
};
double[] da = new double[] {
+0.0,
-0.0,
Double.POSITIVE_INFINITY,
Double.NEGATIVE_INFINITY,
Double.NaN,
+1.0,
-1.0,
};
String[] na = { "CMP", "COMPARE", "EQ", "GE", "GT", "LE", "LT", "NE" };
int[][] ba = new int[na.length][];
for (int j = 0; j < na.length; j++) {
ba[j] = new int[16];
}
for (int xi = 0; xi < fa.length; xi++) {
int xk = fa[xi] >>> 28;
double x = da[xi];
for (int yi = 0; yi < fa.length; yi++) {
int yk = fa[yi] >>> 28 - 1;
double y = da[yi];
ba[0][xk] |= (Double.isNaN (x) || Double.isNaN (y) || x == y ? 0 : x < y ? -1 : 1) << 30 >>> yk; //cmp
ba[1][xk] |= Double.compare (x, y) << 30 >>> yk; //compare
ba[2][xk] |= (x == y ? -1 : 0) << 30 >>> yk; //eq
ba[3][xk] |= (x >= y ? -1 : 0) << 30 >>> yk; //ge
ba[4][xk] |= (x > y ? -1 : 0) << 30 >>> yk; //gt
ba[5][xk] |= (x <= y ? -1 : 0) << 30 >>> yk; //le
ba[6][xk] |= (x < y ? -1 : 0) << 30 >>> yk; //lt
ba[7][xk] |= (x != y ? -1 : 0) << 30 >>> yk; //ne
}
}
for (int ni = 0; ni < na.length; ni++) {
System.out.print (" protected static final int[] EFP_" + na[ni] + "_TABLE = { ");
for (int xk = 0; xk < 16; xk++) {
System.out.print (ba[ni][xk]);
if (xk < 16 - 1) {
System.out.print (", ");
}
}
System.out.println (" };");
}
} //epbMakeCmpTable()
//------------------------------------------------------------------------
// cmp,compare,eq,ge,gt,le,lt,neで引数のどちらかが±0,±Inf,NaNの場合の結果を求めるためのテーブル
public static final int[] EFP_CMP_TABLE = { 205538368, 0, 1077953600, 0, -872397824, 0, 0, 0, -859831104, 0, -859782976, 0, -872397824, 0, 0, 0 };
public static final int[] EFP_COMPARE_TABLE = { 1010844736, 1145062464, 1883259968, 0, -67091392, 0, 0, 0, -54524736, 0, -54476608, 0, -54508544, 0, 0, 0 };
public static final int[] EFP_EQ_TABLE = { -1073741824, 0, 201326592, 0, 12583104, 0, 0, 0, 49152, 0, 3072, 0, 12583104, 0, 0, 0 };
public static final int[] EFP_GE_TABLE = { -1061106496, 0, -859779904, 0, 12635328, 0, 0, 0, 52224, 0, 3072, 0, 12635328, 0, 0, 0 };
public static final int[] EFP_GT_TABLE = { 12635328, 0, -1061106496, 0, 52224, 0, 0, 0, 3072, 0, 0, 0, 52224, 0, 0, 0 };
public static final int[] EFP_LE_TABLE = { -872415232, 0, 201326592, 0, -859832128, 0, 0, 0, -859782976, 0, -859779904, 0, -859832128, 0, 0, 0 };
public static final int[] EFP_LT_TABLE = { 201326592, 0, 0, 0, -872415232, 0, 0, 0, -859832128, 0, -859782976, 0, -872415232, 0, 0, 0 };
public static final int[] EFP_NE_TABLE = { 1019268288, -54473536, -255800128, 0, -67056640, 0, 0, 0, -54522688, 0, -54476608, 0, -67056640, 0, 0, 0 };
//------------------------------------------------------------------------
//定数
// すべてのEFP定数は内部コンストラクタnew EFP(xf,xe,xd,xc)で構築しなければならない
// 公開コンストラクタは丸めの処理が入るので定数の構築には使用できない
public final EFP ZERO = new EFP (P | Z, 0, 0L, 0L); //+0
public final EFP NEGZERO = new EFP (M | Z, 0, 0L, 0L); //-0
public final EFP INF = new EFP (P | I, 0, 0L, 0L); //+Inf
public final EFP NEGINF = new EFP (M | I, 0, 0L, 0L); //-Inf
public final EFP NAN = new EFP ( N, 0, 0L, 0L); //NaN
//------------------------------------------------------------------------
//範囲
// echo read("efp.gp");efppub(["EXDNOMAX",EXDNOMAX],["EXDDEMIN",EXDDEMIN],["NEGEXDDEMIN",-EXDDEMIN],["NEGEXDNOMAX",-EXDNOMAX],["SGLNOMAX",SGLNOMAX],["SGLDEMIN",SGLDEMIN],["NEGSGLDEMIN",-SGLDEMIN],["NEGSGLNOMAX",-SGLNOMAX],["DBLNOMAX",DBLNOMAX],["DBLDEMIN",DBLDEMIN],["NEGDBLDEMIN",-DBLDEMIN],["NEGDBLNOMAX",-DBLNOMAX],["TPLNOMAX",TPLNOMAX],["TPLDEMIN",TPLDEMIN],["NEGTPLDEMIN",-TPLDEMIN],["NEGTPLNOMAX",-TPLNOMAX],["XSGNOMAX",XSGNOMAX],["XSGDEMIN",XSGDEMIN],["NEGXSGDEMIN",-XSGDEMIN],["NEGXSGNOMAX",-XSGNOMAX],["EFPNOMAX",EFPNOMAX],["EFPDEMIN",eval("2^-32768")],["NEGEFPDEMIN",eval("-2^-32768")],["NEGEFPNOMAX",-EFPNOMAX]) | gp -q
public final EFP EXDNOMAX = new EFP (P, 16383, 0xffffffffffffffffL, 0x0000000L << 36); //=1.18973149535723176502126385303e+4932
public final EFP EXDDEMIN = new EFP (P, -16446, 0x8000000000000000L, 0x0000000L << 36); //=1.82259976594123730126420296681e-4951
public final EFP NEGEXDDEMIN = new EFP (M, -16446, 0x8000000000000000L, 0x0000000L << 36); //=-1.82259976594123730126420296681e-4951
public final EFP NEGEXDNOMAX = new EFP (M, 16383, 0xffffffffffffffffL, 0x0000000L << 36); //=-1.18973149535723176502126385303e+4932
public final EFP SGLNOMAX = new EFP (P, 127, 0xffffff0000000000L, 0x0000000L << 36); //=3.40282346638528859811704183485e+38
public final EFP SGLDEMIN = new EFP (P, -149, 0x8000000000000000L, 0x0000000L << 36); //=1.40129846432481707092372958329e-45
public final EFP NEGSGLDEMIN = new EFP (M, -149, 0x8000000000000000L, 0x0000000L << 36); //=-1.40129846432481707092372958329e-45
public final EFP NEGSGLNOMAX = new EFP (M, 127, 0xffffff0000000000L, 0x0000000L << 36); //=-3.40282346638528859811704183485e+38
public final EFP DBLNOMAX = new EFP (P, 1023, 0xfffffffffffff800L, 0x0000000L << 36); //=1.79769313486231570814527423732e+308
public final EFP DBLDEMIN = new EFP (P, -1074, 0x8000000000000000L, 0x0000000L << 36); //=4.94065645841246544176568792868e-324
public final EFP NEGDBLDEMIN = new EFP (M, -1074, 0x8000000000000000L, 0x0000000L << 36); //=-4.94065645841246544176568792868e-324
public final EFP NEGDBLNOMAX = new EFP (M, 1023, 0xfffffffffffff800L, 0x0000000L << 36); //=-1.79769313486231570814527423732e+308
public final EFP TPLNOMAX = new EFP (P, 16383, 0xffffffffffffffffL, 0xffff000L << 36); //=1.18973149535723176508575834251e+4932
public final EFP TPLDEMIN = new EFP (P, -16462, 0x8000000000000000L, 0x0000000L << 36); //=2.78106653738592117502472376527e-4956
public final EFP NEGTPLDEMIN = new EFP (M, -16462, 0x8000000000000000L, 0x0000000L << 36); //=-2.78106653738592117502472376527e-4956
public final EFP NEGTPLNOMAX = new EFP (M, 16383, 0xffffffffffffffffL, 0xffff000L << 36); //=-1.18973149535723176508575834251e+4932
public final EFP XSGNOMAX = new EFP (P, 16383, 0xffffff0000000000L, 0x0000000L << 36); //=1.18973142444370860622365937597e+4932
public final EFP XSGDEMIN = new EFP (P, -16406, 0x8000000000000000L, 0x0000000L << 36); //=2.00396963543420642987649310668e-4939
public final EFP NEGXSGDEMIN = new EFP (M, -16406, 0x8000000000000000L, 0x0000000L << 36); //=-2.00396963543420642987649310668e-4939
public final EFP NEGXSGNOMAX = new EFP (M, 16383, 0xffffff0000000000L, 0x0000000L << 36); //=-1.18973142444370860622365937597e+4932
public final EFP EFPNOMAX = new EFP (P, 32767, 0xffffffffffffffffL, 0xfffffffL << 36); //=1.41546103104495478900155302746e+9864
public final EFP EFPDEMIN = new EFP (P, -32768, 0x8000000000000000L, 0x0000000L << 36); //=7.06483596557763644277740218786e-9865
public final EFP NEGEFPDEMIN = new EFP (M, -32768, 0x8000000000000000L, 0x0000000L << 36); //=-7.06483596557763644277740218786e-9865
public final EFP NEGEFPNOMAX = new EFP (M, 32767, 0xffffffffffffffffL, 0xfffffffL << 36); //=-1.41546103104495478900155302746e+9864
//------------------------------------------------------------------------
//オーバーフローの値
// 指数部が大きくなりすぎたときのオーバーフローの値はいつも±Infというわけではなく丸め桁数と丸めモードと符号によって変化する
// 端数に関係なく±0に近付く方向に丸めるときは±Infではなく絶対値が最大の正規化数を返す
// 絶対値が最大の正規化数は丸め桁数によって異なる
// XSGはアンダーフローしたときは±XSGDEMINだがオーバーフローしたときは±EXDNOMAXになる
// OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | flg >>> 31]
// inner()~outer()の内側ではepbRoundingPrecが効かないことに注意する
public final EFP[] OVFL_RESULTS = new EFP[] {
INF, //EPB_PREC_EXD,EPB_MODE_RN,+
NEGINF, //EPB_PREC_EXD,EPB_MODE_RN,-
EXDNOMAX, //EPB_PREC_EXD,EPB_MODE_RZ,+
NEGEXDNOMAX, //EPB_PREC_EXD,EPB_MODE_RZ,-
EXDNOMAX, //EPB_PREC_EXD,EPB_MODE_RM,+
NEGINF, //EPB_PREC_EXD,EPB_MODE_RM,-
INF, //EPB_PREC_EXD,EPB_MODE_RP,+
NEGEXDNOMAX, //EPB_PREC_EXD,EPB_MODE_RP,-
//
INF, //EPB_PREC_SGL,EPB_MODE_RN,+
NEGINF, //EPB_PREC_SGL,EPB_MODE_RN,-
SGLNOMAX, //EPB_PREC_SGL,EPB_MODE_RZ,+
NEGSGLNOMAX, //EPB_PREC_SGL,EPB_MODE_RZ,-
SGLNOMAX, //EPB_PREC_SGL,EPB_MODE_RM,+
NEGINF, //EPB_PREC_SGL,EPB_MODE_RM,-
INF, //EPB_PREC_SGL,EPB_MODE_RP,+
NEGSGLNOMAX, //EPB_PREC_SGL,EPB_MODE_RP,-
//
INF, //EPB_PREC_DBL,EPB_MODE_RN,+
NEGINF, //EPB_PREC_DBL,EPB_MODE_RN,-
DBLNOMAX, //EPB_PREC_DBL,EPB_MODE_RZ,+
NEGDBLNOMAX, //EPB_PREC_DBL,EPB_MODE_RZ,-
DBLNOMAX, //EPB_PREC_DBL,EPB_MODE_RM,+
NEGINF, //EPB_PREC_DBL,EPB_MODE_RM,-
INF, //EPB_PREC_DBL,EPB_MODE_RP,+
NEGDBLNOMAX, //EPB_PREC_DBL,EPB_MODE_RP,-
//
INF, //EPB_PREC_DBL3,EPB_MODE_RN,+
NEGINF, //EPB_PREC_DBL3,EPB_MODE_RN,-
DBLNOMAX, //EPB_PREC_DBL3,EPB_MODE_RZ,+
NEGDBLNOMAX, //EPB_PREC_DBL3,EPB_MODE_RZ,-
DBLNOMAX, //EPB_PREC_DBL3,EPB_MODE_RM,+
NEGINF, //EPB_PREC_DBL3,EPB_MODE_RM,-
INF, //EPB_PREC_DBL3,EPB_MODE_RP,+
NEGDBLNOMAX, //EPB_PREC_DBL3,EPB_MODE_RP,-
//
INF, //EPB_PREC_TPL,EPB_MODE_RN,+
NEGINF, //EPB_PREC_TPL,EPB_MODE_RN,-
TPLNOMAX, //EPB_PREC_TPL,EPB_MODE_RZ,+
NEGTPLNOMAX, //EPB_PREC_TPL,EPB_MODE_RZ,-
TPLNOMAX, //EPB_PREC_TPL,EPB_MODE_RM,+
NEGINF, //EPB_PREC_TPL,EPB_MODE_RM,-
INF, //EPB_PREC_TPL,EPB_MODE_RP,+
NEGTPLNOMAX, //EPB_PREC_TPL,EPB_MODE_RP,-
//
INF, //EPB_PREC_XSG,EPB_MODE_RN,+
NEGINF, //EPB_PREC_XSG,EPB_MODE_RN,-
EXDNOMAX, //EPB_PREC_XSG,EPB_MODE_RZ,+ XSGNOMAX → EXDNOMAX
NEGEXDNOMAX, //EPB_PREC_XSG,EPB_MODE_RZ,- -XSGNOMAX → -EXDNOMAX
EXDNOMAX, //EPB_PREC_XSG,EPB_MODE_RM,+ XSGNOMAX→EXDNOMAX
NEGINF, //EPB_PREC_XSG,EPB_MODE_RM,-
INF, //EPB_PREC_XSG,EPB_MODE_RP,+
NEGEXDNOMAX, //EPB_PREC_XSG,EPB_MODE_RP,- -XSGNOMAX→-EXDNOMAX
//
INF, //EPB_PREC_EFP,EPB_MODE_RN,+
NEGINF, //EPB_PREC_EFP,EPB_MODE_RN,-
EFPNOMAX, //EPB_PREC_EFP,EPB_MODE_RZ,+
NEGEFPNOMAX, //EPB_PREC_EFP,EPB_MODE_RZ,-
EFPNOMAX, //EPB_PREC_EFP,EPB_MODE_RM,+
NEGINF, //EPB_PREC_EFP,EPB_MODE_RM,-
INF, //EPB_PREC_EFP,EPB_MODE_RP,+
NEGEFPNOMAX, //EPB_PREC_EFP,EPB_MODE_RP,-
};
//------------------------------------------------------------------------
//アンダーフローの値
// 指数部が小さくなりすぎたときのアンダーフローの値はいつも±0というわけではなく丸め桁数と丸めモードと符号によって変化する
// 端数に関係なく±0から遠ざかる方向に丸めるときは±0ではなく絶対値が最小の非正規化数を返す
// 絶対値が最小の非正規化数は丸め桁数によって異なる
// XSGはアンダーフローしたときは±XSGDEMINだがオーバーフローしたときは±EXDNOMAXになる
// UNFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | flg >>> 31]
// inner()~outer()の内側ではepbRoundingPrecが効かないことに注意する
public final EFP[] UNFL_RESULTS = new EFP[] {
ZERO, //EPB_PREC_EXD,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_EXD,EPB_MODE_RN,-
ZERO, //EPB_PREC_EXD,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_EXD,EPB_MODE_RZ,-
ZERO, //EPB_PREC_EXD,EPB_MODE_RM,+
NEGEXDDEMIN, //EPB_PREC_EXD,EPB_MODE_RM,-
EXDDEMIN, //EPB_PREC_EXD,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_EXD,EPB_MODE_RP,-
//
ZERO, //EPB_PREC_SGL,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_SGL,EPB_MODE_RN,-
ZERO, //EPB_PREC_SGL,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_SGL,EPB_MODE_RZ,-
ZERO, //EPB_PREC_SGL,EPB_MODE_RM,+
NEGSGLDEMIN, //EPB_PREC_SGL,EPB_MODE_RM,-
SGLDEMIN, //EPB_PREC_SGL,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_SGL,EPB_MODE_RP,-
//
ZERO, //EPB_PREC_DBL,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_DBL,EPB_MODE_RN,-
ZERO, //EPB_PREC_DBL,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_DBL,EPB_MODE_RZ,-
ZERO, //EPB_PREC_DBL,EPB_MODE_RM,+
NEGDBLDEMIN, //EPB_PREC_DBL,EPB_MODE_RM,-
DBLDEMIN, //EPB_PREC_DBL,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_DBL,EPB_MODE_RP,-
//
ZERO, //EPB_PREC_DBL3,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_DBL3,EPB_MODE_RN,-
ZERO, //EPB_PREC_DBL3,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_DBL3,EPB_MODE_RZ,-
ZERO, //EPB_PREC_DBL3,EPB_MODE_RM,+
NEGDBLDEMIN, //EPB_PREC_DBL3,EPB_MODE_RM,-
DBLDEMIN, //EPB_PREC_DBL3,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_DBL3,EPB_MODE_RP,-
//
ZERO, //EPB_PREC_TPL,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_TPL,EPB_MODE_RN,-
ZERO, //EPB_PREC_TPL,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_TPL,EPB_MODE_RZ,-
ZERO, //EPB_PREC_TPL,EPB_MODE_RM,+
NEGTPLDEMIN, //EPB_PREC_TPL,EPB_MODE_RM,-
TPLDEMIN, //EPB_PREC_TPL,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_TPL,EPB_MODE_RP,-
//
ZERO, //EPB_PREC_XSG,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_XSG,EPB_MODE_RN,-
ZERO, //EPB_PREC_XSG,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_XSG,EPB_MODE_RZ,-
ZERO, //EPB_PREC_XSG,EPB_MODE_RM,+
NEGXSGDEMIN, //EPB_PREC_XSG,EPB_MODE_RM,-
XSGDEMIN, //EPB_PREC_XSG,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_XSG,EPB_MODE_RP,-
//
ZERO, //EPB_PREC_EFP,EPB_MODE_RN,+
NEGZERO, //EPB_PREC_EFP,EPB_MODE_RN,-
ZERO, //EPB_PREC_EFP,EPB_MODE_RZ,+
NEGZERO, //EPB_PREC_EFP,EPB_MODE_RZ,-
ZERO, //EPB_PREC_EFP,EPB_MODE_RM,+
NEGEFPDEMIN, //EPB_PREC_EFP,EPB_MODE_RM,-
EFPDEMIN, //EPB_PREC_EFP,EPB_MODE_RP,+
NEGZERO, //EPB_PREC_EFP,EPB_MODE_RP,-
};
//------------------------------------------------------------------------
// ±1に隣接する値
// 三角関数や双曲線関数で丸めモードによって結果が±1になってはならないのに端数が小さすぎて±1になってしまうことがある
// 結果を調節するときに使う
public final EFP[] NEXTDOWN_MINUSONE = {
// echo read("efp.gp");efpmem([exdnextdown(-1)],[sglnextdown(-1)],[dblnextdown(-1)],[dblnextdown(-1)],[tplnextdown(-1)],[xsgnextdown(-1)],[efpnextdown(-1)]) | gp -q
new EFP (M, 0, 0x8000000000000001L, 0x0000000L << 36), //=-1.00000000000000000010842021725
new EFP (M, 0, 0x8000010000000000L, 0x0000000L << 36), //=-1.00000011920928955078125000000
new EFP (M, 0, 0x8000000000000800L, 0x0000000L << 36), //=-1.00000000000000022204460492503
new EFP (M, 0, 0x8000000000000800L, 0x0000000L << 36), //=-1.00000000000000022204460492503
new EFP (M, 0, 0x8000000000000000L, 0x0001000L << 36), //=-1.00000000000000000000000165436
new EFP (M, 0, 0x8000010000000000L, 0x0000000L << 36), //=-1.00000011920928955078125000000
new EFP (M, 0, 0x8000000000000000L, 0x0000001L << 36), //=-1.00000000000000000000000000040
};
public final EFP[] NEXTUP_MINUSONE = {
// echo read("efp.gp");efpmem([exdnextup(-1)],[sglnextup(-1)],[dblnextup(-1)],[dblnextup(-1)],[tplnextup(-1)],[xsgnextup(-1)],[efpnextup(-1)]) | gp -q
new EFP (M, -1, 0xffffffffffffffffL, 0x0000000L << 36), //=-0.999999999999999999945789891376
new EFP (M, -1, 0xffffff0000000000L, 0x0000000L << 36), //=-0.999999940395355224609375000000
new EFP (M, -1, 0xfffffffffffff800L, 0x0000000L << 36), //=-0.999999999999999888977697537484
new EFP (M, -1, 0xfffffffffffff800L, 0x0000000L << 36), //=-0.999999999999999888977697537484
new EFP (M, -1, 0xffffffffffffffffL, 0xffff000L << 36), //=-0.999999999999999999999999172819
new EFP (M, -1, 0xffffff0000000000L, 0x0000000L << 36), //=-0.999999940395355224609375000000
new EFP (M, -1, 0xffffffffffffffffL, 0xfffffffL << 36), //=-0.999999999999999999999999999798
};
public final EFP[] NEXTDOWN_PLUSONE = {
// echo read("efp.gp");efpmem([exdnextdown(1)],[sglnextdown(1)],[dblnextdown(1)],[dblnextdown(1)],[tplnextdown(1)],[xsgnextdown(1)],[efpnextdown(1)]) | gp -q
new EFP (P, -1, 0xffffffffffffffffL, 0x0000000L << 36), //=0.999999999999999999945789891376
new EFP (P, -1, 0xffffff0000000000L, 0x0000000L << 36), //=0.999999940395355224609375000000
new EFP (P, -1, 0xfffffffffffff800L, 0x0000000L << 36), //=0.999999999999999888977697537484
new EFP (P, -1, 0xfffffffffffff800L, 0x0000000L << 36), //=0.999999999999999888977697537484
new EFP (P, -1, 0xffffffffffffffffL, 0xffff000L << 36), //=0.999999999999999999999999172819
new EFP (P, -1, 0xffffff0000000000L, 0x0000000L << 36), //=0.999999940395355224609375000000
new EFP (P, -1, 0xffffffffffffffffL, 0xfffffffL << 36), //=0.999999999999999999999999999798
};
public final EFP[] NEXTUP_PLUSONE = {
// echo read("efp.gp");efpmem([exdnextup(1)],[sglnextup(1)],[dblnextup(1)],[dblnextup(1)],[tplnextup(1)],[xsgnextup(1)],[efpnextup(1)]) | gp -q
new EFP (P, 0, 0x8000000000000001L, 0x0000000L << 36), //=1.00000000000000000010842021725
new EFP (P, 0, 0x8000010000000000L, 0x0000000L << 36), //=1.00000011920928955078125000000
new EFP (P, 0, 0x8000000000000800L, 0x0000000L << 36), //=1.00000000000000022204460492503
new EFP (P, 0, 0x8000000000000800L, 0x0000000L << 36), //=1.00000000000000022204460492503
new EFP (P, 0, 0x8000000000000000L, 0x0001000L << 36), //=1.00000000000000000000000165436
new EFP (P, 0, 0x8000010000000000L, 0x0000000L << 36), //=1.00000011920928955078125000000
new EFP (P, 0, 0x8000000000000000L, 0x0000001L << 36), //=1.00000000000000000000000000040
};
//------------------------------------------------------------------------
//汎用定数
// echo read("efp.gp");efppub(["NEGONE",-1],["ONE",1],["TWO",2],["THREE",3],["FOUR",4],["FIVE",5],["SIX",6],["SEVEN",7],["EIGHT",8],["NINE",9],["TEN",10],["ELEVEN",11],["TWELVE",12],["THIRTEEN",13],["FOURTEEN",14],["FIFTEEN",15],[SIXTEEN,16]) | gp -q
public final EFP NEGONE = new EFP (M, 0, 0x8000000000000000L, 0x0000000L << 36); //=-1.00000000000000000000000000000
public final EFP ONE = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP TWO = new EFP (P, 1, 0x8000000000000000L, 0x0000000L << 36); //=2.00000000000000000000000000000
public final EFP THREE = new EFP (P, 1, 0xc000000000000000L, 0x0000000L << 36); //=3.00000000000000000000000000000
public final EFP FOUR = new EFP (P, 2, 0x8000000000000000L, 0x0000000L << 36); //=4.00000000000000000000000000000
public final EFP FIVE = new EFP (P, 2, 0xa000000000000000L, 0x0000000L << 36); //=5.00000000000000000000000000000
public final EFP SIX = new EFP (P, 2, 0xc000000000000000L, 0x0000000L << 36); //=6.00000000000000000000000000000
public final EFP SEVEN = new EFP (P, 2, 0xe000000000000000L, 0x0000000L << 36); //=7.00000000000000000000000000000
public final EFP EIGHT = new EFP (P, 3, 0x8000000000000000L, 0x0000000L << 36); //=8.00000000000000000000000000000
public final EFP NINE = new EFP (P, 3, 0x9000000000000000L, 0x0000000L << 36); //=9.00000000000000000000000000000
public final EFP TEN = new EFP (P, 3, 0xa000000000000000L, 0x0000000L << 36); //=10.0000000000000000000000000000
public final EFP ELEVEN = new EFP (P, 3, 0xb000000000000000L, 0x0000000L << 36); //=11.0000000000000000000000000000
public final EFP TWELVE = new EFP (P, 3, 0xc000000000000000L, 0x0000000L << 36); //=12.0000000000000000000000000000
public final EFP THIRTEEN = new EFP (P, 3, 0xd000000000000000L, 0x0000000L << 36); //=13.0000000000000000000000000000
public final EFP FOURTEEN = new EFP (P, 3, 0xe000000000000000L, 0x0000000L << 36); //=14.0000000000000000000000000000
public final EFP FIFTEEN = new EFP (P, 3, 0xf000000000000000L, 0x0000000L << 36); //=15.0000000000000000000000000000
public final EFP SIXTEEN = new EFP (P, 4, 0x8000000000000000L, 0x0000000L << 36); //=16.0000000000000000000000000000
public final EFP[] EFP_DIGIT = {
ZERO,
ONE,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
ELEVEN,
TWELVE,
THIRTEEN,
FOURTEEN,
FIFTEEN,
SIXTEEN,
};
// echo read("efp.gp");efppub(["ONE_2",1/2],["ONE_3",1/3],["TWO_3",2/3],["ONE_4",1/4],["THREE_4",3/4],["ONE_5",1/5],["TWO_5",2/5],["THREE_5",3/5],["FOUR_5",4/5],["ONE_6",1/6],["FIVE_6",5/6],[ONE_10,1/10]) | gp -q
public final EFP ONE_2 = new EFP (P, -1, 0x8000000000000000L, 0x0000000L << 36); //=0.500000000000000000000000000000
public final EFP ONE_3 = new EFP (P, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaabL << 36); //>0.333333333333333333333333333333
public final EFP TWO_3 = new EFP (P, -1, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaabL << 36); //>0.666666666666666666666666666667
public final EFP ONE_4 = new EFP (P, -2, 0x8000000000000000L, 0x0000000L << 36); //=0.250000000000000000000000000000
public final EFP THREE_4 = new EFP (P, -1, 0xc000000000000000L, 0x0000000L << 36); //=0.750000000000000000000000000000
public final EFP ONE_5 = new EFP (P, -3, 0xccccccccccccccccL, 0xccccccdL << 36); //>0.200000000000000000000000000000
public final EFP TWO_5 = new EFP (P, -2, 0xccccccccccccccccL, 0xccccccdL << 36); //>0.400000000000000000000000000000
public final EFP THREE_5 = new EFP (P, -1, 0x9999999999999999L, 0x999999aL << 36); //>0.600000000000000000000000000000
public final EFP FOUR_5 = new EFP (P, -1, 0xccccccccccccccccL, 0xccccccdL << 36); //>0.800000000000000000000000000000
public final EFP ONE_6 = new EFP (P, -3, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaabL << 36); //>0.166666666666666666666666666667
public final EFP FIVE_6 = new EFP (P, -1, 0xd555555555555555L, 0x5555555L << 36); //<0.833333333333333333333333333333
public final EFP ONE_10 = new EFP (P, -4, 0xccccccccccccccccL, 0xccccccdL << 36); //>0.100000000000000000000000000000
// echo read("efp.gp");efppub2(["SQRT2",sqrt(2)],["SQRT2_2",sqrt(2)/2],["DECSQRT2",sqrt(2)-1],["INCSQRT2",sqrt(2)+1]) | gp -q
public final EFP SQRT2 = new EFP (P, 0, 0xb504f333f9de6484L, 0x597d89bL << 36); //<1.41421356237309504880168872421
public final EFP SQRT2A = new EFP (P, -94, 0xdd52afa7c75bd82eL, 0xa24eea1L << 36); //<8.72965282186712870062036635269e-29
public final EFP SQRT2_2 = new EFP (P, -1, 0xb504f333f9de6484L, 0x597d89bL << 36); //<0.707106781186547524400844362105
public final EFP SQRT2_2A = new EFP (P, -95, 0xdd52afa7c75bd82eL, 0xa24eea1L << 36); //<4.36482641093356435031018317635e-29
public final EFP DECSQRT2 = new EFP (P, -2, 0xd413cccfe7799211L, 0x65f626dL << 36); //>0.414213562373095048801688724210
public final EFP DECSQRT2A = new EFP (M, -96, 0x8ab54160e2909f45L, 0x76c457bL << 36); //>-1.36776676496182240864975928293e-29
public final EFP INCSQRT2 = new EFP (P, 1, 0x9a827999fcef3242L, 0x2cbec4eL << 36); //>2.41421356237309504880168872421
public final EFP INCSQRT2A = new EFP (M, -92, 0xc8ab54160e2909f4L, 0x576c458L << 36); //<-3.16600255254486757364601361898e-28
// echo read("efp.gp");efppub2(["PI",Pi],["NEGPI",-Pi],["PI2",Pi*2],["PI_2",Pi/2],["NEGPI_2",-Pi/2],["PI3_2",Pi*3/2],["PI_4",Pi/4],["NEGPI_4",-Pi/4],["PI3_4",Pi*3/4],["NEGPI3_4",-Pi*3/4],["PI_6",Pi/6],["PI_8",Pi/8],["TO_RAD",Pi/180]) | gp -q
public final EFP PI = new EFP (P, 1, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>3.14159265358979323846264338328
public final EFP PIA = new EFP (M, -92, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //>-2.27022372150444021965698652772e-28
public final EFP NEGPI = new EFP (M, 1, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //<-3.14159265358979323846264338328
public final EFP NEGPIA = new EFP (P, -92, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //<2.27022372150444021965698652772e-28
public final EFP PI2 = new EFP (P, 2, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>6.28318530717958647692528676656
public final EFP PI2A = new EFP (M, -91, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //>-4.54044744300888043931397305544e-28
public final EFP PI_2 = new EFP (P, 0, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>1.57079632679489661923132169164
public final EFP PI_2A = new EFP (M, -93, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //>-1.13511186075222010982849326386e-28
public final EFP NEGPI_2 = new EFP (M, 0, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //<-1.57079632679489661923132169164
public final EFP NEGPI_2A = new EFP (P, -93, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //<1.13511186075222010982849326386e-28
public final EFP PI3_2 = new EFP (P, 2, 0x96cbe3f9990e91a7L, 0x9394c9fL << 36); //>4.71238898038468985769396507492
public final EFP PI3_2A = new EFP (M, -91, 0xebeb5d4c6427c8afL, 0x330644dL << 36); //>-7.44430341698824077319353004583e-28
public final EFP PI_4 = new EFP (P, -1, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>0.785398163397448309615660845820
public final EFP PI_4A = new EFP (M, -94, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //>-5.67555930376110054914246631930e-29
public final EFP NEGPI_4 = new EFP (M, -1, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //<-0.785398163397448309615660845820
public final EFP NEGPI_4A = new EFP (P, -94, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //<5.67555930376110054914246631930e-29
public final EFP PI3_4 = new EFP (P, 1, 0x96cbe3f9990e91a7L, 0x9394c9fL << 36); //>2.35619449019234492884698253746
public final EFP PI3_4A = new EFP (M, -92, 0xebeb5d4c6427c8afL, 0x330644dL << 36); //>-3.72215170849412038659676502291e-28
public final EFP NEGPI3_4 = new EFP (M, 1, 0x96cbe3f9990e91a7L, 0x9394c9fL << 36); //<-2.35619449019234492884698253746
public final EFP NEGPI3_4A = new EFP (P, -92, 0xebeb5d4c6427c8afL, 0x330644dL << 36); //<3.72215170849412038659676502291e-28
public final EFP PI_6 = new EFP (P, -1, 0x860a91c16b9b2c23L, 0x2dd9970L << 36); //<0.523598775598298873077107230547
public final EFP PI_6A = new EFP (P, -94, 0xf567ad116e158680L, 0xb633511L << 36); //>9.67951991326453444626518996796e-29
public final EFP PI_8 = new EFP (P, -2, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>0.392699081698724154807830422910
public final EFP PI_8A = new EFP (M, -95, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //>-2.83777965188055027457123315965e-29
public final EFP TO_RAD = new EFP (P, -6, 0x8efa351294e9c8aeL, 0x0ec5f67L << 36); //>0.0174532925199432957692369076849
public final EFP TO_RADA = new EFP (M, -101, 0xb5bd1d937fa42885L, 0x7f250caL << 36); //>-5.60025707306011850554567124038e-31
// echo read("efp.gp");efppub2(["ONE_2PI",1/(2*Pi)],["ONE_PI",1/Pi],["TWO_PI",2/Pi],["FOUR_PI",4/Pi],["TO_DEG",180/Pi]) | gp -q
public final EFP ONE_2PI = new EFP (P, -3, 0xa2f9836e4e441529L, 0xfc2757dL << 36); //<0.159154943091895335768883763373
public final EFP ONE_2PIA = new EFP (P, -98, 0xfa9a6ee06db14accL, 0x9e21c82L << 36); //<6.17784718978010796644368056118e-30
public final EFP ONE_PI = new EFP (P, -2, 0xa2f9836e4e441529L, 0xfc2757dL << 36); //<0.318309886183790671537767526745
public final EFP ONE_PIA = new EFP (P, -97, 0xfa9a6ee06db14accL, 0x9e21c82L << 36); //<1.23556943795602159328873611224e-29
public final EFP TWO_PI = new EFP (P, -1, 0xa2f9836e4e441529L, 0xfc2757dL << 36); //<0.636619772367581343075535053490
public final EFP TWO_PIA = new EFP (P, -96, 0xfa9a6ee06db14accL, 0x9e21c82L << 36); //<2.47113887591204318657747222447e-29
public final EFP FOUR_PI = new EFP (P, 0, 0xa2f9836e4e441529L, 0xfc2757dL << 36); //<1.27323954473516268615107010698
public final EFP FOUR_PIA = new EFP (P, -95, 0xfa9a6ee06db14accL, 0x9e21c82L << 36); //<4.94227775182408637315494444895e-29
public final EFP TO_DEG = new EFP (P, 5, 0xe52ee0d31e0fbdc3L, 0x0a97538L << 36); //>57.2957795130823208767981548141
public final EFP TO_DEGA = new EFP (M, -91, 0xbf2da828cb7d5da0L, 0x8340fd2L << 36); //>-6.03252495991267442675910175947e-28
// echo read("efp.gp");efppub2(["E",exp(1)]) | gp -q
public final EFP E = new EFP (P, 1, 0xadf85458a2bb4a9aL, 0xafdc562L << 36); //<2.71828182845904523536028747135
public final EFP EA = new EFP (P, -97, 0x9cf4f3c762e7160fL, 0x38b4da5L << 36); //<7.73856991537314016398963167104e-30
// echo read("efp.gp");efppub2(["LOG_2",log(2)],["LOG_2_2",log(2)/2],["LOG_10",log(10)],["LOG2_E",1/log(2)],["LOG2_10",log(10)/log(2)],["LOG10_2",log(2)/log(10)],["LOG10_E",1/log(10)]) | gp -q
public final EFP LOG_2 = new EFP (P, -1, 0xb17217f7d1cf79abL, 0xc9e3b3aL << 36); //>0.693147180559945309417232121458
public final EFP LOG_2A = new EFP (M, -94, 0xff81a12a17e1979bL, 0x31ace94L << 36); //<-1.00779491359051436097542460399e-28
public final EFP LOG_2_2 = new EFP (P, -2, 0xb17217f7d1cf79abL, 0xc9e3b3aL << 36); //>0.346573590279972654708616060729
public final EFP LOG_2_2A = new EFP (M, -95, 0xff81a12a17e1979bL, 0x31ace94L << 36); //<-5.03897456795257180487712301994e-29
public final EFP LOG_10 = new EFP (P, 1, 0x935d8dddaaa8ac16L, 0xea56d63L << 36); //>2.30258509299404568401799145468
public final EFP LOG_10A = new EFP (M, -92, 0x8fa59ebae3ae0260L, 0xc4b440eL << 36); //<-2.26634931190478263500410602069e-28
public final EFP LOG2_E = new EFP (P, 0, 0xb8aa3b295c17f0bbL, 0xbe87fedL << 36); //<1.44269504088896340735992468100
public final EFP LOG2_EA = new EFP (P, -97, 0xd23a7d11d6aef551L, 0xbad2b4bL << 36); //<1.03650638666742465296873972532e-29
public final EFP LOG2_10 = new EFP (P, 1, 0xd49a784bcd1b8afeL, 0x492bf70L << 36); //>3.32192809488736234787031942949
public final EFP LOG2_10A = new EFP (M, -95, 0xb25024b32693aa01L, 0xc84c52bL << 36); //>-3.51660504800210370161854327284e-29
public final EFP LOG10_2 = new EFP (P, -2, 0x9a209a84fbcff798L, 0x8f8959bL << 36); //>0.301029995663981195213738894724
public final EFP LOG10_2A = new EFP (M, -96, 0xfd20dba1f654b3ceL, 0xaf0b833L << 36); //<-2.49603825457634309563856476519e-29
public final EFP LOG10_E = new EFP (P, -2, 0xde5bd8a937287195L, 0x355baabL << 36); //>0.434294481903251827651128918917
public final EFP LOG10_EA = new EFP (M, -99, 0xa598479b823973fbL, 0x746cbc0L << 36); //<-2.04111402292715890833493215303e-30
// echo read("efp.gp");for(n=1,14,efppub([Str("TENXP",n),Str("10^(2^",n,")")])) | gp -q
public final EFP TENXP1 = new EFP (P, 6, 0xc800000000000000L, 0x0000000L << 36); //=10^(2^1)=100.000000000000000000000000000
public final EFP TENXP2 = new EFP (P, 13, 0x9c40000000000000L, 0x0000000L << 36); //=10^(2^2)=10000.0000000000000000000000000
public final EFP TENXP3 = new EFP (P, 26, 0xbebc200000000000L, 0x0000000L << 36); //=10^(2^3)=100000000.000000000000000000000
public final EFP TENXP4 = new EFP (P, 53, 0x8e1bc9bf04000000L, 0x0000000L << 36); //=10^(2^4)=10000000000000000.0000000000000
public final EFP TENXP5 = new EFP (P, 106, 0x9dc5ada82b70b59dL, 0xf020000L << 36); //=10^(2^5)=1.00000000000000000000000000000e+32
public final EFP TENXP6 = new EFP (P, 212, 0xc2781f49ffcfa6d5L, 0x3cbf6b7L << 36); //<10^(2^6)=1.00000000000000000000000000000e+64
public final EFP TENXP7 = new EFP (P, 425, 0x93ba47c980e98cdfL, 0xc66f337L << 36); //>10^(2^7)=1.00000000000000000000000000000e+128
public final EFP TENXP8 = new EFP (P, 850, 0xaa7eebfb9df9de8dL, 0xddbb902L << 36); //>10^(2^8)=1.00000000000000000000000000000e+256
public final EFP TENXP9 = new EFP (P, 1700, 0xe319a0aea60e91c6L, 0xcc655c5L << 36); //<10^(2^9)=1.00000000000000000000000000000e+512
public final EFP TENXP10 = new EFP (P, 3401, 0xc976758681750c17L, 0x650d3d3L << 36); //>10^(2^10)=1.00000000000000000000000000000e+1024
public final EFP TENXP11 = new EFP (P, 6803, 0x9e8b3b5dc53d5de4L, 0xa74d28dL << 36); //>10^(2^11)=1.00000000000000000000000000000e+2048
public final EFP TENXP12 = new EFP (P, 13606, 0xc46052028a20979aL, 0xc94c154L << 36); //>10^(2^12)=1.00000000000000000000000000000e+4096
public final EFP TENXP13 = new EFP (P, 27213, 0x96a3a1d17faf211aL, 0x0c7c289L << 36); //<10^(2^13)=1.00000000000000000000000000000e+8192
public final EFP TENXP14 = new EFP (P, 54426, 0xb1485471f16603b5L, 0x6226e11L << 36); //<10^(2^14)=1.00000000000000000000000000000e+16384
public final EFP[] EFP_TEN_POWER_P = {
TEN,
TENXP1,
TENXP2,
TENXP3,
TENXP4,
TENXP5,
TENXP6,
TENXP7,
TENXP8,
TENXP9,
TENXP10,
TENXP11,
TENXP12,
TENXP13,
TENXP14,
INF, //番兵 +Inf
};
// echo read("efp.gp");for(n=1,14,efppub([Str("TENXM",n),Str("10^(-2^",n,")")])) | gp -q
public final EFP TENXM1 = new EFP (P, -7, 0xa3d70a3d70a3d70aL, 0x3d70a3dL << 36); //<10^(-2^1)=0.0100000000000000000000000000000
public final EFP TENXM2 = new EFP (P, -14, 0xd1b71758e219652bL, 0xd3c3611L << 36); //<10^(-2^2)=1.00000000000000000000000000000e-4
public final EFP TENXM3 = new EFP (P, -27, 0xabcc77118461cefcL, 0xfdc20d3L << 36); //>10^(-2^3)=1.00000000000000000000000000000e-8
public final EFP TENXM4 = new EFP (P, -54, 0xe69594bec44de15bL, 0x4c2ebe7L << 36); //>10^(-2^4)=1.00000000000000000000000000000e-16
public final EFP TENXM5 = new EFP (P, -107, 0xcfb11ead453994baL, 0x67de18fL << 36); //>10^(-2^5)=1.00000000000000000000000000000e-32
public final EFP TENXM6 = new EFP (P, -213, 0xa87fea27a539e9a5L, 0x3f2398dL << 36); //<10^(-2^6)=1.00000000000000000000000000000e-64
public final EFP TENXM7 = new EFP (P, -426, 0xddd0467c64bce4a0L, 0xac7cb3fL << 36); //<10^(-2^7)=1.00000000000000000000000000000e-128
public final EFP TENXM8 = new EFP (P, -851, 0xc0314325637a1939L, 0xfa91115L << 36); //<10^(-2^8)=1.00000000000000000000000000000e-256
public final EFP TENXM9 = new EFP (P, -1701, 0x9049ee32db23d21cL, 0x7132d33L << 36); //<10^(-2^9)=1.00000000000000000000000000000e-512
public final EFP TENXM10 = new EFP (P, -3402, 0xa2a682a5da57c0bdL, 0x87a6016L << 36); //>10^(-2^10)=1.00000000000000000000000000000e-1024
public final EFP TENXM11 = new EFP (P, -6804, 0xceae534f34362de4L, 0x492512dL << 36); //<10^(-2^11)=1.00000000000000000000000000000e-2048
public final EFP TENXM12 = new EFP (P, -13607, 0xa6dd04c8d2ce9fdeL, 0x2de3812L << 36); //<10^(-2^12)=1.00000000000000000000000000000e-4096
public final EFP TENXM13 = new EFP (P, -27214, 0xd986c20b686da869L, 0x5d1d4feL << 36); //>10^(-2^13)=1.00000000000000000000000000000e-8192
public final EFP TENXM14 = new EFP (P, -54427, 0xb8d5bbe70e108517L, 0x456e9e1L << 36); //>10^(-2^14)=1.00000000000000000000000000000e-16384
public final EFP[] EFP_TEN_POWER_M = {
ONE_10,
TENXM1,
TENXM2,
TENXM3,
TENXM4,
TENXM5,
TENXM6,
TENXM7,
TENXM8,
TENXM9,
TENXM10,
TENXM11,
TENXM12,
TENXM13,
TENXM14,
ZERO, //番兵 +0
};
//------------------------------------------------------------------------
//asin
// echo read("efp.gp");efpchebyshev("ASIN_C",asin,-1/16,1/16,17) | gp -q
public final EFP ASIN_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP ASIN_C3 = new EFP (P, -3, 0xaaaaaaaaaaaaaaaaL, 0xaa9f5a6L << 36); //=0.166666666666666666666664327061
public final EFP ASIN_C5 = new EFP (P, -4, 0x999999999999999bL, 0x27bc1b8L << 36); //=0.0750000000000000000105385402653
public final EFP ASIN_C7 = new EFP (P, -5, 0xb6db6db6db6d9dfbL, 0x62327e8L << 36); //=0.0446428571428571212813671978867
public final EFP ASIN_C9 = new EFP (P, -6, 0xf8e38e38e465b639L, 0x780782eL << 36); //=0.0303819444444683685951253163427
public final EFP ASIN_C11 = new EFP (P, -6, 0xb745d17238e942a1L, 0xe80f5beL << 36); //=0.0223721590753288857337240816603
public final EFP ASIN_C13 = new EFP (P, -6, 0x8e2765c0b9aaa792L, 0xa93870aL << 36); //=0.0173527705535908188340798484805
public final EFP ASIN_C15 = new EFP (P, -7, 0xe4c6ca7a5689895bL, 0x0fdd729L << 36); //=0.0139634110758853644843472082762
public final EFP ASIN_C17 = new EFP (P, -7, 0xc0428d0d9769d446L, 0x583b42dL << 36); //=0.0117346169921491621622941093289
// 92.12bit
//------------------------------------------------------------------------
//asinh
// echo read("efp.gp");efpchebyshev("ASINH_C",asinh,-1/2,1/2,43) | gp -q
public final EFP ASINH_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP ASINH_C3 = new EFP (M, -3, 0xaaaaaaaaaaaaaaaaL, 0xaaaa73cL << 36); //=-0.166666666666666666666666622305
public final EFP ASINH_C5 = new EFP (P, -4, 0x9999999999999999L, 0x98eba3eL << 36); //=0.0749999999999999999999820129717
public final EFP ASINH_C7 = new EFP (M, -5, 0xb6db6db6db6db6daL, 0x693062cL << 36); //=-0.0446428571428571428536948337862
public final EFP ASINH_C9 = new EFP (P, -6, 0xf8e38e38e38e3802L, 0x877ce5fL << 36); //=0.0303819444444444440632350540650
public final EFP ASINH_C11 = new EFP (M, -6, 0xb745d1745d17072fL, 0x8f119f4L << 36); //=-0.0223721590909090637466150767286
public final EFP ASINH_C13 = new EFP (P, -6, 0x8e27627627566903L, 0xdf845ccL << 36); //=0.0173527644230755851112834055009
public final EFP ASINH_C15 = new EFP (M, -7, 0xe4ccccccc9700e9eL, 0xe0b4a69L << 36); //=-0.0139648437499522191713609105717
public final EFP ASINH_C17 = new EFP (P, -7, 0xbd43c3c369baae2eL, 0x0efcbb2L << 36); //=0.0115518008948602246771685034495
public final EFP ASINH_C19 = new EFP (M, -7, 0x9fef28648d7f5526L, 0x95df2b5L << 36); //=-0.00976160950286693766098184072269
public final EFP ASINH_C21 = new EFP (P, -7, 0x89779e056ca4e338L, 0xd00497cL << 36); //=0.00839033538586369462750852571141
public final EFP ASINH_C23 = new EFP (M, -8, 0xef9dde222ea1963bL, 0xe27b426L << 36); //=-0.00731252046931722928944285830165
public final EFP ASINH_C25 = new EFP (P, -8, 0xd342a867c46a40d7L, 0x608fa17L << 36); //=0.00644715521733314071113327514541
public final EFP ASINH_C27 = new EFP (M, -8, 0xbc1323a7fe6984a7L, 0x201509dL << 36); //=-0.00573958626772545827330135382977
public final EFP ASINH_C29 = new EFP (P, -8, 0xa8c41a9477d0f87aL, 0x533f07cL << 36); //=0.00515033052300720080631063831135
public final EFP ASINH_C31 = new EFP (M, -8, 0x982f5aab1d57a757L, 0x87f7027L << 36); //=-0.00464431693238042269332079800182
public final EFP ASINH_C33 = new EFP (P, -8, 0x88c1b2170947d07cL, 0x03ff2fcL << 36); //=0.00417348094749513993640755085487
public final EFP ASINH_C35 = new EFP (M, -9, 0xef58f638c3ca7cffL, 0x77a770cL << 36); //=-0.00365215312264336578286676378192
public final EFP ASINH_C37 = new EFP (P, -9, 0xc1c49585f23563ecL, 0x9a83aedL << 36); //=0.00295666361302767397480120706092
public final EFP ASINH_C39 = new EFP (M, -9, 0x844314a5dc2c3362L, 0x37b5811L << 36); //=-0.00201815847491166045931431987253
public final EFP ASINH_C41 = new EFP (P, -10, 0x824564bc0126d26dL, 0x0c5dd9fL << 36); //=9.93889376333981375114292565553e-4
public final EFP ASINH_C43 = new EFP (M, -12, 0x85dfcbe40f7ac39fL, 0xb82e7c3L << 36); //=-2.55344781642232531153119989033e-4
// 94.34bit
//------------------------------------------------------------------------
//atan
// echo read("efp.gp");efpchebyshev("ATAN_C",atan,1-sqrt(2),sqrt(2)-1,39) | gp -q
public final EFP ATAN_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP ATAN_C3 = new EFP (M, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaa510L << 36); //=-0.333333333333333333333333188469
public final EFP ATAN_C5 = new EFP (P, -3, 0xccccccccccccccccL, 0xcb75e59L << 36); //=0.199999999999999999999929089265
public final EFP ATAN_C7 = new EFP (M, -3, 0x9249249249249247L, 0xef2e1e8L << 36); //=-0.142857142857142857126478105101
public final EFP ATAN_C9 = new EFP (P, -4, 0xe38e38e38e38e24dL, 0x0fb9b9aL << 36); //=0.111111111111111108934840916430
public final EFP ATAN_C11 = new EFP (M, -4, 0xba2e8ba2e8b9c37fL, 0xd40106dL << 36); //=-0.0909090909090907233954815301475
public final EFP ATAN_C13 = new EFP (P, -4, 0x9d89d89d89c01044L, 0xee8e878L << 36); //=0.0769230769230660198728951590461
public final EFP ATAN_C15 = new EFP (M, -4, 0x888888888479743eL, 0xd1a4c1cL << 36); //=-0.0666666666662052227836546394505
public final EFP ATAN_C17 = new EFP (P, -5, 0xf0f0f0eff12a86f3L, 0x34f4f78L << 36); //=0.0588235293972255773084039586191
public final EFP ATAN_C19 = new EFP (M, -5, 0xd79435cd132b46adL, 0x026fbddL << 36); //=-0.0526315785984461994745177668558
public final EFP ATAN_C21 = new EFP (P, -5, 0xc30c2f05b9b60e24L, 0x4f7cf62L << 36); //=0.0476190411387569357252301278730
public final EFP ATAN_C23 = new EFP (M, -5, 0xb216298497a81754L, 0x9c69988L << 36); //=-0.0434781667513366645605035624712
public final EFP ATAN_C25 = new EFP (P, -5, 0xa3d5e99dc5d0a87cL, 0x531842aL << 36); //=0.0399989247929292486609759555531
public final EFP ATAN_C27 = new EFP (M, -5, 0x97aa006d0e00c9c7L, 0x30d6815L << 36); //=-0.0370273605957438052706320851811
public final EFP ATAN_C29 = new EFP (P, -5, 0x8cf60e9e64655ffeL, 0x38ac19cL << 36); //=0.0344143458408095737006383246276
public final EFP ATAN_C31 = new EFP (M, -5, 0x82959208f1c7a2afL, 0xdae8a29L << 36); //=-0.0318809227456870204466446023911
public final EFP ATAN_C33 = new EFP (P, -6, 0xeb2210cae680d538L, 0x15fff4fL << 36); //=0.0287027671794960285031110247127
public final EFP ATAN_C35 = new EFP (M, -6, 0xc010e629b0e973a6L, 0xe64c5d3L << 36); //=-0.0234455581062579745139013801043
public final EFP ATAN_C37 = new EFP (P, -7, 0xf4fd1335dff0ecefL, 0x1237cb3L << 36); //=0.0149529159166368844370818258508
public final EFP ATAN_C39 = new EFP (M, -8, 0xae06e746e01494ddL, 0xc1bb093L << 36); //=-0.00531088154616611800320323885484
// 92.91bit
//------------------------------------------------------------------------
//atanh
// echo read("efp.gp");efpchebyshev("ATANH_C",atanh,-1/16,1/16,19) | gp -q
public final EFP ATANH_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP ATANH_C3 = new EFP (P, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaab40L << 36); //=0.333333333333333333333333348412
public final EFP ATANH_C5 = new EFP (P, -3, 0xccccccccccccccccL, 0xcb39274L << 36); //=0.199999999999999999999916527823
public final EFP ATANH_C7 = new EFP (P, -3, 0x9249249249249258L, 0xc166b48L << 36); //=0.142857142857142857354447548729
public final EFP ATANH_C9 = new EFP (P, -4, 0xe38e38e38e38399dL, 0xe3605a0L << 36); //=0.111111111111110816314276914861
public final EFP ATANH_C11 = new EFP (P, -4, 0xba2e8ba2eae60f89L, 0xa98ab82L << 36); //=0.0909090909093377689017810115409
public final EFP ATANH_C13 = new EFP (P, -4, 0x9d89d8991665e749L, 0xd36e921L << 36); //=0.0769230767935366725885888098730
public final EFP ATANH_C15 = new EFP (P, -4, 0x88888e4ace4d77aaL, 0xa2aa416L << 36); //=0.0666667095736446080100633321247
public final EFP ATANH_C17 = new EFP (P, -5, 0xf0e7cfa2bdbf9821L, 0x93bcd2aL << 36); //=0.0588148222703778409986221399492
public final EFP ATANH_C19 = new EFP (P, -5, 0xdb9f4d0dedd2896fL, 0x4b48c7fL << 36); //=0.0536187181413551121288347545022
// 99.69bit
public final EFP[] ATH_T = {
// echo read("efp.gp");for(n=0,92,efpmem([Str("1-2/(2^",n,".5+1)")])) | gp -q
new EFP (P, -3, 0xafb0ccc06219b7baL, 0x682764dL << 36), //>1-2/(2^0.5+1)=0.171572875253809902396622551581
new EFP (P, -2, 0xf486f8adc4df1a3fL, 0x3373579L << 36), //>1-2/(2^1.5+1)=0.477592250072517114970463586166
new EFP (P, -1, 0xb31638273cf89250L, 0x55f0c13L << 36), //>1-2/(2^2.5+1)=0.699557790355330309986660974397
new EFP (P, -1, 0xd66b9a67d12abc57L, 0x98d2421L << 36), //<1-2/(2^3.5+1)=0.837579393716775426922621893013
new EFP (P, -1, 0xea548bdf707c71a8L, 0x48f4c93L << 36), //>1-2/(2^4.5+1)=0.915352575350412834517311077936
new EFP (P, -1, 0xf4ee4e9693348047L, 0xc360937L << 36), //<1-2/(2^5.5+1)=0.956761276017646271068242267538
new EFP (P, -1, 0xfa67aba3bd4ef753L, 0x97d0d24L << 36), //>1-2/(2^6.5+1)=0.978144385791264050024830160335
new EFP (P, -1, 0xfd2fe692fd3e80eaL, 0xf06feacL << 36), //>1-2/(2^7.5+1)=0.989012156377834030198271666207
new EFP (P, -1, 0xfe96f56512becc96L, 0x5d9833cL << 36), //>1-2/(2^8.5+1)=0.994490945030288739194890825379
new EFP (P, -1, 0xff4b3af63364e808L, 0x18a7859L << 36), //>1-2/(2^9.5+1)=0.997241673572165532752151151462
new EFP (P, -1, 0xffa58d83926f2d61L, 0x373e4afL << 36), //<1-2/(2^10.5+1)=0.998619885084221356182770883686
new EFP (P, -1, 0xffd2c2c2d8870e17L, 0xed05d07L << 36), //<1-2/(2^11.5+1)=0.999309704370286962147601894210
new EFP (P, -1, 0xffe960618e30f4faL, 0x87ef4d9L << 36), //<1-2/(2^12.5+1)=0.999654792611355549595229809320
new EFP (P, -1, 0xfff4aff0cb566033L, 0x22866e9L << 36), //>1-2/(2^13.5+1)=0.999827381408374463164023282349
new EFP (P, -1, 0xfffa57e86632f050L, 0x0d74b69L << 36), //<1-2/(2^14.5+1)=0.999913686979379216955639576948
new EFP (P, -1, 0xfffd2bf0332a7066L, 0xd4437adL << 36), //<1-2/(2^15.5+1)=0.999956842558427322377129017797
new EFP (P, -1, 0xfffe95f71997573eL, 0xc3c2f8aL << 36), //<1-2/(2^16.5+1)=0.999978421046390553788765568617
new EFP (P, -1, 0xffff4afb4ccbef81L, 0x0515247L << 36), //<1-2/(2^17.5+1)=0.999989210464988558024532263171
new EFP (P, -1, 0xffffa57d9666003cL, 0xba71034L << 36), //<1-2/(2^18.5+1)=0.999994605217942481540092531517
new EFP (P, -1, 0xffffd2bec733012dL, 0xe46d4faL << 36), //<1-2/(2^19.5+1)=0.999997302605333276682525030987
new EFP (P, -1, 0xffffe95f629980b8L, 0xe320c19L << 36), //<1-2/(2^20.5+1)=0.999998651301757145479438792148
new EFP (P, -1, 0xfffff4afb10cc060L, 0xafaddc0L << 36), //<1-2/(2^21.5+1)=0.999999325650651199294269995571
new EFP (P, -1, 0xfffffa57d8766030L, 0xdf9aa0eL << 36), //<1-2/(2^22.5+1)=0.999999662825268756257023430024
new EFP (P, -1, 0xfffffd2bec373018L, 0x80c5c71L << 36), //>1-2/(2^23.5+1)=0.999999831412620167277390168747
new EFP (P, -1, 0xfffffe95f61a980cL, 0x4281f26L << 36), //>1-2/(2^24.5+1)=0.999999915706306530925465490884
new EFP (P, -1, 0xffffff4afb0d0c06L, 0x2184db1L << 36), //>1-2/(2^25.5+1)=0.999999957853152377284369196196
new EFP (P, -1, 0xffffffa57d867603L, 0x10cae9cL << 36), //>1-2/(2^26.5+1)=0.999999978926575966597586691927
new EFP (P, -1, 0xffffffd2bec33701L, 0x8866846L << 36), //<1-2/(2^27.5+1)=0.999999989463287927787642992063
new EFP (P, -1, 0xffffffe95f619a80L, 0xc433642L << 36), //<1-2/(2^28.5+1)=0.999999994731643950016033797887
new EFP (P, -1, 0xfffffff4afb0cd00L, 0x6219b65L << 36), //<1-2/(2^29.5+1)=0.999999997365821971538569960698
new EFP (P, -1, 0xfffffffa57d86670L, 0x310cdbbL << 36), //>1-2/(2^30.5+1)=0.999999998682910984901923244074
new EFP (P, -1, 0xfffffffd2bec3334L, 0x18866dfL << 36), //>1-2/(2^31.5+1)=0.999999999341455492234121187754
new EFP (P, -1, 0xfffffffe95f61999L, 0x0c4336fL << 36), //<1-2/(2^32.5+1)=0.999999999670727746062850485280
new EFP (P, -1, 0xffffffff4afb0cccL, 0x46219b8L << 36), //>1-2/(2^33.5+1)=0.999999999835363873017872715487
new EFP (P, -1, 0xffffffffa57d8666L, 0x1310cdcL << 36), //>1-2/(2^34.5+1)=0.999999999917681936505548225955
new EFP (P, -1, 0xffffffffd2bec333L, 0x058866eL << 36), //>1-2/(2^35.5+1)=0.999999999958840968251927080030
new EFP (P, -1, 0xffffffffe95f6199L, 0x81c4337L << 36), //>1-2/(2^36.5+1)=0.999999999979420484125751781778
new EFP (P, -1, 0xfffffffff4afb0ccL, 0xc0a219bL << 36), //<1-2/(2^37.5+1)=0.999999999989710242062822951330
new EFP (P, -1, 0xfffffffffa57d866L, 0x60410ceL << 36), //>1-2/(2^38.5+1)=0.999999999994855121031398240775
new EFP (P, -1, 0xfffffffffd2bec33L, 0x301c867L << 36), //>1-2/(2^39.5+1)=0.999999999997427560515695811665
new EFP (P, -1, 0xfffffffffe95f619L, 0x980d433L << 36), //<1-2/(2^40.5+1)=0.999999999998713780257847078652
new EFP (P, -1, 0xffffffffff4afb0cL, 0xcc0661aL << 36), //>1-2/(2^41.5+1)=0.999999999999356890128923332531
new EFP (P, -1, 0xffffffffffa57d86L, 0x660320dL << 36), //>1-2/(2^42.5+1)=0.999999999999678445064461614567
new EFP (P, -1, 0xffffffffffd2bec3L, 0x33018c6L << 36), //<1-2/(2^43.5+1)=0.999999999999839222532230794359
new EFP (P, -1, 0xffffffffffe95f61L, 0x9980c53L << 36), //<1-2/(2^44.5+1)=0.999999999999919611266115393948
new EFP (P, -1, 0xfffffffffff4afb0L, 0xccc0626L << 36), //>1-2/(2^45.5+1)=0.999999999999959805633057696166
new EFP (P, -1, 0xfffffffffffa57d8L, 0x6660312L << 36), //>1-2/(2^46.5+1)=0.999999999999979902816528847881
new EFP (P, -1, 0xfffffffffffd2becL, 0x3330189L << 36), //>1-2/(2^47.5+1)=0.999999999999989951408264423890
new EFP (P, -1, 0xfffffffffffe95f6L, 0x19980c4L << 36), //<1-2/(2^48.5+1)=0.999999999999994975704132211932
new EFP (P, -1, 0xffffffffffff4afbL, 0x0ccc062L << 36), //<1-2/(2^49.5+1)=0.999999999999997487852066105963
new EFP (P, -1, 0xffffffffffffa57dL, 0x8666031L << 36), //<1-2/(2^50.5+1)=0.999999999999998743926033052981
new EFP (P, -1, 0xffffffffffffd2beL, 0xc333019L << 36), //>1-2/(2^51.5+1)=0.999999999999999371963016526490
new EFP (P, -1, 0xffffffffffffe95fL, 0x619980cL << 36), //<1-2/(2^52.5+1)=0.999999999999999685981508263245
new EFP (P, -1, 0xfffffffffffff4afL, 0xb0ccc06L << 36), //<1-2/(2^53.5+1)=0.999999999999999842990754131623
new EFP (P, -1, 0xfffffffffffffa57L, 0xd866603L << 36), //<1-2/(2^54.5+1)=0.999999999999999921495377065811
new EFP (P, -1, 0xfffffffffffffd2bL, 0xec33302L << 36), //>1-2/(2^55.5+1)=0.999999999999999960747688532906
new EFP (P, -1, 0xfffffffffffffe95L, 0xf619981L << 36), //>1-2/(2^56.5+1)=0.999999999999999980373844266453
new EFP (P, -1, 0xffffffffffffff4aL, 0xfb0ccc0L << 36), //<1-2/(2^57.5+1)=0.999999999999999990186922133226
new EFP (P, -1, 0xffffffffffffffa5L, 0x7d86660L << 36), //<1-2/(2^58.5+1)=0.999999999999999995093461066613
new EFP (P, -1, 0xffffffffffffffd2L, 0xbec3330L << 36), //<1-2/(2^59.5+1)=0.999999999999999997546730533307
new EFP (P, -1, 0xffffffffffffffe9L, 0x5f61998L << 36), //<1-2/(2^60.5+1)=0.999999999999999998773365266653
new EFP (P, -1, 0xfffffffffffffff4L, 0xafb0cccL << 36), //<1-2/(2^61.5+1)=0.999999999999999999386682633327
new EFP (P, -1, 0xfffffffffffffffaL, 0x57d8666L << 36), //<1-2/(2^62.5+1)=0.999999999999999999693341316663
new EFP (P, -1, 0xfffffffffffffffdL, 0x2bec333L << 36), //<1-2/(2^63.5+1)=0.999999999999999999846670658332
new EFP (P, -1, 0xfffffffffffffffeL, 0x95f619aL << 36), //>1-2/(2^64.5+1)=0.999999999999999999923335329166
new EFP (P, -1, 0xffffffffffffffffL, 0x4afb0cdL << 36), //>1-2/(2^65.5+1)=0.999999999999999999961667664583
new EFP (P, -1, 0xffffffffffffffffL, 0xa57d866L << 36), //<1-2/(2^66.5+1)=0.999999999999999999980833832291
new EFP (P, -1, 0xffffffffffffffffL, 0xd2bec33L << 36), //<1-2/(2^67.5+1)=0.999999999999999999990416916146
new EFP (P, -1, 0xffffffffffffffffL, 0xe95f61aL << 36), //>1-2/(2^68.5+1)=0.999999999999999999995208458073
new EFP (P, -1, 0xffffffffffffffffL, 0xf4afb0dL << 36), //>1-2/(2^69.5+1)=0.999999999999999999997604229036
new EFP (P, -1, 0xffffffffffffffffL, 0xfa57d86L << 36), //<1-2/(2^70.5+1)=0.999999999999999999998802114518
new EFP (P, -1, 0xffffffffffffffffL, 0xfd2bec3L << 36), //<1-2/(2^71.5+1)=0.999999999999999999999401057259
new EFP (P, -1, 0xffffffffffffffffL, 0xfe95f62L << 36), //>1-2/(2^72.5+1)=0.999999999999999999999700528630
new EFP (P, -1, 0xffffffffffffffffL, 0xff4afb1L << 36), //>1-2/(2^73.5+1)=0.999999999999999999999850264315
new EFP (P, -1, 0xffffffffffffffffL, 0xffa57d8L << 36), //<1-2/(2^74.5+1)=0.999999999999999999999925132157
new EFP (P, -1, 0xffffffffffffffffL, 0xffd2becL << 36), //<1-2/(2^75.5+1)=0.999999999999999999999962566079
new EFP (P, -1, 0xffffffffffffffffL, 0xffe95f6L << 36), //<1-2/(2^76.5+1)=0.999999999999999999999981283039
new EFP (P, -1, 0xffffffffffffffffL, 0xfff4afbL << 36), //<1-2/(2^77.5+1)=0.999999999999999999999990641520
new EFP (P, -1, 0xffffffffffffffffL, 0xfffa57eL << 36), //>1-2/(2^78.5+1)=0.999999999999999999999995320760
new EFP (P, -1, 0xffffffffffffffffL, 0xfffd2bfL << 36), //>1-2/(2^79.5+1)=0.999999999999999999999997660380
new EFP (P, -1, 0xffffffffffffffffL, 0xfffe95fL << 36), //<1-2/(2^80.5+1)=0.999999999999999999999998830190
new EFP (P, -1, 0xffffffffffffffffL, 0xffff4b0L << 36), //>1-2/(2^81.5+1)=0.999999999999999999999999415095
new EFP (P, -1, 0xffffffffffffffffL, 0xffffa58L << 36), //>1-2/(2^82.5+1)=0.999999999999999999999999707547
new EFP (P, -1, 0xffffffffffffffffL, 0xffffd2cL << 36), //>1-2/(2^83.5+1)=0.999999999999999999999999853774
new EFP (P, -1, 0xffffffffffffffffL, 0xffffe96L << 36), //>1-2/(2^84.5+1)=0.999999999999999999999999926887
new EFP (P, -1, 0xffffffffffffffffL, 0xfffff4bL << 36), //>1-2/(2^85.5+1)=0.999999999999999999999999963443
new EFP (P, -1, 0xffffffffffffffffL, 0xfffffa5L << 36), //<1-2/(2^86.5+1)=0.999999999999999999999999981722
new EFP (P, -1, 0xffffffffffffffffL, 0xfffffd3L << 36), //>1-2/(2^87.5+1)=0.999999999999999999999999990861
new EFP (P, -1, 0xffffffffffffffffL, 0xfffffe9L << 36), //<1-2/(2^88.5+1)=0.999999999999999999999999995430
new EFP (P, -1, 0xffffffffffffffffL, 0xffffff5L << 36), //>1-2/(2^89.5+1)=0.999999999999999999999999997715
new EFP (P, -1, 0xffffffffffffffffL, 0xffffffaL << 36), //<1-2/(2^90.5+1)=0.999999999999999999999999998858
new EFP (P, -1, 0xffffffffffffffffL, 0xffffffdL << 36), //<1-2/(2^91.5+1)=0.999999999999999999999999999429
new EFP (P, -1, 0xffffffffffffffffL, 0xfffffffL << 36), //>1-2/(2^92.5+1)=0.999999999999999999999999999714
}; //ATH_T
// echo read("efp.gp");efpchebyshev("ATH_C",atanh,2*sqrt(2)-3,3-2*sqrt(2),27) | gp -q
public final EFP ATH_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP ATH_C3 = new EFP (P, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaaafaL << 36); //=0.333333333333333333333333341344
public final EFP ATH_C5 = new EFP (P, -3, 0xccccccccccccccccL, 0xcc9635cL << 36); //=0.199999999999999999999988711045
public final EFP ATH_C7 = new EFP (P, -3, 0x9249249249249249L, 0xb11c709L << 36); //=0.142857142857142857150297250720
public final EFP ATH_C9 = new EFP (P, -4, 0xe38e38e38e38e1f4L, 0xa08ab7fL << 36); //=0.111111111111111108335586715660
public final EFP ATH_C11 = new EFP (P, -4, 0xba2e8ba2e8bba550L, 0x957b4b0L << 36); //=0.0909090909090915592120576087311
public final EFP ATH_C13 = new EFP (P, -4, 0x9d89d89d88f3a6b4L, 0xb83ee9bL << 36); //=0.0769230769229752425509012132237
public final EFP ATH_C15 = new EFP (P, -4, 0x88888888e97610a0L, 0x018bbc5L << 36); //=0.0666666666776860883121262399402
public final EFP ATH_C17 = new EFP (P, -5, 0xf0f0f0b6e98b6c2fL, 0x176ec78L << 36); //=0.0588235285673331770514149020773
public final EFP ATH_C19 = new EFP (P, -5, 0xd79442422528c14bL, 0xdacdc08L << 36); //=0.0526316250055264844984084010822
public final EFP ATH_C21 = new EFP (P, -5, 0xc30a54423d395d6dL, 0xa2f5188L << 36); //=0.0476172725064557245020882061529
public final EFP ATH_C23 = new EFP (P, -5, 0xb247b3a940a7a020L, 0x5cb7483L << 36); //=0.0435254114163771411702547167136
public final EFP ATH_C25 = new EFP (P, -5, 0xa07d6fb3e1085165L, 0x68590abL << 36); //=0.0391821254143583526005317341260
public final EFP ATH_C27 = new EFP (P, -5, 0xb976c8a2f3029b2dL, 0xa0b471bL << 36); //=0.0452792966236194263462909201691
// 98.60bit
//------------------------------------------------------------------------
//cos
// echo read("efp.gp");efpchebyshev("COS_C",cos,-Pi/4,Pi/4,20) | gp -q
public final EFP COS_C0 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP COS_C2 = new EFP (M, -2, 0xffffffffffffffffL, 0xffffff8L << 36); //=-0.499999999999999999999999999192
public final EFP COS_C4 = new EFP (P, -5, 0xaaaaaaaaaaaaaaaaL, 0xaaa9a56L << 36); //=0.0416666666666666666666666138992
public final EFP COS_C6 = new EFP (M, -10, 0xb60b60b60b60b60bL, 0x5d7bff4L << 36); //=-0.00138888888888888888888755433738
public final EFP COS_C8 = new EFP (P, -16, 0xd00d00d00d00d002L, 0x8a46e65L << 36); //=2.48015873015873015699919557419e-5
public final EFP COS_C10 = new EFP (M, -22, 0x93f27dbbc4facfccL, 0xd7af990L << 36); //=-2.75573192239858775556350380978e-7
public final EFP COS_C12 = new EFP (P, -29, 0x8f76c77fc6961076L, 0x0290d00L << 36); //=2.08767569878619213856987201647e-9
public final EFP COS_C14 = new EFP (M, -37, 0xc9cba54576804449L, 0x648c611L << 36); //=-1.14707455958584021049089234187e-11
public final EFP COS_C16 = new EFP (P, -45, 0xd73f9e26754ce09dL, 0xec906ebL << 36); //=4.77947696821877613102951591111e-14
public final EFP COS_C18 = new EFP (M, -53, 0xb412768e7c3c3046L, 0x846cd1fL << 36); //=-1.56187668293428465635746630579e-16
public final EFP COS_C20 = new EFP (P, -62, 0xf0dad505af592189L, 0x064973cL << 36); //=4.08023924165342585701515258359e-19
// 97.20bit
// echo read("efp.gp");efpchebyshev("SIN_C",sin,-Pi/4,Pi/4,21) | gp -q
public final EFP SIN_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP SIN_C3 = new EFP (M, -3, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaa8L << 36); //=-0.166666666666666666666666666532
public final EFP SIN_C5 = new EFP (P, -7, 0x8888888888888888L, 0x88880d0L << 36); //=0.00833333333333333333333332709649
public final EFP SIN_C7 = new EFP (M, -13, 0xd00d00d00d00d00cL, 0xfe77205L << 36); //=-1.98412698412698412698291342662e-4
public final EFP SIN_C9 = new EFP (P, -19, 0xb8ef1d2ab6399c76L, 0xfe4484aL << 36); //=2.75573192239858906394404635468e-6
public final EFP SIN_C11 = new EFP (M, -26, 0xd7322b3faa27078eL, 0x1700055L << 36); //=-2.50521083854417101136670463394e-8
public final EFP SIN_C13 = new EFP (P, -33, 0xb092309d433be4baL, 0xeb15e86L << 36); //=1.60590438368179416703490738961e-10
public final EFP SIN_C15 = new EFP (M, -41, 0xd73f9f392253780eL, 0x670f3ecL << 36); //=-7.64716373079884612335141370435e-13
public final EFP SIN_C17 = new EFP (P, -49, 0xca963aa1cfea3bf8L, 0x08cec0aL << 36); //=2.81145706929778488157207193776e-15
public final EFP SIN_C19 = new EFP (M, -57, 0x97a3db8f70e5ae02L, 0x8f1dd1fL << 36); //=-8.22042461090320344889517792891e-18
public final EFP SIN_C21 = new EFP (P, -66, 0xb791d94ca9fd98fdL, 0x74f2261L << 36); //=1.94362003290782920561352619652e-20
// 96.74bit
//------------------------------------------------------------------------
//cosh
// echo read("efp.gp");efpchebyshev("COSH_C",cosh,-1/8,1/8,14) | gp -q
public final EFP COSH_C0 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP COSH_C2 = new EFP (P, -1, 0x8000000000000000L, 0x0000000L << 36); //=0.500000000000000000000000000000
public final EFP COSH_C4 = new EFP (P, -5, 0xaaaaaaaaaaaaaaaaL, 0xaaa9902L << 36); //=0.0416666666666666666666666096078
public final EFP COSH_C6 = new EFP (P, -10, 0xb60b60b60b60b60bL, 0xa75a997L << 36); //=0.00138888888888888888891810606314
public final EFP COSH_C8 = new EFP (P, -16, 0xd00d00d00d00beb4L, 0xa29cfbaL << 36); //=2.48015873015872942413289979337e-5
public final EFP COSH_C10 = new EFP (P, -22, 0x93f27dbbc74aee4dL, 0x312895cL << 36); //=2.75573192240861864407003360028e-7
public final EFP COSH_C12 = new EFP (P, -29, 0x8f76c72851473b51L, 0xdc04f2cL << 36); //=2.08767562292826617371683025321e-9
public final EFP COSH_C14 = new EFP (P, -37, 0xc9d919ab996aa4aeL, 0x80c913fL << 36); //=1.14737331357355798829750446122e-11
// 100.26bit
//------------------------------------------------------------------------
//exp
public final EFP[] EXP_P_I = {
// echo read("efp.gp");for(n=0,14,efpmem([Str("exp(2^",n,")")])) | gp -q
new EFP (P, 1, 0xadf85458a2bb4a9aL, 0xafdc562L << 36), //<exp(2^0)=2.71828182845904523536028747135
new EFP (P, 2, 0xec7325c6a6ed6e61L, 0x9d1dd10L << 36), //<exp(2^1)=7.38905609893065022723042746058
new EFP (P, 5, 0xda64817139d2c33cL, 0x6b69dffL << 36), //>exp(2^2)=54.5981500331442390781102612029
new EFP (P, 11, 0xba4f53ea38636f85L, 0xf007042L << 36), //<exp(2^3)=2980.95798704172827474359209945
new EFP (P, 23, 0x87975e8540010249L, 0x11f8b84L << 36), //<exp(2^4)=8886110.52050787263676302374078
new EFP (P, 46, 0x8fa1fe625b3163ecL, 0x23c4201L << 36), //>exp(2^5)=78962960182680.6951609780226351
new EFP (P, 92, 0xa12cc167acbe6902L, 0xe71eadaL << 36), //<exp(2^6)=6235149080811616882909238708.93
new EFP (P, 184, 0xcaf2a62eea10bbfaL, 0x9fa6a91L << 36), //>exp(2^7)=3.88770840599459509222267368836e+55
new EFP (P, 369, 0xa0e3d440a5f5d071L, 0x919807cL << 36), //>exp(2^8)=1.51142766500410354252008966571e+111
new EFP (P, 738, 0xca3b2825d4297360L, 0x4e42b3eL << 36), //<exp(2^9)=2.28441358653975664037875151712e+222
new EFP (P, 1477, 0x9fc169073a8d0d13L, 0x21c376bL << 36), //<exp(2^10)=5.21854543436743420112120953370e+444
new EFP (P, 2954, 0xc763a52d0570da4eL, 0xe13cad2L << 36), //<exp(2^11)=2.72332164505571925012480592774e+889
new EFP (P, 5909, 0x9b4c119529dab99dL, 0xde62927L << 36), //<exp(2^12)=7.41648078242898890481921050373e+1778
new EFP (P, 11818, 0xbc6a67ca24e9ba38L, 0x5a44770L << 36), //<exp(2^13)=5.50041871961385074607498352511e+3557
new EFP (P, 23637, 0x8aac74ab03b22463L, 0x55451adL << 36), //<exp(2^14)=3.02546060910784732301427230567e+7115
}; //EXP_P_I
public final EFP[] EXP_M_I = {
// echo read("efp.gp");for(n=0,14,efpmem([Str("exp(-2^",n,")")])) | gp -q
new EFP (P, -2, 0xbc5ab1b16779be35L, 0x75bd8f0L << 36), //<exp(-2^0)=0.367879441171442321595523770161
new EFP (P, -3, 0x8a95551dfc0e5cfeL, 0xdbb7571L << 36), //>exp(-2^1)=0.135335283236612691893999494972
new EFP (P, -6, 0x960aadc109e7a3bfL, 0x4578099L << 36), //<exp(-2^2)=0.0183156388887341802937180212732
new EFP (P, -12, 0xafe10820813d65dfL, 0xe6a33c0L << 36), //<exp(-2^3)=3.35462627902511838821389125781e-4
new EFP (P, -24, 0xf1aaddd7742e56d3L, 0x2fb9f99L << 36), //<exp(-2^4)=1.12535174719259114513775179060e-7
new EFP (P, -47, 0xe42327bb0b2340f1L, 0x4cd0092L << 36), //<exp(-2^5)=1.26641655490941757231209041560e-14
new EFP (P, -93, 0xcb4ea3990f265d5fL, 0x9694038L << 36), //<exp(-2^6)=1.60381089054863785297608703414e-28
new EFP (P, -185, 0xa175cf9cd7d85844L, 0x76b75a8L << 36), //>exp(-2^7)=2.57220937264241482683953808361e-56
new EFP (P, -370, 0xcbaacab56a74dfdcL, 0xe09d13dL << 36), //<exp(-2^8)=6.61626105670948526102953080736e-112
new EFP (P, -739, 0xa2084f6d90498ad1L, 0xc4658daL << 36), //<exp(-2^9)=4.37749103705305145412147276290e-223
new EFP (P, -1478, 0xcd1d09977435cc77L, 0x7a9a998L << 36), //>exp(-2^10)=1.91624277794797998988359419145e-445
new EFP (P, -2955, 0xa45784a7bcca7d6dL, 0xc205c90L << 36), //<exp(-2^11)=3.67198638403779134660860694154e-890
new EFP (P, -5910, 0xd3007fc4b14655ddL, 0x1be84e5L << 36), //>exp(-2^12)=1.34834840045589340763610867190e-1779
new EFP (P, -11819, 0xade9d29e7bfeb08eL, 0x33a8236L << 36), //<exp(-2^13)=1.81804340901196629372122861908e-3558
new EFP (P, -23638, 0xec4bb8768ab8ab91L, 0x718a7e7L << 36), //<exp(-2^14)=3.30528183705185176386021874079e-7116
}; //EXP_M_I
// echo read("efp.gp");efpchebyshev("EXP_C",exp,-1/64,1/64,10) | gp -q
public final EFP EXP_C0 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP EXP_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000001L << 36); //=1.00000000000000000000000000040
public final EFP EXP_C2 = new EFP (P, -1, 0x8000000000000000L, 0x0000000L << 36); //=0.500000000000000000000000000000
public final EFP EXP_C3 = new EFP (P, -3, 0xaaaaaaaaaaaaaaaaL, 0xaa4e330L << 36); //=0.166666666666666666666647544847
public final EFP EXP_C4 = new EFP (P, -5, 0xaaaaaaaaaaaaaaaaL, 0xaa6fd2eL << 36); //=0.0416666666666666666666636245582
public final EFP EXP_C5 = new EFP (P, -7, 0x8888888888888a8eL, 0x59cdd2cL << 36); //=0.00833333333333333377194178560698
public final EFP EXP_C6 = new EFP (P, -10, 0xb60b60b60b60b801L, 0x80edd29L << 36); //=0.00138888888888888894205353133322
public final EFP EXP_C7 = new EFP (P, -13, 0xd00d00cffa827bd9L, 0xd1653b8L << 36); //=1.98412698408592036950274523884e-4
public final EFP EXP_C8 = new EFP (P, -16, 0xd00d00cffddf45a5L, 0xbdc8fc1L << 36); //=2.48015873011673314697922289744e-5
public final EFP EXP_C9 = new EFP (P, -19, 0xb8ef6724028aa32dL, 0x54addf6L << 36); //=2.75574874209809900360756318657e-6
public final EFP EXP_C10 = new EFP (P, -22, 0x93f2b38858c23b84L, 0xa93e7c6L << 36); //=2.75574721303097208995296164475e-7
// 98.10bit
public final EFP[] EXP_P_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("exp(",n,"/64)")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=exp(0/64)=1.00000000000000000000000000000
new EFP (P, 0, 0x8204055aaef1c8bdL, 0x5c3259fL << 36), //<exp(1/64)=1.01574770858668574745853507208
new EFP (P, 0, 0x84102b00893f64c7L, 0x05e841dL << 36), //<exp(2/64)=1.03174340749910267093874781528
new EFP (P, 0, 0x862491b414f45e14L, 0x967f31fL << 36), //>exp(3/64)=1.04799100201663270227673829182
new EFP (P, 0, 0x88415abbe9a76beaL, 0xd8d00cfL << 36), //<exp(4/64)=1.06449445891785942956339059464
new EFP (P, 0, 0x8a66a7e4c4e6b22aL, 0xaf50ce3L << 36), //<exp(5/64)=1.08125780744903960314089465174
new EFP (P, 0, 0x8c949b83a7066b44L, 0x9e8c66eL << 36), //>exp(6/64)=1.09828514030782584865020993426
new EFP (P, 0, 0x8ecb5877f873c9e8L, 0xac7a4d3L << 36), //<exp(7/64)=1.11558061464248075869370450838
new EFP (P, 0, 0x910b022db7ae67ceL, 0x76b441cL << 36), //<exp(8/64)=1.13314845306682631682900722781
new EFP (P, 0, 0x9353bc9fb00b215aL, 0xeb98600L << 36), //<exp(9/64)=1.15099294469117644932213966578
new EFP (P, 0, 0x95a5ac59b963ca80L, 0x9bb3e06L << 36), //<exp(10/64)=1.16911844616950440229818469151
new EFP (P, 0, 0x9800f67b00d7b805L, 0xeae44b2L << 36), //>exp(11/64)=1.18752938276310060558880782283
new EFP (P, 0, 0x9a65c0b85ac1a96aL, 0x7062466L << 36), //>exp(12/64)=1.20623024942098071065558601045
new EFP (P, 0, 0x9cd4315e9e0832fbL, 0xa34f398L << 36), //>exp(13/64)=1.22522561187730757944926592758
new EFP (P, 0, 0x9f4c6f5508ee5d51L, 0xbbdee02L << 36), //<exp(14/64)=1.24452010776609515494619895208
new EFP (P, 0, 0xa1cea21faf8ac771L, 0xd268bc6L << 36), //<exp(15/64)=1.26411844775346636339843460346
new EFP (P, 0, 0xa45af1e1f40c333bL, 0x3de1db5L << 36), //>exp(16/64)=1.28402541668774148407342056806
new EFP (P, 0, 0xa6f1876108f3009dL, 0xa911f65L << 36), //<exp(17/64)=1.30424587476763777548930001105
new EFP (P, 0, 0xa9928c067d67bb65L, 0x16cc14dL << 36), //>exp(18/64)=1.32478475872886556893523756069
new EFP (P, 0, 0xac3e29e2d3d7813bL, 0x0e93c01L << 36), //<exp(19/64)=1.34564708304941053148260309432
new EFP (P, 0, 0xaef48bb022ffa9daL, 0x899232aL << 36), //>exp(20/64)=1.36683794117379636283875677272
new EFP (P, 0, 0xb1b5dcd4c192c269L, 0x39863eeL << 36), //<exp(21/64)=1.38836250675662682438443747530
new EFP (P, 0, 0xb4824965fca1967eL, 0xd7cc083L << 36), //>exp(22/64)=1.41022603492571070569972793418
new EFP (P, 0, 0xb759fe2ad8f3ada4L, 0xeb266efL << 36), //>exp(23/64)=1.43243386356507811497143795682
new EFP (P, 0, 0xba3d289edf7b5311L, 0xa3c5b2dL << 36), //>exp(24/64)=1.45499141461820133605379369199
new EFP (P, 0, 0xbd2bf6f4f511ef19L, 0xfdaedb7L << 36), //<exp(25/64)=1.47790419541173842781020947116
new EFP (P, 0, 0xc026981a3daa2e5dL, 0x65cddb9L << 36), //>exp(26/64)=1.50117780000012275190098436819
new EFP (P, 0, 0xc32d3bb90b262a0aL, 0xee10dd1L << 36), //>exp(27/64)=1.52481791053132670462330880246
new EFP (P, 0, 0xc640123bd8007ee1L, 0x26da077L << 36), //>exp(28/64)=1.54883029863413309799855198460
new EFP (P, 0, 0xc95f4cd04df7fdb9L, 0x9bfe7cfL << 36), //>exp(29/64)=1.57322082682725288629956103460
new EFP (P, 0, 0xcc8b1d6a58ee609bL, 0x8c7b82aL << 36), //>exp(30/64)=1.59799544995063326789964514708
new EFP (P, 0, 0xcfc3b6c7462b3282L, 0xc0bf5ecL << 36), //>exp(31/64)=1.62316021661930561000723988290
new EFP (P, 0, 0xd3094c70f034de4bL, 0x96ff7d6L << 36), //>exp(32/64)=1.64872127070012814684865078781
new EFP (P, 0, 0xd65c12c0f772a298L, 0xdbec9f1L << 36), //>exp(33/64)=1.67468485281178399151929488215
new EFP (P, 0, 0xd9bc3ee407caf517L, 0x6670eb8L << 36), //<exp(34/64)=1.70105730184840067940618349548
new EFP (P, 0, 0xdd2a06dd2b72af4bL, 0x7809cf2L << 36), //>exp(35/64)=1.72784505652716322817720155244
new EFP (P, 0, 0xe0a5a1892b223221L, 0x955289eL << 36), //>exp(36/64)=1.75505465696029855724404703660
new EFP (P, 0, 0xe42f46a1fbe683ddL, 0x1461033L << 36), //<exp(37/64)=1.78269274625181505976568319611
new EFP (P, 0, 0xe7c72ec23ac545bfL, 0x66c74a2L << 36), //<exp(38/64)=1.81076607211938716412053043885
new EFP (P, 0, 0xeb6d9368b66b3bf1L, 0xc77fd15L << 36), //>exp(39/64)=1.83928148854178086081396691197
new EFP (P, 0, 0xef22aefc071e02e5L, 0x44bd839L << 36), //<exp(40/64)=1.86824595743222240650183562019
new EFP (P, 0, 0xf2e6bcce352a7191L, 0x2542fa9L << 36), //>exp(41/64)=1.89766655033811875072299372819
new EFP (P, 0, 0xf6b9f9206e0a0fc3L, 0xabd8e27L << 36), //>exp(42/64)=1.92755045016754466459088319259
new EFP (P, 0, 0xfa9ca126c87af32bL, 0xb68e7a5L << 36), //<exp(43/64)=1.95790495294291808566640006188
new EFP (P, 0, 0xfe8ef30c17c644e9L, 0x61db684L << 36), //<exp(44/64)=1.98873746958229183111747734965
new EFP (P, 1, 0x814896fae739522fL, 0xd207331L << 36), //>exp(45/64)=2.02005552770869657368538323652
new EFP (P, 1, 0x8351c903f850495fL, 0xf940cd1L << 36), //>exp(46/64)=2.05186677348797682356990329034
new EFP (P, 1, 0x856330348b2806b5L, 0x6ded10fL << 36), //<exp(47/64)=2.08417897349556861578737600208
new EFP (P, 1, 0x877ceda33ee7bdeaL, 0x61ab772L << 36), //>exp(48/64)=2.11700001661267466854536981984
new EFP (P, 1, 0x899f22ec174a8c1aL, 0x3d1e65aL << 36), //>exp(49/64)=2.15033791595229995544075729131
new EFP (P, 1, 0x8bc9f23296628075L, 0x3fa07acL << 36), //<exp(50/64)=2.18420081081561792457635501545
new EFP (P, 1, 0x8dfd7e23ded395adL, 0xcd8bb99L << 36), //<exp(51/64)=2.21859696867914500278504863552
new EFP (P, 1, 0x9039e9f8dea8bffcL, 0x88e9e18L << 36), //<exp(52/64)=2.25353478721320854485733107843
new EFP (P, 1, 0x927f597882e5bd3aL, 0x5153fb8L << 36), //<exp(53/64)=2.28902279633220102782484126941
new EFP (P, 1, 0x94cdf0f9f3f8e05cL, 0x238b7d8L << 36), //<exp(54/64)=2.32506966027712105082411019795
new EFP (P, 1, 0x9725d566db309f9dL, 0x44caba1L << 36), //<exp(55/64)=2.36168417973090958374598641969
new EFP (P, 1, 0x99872c3db1593ce1L, 0x10ffabeL << 36), //>exp(56/64)=2.39887529396709791469164573372
new EFP (P, 1, 0x9bf21b9416a77258L, 0x29f648fL << 36), //>exp(57/64)=2.43665208303229187916051857011
new EFP (P, 1, 0x9e66ca193415a245L, 0xd019082L << 36), //<exp(58/64)=2.47502376996302521487450632646
new EFP (P, 1, 0xa0e55f1826599febL, 0x28fc34fL << 36), //>exp(59/64)=2.51399972303752327721338612207
new EFP (P, 1, 0xa36e027a7299c128L, 0x96ff655L << 36), //>exp(60/64)=2.55358945806292687344696507755
new EFP (P, 1, 0xa600dcca8508845aL, 0xa0a2a0dL << 36), //<exp(61/64)=2.59380264069853463138124458905
new EFP (P, 1, 0xa89e1736398eb461L, 0xfd1d370L << 36), //>exp(62/64)=2.63464908881563111180226593835
new EFP (P, 1, 0xab45db916eac95afL, 0x15018e6L << 36), //>exp(63/64)=2.67613877489447680634939027005
}; //EXP_P_T
public final EFP[] EXP_M_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("exp(-",n,"/64)")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=exp(-0/64)=1.00000000000000000000000000000
new EFP (P, -1, 0xfc07f55ff77d2493L, 0xe885eebL << 36), //>exp(-1/64)=0.984496437005408405986988829697
new EFP (P, -1, 0xf81fab5445aebc8aL, 0x58055fdL << 36), //>exp(-2/64)=0.969233234476344081848109193246
new EFP (P, -1, 0xf446e357f67dfd8eL, 0x33bd6c8L << 36), //>exp(-3/64)=0.954206665969188316193630283451
new EFP (P, -1, 0xf07d5fde38151e72L, 0xf18ff03L << 36), //<exp(-4/64)=0.939413062813475786119710824622
new EFP (P, -1, 0xecc2e44e820d18c3L, 0xcc6f18aL << 36), //>exp(-5/64)=0.924848813216204834253805278288
new EFP (P, -1, 0xe9173500cbe0159aL, 0xa3084a2L << 36), //>exp(-6/64)=0.910510361380034127843504886276
new EFP (P, -1, 0xe57a1739d263ec94L, 0x8222e86L << 36), //<exp(-7/64)=0.896394206635150411490036193614
new EFP (P, -1, 0xe1eb51276c110c3cL, 0x3eb126aL << 36), //>exp(-8/64)=0.882496902584595402864892143229
new EFP (P, -1, 0xde6aa9dcebdb100bL, 0x56a61aaL << 36), //>exp(-9/64)=0.868815056262843166738503531191
new EFP (P, -1, 0xdaf7e94f9261313dL, 0x5fd7d71L << 36), //>exp(-10/64)=0.855345327307422537695731635071
new EFP (P, -1, 0xd792d8530d3da531L, 0x2b5abcbL << 36), //<exp(-11/64)=0.842084427143382346804098369012
new EFP (P, -1, 0xd43b4096043bde02L, 0xc9dd905L << 36), //<exp(-12/64)=0.829029118180400343014645509343
new EFP (P, -1, 0xd0f0ec9eb43e8078L, 0xe9af6bbL << 36), //<exp(-13/64)=0.816176213022339786977651290021
new EFP (P, -1, 0xcdb3a7c7979ebd5cL, 0x80489dbL << 36), //>exp(-14/64)=0.803522573689060733999784586587
new EFP (P, -1, 0xca833e3c1bcf93e9L, 0x0747d1aL << 36), //>exp(-15/64)=0.791065110850296014797613273422
new EFP (P, -1, 0xc75f7cf564105743L, 0x415cbcaL << 36), //>exp(-16/64)=0.778800783071404868245170266978
new EFP (P, -1, 0xc44831b718faa1d9L, 0xc29d8daL << 36), //>exp(-17/64)=0.766726596070820080189659545196
new EFP (P, -1, 0xc13d2b0c44b8af4aL, 0x68aa4e8L << 36), //>exp(-18/64)=0.754839601989007337327347095918
new EFP (P, -1, 0xbe3e38443bb1dfefL, 0x65597dbL << 36), //>exp(-19/64)=0.743136898668758315788243931197
new EFP (P, -1, 0xbb4b296f917bf09aL, 0x22fbaa2L << 36), //<exp(-20/64)=0.731615628946641791159559420491
new EFP (P, -1, 0xb863cf5d19e0354eL, 0x91dbb17L << 36), //<exp(-21/64)=0.720272979955439780859653963562
new EFP (P, -1, 0xb587fb96f5c4e712L, 0xa053452L << 36), //>exp(-22/64)=0.709106182437398411721447410017
new EFP (P, -1, 0xb2b7805fabcb5327L, 0xcdbad0eL << 36), //<exp(-23/64)=0.698112510068125846011729230536
new EFP (P, -1, 0xaff230af4c747553L, 0xd8db805L << 36), //>exp(-24/64)=0.687289278790972198545202339147
new EFP (P, -1, 0xad37e030a19e3f45L, 0x315a9f6L << 36), //<exp(-25/64)=0.676633846161728936684014615264
new EFP (P, -1, 0xaa88633e692c84abL, 0x9760affL << 36), //<exp(-26/64)=0.666143610703487774469791357130
new EFP (P, -1, 0xa7e38ee09ab13658L, 0x8e4fa89L << 36), //>exp(-27/64)=0.655816011271501552530892254763
new EFP (P, -1, 0xa54938c9b7e846b1L, 0x22756d1L << 36), //<exp(-28/64)=0.645648526427892037348355680061
new EFP (P, -1, 0xa2b9375427dc3ef5L, 0xfdb6013L << 36), //<exp(-29/64)=0.635638673826051977545950221758
new EFP (P, -1, 0xa033617f9c893772L, 0xb7f2709L << 36), //>exp(-30/64)=0.625784009604591121679874456535
new EFP (P, -1, 0x9db78eee82d48c8cL, 0x5e432e4L << 36), //>exp(-31/64)=0.616082127790678232119777202994
new EFP (P, -1, 0x9b4597e37cb04ff3L, 0xd675a35L << 36), //<exp(-32/64)=0.606530659712633423603799534991
new EFP (P, -1, 0x98dd553ee54217fdL, 0x5f7533bL << 36), //>exp(-33/64)=0.597127273421627413476334433038
new EFP (P, -1, 0x967ea07c5ee56f55L, 0x27376f0L << 36), //>exp(-34/64)=0.587869673122346494029544878732
new EFP (P, -1, 0x942953b06ae2c503L, 0xc6e249aL << 36), //<exp(-35/64)=0.578755598612484226311212770922
new EFP (P, -1, 0x91dd49860ab457feL, 0x49ecbc0L << 36), //<exp(-36/64)=0.569782824730923009766629689829
new EFP (P, -1, 0x8f9a5d3c6ab3325dL, 0xe98839bL << 36), //>exp(-37/64)=0.560949160814470803677121262158
new EFP (P, -1, 0x8d606aa49606deddL, 0x68c91a3L << 36), //<exp(-38/64)=0.552252450163020365060397724731
new EFP (P, -1, 0x8b2f4e1f33b31766L, 0x67ee085L << 36), //>exp(-39/64)=0.543690569513000424018191779441
new EFP (P, -1, 0x8906e49a4c9f3d59L, 0x58a5d18L << 36), //>exp(-40/64)=0.535261428518990241956622508022
new EFP (P, -1, 0x86e70b8f1a73fbd8L, 0x1858e19L << 36), //>exp(-41/64)=0.526962969243370991158669068037
new EFP (P, -1, 0x84cfa0ffdf2c01beL, 0x9229f8cL << 36), //>exp(-42/64)=0.518793165653889356342645457337
new EFP (P, -1, 0x82c08375c5354c26L, 0xfed9d9bL << 36), //>exp(-43/64)=0.510750023129010690574689186791
new EFP (P, -1, 0x80b991fec8010361L, 0x182aa18L << 36), //<exp(-44/64)=0.502831577970940959688636611438
new EFP (P, -2, 0xfd75585749c0e65aL, 0xe0e13c7L << 36), //<exp(-45/64)=0.495035896926198581667568450965
new EFP (P, -2, 0xf987641ba81c57c1L, 0x08b166eL << 36), //>exp(-46/64)=0.487361076713619110714884696034
new EFP (P, -2, 0xf5a9086b1385b9a8L, 0xb38238dL << 36), //>exp(-47/64)=0.479805243559677530439035766024
new EFP (P, -2, 0xf1da075f7e6bf297L, 0x7e1e9a0L << 36), //>exp(-48/64)=0.472366552741014707138046550943
new EFP (P, -2, 0xee1a240886d56f4fL, 0x1d073e3L << 36), //>exp(-49/64)=0.465043188134056313033903075269
new EFP (P, -2, 0xea692267a754ef29L, 0x4911dc3L << 36), //<exp(-50/64)=0.457833361771614260902146840654
new EFP (P, -2, 0xe6c6c76c771c2d60L, 0x96a4be2L << 36), //<exp(-51/64)=0.450735313406362396291400791633
new EFP (P, -2, 0xe332d8f0f8f06820L, 0xcd7f8e6L << 36), //<exp(-52/64)=0.443747310081079871847240349999
new EFP (P, -2, 0xdfad1db5f8c5b458L, 0x70f8209L << 36), //<exp(-53/64)=0.436867645705557280554577433900
new EFP (P, -2, 0xdc355d5f77c6f7b3L, 0x2d36b03L << 36), //<exp(-54/64)=0.430094640640062251395946518606
new EFP (P, -2, 0xd8cb6071269148f0L, 0x7444892L << 36), //<exp(-55/64)=0.423426641285262812386917145715
new EFP (P, -2, 0xd56ef04aed6a5a01L, 0x2a76dd4L << 36), //<exp(-56/64)=0.416862019678508402585297182336
new EFP (P, -2, 0xd21fd725823a6f09L, 0x0871f0bL << 36), //<exp(-57/64)=0.410399173096369966862764164781
new EFP (P, -2, 0xcedde00f0c13419aL, 0x4cddcf7L << 36), //>exp(-58/64)=0.404036523663342095355029060572
new EFP (P, -2, 0xcba8d6e7d40e0852L, 0x3c9f035L << 36), //>exp(-59/64)=0.397772517966611673942683333515
new EFP (P, -2, 0xc880885f034bb070L, 0x530b9f4L << 36), //<exp(-60/64)=0.391605626676798993226807728469
new EFP (P, -2, 0xc564c1ef6de32926L, 0x3b6f5ecL << 36), //<exp(-61/64)=0.385534344174578721612836653797
new EFP (P, -2, 0xc25551dc6a8a6f40L, 0xdc958f1L << 36), //<exp(-62/64)=0.379557188183089583659076182722
new EFP (P, -2, 0xbf52072eb6c7d377L, 0xd431325L << 36), //>exp(-63/64)=0.373672699406042998133147992189
}; //EXP_M_T
//------------------------------------------------------------------------
//exp10
public final EFP[] EXP10_P_I = {
// echo read("efp.gp");for(n=0,13,efpmem([Str("10^(2^",n,")")])) | gp -q
new EFP (P, 3, 0xa000000000000000L, 0x0000000L << 36), //=10^(2^0)=10.0000000000000000000000000000
new EFP (P, 6, 0xc800000000000000L, 0x0000000L << 36), //=10^(2^1)=100.000000000000000000000000000
new EFP (P, 13, 0x9c40000000000000L, 0x0000000L << 36), //=10^(2^2)=10000.0000000000000000000000000
new EFP (P, 26, 0xbebc200000000000L, 0x0000000L << 36), //=10^(2^3)=100000000.000000000000000000000
new EFP (P, 53, 0x8e1bc9bf04000000L, 0x0000000L << 36), //=10^(2^4)=10000000000000000.0000000000000
new EFP (P, 106, 0x9dc5ada82b70b59dL, 0xf020000L << 36), //=10^(2^5)=1.00000000000000000000000000000e+32
new EFP (P, 212, 0xc2781f49ffcfa6d5L, 0x3cbf6b7L << 36), //<10^(2^6)=1.00000000000000000000000000000e+64
new EFP (P, 425, 0x93ba47c980e98cdfL, 0xc66f337L << 36), //>10^(2^7)=1.00000000000000000000000000000e+128
new EFP (P, 850, 0xaa7eebfb9df9de8dL, 0xddbb902L << 36), //>10^(2^8)=1.00000000000000000000000000000e+256
new EFP (P, 1700, 0xe319a0aea60e91c6L, 0xcc655c5L << 36), //<10^(2^9)=1.00000000000000000000000000000e+512
new EFP (P, 3401, 0xc976758681750c17L, 0x650d3d3L << 36), //>10^(2^10)=1.00000000000000000000000000000e+1024
new EFP (P, 6803, 0x9e8b3b5dc53d5de4L, 0xa74d28dL << 36), //>10^(2^11)=1.00000000000000000000000000000e+2048
new EFP (P, 13606, 0xc46052028a20979aL, 0xc94c154L << 36), //>10^(2^12)=1.00000000000000000000000000000e+4096
new EFP (P, 27213, 0x96a3a1d17faf211aL, 0x0c7c289L << 36), //<10^(2^13)=1.00000000000000000000000000000e+8192
}; //EXP10_P_I
public final EFP[] EXP10_M_I = {
// echo read("efp.gp");for(n=0,13,efpmem([Str("10^(-2^",n,")")])) | gp -q
new EFP (P, -4, 0xccccccccccccccccL, 0xccccccdL << 36), //>10^(-2^0)=0.100000000000000000000000000000
new EFP (P, -7, 0xa3d70a3d70a3d70aL, 0x3d70a3dL << 36), //<10^(-2^1)=0.0100000000000000000000000000000
new EFP (P, -14, 0xd1b71758e219652bL, 0xd3c3611L << 36), //<10^(-2^2)=1.00000000000000000000000000000e-4
new EFP (P, -27, 0xabcc77118461cefcL, 0xfdc20d3L << 36), //>10^(-2^3)=1.00000000000000000000000000000e-8
new EFP (P, -54, 0xe69594bec44de15bL, 0x4c2ebe7L << 36), //>10^(-2^4)=1.00000000000000000000000000000e-16
new EFP (P, -107, 0xcfb11ead453994baL, 0x67de18fL << 36), //>10^(-2^5)=1.00000000000000000000000000000e-32
new EFP (P, -213, 0xa87fea27a539e9a5L, 0x3f2398dL << 36), //<10^(-2^6)=1.00000000000000000000000000000e-64
new EFP (P, -426, 0xddd0467c64bce4a0L, 0xac7cb3fL << 36), //<10^(-2^7)=1.00000000000000000000000000000e-128
new EFP (P, -851, 0xc0314325637a1939L, 0xfa91115L << 36), //<10^(-2^8)=1.00000000000000000000000000000e-256
new EFP (P, -1701, 0x9049ee32db23d21cL, 0x7132d33L << 36), //<10^(-2^9)=1.00000000000000000000000000000e-512
new EFP (P, -3402, 0xa2a682a5da57c0bdL, 0x87a6016L << 36), //>10^(-2^10)=1.00000000000000000000000000000e-1024
new EFP (P, -6804, 0xceae534f34362de4L, 0x492512dL << 36), //<10^(-2^11)=1.00000000000000000000000000000e-2048
new EFP (P, -13607, 0xa6dd04c8d2ce9fdeL, 0x2de3812L << 36), //<10^(-2^12)=1.00000000000000000000000000000e-4096
new EFP (P, -27214, 0xd986c20b686da869L, 0x5d1d4feL << 36), //>10^(-2^13)=1.00000000000000000000000000000e-8192
}; //EXP10_M_I
// echo read("efp.gp");eval("exp10(x)=10^x");efpchebyshev("EXP10_C",exp10,-1/64,1/64,11) | gp -q
public final EFP EXP10_C0 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP EXP10_C1 = new EFP (P, 1, 0x935d8dddaaa8ac16L, 0xea56d63L << 36); //=2.30258509299404568401799145491
public final EFP EXP10_C2 = new EFP (P, 1, 0xa9a92639e753443aL, 0x80aa0a5L << 36); //=2.65094905523919900528083460848
public final EFP EXP10_C3 = new EFP (P, 1, 0x82382c8ef1652304L, 0x6a4fce8L << 36); //=2.03467859229347619683099182492
public final EFP EXP10_C4 = new EFP (P, 0, 0x95ebb04fecc62263L, 0x3516d57L << 36); //=1.17125514891226696311068508120
public final EFP EXP10_C5 = new EFP (P, -1, 0x8a14ffe8ea6bb111L, 0x0f9d433L << 36); //=0.539382929195581410178946055296
public final EFP EXP10_C6 = new EFP (P, -3, 0xd3f6b8423e47031dL, 0xb2e8d4cL << 36); //=0.206995848696869277613713506791
public final EFP EXP10_C7 = new EFP (P, -4, 0x8b726fe199d4dd8aL, 0x0319896L << 36); //=0.0680893650744373537029952682197
public final EFP EXP10_C8 = new EFP (P, -6, 0xa08b582ea51b0457L, 0xa2bc993L << 36); //=0.0195976946171499984930236007292
public final EFP EXP10_C9 = new EFP (P, -8, 0xa44be22db201cf47L, 0x94dcaeaL << 36); //=0.00501392883178657960091531266074
public final EFP EXP10_C10 = new EFP (P, -10, 0x9753b9561c0a683fL, 0x0135acdL << 36); //=0.00115453374296954907615286737273
public final EFP EXP10_C11 = new EFP (P, -13, 0xfd69aac60b9f8924L, 0x6d6c8b2L << 36); //=2.41673242615286373608040289945e-4
// 95.99bit
public final EFP[] EXP10_P_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("10^(",n,"/64)")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(0/64)=1.00000000000000000000000000000
new EFP (P, 0, 0x84b06346cc5e15f9L, 0x701148dL << 36), //>10^(1/64)=1.03663292843769799729165172493
new EFP (P, 0, 0x898cbfd35533bb59L, 0x3c49e31L << 36), //<10^(2/64)=1.07460782832131749721594153196
new EFP (P, 0, 0x8e96b208a3664881L, 0x0ec125aL << 36), //<10^(3/64)=1.11397385999480237628676508624
new EFP (P, 0, 0x93cfe56520272d66L, 0x5aa4cf9L << 36), //<10^(4/64)=1.15478198468945817966648288730
new EFP (P, 0, 0x993a151041524281L, 0xa5bb585L << 36), //>10^(5/64)=1.19708503049572996552827088892
new EFP (P, 0, 0x9ed70c6d6669efa1L, 0xfe3df3cL << 36), //<10^(6/64)=1.24093776075171956609870735535
new EFP (P, 0, 0xa4a8a7b416dcf6d2L, 0xcb3598fL << 36), //>10^(7/64)=1.28639694493697450748440704963
new EFP (P, 0, 0xaab0d48dd40a21eeL, 0xe3993e6L << 36), //<10^(8/64)=1.33352143216332402567593171530
new EFP (P, 0, 0xb0f192b9b34f3a68L, 0x955eb28L << 36), //>10^(9/64)=1.38237222735789961915257040197
new EFP (P, 0, 0xb76cf4b5f65b3109L, 0xa96afc1L << 36), //>10^(10/64)=1.43301257023696274155836644455
new EFP (P, 0, 0xbe25206fd9f7d185L, 0xaebfd1dL << 36), //>10^(11/64)=1.48550801717277507269503768560
new EFP (P, 0, 0xc51c4ff9d58e742dL, 0x8b26b72L << 36), //>10^(12/64)=1.53992652605949198957048599495
new EFP (P, 0, 0xcc54d24887cd8593L, 0x587bd74L << 36), //<10^(13/64)=1.59633854428794223977352853358
new EFP (P, 0, 0xd3d10bf68f0b258cL, 0xf7a8720L << 36), //>10^(14/64)=1.65481709994318142294561394026
new EFP (P, 0, 0xdb93780f8e4c4878L, 0xa97bdbaL << 36), //<10^(15/64)=1.71543789634287892263242774792
new EFP (P, 0, 0xe39ea8e2a2387187L, 0xf37c989L << 36), //>10^(16/64)=1.77827941003892280122542119519
new EFP (P, 0, 0xebf548dc8bb914d9L, 0x7f50e38L << 36), //<10^(17/64)=1.84342299240911047379928682108
new EFP (P, 0, 0xf49a1b69d891c56dL, 0x960a16fL << 36), //>10^(18/64)=1.91095297497044051626887333608
new EFP (P, 0, 0xfd8ffde154e45e46L, 0x6d275e3L << 36), //<10^(19/64)=1.98095677855033875589271948122
new EFP (P, 1, 0x836cf43b89a99c01L, 0x4fdf0c0L << 36), //>10^(20/64)=2.05352502645714607460575234830
new EFP (P, 1, 0x883d779c2e260ef2L, 0x8fcb8a1L << 36), //>10^(21/64)=2.12875166179637259331084646179
new EFP (P, 1, 0x8d3b21886bfd0401L, 0xb2e86d9L << 36), //<10^(22/64)=2.20673406908458980028232378190
new EFP (P, 1, 0x9267996ca4b54f44L, 0xfac62acL << 36), //>10^(23/64)=2.28757320031839568693918290553
new EFP (P, 1, 0x97c496381a501b96L, 0x8f187f6L << 36), //>10^(24/64)=2.37137370566165526165175275748
new EFP (P, 1, 0x9d53deee66493377L, 0x48d07c3L << 36), //>10^(25/64)=2.45824406892019739301085187675
new EFP (P, 1, 0xa3174b3e44c3bf1cL, 0x5882b85L << 36), //>10^(26/64)=2.54829674797934652767525759152
new EFP (P, 1, 0xa910c41de5dcba7fL, 0x26e2683L << 36), //<10^(27/64)=2.64164832038609245760602422495
new EFP (P, 1, 0xaf42446cf8f10ddbL, 0xdeffc99L << 36), //<10^(28/64)=2.73841963426436129418869698739
new EFP (P, 1, 0xb5add99ca78b05aeL, 0xb531acaL << 36), //>10^(29/64)=2.83873596475875476410634665940
new EFP (P, 1, 0xbc55a45db7a285f3L, 0x2c86e23L << 36), //<10^(30/64)=2.94272717620928181136420323011
new EFP (P, 1, 0xc33bd9550ee56612L, 0x36b705cL << 36), //<10^(31/64)=3.05052789026702553649413782738
new EFP (P, 1, 0xca62c1d6d2da9490L, 0x2515e42L << 36), //>10^(32/64)=3.16227766016837933199889354443
new EFP (P, 1, 0xd1ccbca863e3a684L, 0x9dcd927L << 36), //<10^(33/64)=3.27812115139345863868052715836
new EFP (P, 1, 0xd97c3ec973660921L, 0xc624e27L << 36), //>10^(34/64)=3.39820832894255937150660921812
new EFP (P, 1, 0xe173d44477bfebc8L, 0xc9e83d6L << 36), //<10^(35/64)=3.52269465147310144505670477089
new EFP (P, 1, 0xe9b62106c31def2cL, 0x8c4b218L << 36), //<10^(36/64)=3.65174127254837705824995256605
new EFP (P, 1, 0xf245e1c084ce80edL, 0x038ee92L << 36), //>10^(37/64)=3.78551524925862997316336724952
new EFP (P, 1, 0xfb25ecccff4f619aL, 0x3e59575L << 36), //<10^(38/64)=3.92418975848453586166641294060
new EFP (P, 2, 0x822c9991a00501dfL, 0x459ef69L << 36), //>10^(39/64)=4.06794432108304725128134842000
new EFP (P, 2, 0x86f160a7d4429212L, 0x10e2195L << 36), //>10^(40/64)=4.21696503428582248569013359509
new EFP (P, 2, 0x8be2e03b4ddf0e98L, 0x12bb325L << 36), //>10^(41/64)=4.37144481261108970238502724308
new EFP (P, 2, 0x9102bbb052b20069L, 0x01f46c1L << 36), //>10^(42/64)=4.53158363760081788320489309709
new EFP (P, 2, 0x9652a5c839e93b97L, 0xa26a9f7L << 36), //<10^(43/64)=4.69758881670649182019894641275
new EFP (P, 2, 0x9bd461318075e327L, 0xba8d5a6L << 36), //<10^(44/64)=4.86967525165863114935297485034
new EFP (P, 2, 0xa189c11d24a8aa65L, 0x85c7857L << 36), //<10^(45/64)=5.04806571666747076993748259343
new EFP (P, 2, 0xa774a9d97a7cc699L, 0x267ff04L << 36), //<10^(46/64)=5.23299114681494688097670550264
new EFP (P, 2, 0xad971172abe13529L, 0x4e7987eL << 36), //<10^(47/64)=5.42469093701132600419719579894
new EFP (P, 2, 0xb3f300591a312caeL, 0x82ddc80L << 36), //>10^(48/64)=5.62341325190349080394951039776
new EFP (P, 2, 0xba8a920dd7ff6294L, 0x8fdbe3cL << 36), //>10^(49/64)=5.82941534713607396382074746488
new EFP (P, 2, 0xc15ff5d5745ce801L, 0xf9cbdb1L << 36), //>10^(50/64)=6.04296390238132819036274581338
new EFP (P, 2, 0xc8756f7152dc6b33L, 0xd916f2aL << 36), //<10^(51/64)=6.26433536656885561228272629955
new EFP (P, 2, 0xcfcd57dfcdbe57f5L, 0x06243dfL << 36), //>10^(52/64)=6.49381631576211315128032840698
new EFP (P, 2, 0xd76a1e2361f25a79L, 0x376f47eL << 36), //<10^(53/64)=6.73170382414498230366796296997
new EFP (P, 2, 0xdf4e481126efea96L, 0x226ac46L << 36), //<10^(54/64)=6.97830584859866338414831761727
new EFP (P, 2, 0xe77c7326d6d287faL, 0x80d6746L << 36), //>10^(55/64)=7.23394162736674761521631443578
new EFP (P, 2, 0xeff75568ada7ffc1L, 0x9a2a3e9L << 36), //<10^(56/64)=7.49894209332455827302184275615
new EFP (P, 2, 0xf8c1be4769784541L, 0xfbc290fL << 36), //>10^(57/64)=7.77365030238775803292348188791
new EFP (P, 3, 0x80ef4bc75b9ffbd5L, 0x0910ec4L << 36), //>10^(58/64)=8.05842187761481817002575395741
new EFP (P, 3, 0x85a8732e2df0c035L, 0xb3cb958L << 36), //<10^(59/64)=8.35362546957826173294463685160
new EFP (P, 3, 0x8a8de610357adc41L, 0x4850544L << 36), //>10^(60/64)=8.65964323360065352353169183420
new EFP (P, 3, 0x8fa143d3703294f4L, 0x841b5f8L << 36), //>10^(61/64)=8.97687132447314194541938363834
new EFP (P, 3, 0x94e43b157a67a6c0L, 0x97fe98cL << 36), //>10^(62/64)=9.30572040929698979290646316499
new EFP (P, 3, 0x9a588a3a43ff4e3cL, 0x381b0ceL << 36), //<10^(63/64)=9.64661619911199213711208256038
}; //EXP10_P_T
public final EFP[] EXP10_M_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("10^(-",n,"/64)")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(-0/64)=1.00000000000000000000000000000
new EFP (P, -1, 0xf6f4105d39987d2dL, 0x2691ae4L << 36), //>10^(-1/64)=0.964661619911199213711208256038
new EFP (P, -1, 0xee39f8225d72a467L, 0x59975acL << 36), //<10^(-2/64)=0.930572040929698979290646316499
new EFP (P, -1, 0xe5ced2ebe6b754baL, 0x6cf898cL << 36), //<10^(-3/64)=0.897687132447314194541938363834
new EFP (P, -1, 0xddafd68055916068L, 0x73b3b9fL << 36), //<10^(-4/64)=0.865964323360065352353169183420
new EFP (P, -1, 0xd5da51e37cb466bcL, 0x52df55aL << 36), //>10^(-5/64)=0.835362546957826173294463685160
new EFP (P, -1, 0xce4bac722c332c88L, 0x0e8179fL << 36), //<10^(-6/64)=0.805842187761481817002575395741
new EFP (P, -1, 0xc7016505edf9d101L, 0x963540cL << 36), //>10^(-7/64)=0.777365030238775803292348188791
new EFP (P, -1, 0xbff911208aeccc9aL, 0xe1bb654L << 36), //<10^(-8/64)=0.749894209332455827302184275615
new EFP (P, -1, 0xb9305c1f12420662L, 0x00ab904L << 36), //<10^(-9/64)=0.723394162736674761521631443578
new EFP (P, -1, 0xb2a506741f265544L, 0xe85569fL << 36), //>10^(-10/64)=0.697830584859866338414831761727
new EFP (P, -1, 0xac54e4e91b284860L, 0xf925d32L << 36), //>10^(-11/64)=0.673170382414498230366796296997
new EFP (P, -1, 0xa63ddfe63e31dff7L, 0x381cfe5L << 36), //<10^(-12/64)=0.649381631576211315128032840698
new EFP (P, -1, 0xa05df2c10f16bc29L, 0x7a78c22L << 36), //>10^(-13/64)=0.626433536656885561228272629955
new EFP (P, -1, 0x9ab32b1129e3ecceL, 0x616fe27L << 36), //>10^(-14/64)=0.604296390238132819036274581338
new EFP (P, -1, 0x953ba80b1332b543L, 0xa649830L << 36), //>10^(-15/64)=0.582941534713607396382074746488
new EFP (P, -1, 0x8ff599e0e1c0f08bL, 0x9be4a00L << 36), //>10^(-16/64)=0.562341325190349080394951039776
new EFP (P, -1, 0x8adf41288980f754L, 0x3ec79ffL << 36), //>10^(-17/64)=0.542469093701132600419719579894
new EFP (P, -1, 0x85f6ee4795309ee0L, 0xeb998d0L << 36), //<10^(-18/64)=0.523299114681494688097670550264
new EFP (P, -1, 0x813b00e41d53bb84L, 0x6b06046L << 36), //>10^(-19/64)=0.504806571666747076993748259343
new EFP (P, -2, 0xf953ceb59a56383fL, 0x90e22a4L << 36), //>10^(-20/64)=0.486967525165863114935297485034
new EFP (P, -2, 0xf0843c738fdb928cL, 0x3710ff2L << 36), //<10^(-21/64)=0.469758881670649182019894641275
new EFP (P, -2, 0xe8045f80845000a8L, 0x0320aceL << 36), //>10^(-22/64)=0.453158363760081788320489309709
new EFP (P, -2, 0xdfd166c54964e426L, 0x845eb6eL << 36), //<10^(-23/64)=0.437144481261108970238502724308
new EFP (P, -2, 0xd7e89aa6206a8350L, 0x1b035bbL << 36), //<10^(-24/64)=0.421696503428582248569013359509
new EFP (P, -2, 0xd0475c1c333b3632L, 0x08fe574L << 36), //<10^(-25/64)=0.406794432108304725128134842000
new EFP (P, -2, 0xc8eb23d732a5e7aeL, 0x9847791L << 36), //>10^(-26/64)=0.392418975848453586166641294060
new EFP (P, -2, 0xc1d18166d0a533f0L, 0xcfa5875L << 36), //>10^(-27/64)=0.378551524925862997316336724952
new EFP (P, -2, 0xbaf81a6bcf4b25bdL, 0x3d08e7aL << 36), //>10^(-28/64)=0.365174127254837705824995256605
new EFP (P, -2, 0xb45ca9d05fccbca0L, 0xa186978L << 36), //<10^(-29/64)=0.352269465147310144505670477089
new EFP (P, -2, 0xadfcff078f84d41bL, 0x04ea4ecL << 36), //>10^(-30/64)=0.339820832894255937150660921812
new EFP (P, -2, 0xa7d6fd53831c8536L, 0xe4a4753L << 36), //>10^(-31/64)=0.327812115139345863868052715836
new EFP (P, -2, 0xa1e89b12424876d9L, 0xb744b68L << 36), //>10^(-32/64)=0.316227766016837933199889354443
new EFP (P, -2, 0x9c2fe110d8b784dbL, 0x5ef8d17L << 36), //>10^(-33/64)=0.305052789026702553649413782738
new EFP (P, -2, 0x96aae9e492e86b28L, 0xf06be83L << 36), //>10^(-34/64)=0.294272717620928181136420323011
new EFP (P, -2, 0x9157e14a1fa26af2L, 0x2a8e23bL << 36), //>10^(-35/64)=0.283873596475875476410634665940
new EFP (P, -2, 0x8c35038a60c0d7e3L, 0x18cca14L << 36), //<10^(-36/64)=0.273841963426436129418869698739
new EFP (P, -2, 0x87409ce4b7e3c865L, 0xb8b5203L << 36), //>10^(-37/64)=0.264164832038609245760602422495
new EFP (P, -2, 0x827908fe9d6965b0L, 0x46cef9dL << 36), //<10^(-38/64)=0.254829674797934652767525759152
new EFP (P, -3, 0xfbb964b0a3a85258L, 0x7480c6bL << 36), //>10^(-39/64)=0.245824406892019739301085187675
new EFP (P, -3, 0xf2d4238cf6e6928aL, 0x7e8d989L << 36), //<10^(-40/64)=0.237137370566165526165175275748
new EFP (P, -3, 0xea3f5be107887ed4L, 0xc470446L << 36), //>10^(-41/64)=0.228757320031839568693918290553
new EFP (P, -3, 0xe1f835a7132e6ccfL, 0x84a715cL << 36), //>10^(-42/64)=0.220673406908458980028232378190
new EFP (P, -3, 0xd9fbf2937d09b184L, 0x1945a9bL << 36), //<10^(-43/64)=0.212875166179637259331084646179
new EFP (P, -3, 0xd247ed2c0f75c668L, 0x7fcb466L << 36), //>10^(-44/64)=0.205352502645714607460575234830
new EFP (P, -3, 0xcad997e7771d1838L, 0x5752b1cL << 36), //<10^(-45/64)=0.198095677855033875589271948122
new EFP (P, -3, 0xc3ae7c54ad416abeL, 0x11a1abfL << 36), //>10^(-46/64)=0.191095297497044051626887333608
new EFP (P, -3, 0xbcc43a4a0960dd7aL, 0xcc40b60L << 36), //<10^(-47/64)=0.184342299240911047379928682108
new EFP (P, -3, 0xb618871bb4f9f46cL, 0xc2ca13aL << 36), //<10^(-48/64)=0.177827941003892280122542119519
new EFP (P, -3, 0xafa92cd93ea36d2dL, 0x5463162L << 36), //>10^(-49/64)=0.171543789634287892263242774792
new EFP (P, -3, 0xa97409920c08ead7L, 0x2c86c19L << 36), //<10^(-50/64)=0.165481709994318142294561394026
new EFP (P, -3, 0xa3770ea06ca46adcL, 0x46c9790L << 36), //<10^(-51/64)=0.159633854428794223977352853358
new EFP (P, -3, 0x9db03ffb113ec357L, 0xa2855f5L << 36), //>10^(-52/64)=0.153992652605949198957048599495
new EFP (P, -3, 0x981db38cae5fdad1L, 0x589974aL << 36), //<10^(-53/64)=0.148550801717277507269503768560
new EFP (P, -3, 0x92bd909191e28da1L, 0x5455967L << 36), //<10^(-54/64)=0.143301257023696274155836644455
new EFP (P, -3, 0x8d8e0efaf5d8fb86L, 0xdde55baL << 36), //>10^(-55/64)=0.138237222735789961915257040197
new EFP (P, -3, 0x888d76d7dcd4e7f2L, 0x4fadcb8L << 36), //<10^(-56/64)=0.133352143216332402567593171530
new EFP (P, -3, 0x83ba1fc3457d9242L, 0x3c2ae0cL << 36), //>10^(-57/64)=0.128639694493697450748440704963
new EFP (P, -4, 0xfe24e0af0a431903L, 0x30631faL << 36), //<10^(-58/64)=0.124093776075171956609870735535
new EFP (P, -4, 0xf529bb4d35506a69L, 0x092bc07L << 36), //<10^(-59/64)=0.119708503049572996552827088892
new EFP (P, -4, 0xec7fd56e99d848a3L, 0xc43ae5bL << 36), //<10^(-60/64)=0.115478198468945817966648288730
new EFP (P, -4, 0xe424500dd23d40ceL, 0x7e01d5dL << 36), //<10^(-61/64)=0.111397385999480237628676508624
new EFP (P, -4, 0xdc14661eeeb92bc1L, 0xfa0fd1cL << 36), //>10^(-62/64)=0.107460782832131749721594153196
new EFP (P, -4, 0xd44d6ba47a302328L, 0xb34edaeL << 36), //<10^(-63/64)=0.103663292843769799729165172493
}; //EXP10_M_T
//------------------------------------------------------------------------
//exp2
// echo read("efp.gp");eval("exp2(x)=2^x");efpchebyshev("EXP2P_C",exp2,0,1/64,8) | gp -q
public final EFP EXP2P_C0 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP EXP2P_C1 = new EFP (P, -1, 0xb17217f7d1cf79abL, 0xc9e3289L << 36); //=0.693147180559945309417231672224
public final EFP EXP2P_C2 = new EFP (P, -3, 0xf5fdeffc162c7543L, 0x87306ceL << 36); //=0.240226506959100712334317834550
public final EFP EXP2P_C3 = new EFP (P, -5, 0xe35846b82505fbc4L, 0xf77c6dfL << 36); //=0.0555041086648215794495051454975
public final EFP EXP2P_C4 = new EFP (P, -7, 0x9d955b7dd276b5acL, 0xbf41024L << 36); //=0.00961812910762864290798786714666
public final EFP EXP2P_C5 = new EFP (P, -10, 0xaec3ff3c41fa05ceL, 0xd0dbae7L << 36); //=0.00133335581461220558296277742225
public final EFP EXP2P_C6 = new EFP (P, -13, 0xa18489b6bbee153cL, 0x79516f1L << 36); //=1.54035307260420586747761266932e-4
public final EFP EXP2P_C7 = new EFP (P, -17, 0xffe516c43da39259L, 0x7cbaceaL << 36); //=1.52525233411920778640460590036e-5
public final EFP EXP2P_C8 = new EFP (P, -20, 0xb256aa5495805ceeL, 0xb4df34eL << 36); //=1.32872563999697042645099045935e-6
// 93.22bit
// echo read("efp.gp");eval("exp2(x)=2^x");efpchebyshev("EXP2M_C",exp2,-1/64,0,8) | gp -q
public final EFP EXP2M_C0 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP EXP2M_C1 = new EFP (P, -1, 0xb17217f7d1cf79abL, 0xc9e32a0L << 36); //=0.693147180559945309417231676869
public final EFP EXP2M_C2 = new EFP (P, -3, 0xf5fdeffc162c7543L, 0x6a5f7f6L << 36); //=0.240226506959100712332792321650
public final EFP EXP2M_C3 = new EFP (P, -5, 0xe35846b82505fbc6L, 0x6a8d50cL << 36); //=0.0555041086648215794544161625987
public final EFP EXP2M_C4 = new EFP (P, -7, 0x9d955b7dd270c42fL, 0x60d628cL << 36); //=0.00961812910762831298749547774027
public final EFP EXP2M_C5 = new EFP (P, -10, 0xaec3ff3c422238b3L, 0x26278f5L << 36); //=0.00133335581461248451814736607925
public final EFP EXP2M_C6 = new EFP (P, -13, 0xa184894230721e7bL, 0x5e05decL << 36); //=1.54035300635612277279514659537e-4
public final EFP EXP2M_C7 = new EFP (P, -17, 0xffe518860467684dL, 0x1c0262cL << 36); //=1.52525249391189379086239626896e-5
public final EFP EXP2M_C8 = new EFP (P, -20, 0xb06adfb7eea07e61L, 0xba36904L << 36); //=1.31441262493409658027106967485e-6
// 93.24bit
public final EFP[] EXP2P_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("2^(",n,"/64)")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=2^(0/64)=1.00000000000000000000000000000
new EFP (P, 0, 0x8164d1f3bc030773L, 0x7be5652L << 36), //<2^(1/64)=1.01088928605170046002040979056
new EFP (P, 0, 0x82cd8698ac2ba1d7L, 0x3e2a476L << 36), //>2^(2/64)=1.02189714865411667823448013478
new EFP (P, 0, 0x843a28c3acde4046L, 0x1af92edL << 36), //>2^(3/64)=1.03302487902122842250010828397
new EFP (P, 0, 0x85aac367cc487b14L, 0xc5c95b9L << 36), //>2^(4/64)=1.04427378242741384032196647874
new EFP (P, 0, 0x871f61969e8d1010L, 0x3a1727cL << 36), //<2^(5/64)=1.05564517836055715880834132515
new EFP (P, 0, 0x88980e8092da8527L, 0x5df8d77L << 36), //>2^(6/64)=1.06714040067682361816952112099
new EFP (P, 0, 0x8a14d575496efd9aL, 0x080ca1eL << 36), //>2^(7/64)=1.07876079775711979374068003744
new EFP (P, 0, 0x8b95c1e3ea8bd6e6L, 0xfbe4628L << 36), //<2^(8/64)=1.09050773266525765920701065576
new EFP (P, 0, 0x8d1adf5b7e5ba9e5L, 0xb4c7b49L << 36), //<2^(9/64)=1.10238258330784094355641420943
new EFP (P, 0, 0x8ea4398b45cd53c0L, 0x2dc0145L << 36), //>2^(10/64)=1.11438674259589253630881295692
new EFP (P, 0, 0x9031dc431466b1dcL, 0x775814bL << 36), //>2^(11/64)=1.12652161860824189979479864379
new EFP (P, 0, 0x91c3d373ab11c336L, 0x0fd6d8eL << 36), //<2^(12/64)=1.13878863475669165370383028384
new EFP (P, 0, 0x935a2b2f13e6e92bL, 0xd339941L << 36), //>2^(13/64)=1.15118922995298270581775963520
new EFP (P, 0, 0x94f4efa8fef70961L, 0x2e8afadL << 36), //<2^(14/64)=1.16372485877757751381357359909
new EFP (P, 0, 0x96942d3720185a00L, 0x48ea9b7L << 36), //>2^(15/64)=1.17639699165028127628464572848
new EFP (P, 0, 0x9837f0518db8a96fL, 0x46ad232L << 36), //>2^(16/64)=1.18920711500272106671749997056
new EFP (P, 0, 0x99e0459320b7fa64L, 0xe43086dL << 36), //>2^(17/64)=1.20215673145270314209639695750
new EFP (P, 0, 0x9b8d39b9d54e5538L, 0xa2a817aL << 36), //<2^(18/64)=1.21524735998046887811652025134
new EFP (P, 0, 0x9d3ed9a72cffb750L, 0xde494cfL << 36), //<2^(19/64)=1.22848053610687000569400895779
new EFP (P, 0, 0x9ef5326091a111adL, 0xa0911f1L << 36), //>2^(20/64)=1.24185781207348404859367746873
new EFP (P, 0, 0xa0b0510fb9714fc2L, 0x192dc7aL << 36), //>2^(21/64)=1.25538075702469108957939065744
new EFP (P, 0, 0xa27043030c496818L, 0x9b7a04fL << 36), //>2^(22/64)=1.26905095719173322255441908103
new EFP (P, 0, 0xa43515ae09e6809eL, 0x0d1db48L << 36), //<2^(23/64)=1.28287001607877828072666978102
new EFP (P, 0, 0xa5fed6a9b15138eaL, 0x1cbd7f6L << 36), //<2^(24/64)=1.29683955465100966593375411779
new EFP (P, 0, 0xa7cd93b4e9653569L, 0x9ec5b4dL << 36), //<2^(25/64)=1.31096121152476434192299178633
new EFP (P, 0, 0xa9a15ab4ea7c0ef8L, 0x541e24fL << 36), //>2^(26/64)=1.32523664315974129462953709550
new EFP (P, 0, 0xab7a39b5a93ed337L, 0x658023bL << 36), //<2^(27/64)=1.33966752405330300536003066972
new EFP (P, 0, 0xad583eea42a14ac6L, 0x4980a8dL << 36), //>2^(28/64)=1.35425554693689272829801474014
new EFP (P, 0, 0xaf3b78ad690a4374L, 0xdf26102L << 36), //>2^(29/64)=1.36900242297459061192960113298
new EFP (P, 0, 0xb123f581d2ac258fL, 0x87d037fL << 36), //>2^(30/64)=1.38390988196383195487265952727
new EFP (P, 0, 0xb311c412a9112489L, 0x3ecf14eL << 36), //>2^(31/64)=1.39897967253831114020952813672
new EFP (P, 0, 0xb504f333f9de6484L, 0x597d89bL << 36), //<2^(32/64)=1.41421356237309504880168872421
new EFP (P, 0, 0xb6fd91e328d17791L, 0x07165f1L << 36), //>2^(33/64)=1.42961333839197001123506577828
new EFP (P, 0, 0xb8fbaf4762fb9ee9L, 0x1b87978L << 36), //>2^(34/64)=1.44518080697704662003700624147
new EFP (P, 0, 0xbaff5ab2133e45fbL, 0x74d519dL << 36), //<2^(35/64)=1.46091779418064698865130289031
new EFP (P, 0, 0xbd08a39f580c36beL, 0xa8811fbL << 36), //<2^(36/64)=1.47682614593949931138690748037
new EFP (P, 0, 0xbf1799b67a731082L, 0xe815d0bL << 36), //>2^(37/64)=1.49290772829126484920064353149
new EFP (P, 0, 0xc12c4cca66709456L, 0x7c457d6L << 36), //>2^(38/64)=1.50916442759342273976601955103
new EFP (P, 0, 0xc346ccda24976407L, 0x20ec856L << 36), //<2^(39/64)=1.52559815074453830685125368952
new EFP (P, 0, 0xc5672a115506daddL, 0x3e2ad0dL << 36), //>2^(40/64)=1.54221082540794082361229186209
new EFP (P, 0, 0xc78d74c8abb9b15cL, 0xc13a2e4L << 36), //>2^(41/64)=1.55900440023783696703372808947
new EFP (P, 0, 0xc9b9bd866e2f27a2L, 0x80e1f93L << 36), //>2^(42/64)=1.57598084510788648645527016018
new EFP (P, 0, 0xcbec14fef2727c5cL, 0xf4907c9L << 36), //>2^(43/64)=1.59314215134226689793724864312
new EFP (P, 0, 0xce248c151f8480e3L, 0xe235839L << 36), //>2^(44/64)=1.61049033194925430817952066736
new EFP (P, 0, 0xd06333daef2b2594L, 0xd6d45c6L << 36), //<2^(45/64)=1.62802742185734776684821852201
new EFP (P, 0, 0xd2a81d91f12ae45aL, 0x12248e5L << 36), //<2^(46/64)=1.64575547815396484451875672473
new EFP (P, 0, 0xd4f35aabcfedfa1fL, 0x5921df0L << 36), //>2^(47/64)=1.66367658032673643504633645698
new EFP (P, 0, 0xd744fccad69d6af4L, 0x39a68bcL << 36), //>2^(48/64)=1.68179283050742908606225095247
new EFP (P, 0, 0xd99d15c278afd7b5L, 0xfe873dfL << 36), //>2^(49/64)=1.70010635371852346950136257350
new EFP (P, 0, 0xdbfbb797daf23755L, 0x3d840d6L << 36), //>2^(50/64)=1.71861929812247791562934437646
new EFP (P, 0, 0xde60f4825e0e9123L, 0xdd07a2eL << 36), //>2^(51/64)=1.73733383527370624899420208187
new EFP (P, 0, 0xe0ccdeec2a94e111L, 0x0658950L << 36), //<2^(52/64)=1.75625216037329948311216061938
new EFP (P, 0, 0xe33f8972be8a5a51L, 0x09bfe90L << 36), //<2^(53/64)=1.77537649252652125255055920020
new EFP (P, 0, 0xe5b906e77c8348a8L, 0x1e5e8f5L << 36), //>2^(54/64)=1.79470907500310718642770324213
new EFP (P, 0, 0xe8396a503c4bdc68L, 0x791790dL << 36), //<2^(55/64)=1.81425217550039875624983460036
new EFP (P, 0, 0xeac0c6e7dd24392eL, 0xd02d75bL << 36), //<2^(56/64)=1.83400808640934246348708318959
new EFP (P, 0, 0xed4f301ed9942b84L, 0x600d2dbL << 36), //<2^(57/64)=1.85397912508338556839245307034
new EFP (P, 0, 0xefe4b99bdcdaf5cbL, 0x46561cfL << 36), //<2^(58/64)=1.87416763411029990132999894995
new EFP (P, 0, 0xf281773c59ffb139L, 0xe8980aaL << 36), //>2^(59/64)=1.89457598158696564134021865343
new EFP (P, 0, 0xf5257d152486cc2cL, 0x7b9d0c8L << 36), //>2^(60/64)=1.91520656139714729387261127030
new EFP (P, 0, 0xf7d0df730ad13bb8L, 0xfe90d49L << 36), //<2^(61/64)=1.93606179349229445059805590457
new EFP (P, 0, 0xfa83b2db722a033aL, 0x7c25bb1L << 36), //<2^(62/64)=1.95714412417540026901832225163
new EFP (P, 0, 0xfd3e0c0cf486c174L, 0x853f3a6L << 36), //>2^(63/64)=1.97845602638795096825824991813
}; //EXP2P_T
public final EFP[] EXP2M_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("2^(-",n,"/64)")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=2^(-0/64)=1.00000000000000000000000000000
new EFP (P, -1, 0xfd3e0c0cf486c174L, 0x853f3a6L << 36), //>2^(-1/64)=0.989228013193975484129124959066
new EFP (P, -1, 0xfa83b2db722a033aL, 0x7c25bb1L << 36), //<2^(-2/64)=0.978572062087700134509161125813
new EFP (P, -1, 0xf7d0df730ad13bb8L, 0xfe90d49L << 36), //<2^(-3/64)=0.968030896746147225299027952283
new EFP (P, -1, 0xf5257d152486cc2cL, 0x7b9d0c8L << 36), //>2^(-4/64)=0.957603280698573646936305635148
new EFP (P, -1, 0xf281773c59ffb139L, 0xe8980aaL << 36), //>2^(-5/64)=0.947287990793482820670109326713
new EFP (P, -1, 0xefe4b99bdcdaf5cbL, 0x46561cfL << 36), //<2^(-6/64)=0.937083817055149950664999474977
new EFP (P, -1, 0xed4f301ed9942b84L, 0x600d2dbL << 36), //<2^(-7/64)=0.926989562541692784196226535169
new EFP (P, -1, 0xeac0c6e7dd24392eL, 0xd02d75bL << 36), //<2^(-8/64)=0.917004043204671231743541594794
new EFP (P, -1, 0xe8396a503c4bdc68L, 0x791790dL << 36), //<2^(-9/64)=0.907126087750199378124917300181
new EFP (P, -1, 0xe5b906e77c8348a8L, 0x1e5e8f5L << 36), //>2^(-10/64)=0.897354537501553593213851621064
new EFP (P, -1, 0xe33f8972be8a5a51L, 0x09bfe90L << 36), //<2^(-11/64)=0.887688246263260626275279600100
new EFP (P, -1, 0xe0ccdeec2a94e111L, 0x0658950L << 36), //<2^(-12/64)=0.878126080186649741556080309688
new EFP (P, -1, 0xde60f4825e0e9123L, 0xdd07a2eL << 36), //>2^(-13/64)=0.868666917636853124497101040936
new EFP (P, -1, 0xdbfbb797daf23755L, 0x3d840d6L << 36), //>2^(-14/64)=0.859309649061238957814672188228
new EFP (P, -1, 0xd99d15c278afd7b5L, 0xfe873dfL << 36), //>2^(-15/64)=0.850053176859261734750681286749
new EFP (P, -1, 0xd744fccad69d6af4L, 0x39a68bcL << 36), //>2^(-16/64)=0.840896415253714543031125476233
new EFP (P, -1, 0xd4f35aabcfedfa1fL, 0x5921df0L << 36), //>2^(-17/64)=0.831838290163368217523168228488
new EFP (P, -1, 0xd2a81d91f12ae45aL, 0x12248e5L << 36), //<2^(-18/64)=0.822877739076982422259378362363
new EFP (P, -1, 0xd06333daef2b2594L, 0xd6d45c6L << 36), //<2^(-19/64)=0.814013710928673883424109261007
new EFP (P, -1, 0xce248c151f8480e3L, 0xe235839L << 36), //>2^(-20/64)=0.805245165974627154089760333679
new EFP (P, -1, 0xcbec14fef2727c5cL, 0xf4907c9L << 36), //>2^(-21/64)=0.796571075671133448968624321560
new EFP (P, -1, 0xc9b9bd866e2f27a2L, 0x80e1f93L << 36), //>2^(-22/64)=0.787990422553943243227635080091
new EFP (P, -1, 0xc78d74c8abb9b15cL, 0xc13a2e4L << 36), //>2^(-23/64)=0.779502200118918483516864044737
new EFP (P, -1, 0xc5672a115506daddL, 0x3e2ad0dL << 36), //>2^(-24/64)=0.771105412703970411806145931045
new EFP (P, -1, 0xc346ccda24976407L, 0x20ec856L << 36), //<2^(-25/64)=0.762799075372269153425626844758
new EFP (P, -1, 0xc12c4cca66709456L, 0x7c457d6L << 36), //>2^(-26/64)=0.754582213796711369883009775517
new EFP (P, -1, 0xbf1799b67a731082L, 0xe815d0bL << 36), //>2^(-27/64)=0.746453864145632424600321765743
new EFP (P, -1, 0xbd08a39f580c36beL, 0xa8811fbL << 36), //<2^(-28/64)=0.738413072969749655693453740187
new EFP (P, -1, 0xbaff5ab2133e45fbL, 0x74d519dL << 36), //<2^(-29/64)=0.730458897090323494325651445155
new EFP (P, -1, 0xb8fbaf4762fb9ee9L, 0x1b87978L << 36), //>2^(-30/64)=0.722590403488523310018503120736
new EFP (P, -1, 0xb6fd91e328d17791L, 0x07165f1L << 36), //>2^(-31/64)=0.714806669195985005617532889138
new EFP (P, -1, 0xb504f333f9de6484L, 0x597d89bL << 36), //<2^(-32/64)=0.707106781186547524400844362105
new EFP (P, -1, 0xb311c412a9112489L, 0x3ecf14eL << 36), //>2^(-33/64)=0.699489836269155570104764068358
new EFP (P, -1, 0xb123f581d2ac258fL, 0x87d037fL << 36), //>2^(-34/64)=0.691954940981915977436329763633
new EFP (P, -1, 0xaf3b78ad690a4374L, 0xdf26102L << 36), //>2^(-35/64)=0.684501211487295305964800566491
new EFP (P, -1, 0xad583eea42a14ac6L, 0x4980a8dL << 36), //>2^(-36/64)=0.677127773468446364149007370070
new EFP (P, -1, 0xab7a39b5a93ed337L, 0x658023bL << 36), //<2^(-37/64)=0.669833762026651502680015334862
new EFP (P, -1, 0xa9a15ab4ea7c0ef8L, 0x541e24fL << 36), //>2^(-38/64)=0.662618321579870647314768547749
new EFP (P, -1, 0xa7cd93b4e9653569L, 0x9ec5b4dL << 36), //<2^(-39/64)=0.655480605762382170961495893165
new EFP (P, -1, 0xa5fed6a9b15138eaL, 0x1cbd7f6L << 36), //<2^(-40/64)=0.648419777325504832966877058896
new EFP (P, -1, 0xa43515ae09e6809eL, 0x0d1db48L << 36), //<2^(-41/64)=0.641435008039389140363334890511
new EFP (P, -1, 0xa27043030c496818L, 0x9b7a04fL << 36), //>2^(-42/64)=0.634525478595866611277209540516
new EFP (P, -1, 0xa0b0510fb9714fc2L, 0x192dc7aL << 36), //>2^(-43/64)=0.627690378512345544789695328721
new EFP (P, -1, 0x9ef5326091a111adL, 0xa0911f1L << 36), //>2^(-44/64)=0.620928906036742024296838734363
new EFP (P, -1, 0x9d3ed9a72cffb750L, 0xde494cfL << 36), //<2^(-45/64)=0.614240268053435002847004478896
new EFP (P, -1, 0x9b8d39b9d54e5538L, 0xa2a817aL << 36), //<2^(-46/64)=0.607623679990234439058260125669
new EFP (P, -1, 0x99e0459320b7fa64L, 0xe43086dL << 36), //>2^(-47/64)=0.601078365726351571048198478749
new EFP (P, -1, 0x9837f0518db8a96fL, 0x46ad232L << 36), //>2^(-48/64)=0.594603557501360533358749985280
new EFP (P, -1, 0x96942d3720185a00L, 0x48ea9b7L << 36), //>2^(-49/64)=0.588198495825140638142322864242
new EFP (P, -1, 0x94f4efa8fef70961L, 0x2e8afadL << 36), //<2^(-50/64)=0.581862429388788756906786799546
new EFP (P, -1, 0x935a2b2f13e6e92bL, 0xd339941L << 36), //>2^(-51/64)=0.575594614976491352908879817601
new EFP (P, -1, 0x91c3d373ab11c336L, 0x0fd6d8eL << 36), //<2^(-52/64)=0.569394317378345826851915141921
new EFP (P, -1, 0x9031dc431466b1dcL, 0x775814bL << 36), //>2^(-53/64)=0.563260809304120949897399321894
new EFP (P, -1, 0x8ea4398b45cd53c0L, 0x2dc0145L << 36), //>2^(-54/64)=0.557193371297946268154406478460
new EFP (P, -1, 0x8d1adf5b7e5ba9e5L, 0xb4c7b49L << 36), //<2^(-55/64)=0.551191291653920471778207104713
new EFP (P, -1, 0x8b95c1e3ea8bd6e6L, 0xfbe4628L << 36), //<2^(-56/64)=0.545253866332628829603505327880
new EFP (P, -1, 0x8a14d575496efd9aL, 0x080ca1eL << 36), //>2^(-57/64)=0.539380398878559896870340018719
new EFP (P, -1, 0x88980e8092da8527L, 0x5df8d77L << 36), //>2^(-58/64)=0.533570200338411809084760560496
new EFP (P, -1, 0x871f61969e8d1010L, 0x3a1727cL << 36), //<2^(-59/64)=0.527822589180278579404170662576
new EFP (P, -1, 0x85aac367cc487b14L, 0xc5c95b9L << 36), //>2^(-60/64)=0.522136891213706920160983239370
new EFP (P, -1, 0x843a28c3acde4046L, 0x1af92edL << 36), //>2^(-61/64)=0.516512439510614211250054141985
new EFP (P, -1, 0x82cd8698ac2ba1d7L, 0x3e2a476L << 36), //>2^(-62/64)=0.510948574327058339117240067392
new EFP (P, -1, 0x8164d1f3bc030773L, 0x7be5652L << 36), //<2^(-63/64)=0.505444643025850230010204895281
}; //EXP2M_T
//------------------------------------------------------------------------
//exp2m1
// echo read("efp.gp");eval("exp2m1(x)=2^x-1");efppoly("EXP2M1_C",exp2m1,sum(n=1,17,eval("efp(log(2)^n/factorial(n))*x^n")),-1/4,1/4) | gp -q
public final EFP EXP2M1_C1 = new EFP (P, -1, 0xb17217f7d1cf79abL, 0xc9e3b3aL << 36); //=0.693147180559945309417232121559
public final EFP EXP2M1_C2 = new EFP (P, -3, 0xf5fdeffc162c7543L, 0x78b5837L << 36); //=0.240226506959100712333551263143
public final EFP EXP2M1_C3 = new EFP (P, -5, 0xe35846b82505fc59L, 0x9d3b15eL << 36); //=0.0555041086648215799531422637737
public final EFP EXP2M1_C4 = new EFP (P, -7, 0x9d955b7dd273b94eL, 0x65df05bL << 36); //=0.00961812910762847716197907157485
public final EFP EXP2M1_C5 = new EFP (P, -10, 0xaec3ff3c53398883L, 0x8bfb4d3L << 36); //=0.00133335581464284434234122219898
public final EFP EXP2M1_C6 = new EFP (P, -13, 0xa184897c363c3b7aL, 0x58544c3L << 36); //=1.54035303933816099544370973310e-4
public final EFP EXP2M1_C7 = new EFP (P, -17, 0xffe5fe2c45863435L, 0x8a8e644L << 36); //=1.52527338040598402800254390122e-5
public final EFP EXP2M1_C8 = new EFP (P, -20, 0xb160111d2e411fecL, 0x7ff3037L << 36); //=1.32154867901443094884037582290e-6
public final EFP EXP2M1_C9 = new EFP (P, -24, 0xda929e9caf3e1ed2L, 0x53872d2L << 36); //=1.01780860092396997274900075965e-7
public final EFP EXP2M1_C10 = new EFP (P, -28, 0xf267a8ac5c764fb7L, 0xed0eca9L << 36); //=7.05491162080112332987539218087e-9
public final EFP EXP2M1_C11 = new EFP (P, -32, 0xf465639a8dd92607L, 0xabccaf2L << 36); //=4.44553827187081149759640855868e-10
public final EFP EXP2M1_C12 = new EFP (P, -36, 0xe1deb287e14c2f15L, 0xab43f0cL << 36); //=2.56784359934882051419948023929e-11
public final EFP EXP2M1_C13 = new EFP (P, -40, 0xc0b0c98b3687cb14L, 0x0d61808L << 36); //=1.36914888539041288808919539964e-12
public final EFP EXP2M1_C14 = new EFP (P, -44, 0x98a4b26ac3c54b9fL, 0x8a1b12bL << 36); //=6.77872635482254563344910431422e-14
public final EFP EXP2M1_C15 = new EFP (P, -49, 0xe1b7421d82010f33L, 0xd8abf8dL << 36); //=3.13243670708842862163494444075e-15
public final EFP EXP2M1_C16 = new EFP (P, -53, 0x9c744d73cfc59c91L, 0xc7f2765L << 36); //=1.35702479487551471931129662273e-16
public final EFP EXP2M1_C17 = new EFP (P, -58, 0xcc2225a0e12d3eabL, 0x0ec4008L << 36); //=5.53304653245824204348554609564e-18
// 92.12bit
//------------------------------------------------------------------------
//expm1
// echo read("efp.gp");efppoly("EXPM1_C",expm1,sum(n=1,18,eval("efp(1/factorial(n))*x^n")),-1/4,1/4) | gp -q
public final EFP EXPM1_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP EXPM1_C2 = new EFP (P, -1, 0x8000000000000000L, 0x0000000L << 36); //=0.500000000000000000000000000000
public final EFP EXPM1_C3 = new EFP (P, -3, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaabL << 36); //=0.166666666666666666666666666683
public final EFP EXPM1_C4 = new EFP (P, -5, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaabL << 36); //=0.0416666666666666666666666666709
public final EFP EXPM1_C5 = new EFP (P, -7, 0x8888888888888888L, 0x8888889L << 36); //=0.00833333333333333333333333333481
public final EFP EXPM1_C6 = new EFP (P, -10, 0xb60b60b60b60b60bL, 0x60b60b6L << 36); //=0.00138888888888888888888888888887
public final EFP EXPM1_C7 = new EFP (P, -13, 0xd00d00d00d00d00dL, 0x00d00d0L << 36); //=1.98412698412698412698412698410e-4
public final EFP EXPM1_C8 = new EFP (P, -16, 0xd00d00d00d00d00dL, 0x00d00d0L << 36); //=2.48015873015873015873015873013e-5
public final EFP EXPM1_C9 = new EFP (P, -19, 0xb8ef1d2ab6399c7dL, 0x560e447L << 36); //=2.75573192239858906525573192228e-6
public final EFP EXPM1_C10 = new EFP (P, -22, 0x93f27dbbc4fae397L, 0x780b69fL << 36); //=2.75573192239858906525573192209e-7
public final EFP EXPM1_C11 = new EFP (P, -26, 0xd7322b3faa271c7fL, 0x3a3f25cL << 36); //=2.50521083854417187750521083848e-8
public final EFP EXPM1_C12 = new EFP (P, -29, 0x8f76c77fc6c4bdaaL, 0x26d4c3dL << 36); //=2.08767569878680989792100903181e-9
public final EFP EXPM1_C13 = new EFP (P, -33, 0xb092309d43684be5L, 0x1c198e9L << 36); //=1.60590438368216145993923771696e-10
public final EFP EXPM1_C14 = new EFP (P, -37, 0xc9cba54603e4e905L, 0xd6f8a2fL << 36); //=1.14707455977297247138516979787e-11
public final EFP EXPM1_C15 = new EFP (P, -41, 0xd73f9f399dc0f88eL, 0xc32b587L << 36); //=7.64716373181981647590113198495e-13
public final EFP EXPM1_C16 = new EFP (P, -45, 0xd73f9f399dc0f88eL, 0xc32b587L << 36); //=4.77947733238738529743820749060e-14
public final EFP EXPM1_C17 = new EFP (P, -49, 0xca963b81856a5359L, 0x3028cbcL << 36); //=2.81145725434552076319894558321e-15
public final EFP EXPM1_C18 = new EFP (P, -53, 0xb413c31dcbecbbddL, 0x8024435L << 36); //=1.56192069685862264622163643497e-16
// 92.61bit
//------------------------------------------------------------------------
//ieeerempi2
public static final int[] TWO_PI_ARRAY = {
// perl ../misc/two_pi.pl
0x00000000, 0x00000000, 0x00000000, 0x517cc1b7, 0x1391054a, 0x3f84eafa, 0x1f534ddc, 0x06db14ac, 0x64f10e41, 0x03fca2c7,
0x2bdebbc5, 0x30db9237, 0x0e909374, 0x5c00c925, 0x6ea09d19, 0x10e7f0ef, 0x2c72c4a6, 0x4e7dd104, 0x35f52ebb, 0x224274ce,
0x1c09ad17, 0x6fc82732, 0x1d639835, 0x19cfa4e4, 0x117e2ef7, 0x7250763f, 0x7897ffde, 0x02cc07f7, 0x4bc462d6, 0x414da3ed,
0x5367ecf2, 0x3e584dba, 0x3d18fd9a, 0x3cbfd45a, 0x7527bac7, 0x75f2f8bd, 0x4f41ce7d, 0x714a525d, 0x26bfb5fb, 0x08fc6ae8,
0x21580cc1, 0x0df8f6d7, 0x2bf0cfbc, 0x104d7a1b, 0x076a78e4, 0x2c2bdcc3, 0x30865998, 0x2af8a503, 0x210237ff, 0x31009ae6,
0x27310606, 0x0aab6539, 0x6a325838, 0x4f78118d, 0x347c419c, 0x1b3e6ee7, 0x2024aa0d, 0x3388ed17, 0x161ca6dd, 0x57a268ab,
0x46414fa9, 0x3fe0e0a7, 0x77e33e83, 0x1616f27c, 0x60c9f6ef, 0x067a4dde, 0x6b1e5ef8, 0x4f9d0f9a, 0x72bc9fc7, 0x30fe2432,
0x07c7c246, 0x57d376ab, 0x5cb4c10c, 0x762b8c29, 0x359d19c3, 0x616256a0, 0x534b1740, 0x0188cfb0, 0x62d71e39, 0x5634d803,
0x08cdf34a, 0x692f4f69, 0x555537f6, 0x1f6b8c08, 0x28ff1d93, 0x2553ac95, 0x3d770f87, 0x631abd83, 0x6b9c545d, 0x2c9381b3,
0x563b3884, 0x53e59192, 0x1de2b588, 0x6a8b5723, 0x7001b0af, 0x0efe70cf, 0x7cc67da8, 0x3cccc2af, 0x1947fbac, 0x6c3fbf5b,
0x5948a27a, 0x064c17fc, 0x6cdc4ef0, 0x49b366a1, 0x7d775f78, 0x2dbc76b1, 0x129bde28, 0x11697443, 0x0a135638, 0x465958c2,
0x6e308cb7, 0x6f028600, 0x5e9c77cd, 0x37c03068, 0x132e6212, 0x4180a441, 0x56e3bd5f, 0x7615be5d, 0x11e434a4, 0x469b3886,
0x6376a909, 0x3f5d9cc2, 0x6aa4280a, 0x5a4ce9f9, 0x29819fdd, 0x6b907854, 0x3883c617, 0x439c52d4, 0x32bef75d, 0x5ec74c5b,
0x4bbff4ef, 0x40c6b3e0, 0x49917295, 0x26db395a, 0x2a8288d6, 0x0e13be48, 0x48509812, 0x368c2588, 0x59c444c5, 0x6448d926,
0x7cc5c02b, 0x287a9ca9, 0x12910d5f, 0x6fe5f006, 0x32507bbb, 0x1ce1ea7c, 0x1380f1ec, 0x61f3d994, 0x3e31e501, 0x3267ce38,
0x1b3092ef, 0x1a285ce0, 0x4a21ec82, 0x573f6a5d, 0x4292472f, 0x193db6aa, 0x432429dc, 0x43fced72, 0x6cb314a1, 0x33cf13ca,
0x06277fd2, 0x2f29d109, 0x66e29731, 0x4cb5f6c4, 0x0d97d7c3, 0x5fb77693, 0x2486ca46, 0x3a139389, 0x497636e0, 0x2b3e13cb,
0x3c25318d, 0x1cba7b8e, 0x014c0043, 0x01ad0109, 0x358ee2c9, 0x05523817, 0x1dd0935a, 0x7b4cfbee, 0x72486eef, 0x0b4fd34a,
0x23bda46d, 0x0a2a7a3e, 0x20acf339, 0x4103f25f, 0x55a18ec9, 0x3e7dba06, 0x5d407f89, 0x4294a92a, 0x70190dc4, 0x1b0da649,
0x032754c5, 0x5ea38a73, 0x39511704, 0x1216d3ea, 0x2ad56614, 0x4e8393a8, 0x011776ce, 0x7698aedd, 0x217f9877, 0x6b5a4dd1,
0x1c74a5a6, 0x2d59998c, 0x5414ad6a, 0x714844ec, 0x62141c8b, 0x17d48092, 0x40777703, 0x07993fe0, 0x02a1c7a9, 0x1384cc7b,
0x606483dd, 0x4bcb9fd1, 0x7f6510e3, 0x10c1bbc8, 0x1319d399, 0x146386ef, 0x1edc5cef, 0x3e10566e, 0x15a0805c, 0x49c02d49,
0x0444363a, 0x01f5f00d, 0x44bffdb0, 0x7c81c3b0, 0x61645695, 0x457796c3, 0x3989c7bd, 0x20080279, 0x3489dd52, 0x3ed6dd77,
0x322dbaa1, 0x20517934, 0x25da0d90, 0x66761235, 0x140eaa3a, 0x28e1518e, 0x6bbb6bc4, 0x44cb89b8, 0x26d9c7a2, 0x6cbab604,
0x0cfc0fdb, 0x60131880, 0x2b99316d, 0x03da1c8a, 0x480316f0, 0x7b18925e, 0x54badc6a, 0x2e527669, 0x5e9cdaa7, 0x4d292556,
0x6842ddde, 0x318cf7c6, 0x1d94a2da, 0x06fb7f95, 0x3a1ae311, 0x2efd0d70, 0x036bec31, 0x4c9ac96e, 0x05ed3065, 0x14dfab2b,
0x4ebfd1ee, 0x3f2d5e77, 0x675df932, 0x4184055f, 0x5a319857, 0x16080c45, 0x7a1de4d9, 0x52599ec7, 0x46d5c273, 0x26dd2849,
0x6a4be13b, 0x291998d5, 0x2bc2a195, 0x1f4b83a4, 0x0f3f0bcd, 0x3c2dbb7c, 0x48c122de, 0x6e42f12a, 0x3a6c6e26, 0x7378075f,
0x3d612a6e, 0x6fb58974, 0x66aacfcf, 0x3b0e8168, 0x4b7c6c70, 0x33318ef5, 0x5c3da488, 0x3502efbf, 0x520318bf, 0x615935d9,
0x5dbc5c3f, 0x36ef680f, 0x71e42db6, 0x654744b4, 0x39aaf009, 0x1a9d6822, 0x5edad0b4, 0x52fd0097, 0x2707da0e, 0x553b50ac,
0x5eca8485, 0x45b6fb9f, 0x5e5fafed, 0x5c4fedf4, 0x25b1db93, 0x79520ce1, 0x003e156e, 0x42ffc3fe, 0x41cf8a0c, 0x6cec30c3,
0x02aeabd4, 0x6d7f3d9b, 0x39b63ce5, 0x4f2ab77e, 0x3148d784, 0x0b6f9821, 0x4b71cd58, 0x24b9ce19, 0x1b8cb30f, 0x6b65fd10,
0x029391b0, 0x0b41bab4, 0x476f21d2, 0x0931422e, 0x2e52585c, 0x1c0acd60, 0x15299375, 0x2a85bea8, 0x7b13c4cd, 0x3edc27c8,
0x305da92e, 0x42e1d90e, 0x4d8ca869, 0x16e11a96, 0x1ea21f71, 0x37234c7b, 0x5ffc9e00, 0x06185a81, 0x0da0cd4f, 0x4cd29069,
0x68acc297, 0x25e85f36, 0x4cbda11d, 0x05f3ee0e, 0x6e6ef45e, 0x57034594, 0x5c6a0817, 0x2a972a80, 0x09fc051f, 0x70c0fc2c,
0x40b148d4, 0x0cb6f5f4, 0x1cabf76a, 0x6c4ad669, 0x097bfef3, 0x02cf5fdc, 0x53da9a2a, 0x05494b58, 0x44fbcf82, 0x6cc2d6bc,
0x571fd235, 0x1a1b4c74, 0x205f57a4, 0x589f8a4a, 0x4e200048, 0x1990dbae, 0x1b6dec9f, 0x2b05f88b, 0x1535ac1c, 0x03596119,
0x50c0b248, 0x2aa8877d, 0x47b0dca5, 0x2760d466, 0x540c07bd, 0x6036622f, 0x03e8a53b, 0x1195ac83, 0x73e8de64, 0x3e6c324d,
0x4c6fb670, 0x72f49a8b, 0x077c5e36, 0x489ed781, 0x70eae918, 0x308cbeea, 0x55f5bdd2, 0x6349372e, 0x4bab3b51, 0x01c847c3,
0x487c461e, 0x4fe94f9e, 0x5b9f29f0, 0x446b22df, 0x45e0088d, 0x6bfff135, 0x1bb1bf6c, 0x1821126e, 0x45d7cb2a, 0x6b5ceb76,
0x35edc8f9, 0x54238d53, 0x4ff7df73, 0x14dd64da, 0x54402dc3, 0x365c4497, 0x274607de, 0x2c56c3a1, 0x30543430, 0x310328cc,
0x7e162901, 0x3b3d4fdf, 0x3f7f7bd1, 0x2ac6cfdb, 0x113d9ecb, 0x4dd45fe4, 0x5f109ea0, 0x6386dde2, 0x36c59456, 0x546c5ad4,
0x2d03b333, 0x65b12246, 0x4576f895, 0x31671e74, 0x66e4835a, 0x54bcd738, 0x2a3ecc5f, 0x08a505fe, 0x7efd385b, 0x2771c590,
0x6e284d4e, 0x4d4da7e6, 0x47bbbf24, 0x6a5cc272, 0x2f442138, 0x646c8d85, 0x3f205a92, 0x5f7b0385, 0x784b4538, 0x64ca7661,
0x09537154, 0x55ad8d81, 0x16190bb8, 0x380d324a, 0x5a581689, 0x5dca47e1, 0x7117f11b, 0x2fa7ae5f, 0x70b6f0d3, 0x5d786998,
0x5de8605e, 0x6ecdc733, 0x7bcce4ae, 0x02f9336b, 0x061bc57e, 0x0e341a88, 0x40fb6121, 0x63bbba38, 0x2da118af, 0x231610eb,
0x7cd6661e, 0x5b380a93, 0x6fa864ff, 0x6032b573, 0x6794d88a, 0x12455a71, 0x5c9367aa, 0x742a9c13, 0x20a6f9f2, 0x5481aa36,
0x133990ed, 0x3d4a402b, 0x27c2c996, 0x4f10ff2e, 0x4c8836d1, 0x7cd9c910, 0x52a09ec8, 0x39f31b93, 0x7405547d, 0x61d3a70a,
0x0bad9f7e, 0x3bfcbfa8, 0x5ea4677b, 0x3d565d51, 0x3d9548e2, 0x056ab748, 0x1086e598, 0x31510c1a, 0x1ce79b8e, 0x13a93dca,
0x40fb49e9, 0x2b7fe507, 0x47229671, 0x257f5298, 0x5c1d3cfc, 0x287d72d6, 0x6e1b151d, 0x44870a77, 0x06219479, 0x1643b088,
0x1ed30a86, 0x45900257, 0x74390268, 0x4449e3c7, 0x1312a1ef, 0x37cb8475, 0x44eaf426, 0x4533fbdf, 0x64834ae8, 0x6cb63267,
0x50b7cbdd, 0x628d231e, 0x749f7785, 0x52332935, 0x1529a828, 0x67345a76, 0x424827d1, 0x195309cc, 0x38270237, 0x63f195c8,
0x3e3bd69f, 0x4eac2811, 0x71212a9d, 0x5aa6bf37, 0x5446696a, 0x7f36badb, 0x78261dd9, 0x3011b0b4, 0x7ceb1286, 0x4506dbda,
0x727a8d39, 0x54dc412e, 0x0c9ad6c9, 0x68dda680, 0x07700d25, 0x2fa7e26a, 0x640601c7, 0x41c27f13, 0x3295f364, 0x5478d753,
0x52ce3f13, 0x1d565768, 0x7270babc, 0x1d39a5d3, 0x014b74d3, 0x70ac75d6, 0x7e8a31bb, 0x1b2c4adb, 0x51fdea65, 0x18755a72,
0x2251e7f3, 0x76c4ba75, 0x6ea53f62, 0x5c03ccc3, 0x34393d8e, 0x5291d519, 0x41a3858c, 0x76a77631, 0x01d3a9d4, 0x009e8660,
0x6f97e18b, 0x4e77e51e, 0x39b5bf0b, 0x611a913a, 0x1fa891f0, 0x1aa5a3e3, 0x1add3909, 0x26fc988e, 0x42d0ac95, 0x12db65c4,
0x64b25ef1, 0x1a9de352, 0x0692b42a, 0x5925cc9d, 0x08657309, 0x0cc167d9, 0x446c6821, 0x65177b9d, 0x6160e142, 0x75b20ee8,
0x2ee8f956, 0x3a8b2f71, 0x42a4483f, 0x1995d7c2, 0x219cb234, 0x365f5360, 0x50f3ddf9, 0x7ab9edb0, 0x6d3f88cf, 0x4d8834dd,
0x6a318775, 0x5135e2f2, 0x733a9c22, 0x29b8afc4, 0x0196f1e8, 0x1cdf2428, 0x574b4bd3, 0x52aabb2d, 0x6c2e7d75, 0x2b182706,
0x00b83bf1, 0x014177f3, 0x337125a7, 0x1116fdfb, 0x067620e3, 0x038cc33c, 0x6b20d55b, 0x5a89bbcf, 0x2026be45, 0x121ae7bc,
0x0b0da5ce, 0x3fac560c, 0x4d1c9199, 0x6f434273, 0x626bc455, 0x2f3ac2e5, 0x55c47451, 0x10d32290, 0x0d6056ad, 0x55eb17b2,
0x25bb8308, 0x25fe6bad, 0x588a6768, 0x24ab28f5, 0x2e782937, 0x3dfcae20, 0x10836a39, 0x7c7518cf, 0x0e077ab2, 0x1639592d,
0x337f21ed, 0x282f4cc2, 0x1d0e7f15, 0x5806636e, 0x3b8bf886, 0x72b546e1, 0x50d88c39, 0x7279faad, 0x28f2d733, 0x0028d781,
0x06827f2d, 0x682b43aa, 0x6b236ff7, 0x1297a5e3, 0x6e29645f, 0x758b2b8a, 0x5de212c3, 0x458994b2, 0x73fd40d9, 0x44c5f4f6,
0x16f4d9a6, 0x1567f3f8, 0x1d00f535, 0x408dfb22, 0x631b1bfc, 0x5da282de, 0x5f203386, 0x28d7ac86, 0x4fd91cdf, 0x22a1af9a,
0x14f8ad6a, 0x5935d902, 0x31485f9d, 0x15fdd6dc, 0x79dbd6e6, 0x5e2b9f94, 0x318214b5, 0x36f4ff26, 0x543f0d7d, 0x35dab45a,
0x0c1c9605, 0x38c975b7, 0x2476481f, 0x22895d47, 0x46343566, 0x136ada18, 0x58788dfc, 0x344413df, 0x7958e234, 0x49bcc1af,
0x52992f70, 0x05857c27, 0x3e80a00b, 0x395188ae, 0x17c786f4, 0x21b69a70, 0x69e85969, 0x3b595648, 0x7e289b08, 0x60e1e008,
0x1412fc9f, 0x52fb951c, 0x271a1e38, 0x554eca19, 0x7e155927, 0x249a71c0, 0x2a4bdd54, 0x67e14c7b, 0x34399971, 0x715baad4,
0x629f0023, 0x63358a9a, 0x22ea0b4f, 0x2f9f0306, 0x2127ff49, 0x535ca59c, 0x7a5fdde9, 0x67037d85, 0x3a294333, 0x5d53a7c6,
0x766ddb83, 0x27a86d04, 0x4211be21, 0x15c7aa13, 0x1a032eae, 0x16fe5a05, 0x3ee6ccf8, 0x503ba362, 0x6bad8c0a, 0x7ecb5cbd,
0x54b72670, 0x4efeb2a3, 0x5521ccd6, 0x5b24b5ac, 0x1158acee, 0x5e5434b8, 0x47ca2cfa, 0x4dc9ebdb, 0x6e2520f4, 0x712d6079,
0x479cb1d0, 0x412ec476, 0x6df4e0ce, 0x218dccdd, 0x112dc112, 0x01a06f3c, 0x0a83fb99, 0x4cf103b8, 0x0ae80abf, 0x669460db,
0x6b378631, 0x1f046ecc, 0x6b9959db, 0x21603fd5, 0x2f580e29, 0x2ae0ad5d, 0x6bf5b0bd, 0x4af4a5f0, 0x02e7ace9, 0x43c47e49,
0x2d62c9ac, 0x278d6bae, 0x104be4ed, 0x5c16985d, 0x546c0ed2, 0x72af0b2a, 0x61e1a03e, 0x7eced683, 0x6698ec3a, 0x7142ea4b,
0x5f24a858, 0x6e9c3272, 0x06f911c9, 0x0d5513a3, 0x1fc36964, 0x67ed3ad4, 0x2578ec29, 0x7cfd545a, 0x2b766f3e, 0x76b83a17,
0x688dd533, 0x7f6f1b7b, 0x7bd82cc2, 0x16398030, 0x29ebb591, 0x28bd8e64, 0x5adfbbc3, 0x1bc4cf94, 0x73d1a019, 0x21dc51ba,
0x258a3a9a, 0x46e4c4c5, 0x6928185e, 0x530afef7, 0x2d875f8b, 0x1f4f5d6f, 0x148d28b4, 0x463d8e26, 0x00bc57e7, 0x30a17145,
0x5b016cdd, 0x2b1c719f, 0x52ced170, 0x525ea256, 0x04b90d6f, 0x6c1ccaef, 0x2b714760, 0x4c558061, 0x1a2a9160, 0x12d57856,
0x4f909d7d, 0x32160cfc, 0x774b63e8, 0x5580957f, 0x3f205106, 0x6cf7f633, 0x76d4d795, 0x2bffd269, 0x6c2ca700, 0x4c9bac8e,
0x34a1ad86, 0x19f38439, 0x16f7e283, 0x77df8d0a, 0x251e13b6, 0x32e8b8c3, 0x46a1068a, 0x1e9c5c29, 0x5b2fa425, 0x02e01623,
0x51ce180d, 0x66090a25, 0x5df2cab5, 0x552ac91c, 0x2e89ef09, 0x0c000db6, 0x6951b1e0, 0x789a0cbc, 0x6ae6f080, 0x197c594d,
0x10fa6934, 0x798f992f, 0x4bfbe442, 0x665adf98, 0x0215d378, 0x367fd774, 0x574985bf, 0x447087e5, 0x4828acdf, 0x26924cf7,
0x0f3ac27c, 0x0df67285, 0x60d6c4e2, 0x260b1d34, 0x22381ff4, 0x019645ba, 0x531bc9b6, 0x1e29e4a7, 0x2cb63fe8, 0x3c34ff74,
0x45e57b7c, 0x131273c5, 0x24ab0a65, 0x4683a26a, 0x2f7d5a42, 0x0c8e8918, 0x68b0e425, 0x2ede222c, 0x1fffc690, 0x1951ff6c,
0x390fa5f7, 0x72db49bf, 0x1a472a23, 0x3edb35f5, 0x2c822c06, 0x7b751e95, 0x20b4c1e8, 0x7201c30a, 0x1a568076, 0x3a3229c0,
0x0e8de742, 0x11c7a6ac, 0x0108583f, 0x61b495f1, 0x20f7527e, 0x2f65cc0e, 0x412fb7e9, 0x0f43e808, 0x5dc68477, 0x7a9463f7,
0x5fc162d6, 0x6949775c, 0x0a355126, 0x3f132edb, 0x7166ef0a, 0x4d1d3a6f, 0x61ad61d1, 0x4fdab592, 0x71a3b69c, 0x35df937d,
0x137af459, 0x4a907aed, 0x3ac1d542, 0x18e3e8d7, 0x5e8fac78, 0x14a4ae49, 0x6aabefb6, 0x77e37c4c, 0x3e4f0dde, 0x7ed7dccf,
0x3bac1d8a, 0x758937b9, 0x773b8d06, 0x44928857, 0x36123085, 0x6cfe74b3, 0x542cde0f, 0x75489536, 0x0bed8292, 0x2413fd2b,
0x5a2b596b, 0x5802b312, 0x1466722c, 0x5fd5e188, 0x2cfc3e6c, 0x457efa07, 0x7ca7008b, 0x30042951, 0x4d63ead1, 0x1dd4a4df,
0x3fb0dc1e, 0x49a31414, 0x4325445a, 0x5d3b0f83, 0x33285b53, 0x22a6d56b, 0x60ce333d, 0x261489f9, 0x206fdd19, 0x0473cf16,
0x12aff801, 0x3afc227c, 0x60cb396d, 0x71adb49d, 0x24f0aed6, 0x60dec1f8, 0x74bbf1d8, 0x6317b251, 0x7ddc3bf1, 0x39715e5c,
0x5dd12bf8, 0x0b70339b, 0x1751f725, 0x25cf2702, 0x66ad9d94, 0x5c36fbf7, 0x2cd904e7, 0x1705954c, 0x6522c5ae, 0x34701d5f,
0x1d1f3539, 0x4e5ac6f3, 0x58b21a8d, 0x5604296f, 0x59f20834, 0x71553e1c, 0x645dcd7a, 0x75f00a6f, 0x2dd36c8a, 0x2b16683e,
0x5217a178, 0x14afab5a, 0x78298160, 0x1561f22d, 0x44c17ce8, 0x7de4db61, 0x50910214, 0x513bc866, 0x478f0860, 0x5bea3878,
0x2001c11d, 0x1c94c363, 0x4f10f050, 0x4c8e924f, 0x4e6ce03d, 0x5d1db956, 0x796b4a2b, 0x76bbf110, 0x6f4060ad, 0x209f4870,
0x020eed54, 0x0003cfb4, 0x01b409a1, 0x1cd56a51, 0x5e1a1f1b, 0x0ad47bed, 0x0cc38b4a, 0x5bd71ce4, 0x76b45f98, 0x2f10a374,
0x345d3ab0, 0x6d3f6a7c, 0x7d00e32a, 0x5790fb34, 0x6a007a58, 0x2631f0a8, 0x53537781, 0x47e6d0a0, 0x1ef295fa, 0x12cb2e53,
0x1cc6f20c, 0x1f08d6aa, 0x4e0bd445, 0x0107ab02, 0x7692436d, 0x3c67f4e8, 0x04a2717c, 0x270b82ce, 0x284fedd0, 0x5856f438,
0x2dd7e754, 0x54aa2e82, 0x009d1952, 0x433b5bf8, 0x79923e89, 0x6e4a9f6e, 0x4173ab12, 0x06c14fa3, 0x1a1800a9, 0x04e69bb2,
0x56165d57, 0x432db958, 0x7e07141f, 0x15435c6f, 0x52777a77, 0x33496069, 0x3c48a10c, 0x0cd25a95, 0x0a91f166, 0x265bc1be,
0x67f67d7a, 0x719c9e48, 0x3e44fddd, 0x292e3d83, 0x46297725, 0x55068553, 0x3e829c3a, 0x02de9ef9, 0x2f4cf771, 0x0f7af4b0,
0x2a4a6256, 0x2c1f745d, 0x1b3c5c63, 0x415065a9, 0x144eec3f, 0x10adfef5, 0x7a8dd087, 0x5ba28ec9, 0x1e715b24, 0x2e781501,
0x196aafdb, 0x6ddc0ff5, 0x6a7db0b8, 0x2922c055, 0x1769411c, 0x7434d29c, 0x557218d4, 0x4d8688d7, 0x1fbe0ab7, 0x4e7d4e64,
0x2d3d2515, 0x7780f9d5, 0x701dfb6b, 0x4d9b6fed, 0x010dfebe, 0x7fecdbf5, 0x4882d11f, 0x276ba7ec, 0x7bb0cd6c, 0x259938b0,
};
//------------------------------------------------------------------------
//log
// echo read("efp.gp");eval("f(x)=log((1+x)/(1-x))");efpchebyshev("LOG_C",f,2*sqrt(2)-3,3-2*sqrt(2),27) | gp -q
public final EFP LOG_C1 = new EFP (P, 1, 0x8000000000000000L, 0x0000000L << 36); //=2.00000000000000000000000000000
public final EFP LOG_C3 = new EFP (P, -1, 0xaaaaaaaaaaaaaaaaL, 0xaaaaafaL << 36); //=0.666666666666666666666666682688
public final EFP LOG_C5 = new EFP (P, -2, 0xccccccccccccccccL, 0xcc9635cL << 36); //=0.399999999999999999999977422089
public final EFP LOG_C7 = new EFP (P, -2, 0x9249249249249249L, 0xb11c709L << 36); //=0.285714285714285714300594501439
public final EFP LOG_C9 = new EFP (P, -3, 0xe38e38e38e38e1f4L, 0xa08ab7fL << 36); //=0.222222222222222216671173431320
public final EFP LOG_C11 = new EFP (P, -3, 0xba2e8ba2e8bba550L, 0x957b4b0L << 36); //=0.181818181818183118424115217462
public final EFP LOG_C13 = new EFP (P, -3, 0x9d89d89d88f3a6b4L, 0xb83ee9bL << 36); //=0.153846153845950485101802426447
public final EFP LOG_C15 = new EFP (P, -3, 0x88888888e97610a0L, 0x018bbc5L << 36); //=0.133333333355372176624252479880
public final EFP LOG_C17 = new EFP (P, -4, 0xf0f0f0b6e98b6c2fL, 0x176ec78L << 36); //=0.117647057134666354102829804155
public final EFP LOG_C19 = new EFP (P, -4, 0xd79442422528c14bL, 0xdacdc08L << 36); //=0.105263250011052968996816802164
public final EFP LOG_C21 = new EFP (P, -4, 0xc30a54423d395d6dL, 0xa2f5188L << 36); //=0.0952345450129114490041764123058
public final EFP LOG_C23 = new EFP (P, -4, 0xb247b3a940a7a020L, 0x5cb7483L << 36); //=0.0870508228327542823405094334272
public final EFP LOG_C25 = new EFP (P, -4, 0xa07d6fb3e1085165L, 0x68590abL << 36); //=0.0783642508287167052010634682520
public final EFP LOG_C27 = new EFP (P, -4, 0xb976c8a2f3029b2dL, 0xa0b471bL << 36); //=0.0905585932472388526925818403382
// 98.60bit
//------------------------------------------------------------------------
//log10
// echo read("efp.gp");eval("f(x)=log((1+x)/(1-x))/log(10)");efpchebyshev("LOG10_C",f,2*sqrt(2)-3,3-2*sqrt(2),27) | gp -q
public final EFP LOG10_C1 = new EFP (P, -1, 0xde5bd8a937287195L, 0x355baabL << 36); //=0.868588963806503655302257837837
public final EFP LOG10_C3 = new EFP (P, -2, 0x943d3b1b7a1af663L, 0x78e7cb7L << 36); //=0.289529654602167885100752619580
public final EFP LOG10_C5 = new EFP (P, -3, 0xb1e313ba9286c144L, 0x2a80513L << 36); //=0.173717792761300731060441762115
public final EFP LOG10_C7 = new EFP (P, -4, 0xfe1fd30a882e38abL, 0x7a44130L << 36); //=0.124084137686643379335356372423
public final EFP LOG10_C9 = new EFP (P, -4, 0xc5a6f979f823f1cbL, 0x86cedb8L << 36); //=0.0965098848673892926227943455482
public final EFP LOG10_C11 = new EFP (P, -4, 0xa1b729353f6480daL, 0x7d9f583L << 36); //=0.0789626330733190788064418159654
public final EFP LOG10_C13 = new EFP (P, -4, 0x88d60f2d0d7965b3L, 0x533de4bL << 36); //=0.0668145356773350395174370490118
public final EFP LOG10_C15 = new EFP (P, -5, 0xed2ec4f96bbfdbfdL, 0xfddb370L << 36); //=0.0579059309300049250489272107676
public final EFP LOG10_C17 = new EFP (P, -5, 0xd147624ebd9efe71L, 0xccd7fdfL << 36); //=0.0510934677257421907379148609296
public final EFP LOG10_C19 = new EFP (P, -5, 0xbb3fe99c80f7032eL, 0x107f05cL << 36); //=0.0457152486270027163909629543765
public final EFP LOG10_C21 = new EFP (P, -5, 0xa968eecf07930e0cL, 0xbd58cd0L << 36); //=0.0413598373856742928826627330520
public final EFP LOG10_C23 = new EFP (P, -5, 0x9ada242bfa9153a2L, 0x1833fc8L << 36); //=0.0378056920014027856718189387863
public final EFP LOG10_C25 = new EFP (P, -5, 0x8b665b489db905f7L, 0x74ec677L << 36); //=0.0340331617133939941648757175539
public final EFP LOG10_C27 = new EFP (P, -5, 0xa1178c2d7152670fL, 0x3d41c7cL << 36); //=0.0393290973361969170732439582255
// 96.83bit
public final EFP[] ACCURATE_LOG10_BASE = {
// echo read("efp.gp");p=0;for(n=0,39,q=floor(log(10)/log(2)*n);for(i=p+1,q-1,print(" null, //",i));p=q;efpmem([Str("10^",n)])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^0=1.00000000000000000000000000000
null, //1
null, //2
new EFP (P, 3, 0xa000000000000000L, 0x0000000L << 36), //=10^1=10.0000000000000000000000000000
null, //4
null, //5
new EFP (P, 6, 0xc800000000000000L, 0x0000000L << 36), //=10^2=100.000000000000000000000000000
null, //7
null, //8
new EFP (P, 9, 0xfa00000000000000L, 0x0000000L << 36), //=10^3=1000.00000000000000000000000000
null, //10
null, //11
null, //12
new EFP (P, 13, 0x9c40000000000000L, 0x0000000L << 36), //=10^4=10000.0000000000000000000000000
null, //14
null, //15
new EFP (P, 16, 0xc350000000000000L, 0x0000000L << 36), //=10^5=100000.000000000000000000000000
null, //17
null, //18
new EFP (P, 19, 0xf424000000000000L, 0x0000000L << 36), //=10^6=1000000.00000000000000000000000
null, //20
null, //21
null, //22
new EFP (P, 23, 0x9896800000000000L, 0x0000000L << 36), //=10^7=10000000.0000000000000000000000
null, //24
null, //25
new EFP (P, 26, 0xbebc200000000000L, 0x0000000L << 36), //=10^8=100000000.000000000000000000000
null, //27
null, //28
new EFP (P, 29, 0xee6b280000000000L, 0x0000000L << 36), //=10^9=1000000000.00000000000000000000
null, //30
null, //31
null, //32
new EFP (P, 33, 0x9502f90000000000L, 0x0000000L << 36), //=10^10=10000000000.0000000000000000000
null, //34
null, //35
new EFP (P, 36, 0xba43b74000000000L, 0x0000000L << 36), //=10^11=100000000000.000000000000000000
null, //37
null, //38
new EFP (P, 39, 0xe8d4a51000000000L, 0x0000000L << 36), //=10^12=1000000000000.00000000000000000
null, //40
null, //41
null, //42
new EFP (P, 43, 0x9184e72a00000000L, 0x0000000L << 36), //=10^13=10000000000000.0000000000000000
null, //44
null, //45
new EFP (P, 46, 0xb5e620f480000000L, 0x0000000L << 36), //=10^14=100000000000000.000000000000000
null, //47
null, //48
new EFP (P, 49, 0xe35fa931a0000000L, 0x0000000L << 36), //=10^15=1000000000000000.00000000000000
null, //50
null, //51
null, //52
new EFP (P, 53, 0x8e1bc9bf04000000L, 0x0000000L << 36), //=10^16=10000000000000000.0000000000000
null, //54
null, //55
new EFP (P, 56, 0xb1a2bc2ec5000000L, 0x0000000L << 36), //=10^17=100000000000000000.000000000000
null, //57
null, //58
new EFP (P, 59, 0xde0b6b3a76400000L, 0x0000000L << 36), //=10^18=1000000000000000000.00000000000
null, //60
null, //61
null, //62
new EFP (P, 63, 0x8ac7230489e80000L, 0x0000000L << 36), //=10^19=10000000000000000000.0000000000
null, //64
null, //65
new EFP (P, 66, 0xad78ebc5ac620000L, 0x0000000L << 36), //=10^20=100000000000000000000.000000000
null, //67
null, //68
new EFP (P, 69, 0xd8d726b7177a8000L, 0x0000000L << 36), //=10^21=1000000000000000000000.00000000
null, //70
null, //71
null, //72
new EFP (P, 73, 0x878678326eac9000L, 0x0000000L << 36), //=10^22=10000000000000000000000.0000000
null, //74
null, //75
new EFP (P, 76, 0xa968163f0a57b400L, 0x0000000L << 36), //=10^23=100000000000000000000000.000000
null, //77
null, //78
new EFP (P, 79, 0xd3c21bcecceda100L, 0x0000000L << 36), //=10^24=1000000000000000000000000.00000
null, //80
null, //81
null, //82
new EFP (P, 83, 0x84595161401484a0L, 0x0000000L << 36), //=10^25=10000000000000000000000000.0000
null, //84
null, //85
new EFP (P, 86, 0xa56fa5b99019a5c8L, 0x0000000L << 36), //=10^26=100000000000000000000000000.000
null, //87
null, //88
new EFP (P, 89, 0xcecb8f27f4200f3aL, 0x0000000L << 36), //=10^27=1000000000000000000000000000.00
null, //90
null, //91
null, //92
new EFP (P, 93, 0x813f3978f8940984L, 0x4000000L << 36), //=10^28=10000000000000000000000000000.0
null, //94
null, //95
new EFP (P, 96, 0xa18f07d736b90be5L, 0x5000000L << 36), //=10^29=100000000000000000000000000000
null, //97
null, //98
new EFP (P, 99, 0xc9f2c9cd04674edeL, 0xa400000L << 36), //=10^30=1.00000000000000000000000000000e+30
null, //100
null, //101
new EFP (P, 102, 0xfc6f7c4045812296L, 0x4d00000L << 36), //=10^31=1.00000000000000000000000000000e+31
null, //103
null, //104
null, //105
new EFP (P, 106, 0x9dc5ada82b70b59dL, 0xf020000L << 36), //=10^32=1.00000000000000000000000000000e+32
null, //107
null, //108
new EFP (P, 109, 0xc5371912364ce305L, 0x6c28000L << 36), //=10^33=1.00000000000000000000000000000e+33
null, //110
null, //111
new EFP (P, 112, 0xf684df56c3e01bc6L, 0xc732000L << 36), //=10^34=1.00000000000000000000000000000e+34
null, //113
null, //114
null, //115
new EFP (P, 116, 0x9a130b963a6c115cL, 0x3c7f400L << 36), //=10^35=1.00000000000000000000000000000e+35
null, //117
null, //118
new EFP (P, 119, 0xc097ce7bc90715b3L, 0x4b9f100L << 36), //=10^36=1.00000000000000000000000000000e+36
null, //120
null, //121
new EFP (P, 122, 0xf0bdc21abb48db20L, 0x1e86d40L << 36), //=10^37=1.00000000000000000000000000000e+37
null, //123
null, //124
null, //125
new EFP (P, 126, 0x96769950b50d88f4L, 0x1314448L << 36), //=10^38=1.00000000000000000000000000000e+38
null, //127
null, //128
new EFP (P, 129, 0xbc143fa4e250eb31L, 0x17d955aL << 36), //=10^39=1.00000000000000000000000000000e+39
};
//------------------------------------------------------------------------
//log1p
// echo read("efp.gp");efppub(["LOG1P_A","sqrt(2)/2-1"],["LOG1P_B","sqrt(2)-1"]) | gp -q
public final EFP LOG1P_A = new EFP (M, -2, 0x95f619980c4336f7L, 0x4d04ecaL << 36); //<sqrt(2)/2-1=-0.292893218813452475599155637895
public final EFP LOG1P_B = new EFP (P, -2, 0xd413cccfe7799211L, 0x65f626dL << 36); //>sqrt(2)-1=0.414213562373095048801688724210
//------------------------------------------------------------------------
//log2
// echo read("efp.gp");eval("f(x)=log((1+x)/(1-x))/log(2)");efpchebyshev("LOG2_C",f,2*sqrt(2)-3,3-2*sqrt(2),27) | gp -q
public final EFP LOG2_C1 = new EFP (P, 1, 0xb8aa3b295c17f0bbL, 0xbe87fedL << 36); //=2.88539008177792681471984936198
public final EFP LOG2_C3 = new EFP (P, -1, 0xf6384ee1d01feba4L, 0xfe0ab04L << 36); //=0.961796693925975604906616477151
public final EFP LOG2_C5 = new EFP (P, -1, 0x93bb62877cdff3c9L, 0x651237dL << 36); //=0.577078016355585362943937299454
public final EFP LOG2_C7 = new EFP (P, -2, 0xd30bb153d6f6c9fbL, 0xeda6121L << 36); //=0.412198583111132402124303236615
public final EFP LOG2_C9 = new EFP (P, -2, 0xa42589ebe015469bL, 0xde296e2L << 36); //=0.320598897975325193627068255683
public final EFP LOG2_C11 = new EFP (P, -2, 0x864d424ca0127799L, 0x7cdb742L << 36); //=0.262308189252540677191282011266
public final EFP LOG2_C13 = new EFP (P, -3, 0xe347ab469770ad93L, 0x0c89676L << 36); //=0.221953083213393290074079579936
public final EFP LOG2_C15 = new EFP (P, -3, 0xc4f9d8b532564b9eL, 0x7d50b7aL << 36); //=0.192359338816990450904061345775
public final EFP LOG2_C17 = new EFP (P, -3, 0xadcd64b1c6112030L, 0x2abb956L << 36); //=0.169728825903363689895336947859
public final EFP LOG2_C19 = new EFP (P, -3, 0x9b81e9e58a334402L, 0x0adf93dL << 36); //=0.151862768778801240948586652949
public final EFP LOG2_C21 = new EFP (P, -3, 0x8cb11e7e743a9994L, 0xf74da62L << 36); //=0.137394405811444109070588133256
public final EFP LOG2_C23 = new EFP (P, -3, 0x809a15f248e3a311L, 0x83d14aaL << 36); //=0.125587790406118348750302928355
public final EFP LOG2_C25 = new EFP (P, -4, 0xe789c1589b85b20fL, 0xbe84fc9L << 36); //=0.113055716053568431590620272062
public final EFP LOG2_C27 = new EFP (P, -3, 0x85c8b3f2b1daf78cL, 0x52db8eeL << 36); //=0.130648433387672262093665382456
// 96.81bit
//------------------------------------------------------------------------
//lgamma
// echo read("efp.gp");n=14;c=vector(n,k,bernfrac(2*k)/(2*k*(2*k-1)));for(k=1,n,efppub([Str("LGAMMA_C",k),Str(c[k])]));efpclose(lngamma,"(x-1/2)*log(x)-x+log(2*Pi)/2+sum(k=1,n,c[k]/x^(2*k-1))",13,100) | gp -q
public final EFP LGAMMA_C1 = new EFP (P, -4, 0xaaaaaaaaaaaaaaaaL, 0xaaaaaabL << 36); //>1/12=0.0833333333333333333333333333333
public final EFP LGAMMA_C2 = new EFP (M, -9, 0xb60b60b60b60b60bL, 0x60b60b6L << 36); //>-1/360=-0.00277777777777777777777777777778
public final EFP LGAMMA_C3 = new EFP (P, -11, 0xd00d00d00d00d00dL, 0x00d00d0L << 36); //<1/1260=7.93650793650793650793650793651e-4
public final EFP LGAMMA_C4 = new EFP (M, -11, 0x9c09c09c09c09c09L, 0xc09c09cL << 36); //>-1/1680=-5.95238095238095238095238095238e-4
public final EFP LGAMMA_C5 = new EFP (P, -11, 0xdca8f158c7f91ab8L, 0x7539c03L << 36); //<1/1188=8.41750841750841750841750841751e-4
public final EFP LGAMMA_C6 = new EFP (M, -10, 0xfb5586ccc9e3e40fL, 0xb5586cdL << 36); //<-691/360360=-0.00191752691752691752691752691753
public final EFP LGAMMA_C7 = new EFP (P, -8, 0xd20d20d20d20d20dL, 0x20d20d2L << 36); //<1/156=0.00641025641025641025641025641026
public final EFP LGAMMA_C8 = new EFP (M, -6, 0xf21436587a9cbee1L, 0x0325477L << 36); //<-3617/122400=-0.0295506535947712418300653594771
public final EFP LGAMMA_C9 = new EFP (P, -3, 0xb7f4b1c0f033ffd0L, 0xc3b7f4bL << 36); //<43867/244188=0.179644372368830573164938490016
public final EFP LGAMMA_C10 = new EFP (M, 0, 0xb23b3808c0f9cf6dL, 0xedce731L << 36); //>-174611/125400=-1.39243221690590111642743221691
public final EFP LGAMMA_C11 = new EFP (P, 3, 0xd672219167002d3aL, 0x7a9c886L << 36); //<77683/5796=13.4028640441683919944789510007
public final EFP LGAMMA_C12 = new EFP (M, 7, 0x9cd9292e6660d55bL, 0x3f712ecL << 36); //<-236364091/1506960=-156.848284626002017306365132452
public final EFP LGAMMA_C13 = new EFP (P, 11, 0x8911a740da740da7L, 0x40da741L << 36); //>657931/300=2193.10333333333333333333333333
public final EFP LGAMMA_C14 = new EFP (M, 15, 0x8d0cc570e255bf59L, 0xff6eec2L << 36); //>-3392780147/93960=-36108.7712537249893571732652192
// 92.41bit
// echo read("efp.gp");efppub(["LOGTWOPI_2",log(2*Pi)/2]) | gp -q
public final EFP LOGTWOPI_2 = new EFP (P, -1, 0xeb3f8e4325f5a534L, 0x94bc900L << 36); //<0.918938533204672741780329736406
//------------------------------------------------------------------------
//setapery
public final EFP[] ROUNDED_APERY = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([zeta(3),rm,strrmf(rm,"ζ(3)")])) | gp -q
new EFP (P, 0, 0x99dd0027803109c1L, 0xb8b8ae3L << 36), //>RN(ζ(3))=1.20205690315959428539973816151
new EFP (P, 0, 0x99dd0027803109c1L, 0xb8b8ae2L << 36), //<RZ(ζ(3))=1.20205690315959428539973816151
new EFP (P, 0, 0x99dd0027803109c1L, 0xb8b8ae2L << 36), //<RM(ζ(3))=1.20205690315959428539973816151
new EFP (P, 0, 0x99dd0027803109c1L, 0xb8b8ae3L << 36), //>RP(ζ(3))=1.20205690315959428539973816151
};
//------------------------------------------------------------------------
//setcatalan
public final EFP[] ROUNDED_CATALAN = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([Catalan,rm,strrmf(rm,"G")])) | gp -q
new EFP (P, -1, 0xea7cb89f409ae845L, 0x215822eL << 36), //<RN(G)=0.915965594177219015054603514932
new EFP (P, -1, 0xea7cb89f409ae845L, 0x215822eL << 36), //<RZ(G)=0.915965594177219015054603514932
new EFP (P, -1, 0xea7cb89f409ae845L, 0x215822eL << 36), //<RM(G)=0.915965594177219015054603514932
new EFP (P, -1, 0xea7cb89f409ae845L, 0x215822fL << 36), //>RP(G)=0.915965594177219015054603514932
};
//------------------------------------------------------------------------
//seteuler
public final EFP[] ROUNDED_EULER = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([Euler,rm,strrmf(rm,"γ")])) | gp -q
new EFP (P, -1, 0x93c467e37db0c7a4L, 0xd1be3f8L << 36), //<RN(γ)=0.577215664901532860606512090082
new EFP (P, -1, 0x93c467e37db0c7a4L, 0xd1be3f8L << 36), //<RZ(γ)=0.577215664901532860606512090082
new EFP (P, -1, 0x93c467e37db0c7a4L, 0xd1be3f8L << 36), //<RM(γ)=0.577215664901532860606512090082
new EFP (P, -1, 0x93c467e37db0c7a4L, 0xd1be3f9L << 36), //>RP(γ)=0.577215664901532860606512090082
};
//------------------------------------------------------------------------
//setnapier
public final EFP[] ROUNDED_NAPIER = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([exp(1),rm,strrmf(rm,"e")])) | gp -q
new EFP (P, 1, 0xadf85458a2bb4a9aL, 0xafdc562L << 36), //<RN(e)=2.71828182845904523536028747135
new EFP (P, 1, 0xadf85458a2bb4a9aL, 0xafdc562L << 36), //<RZ(e)=2.71828182845904523536028747135
new EFP (P, 1, 0xadf85458a2bb4a9aL, 0xafdc562L << 36), //<RM(e)=2.71828182845904523536028747135
new EFP (P, 1, 0xadf85458a2bb4a9aL, 0xafdc563L << 36), //>RP(e)=2.71828182845904523536028747135
};
//------------------------------------------------------------------------
//setpi
public final EFP[] ROUNDED_PI = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([Pi,rm,strrmf(rm,"π")])) | gp -q
new EFP (P, 1, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //>RN(π)=3.14159265358979323846264338328
new EFP (P, 1, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //<RZ(π)=3.14159265358979323846264338328
new EFP (P, 1, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //<RM(π)=3.14159265358979323846264338328
new EFP (P, 1, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //>RP(π)=3.14159265358979323846264338328
};
public final EFP[] ROUNDED_NEGPI = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([-Pi,rm,strrmf(rm,"-π")])) | gp -q
new EFP (M, 1, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //<RN(-π)=-3.14159265358979323846264338328
new EFP (M, 1, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //>RZ(-π)=-3.14159265358979323846264338328
new EFP (M, 1, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //<RM(-π)=-3.14159265358979323846264338328
new EFP (M, 1, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //>RP(-π)=-3.14159265358979323846264338328
};
public final EFP[] ROUNDED_PI_2 = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([Pi/2,rm,strrmf(rm,"π/2")])) | gp -q
new EFP (P, 0, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //>RN(π/2)=1.57079632679489661923132169164
new EFP (P, 0, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //<RZ(π/2)=1.57079632679489661923132169164
new EFP (P, 0, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //<RM(π/2)=1.57079632679489661923132169164
new EFP (P, 0, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //>RP(π/2)=1.57079632679489661923132169164
};
public final EFP[] ROUNDED_NEGPI_2 = {
// echo read("efp.gp");for(rm=RN,RP,efpmem([-Pi/2,rm,strrmf(rm,"-π/2")])) | gp -q
new EFP (M, 0, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //<RN(-π/2)=-1.57079632679489661923132169164
new EFP (M, 0, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //>RZ(-π/2)=-1.57079632679489661923132169164
new EFP (M, 0, 0xc90fdaa22168c234L, 0xc4c6629L << 36), //<RM(-π/2)=-1.57079632679489661923132169164
new EFP (M, 0, 0xc90fdaa22168c234L, 0xc4c6628L << 36), //>RP(-π/2)=-1.57079632679489661923132169164
};
//------------------------------------------------------------------------
//sinh
// echo read("efp.gp");efpchebyshev("SINH_C",sinh,-1/8,1/8,13) | gp -q
public final EFP SINH_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP SINH_C3 = new EFP (P, -3, 0xaaaaaaaaaaaaaaaaL, 0xaaa8d3bL << 36); //=0.166666666666666666666666286213
public final EFP SINH_C5 = new EFP (P, -7, 0x8888888888888888L, 0xd801ef0L << 36); //=0.00833333333333333333359629146849
public final EFP SINH_C7 = new EFP (P, -13, 0xd00d00d00d00b865L, 0xe08a011L << 36); //=1.98412698412698332559486447243e-4
public final EFP SINH_C9 = new EFP (P, -19, 0xb8ef1d2ab9d6b01dL, 0x54d1cf9L << 36); //=2.75573192241112619181294637312e-6
public final EFP SINH_C11 = new EFP (P, -26, 0xd7322aa84ab102a5L, 0xf1b3e2aL << 36); //=2.50521073350812546986376674718e-8
public final EFP SINH_C13 = new EFP (P, -33, 0xb09ecdc339d62e71L, 0x8115862L << 36); //=1.60635251803005018933289429222e-10
// 92.06bit
//------------------------------------------------------------------------
//sqrt1pm1
// echo read("efp.gp");eval("sqrt1pm1(x)=sqrt(1+x)-1");efppoly("SQRT1PM1_C",sqrt1pm1,sum(n=1,11,eval("efp((-1)^(n-1)/2^(2*n-1)*factorial(2*n-2)/factorial(n-1)/factorial(n))*x^n")),-1/256,1/256) | gp -q
public final EFP SQRT1PM1_C1 = new EFP (P, -1, 0x8000000000000000L, 0x0000000L << 36); //=0.500000000000000000000000000000
public final EFP SQRT1PM1_C2 = new EFP (M, -3, 0x8000000000000000L, 0x0000000L << 36); //=-0.125000000000000000000000000000
public final EFP SQRT1PM1_C3 = new EFP (P, -4, 0x8000000000000000L, 0x0000000L << 36); //=0.0625000000000000000000000000000
public final EFP SQRT1PM1_C4 = new EFP (M, -5, 0xa000000000000000L, 0x0000000L << 36); //=-0.0390625000000000000000000000000
public final EFP SQRT1PM1_C5 = new EFP (P, -6, 0xe000000000000000L, 0x0000000L << 36); //=0.0273437500000000000000000000000
public final EFP SQRT1PM1_C6 = new EFP (M, -6, 0xa800000000000000L, 0x0000000L << 36); //=-0.0205078125000000000000000000000
public final EFP SQRT1PM1_C7 = new EFP (P, -6, 0x8400000000000000L, 0x0000000L << 36); //=0.0161132812500000000000000000000
public final EFP SQRT1PM1_C8 = new EFP (M, -7, 0xd680000000000000L, 0x0000000L << 36); //=-0.0130920410156250000000000000000
public final EFP SQRT1PM1_C9 = new EFP (P, -7, 0xb2c0000000000000L, 0x0000000L << 36); //=0.0109100341796875000000000000000
public final EFP SQRT1PM1_C10 = new EFP (M, -7, 0x97f0000000000000L, 0x0000000L << 36); //=-0.00927352905273437500000000000000
public final EFP SQRT1PM1_C11 = new EFP (P, -7, 0x8338000000000000L, 0x0000000L << 36); //=0.00800895690917968750000000000000
// 94.15bit
//------------------------------------------------------------------------
//tan
// echo read("efp.gp");efpchebyshev("TAN_C",tan,-Pi/8,Pi/8,33) | gp -q
public final EFP TAN_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP TAN_C3 = new EFP (P, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaaa29L << 36); //=0.333333333333333333333333320240
public final EFP TAN_C5 = new EFP (P, -3, 0x8888888888888888L, 0x88a184aL << 36); //=0.133333333333333333333338500055
public final EFP TAN_C7 = new EFP (P, -5, 0xdd0dd0dd0dd0dd0dL, 0x88b7614L << 36); //=0.0539682539682539682530133941980
public final EFP TAN_C9 = new EFP (P, -6, 0xb327a4416087cfd4L, 0xf296a40L << 36); //=0.0218694885361552029227142001132
public final EFP TAN_C11 = new EFP (P, -7, 0x91371aaf3611c538L, 0x2426582L << 36); //=0.00886323552990218979030206294531
public final EFP TAN_C13 = new EFP (P, -9, 0xeb69e870ac055209L, 0xe907d72L << 36); //=0.00359212803657279090096708386671
public final EFP TAN_C15 = new EFP (P, -10, 0xbed1b229560565dcL, 0x00f1ae8L << 36); //=0.00145583438704125904461672464275
public final EFP TAN_C17 = new EFP (P, -11, 0x9aac124127c7ff13L, 0xd521318L << 36); //=5.90027441184109978354508200940e-4
public final EFP TAN_C19 = new EFP (P, -13, 0xfabebb506d37becdL, 0x7712cf3L << 36); //=2.39129110038142690434570082910e-4
public final EFP TAN_C21 = new EFP (P, -14, 0xcb3f13fd9e491aeeL, 0xb4ecd04L << 36); //=9.69154352110963087881307906904e-5
public final EFP TAN_C23 = new EFP (P, -15, 0xa4be2f633cfa3709L, 0x2c90e93L << 36); //=3.92777706570966668331421947349e-5
public final EFP TAN_C25 = new EFP (P, -16, 0x859266daac37850cL, 0xcb7028bL << 36); //=1.59230091488831402827144234198e-5
public final EFP TAN_C27 = new EFP (P, -18, 0xd7bbef57337218a7L, 0x4e73cafL << 36); //=6.42937781805301206613497744639e-6
public final EFP TAN_C29 = new EFP (P, -19, 0xb53ca49c91cc2ce0L, 0x289f9c2L << 36); //=2.70064006408567688822953124006e-6
public final EFP TAN_C31 = new EFP (P, -21, 0xe1a12ebdc4e0aba8L, 0x6c3a02cL << 36); //=8.40535832440159769242845888336e-7
public final EFP TAN_C33 = new EFP (P, -21, 0xc9eb997dffc9ad78L, 0x01e7a8fL << 36); //=7.52211775090032809509059318805e-7
// 96.07bit
// echo read("efp.gp");efpchebyshev("TAN7_C",tan,-Pi/256,Pi/256,11) | gp -q
public final EFP TAN7_C1 = new EFP (P, -1, 0xffffffffffffffffL, 0xfffffffL << 36); //=0.999999999999999999999999999798
public final EFP TAN7_C3 = new EFP (P, -2, 0xaaaaaaaaaaaaaaaaL, 0xaae677dL << 36); //=0.333333333333333333333358066592
public final EFP TAN7_C5 = new EFP (P, -3, 0x8888888888888827L, 0x9679788L << 36); //=0.133333333333333332019476238145
public final EFP TAN7_C7 = new EFP (P, -5, 0xdd0dd0dd0e579281L, 0x2b6ed88L << 36); //=0.0539682539682838796143366171397
public final EFP TAN7_C9 = new EFP (P, -6, 0xb327a413e1bf5c5dL, 0x5ebd854L << 36); //=0.0218694882051337203598644737927
public final EFP TAN7_C11 = new EFP (P, -7, 0x913e7ab6529ea4edL, 0x6ea7f3bL << 36); //=0.00886499389279463946555596271447
// 92.00bit
public final EFP[] TAN7_T = {
// echo read("efp.gp");for(n=0,63,efpmem([Str("tan(",n,"*Pi/128)")])) | gp -q
new EFP (), //=tan(0*Pi/128)=0.00000000000000000000000000000
new EFP (P, -6, 0xc91a3123d48f7fddL, 0x894dd4bL << 36), //>tan(1*Pi/128)=0.0245486221089254441045797539609
new EFP (P, -5, 0xc9393c51d88b101aL, 0xda13cefL << 36), //>tan(2*Pi/128)=0.0491268497694672541053433212713
new EFP (P, -4, 0x9711ce67f9c18b0fL, 0x459611fL << 36), //<tan(3*Pi/128)=0.0737644315224492888923977217788
new EFP (P, -4, 0xc9b5dc62d96d130fL, 0xa0a9ed1L << 36), //<tan(4*Pi/128)=0.0984914033571642530771975212913
new EFP (P, -4, 0xfc98c1d46dcf46edL, 0xdf92d54L << 36), //>tan(5*Pi/128)=0.123338236136738677947004130613
new EFP (P, -3, 0x97e5639d3032012cL, 0xfb5a747L << 36), //>tan(6*Pi/128)=0.148335987538347428753676511487
new EFP (P, -3, 0xb1ae4c867069ae62L, 0x1454a67L << 36), //<tan(7*Pi/128)=0.173516460137855760223211669841
new EFP (P, -3, 0xcbafaf02a98ac03dL, 0xeba6ce9L << 36), //>tan(8*Pi/128)=0.198912367379658006911597622645
new EFP (P, -3, 0xe5f2675a5a679294L, 0xb7c658cL << 36), //<tan(9*Pi/128)=0.224557509317129320242538359449
new EFP (P, -2, 0x803fd3ac3135715aL, 0x6d6c3c9L << 36), //>tan(10*Pi/128)=0.250486960191305461595702160125
new EFP (P, -2, 0x8db081e9acbf49cbL, 0xda4f636L << 36), //<tan(11*Pi/128)=0.276737270140414338944617036500
new EFP (P, -2, 0x9b5041aae31ede28L, 0xfb2e402L << 36), //<tan(12*Pi/128)=0.303346683607342391675883946941
new EFP (P, -2, 0xa924570b80d8bb7dL, 0x2ec70f1L << 36), //>tan(13*Pi/128)=0.330355377344333924545492908196
new EFP (P, -2, 0xb7324fbebc324978L, 0xe945dc4L << 36), //>tan(14*Pi/128)=0.357805721314524104672487743774
new EFP (P, -2, 0xc5800cb59e810e8cL, 0xd859b1fL << 36), //>tan(15*Pi/128)=0.385742566271121235453424624094
new EFP (P, -2, 0xd413cccfe7799211L, 0x65f626dL << 36), //>tan(16*Pi/128)=0.414213562373095048801688724210
new EFP (P, -2, 0xe2f438c2f33db07fL, 0xd5fe854L << 36), //>tan(17*Pi/128)=0.443269513890864334105794704813
new EFP (P, -2, 0xf228706939f3d282L, 0xa45e2bdL << 36), //>tan(18*Pi/128)=0.472964775891319928124438237973
new EFP (P, -1, 0x80dc0cdad3e7ba17L, 0xf9dd77dL << 36), //<tan(19*Pi/128)=0.503357699799294262733245622354
new EFP (P, -1, 0x88d5b8c841a75c35L, 0x36865c3L << 36), //<tan(20*Pi/128)=0.534511135950791641089685961295
new EFP (P, -1, 0x9105af7823c1286bL, 0xb5bee4cL << 36), //<tan(21*Pi/128)=0.566493002730343981076271533491
new EFP (P, -1, 0x9970c44823ffe5deL, 0x977bc33L << 36), //>tan(22*Pi/128)=0.599376933681923766271389869014
new EFP (P, -1, 0xa21c36dce72ed4b0L, 0x5750623L << 36), //<tan(23*Pi/128)=0.633243016177569127534323438301
new EFP (P, -1, 0xab0dc155bfcc82f5L, 0x18a42e5L << 36), //<tan(24*Pi/128)=0.668178637919298919997757686523
new EFP (P, -1, 0xb44ba8a3a8edb143L, 0x9bc2d44L << 36), //>tan(25*Pi/128)=0.704279460865044244278980120940
new EFP (P, -1, 0xbddccf694c8674abL, 0x158e376L << 36), //<tan(26*Pi/128)=0.741650546272035369581266691172
new EFP (P, -1, 0xc7c8cbdfc2f75687L, 0x408e56bL << 36), //>tan(27*Pi/128)=0.780407659653943632354200451174
new EFP (P, -1, 0xd218015721427e59L, 0x247f018L << 36), //<tan(28*Pi/128)=0.820678790828660330972281985331
new EFP (P, -1, 0xdcd3be0c60d7916fL, 0xc7e578dL << 36), //<tan(29*Pi/128)=0.862605932256739891215212659727
new EFP (P, -1, 0xe8065e39c269718dL, 0xcad85e6L << 36), //<tan(30*Pi/128)=0.906347169019147157946142717269
new EFP (P, -1, 0xf3bb757e48b83322L, 0xbd576feL << 36), //<tan(31*Pi/128)=0.952079146700925348585664892261
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=tan(32*Pi/128)=1.00000000000000000000000000000
new EFP (P, 0, 0x86714e8441e4ca93L, 0x0c4cf4eL << 36), //<tan(33*Pi/128)=1.05033284623985985679635153480
new EFP (P, 0, 0x8d39eaa93c625b28L, 0xd9816cdL << 36), //<tan(34*Pi/128)=1.10332997573347566410053775985
new EFP (P, 0, 0x946337ed7c784903L, 0x22c9598L << 36), //<tan(35*Pi/128)=1.15927790733343474872256568270
new EFP (P, 0, 0x9bf7ec6c3b03ef3cL, 0x0d29346L << 36), //<tan(36*Pi/128)=1.21850352558797634479547723062
new EFP (P, 0, 0xa4044fc5fa1663f0L, 0xd6fd49aL << 36), //>tan(37*Pi/128)=1.28138158003655455554560477142
new EFP (P, 0, 0xac96888a17d2a96aL, 0x085e3bcL << 36), //<tan(38*Pi/128)=1.34834391348672015293303458505
new EFP (P, 0, 0xb5befc31328ffd5eL, 0x4284584L << 36), //>tan(39*Pi/128)=1.41989090349409245362395560849
new EFP (P, 0, 0xbf90c712d3a30a83L, 0x3f4d2a9L << 36), //<tan(40*Pi/128)=1.49660576266548901760113513494
new EFP (P, 0, 0xca2253a310915399L, 0x7dd7470L << 36), //<tan(41*Pi/128)=1.57917256796020898378319991425
new EFP (P, 0, 0xd58e1aec53a74f24L, 0x82443ddL << 36), //>tan(42*Pi/128)=1.66839920558350704845076179161
new EFP (P, 0, 0xe1f39c0435e07a14L, 0x725b359L << 36), //>tan(43*Pi/128)=1.76524687009419151361905127152
new EFP (P, 0, 0xef789db9e0a0310fL, 0xb3e75c7L << 36), //<tan(44*Pi/128)=1.87086841178938948108520133434
new EFP (P, 0, 0xfe4ad5d6b67a51b7L, 0x127cf35L << 36), //>tan(45*Pi/128)=1.98665879234336500189577900470
new EFP (P, 1, 0x87510eb8b7dfb97cL, 0xe6cb464L << 36), //>tan(46*Pi/128)=2.11432235754864059006900220864
new EFP (P, 1, 0x9061b6353f9c6ed6L, 0xe02bffdL << 36), //<tan(47*Pi/128)=2.25596385192915864999808013935
new EFP (P, 1, 0x9a827999fcef3242L, 0x2cbec4eL << 36), //>tan(48*Pi/128)=2.41421356237309504880168872421
new EFP (P, 1, 0xa5e9ec3ff0327cfaL, 0x748ca31L << 36), //<tan(49*Pi/128)=2.59240251773807256365450014380
new EFP (P, 1, 0xb2de3664128a386bL, 0x2a51effL << 36), //>tan(50*Pi/128)=2.79481277249047679426344220502
new EFP (P, 1, 0xc1bb136b87edc0d9L, 0xae371daL << 36), //<tan(51*Pi/128)=3.02704320431777423041156207831
new EFP (P, 1, 0xd2facf483006e648L, 0x5eb2f29L << 36), //<tan(52*Pi/128)=3.29655820893832042687815421683
new EFP (P, 1, 0xe7442b29893f385dL, 0xfd8e2a3L << 36), //<tan(53*Pi/128)=3.61353568130742843584614061971
new EFP (P, 1, 0xff80982f66c6df3bL, 0x0194e40L << 36), //<tan(54*Pi/128)=3.99222378377008442376610482881
new EFP (P, 2, 0x8e80a1f38ab2f611L, 0x8c89790L << 36), //<tan(55*Pi/128)=4.45320222441441050038054277672
new EFP (P, 2, 0xa0dff712123b8844L, 0x1c1bfb5L << 36), //>tan(56*Pi/128)=5.02733949212584810451497507106
new EFP (P, 2, 0xb86ba8c8460d85deL, 0x3af4952L << 36), //<tan(57*Pi/128)=5.76314200511880934875009607987
new EFP (P, 2, 0xd7b9fa6519887651L, 0xc68dc64L << 36), //>tan(58*Pi/128)=6.74145240541498828250998494514
new EFP (P, 3, 0x81b97d9b5c3f0e2bL, 0x5c8997bL << 36), //>tan(59*Pi/128)=8.10778580367690752547921378823
new EFP (P, 3, 0xa27362cad7ee626aL, 0x3b5d4f3L << 36), //>tan(60*Pi/128)=10.1531703876088604621071476634
new EFP (P, 3, 0xd8e81e01e97bf967L, 0xe518f26L << 36), //>tan(61*Pi/128)=13.5566692423524258539123676121
new EFP (P, 4, 0xa2d7ff6900daa7f2L, 0x48ca591L << 36), //>tan(62*Pi/128)=20.3554676249871881783196386481
new EFP (P, 5, 0xa2f122af255539e2L, 0x447b82dL << 36), //>tan(63*Pi/128)=40.7354838720833018007438570502
}; //TAN7_T
// echo read("efp.gp");efppub(["TAN7_X",Pi/256],["TAN7_Y",128/Pi]) | gp -q
public final EFP TAN7_X = new EFP (P, -7, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>0.0122718463030851298377447007159
public final EFP TAN7_Y = new EFP (P, 5, 0xa2f9836e4e441529L, 0xfc2757dL << 36); //<40.7436654315252059568342434234
// echo read("efp.gp");efppub2(["TAN7_Z",Pi/128]) | gp -q
public final EFP TAN7_Z = new EFP (P, -6, 0xc90fdaa22168c234L, 0xc4c6629L << 36); //>0.0245436926061702596754894014319
public final EFP TAN7_ZA = new EFP (M, -99, 0x8fe47c65dadfb63eL, 0xeeb3067L << 36); //>-1.77361228242534392160702072478e-30
// echo read("efp.gp");efpchebyshev("TAN8_C",tan,-1/8,1/8,21) | gp -q
public final EFP TAN8_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP TAN8_C3 = new EFP (P, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaaa02L << 36); //=0.333333333333333333333333316302
public final EFP TAN8_C5 = new EFP (P, -3, 0x8888888888888888L, 0x8911d7aL << 36); //=0.133333333333333333333361728159
public final EFP TAN8_C7 = new EFP (P, -5, 0xdd0dd0dd0dd0dd07L, 0x61e9558L << 36); //=0.0539682539682539682321710253282
public final EFP TAN8_C9 = new EFP (P, -6, 0xb327a4416087e508L, 0x1c05687L << 36); //=0.0218694885361552121166839881208
public final EFP TAN8_C11 = new EFP (P, -7, 0x91371aaf35e647d2L, 0x9bd741cL << 36); //=0.00886323552989977561974347061451
public final EFP TAN8_C13 = new EFP (P, -9, 0xeb69e8711de22b89L, 0x087ca38L << 36); //=0.00359212803697731245050214719004
public final EFP TAN8_C15 = new EFP (P, -10, 0xbed1b1c7d2310830L, 0x871a5a7L << 36); //=0.00145583434269658967823487137542
public final EFP TAN8_C17 = new EFP (P, -11, 0x9aac48a4e5208639L, 0x1e07899L << 36); //=5.90030607075966038694572991909e-4
public final EFP TAN8_C19 = new EFP (P, -13, 0xfa98b158590773f4L, 0xfa72a4eL << 36); //=2.38987403937913425869285486804e-4
public final EFP TAN8_C21 = new EFP (P, -14, 0xd2cd5a371c03b30eL, 0x42cac1cL << 36); //=1.00518301880738120215681257530e-4
// 97.78bit
//------------------------------------------------------------------------
//tanh
// echo read("efp.gp");efpchebyshev("TANH_C",tanh,-1/4,1/4,27) | gp -q
public final EFP TANH_C1 = new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36); //=1.00000000000000000000000000000
public final EFP TANH_C3 = new EFP (M, -2, 0xaaaaaaaaaaaaaaaaL, 0xaaaaa63L << 36); //=-0.333333333333333333333333326097
public final EFP TANH_C5 = new EFP (P, -3, 0x8888888888888888L, 0x88710efL << 36); //=0.133333333333333333333328478820
public final EFP TANH_C7 = new EFP (M, -5, 0xdd0dd0dd0dd0dd0dL, 0x5eb1c0fL << 36); //=-0.0539682539682539682524572379576
public final EFP TANH_C9 = new EFP (P, -6, 0xb327a4416087cefcL, 0x3226807L << 36); //=0.0218694885361552025555225187555
public final EFP TANH_C11 = new EFP (M, -7, 0x91371aaf36115c72L, 0x1057753L << 36); //=-0.00886323552990216707111881201890
public final EFP TANH_C13 = new EFP (P, -9, 0xeb69e870ab51ac87L, 0xbc93275L << 36); //=0.00359212803657029780471621830554
public final EFP TANH_C15 = new EFP (M, -10, 0xbed1b2291c9448e3L, 0x025162cL << 36); //=-0.00145583438693922182445491583494
public final EFP TANH_C17 = new EFP (P, -11, 0x9aac122e2d563679L, 0x7f53bd9L << 36); //=5.90027436868944449269862181218e-4
public final EFP TANH_C19 = new EFP (M, -13, 0xfabeb45554b7f61dL, 0xed9a4e5L << 36); //=-2.39129008453513280762151644074e-4
public final EFP TANH_C21 = new EFP (P, -14, 0xcb3e00a83f1f1703L, 0x594e12fL << 36); //=9.69134318963417667915644434482e-5
public final EFP TANH_C23 = new EFP (M, -15, 0xa4a40e3c50e76340L, 0x922c2ccL << 36); //=-3.92534356637388369814427537735e-5
public final EFP TANH_C25 = new EFP (P, -16, 0x83c53e40035eb57fL, 0x80a5513L << 36); //=1.57082654369358742080398893111e-5
public final EFP TANH_C27 = new EFP (M, -18, 0xb47b24ce1d988d76L, 0xa0271b7L << 36); //=-5.37875385140937293082445934922e-6
// 97.70bit
//------------------------------------------------------------------------
//toString
public final EFP[] EFP_TEN_P16QR = {
// echo read("efp.gp");for(i=0,50,q=eval("i>>4");r=bitand(i,15);efpmem([Str("10^(16^",q,"*",r,")")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(16^0*0)=1.00000000000000000000000000000
new EFP (P, 3, 0xa000000000000000L, 0x0000000L << 36), //=10^(16^0*1)=10.0000000000000000000000000000
new EFP (P, 6, 0xc800000000000000L, 0x0000000L << 36), //=10^(16^0*2)=100.000000000000000000000000000
new EFP (P, 9, 0xfa00000000000000L, 0x0000000L << 36), //=10^(16^0*3)=1000.00000000000000000000000000
new EFP (P, 13, 0x9c40000000000000L, 0x0000000L << 36), //=10^(16^0*4)=10000.0000000000000000000000000
new EFP (P, 16, 0xc350000000000000L, 0x0000000L << 36), //=10^(16^0*5)=100000.000000000000000000000000
new EFP (P, 19, 0xf424000000000000L, 0x0000000L << 36), //=10^(16^0*6)=1000000.00000000000000000000000
new EFP (P, 23, 0x9896800000000000L, 0x0000000L << 36), //=10^(16^0*7)=10000000.0000000000000000000000
new EFP (P, 26, 0xbebc200000000000L, 0x0000000L << 36), //=10^(16^0*8)=100000000.000000000000000000000
new EFP (P, 29, 0xee6b280000000000L, 0x0000000L << 36), //=10^(16^0*9)=1000000000.00000000000000000000
new EFP (P, 33, 0x9502f90000000000L, 0x0000000L << 36), //=10^(16^0*10)=10000000000.0000000000000000000
new EFP (P, 36, 0xba43b74000000000L, 0x0000000L << 36), //=10^(16^0*11)=100000000000.000000000000000000
new EFP (P, 39, 0xe8d4a51000000000L, 0x0000000L << 36), //=10^(16^0*12)=1000000000000.00000000000000000
new EFP (P, 43, 0x9184e72a00000000L, 0x0000000L << 36), //=10^(16^0*13)=10000000000000.0000000000000000
new EFP (P, 46, 0xb5e620f480000000L, 0x0000000L << 36), //=10^(16^0*14)=100000000000000.000000000000000
new EFP (P, 49, 0xe35fa931a0000000L, 0x0000000L << 36), //=10^(16^0*15)=1000000000000000.00000000000000
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(16^1*0)=1.00000000000000000000000000000
new EFP (P, 53, 0x8e1bc9bf04000000L, 0x0000000L << 36), //=10^(16^1*1)=10000000000000000.0000000000000
new EFP (P, 106, 0x9dc5ada82b70b59dL, 0xf020000L << 36), //=10^(16^1*2)=1.00000000000000000000000000000e+32
new EFP (P, 159, 0xaf298d050e4395d6L, 0x9670b13L << 36), //>10^(16^1*3)=1.00000000000000000000000000000e+48
new EFP (P, 212, 0xc2781f49ffcfa6d5L, 0x3cbf6b7L << 36), //<10^(16^1*4)=1.00000000000000000000000000000e+64
new EFP (P, 265, 0xd7e77a8f87daf7fbL, 0xdc33746L << 36), //>10^(16^1*5)=1.00000000000000000000000000000e+80
new EFP (P, 318, 0xefb3ab16c59b14a2L, 0xc5cfe95L << 36), //>10^(16^1*6)=1.00000000000000000000000000000e+96
new EFP (P, 372, 0x850fadc09923329eL, 0x03e2cf7L << 36), //>10^(16^1*7)=1.00000000000000000000000000000e+112
new EFP (P, 425, 0x93ba47c980e98cdfL, 0xc66f337L << 36), //>10^(16^1*8)=1.00000000000000000000000000000e+128
new EFP (P, 478, 0xa402b9c5a8d3a6e7L, 0x5f16207L << 36), //>10^(16^1*9)=1.00000000000000000000000000000e+144
new EFP (P, 531, 0xb616a12b7fe617aaL, 0x577b987L << 36), //>10^(16^1*10)=1.00000000000000000000000000000e+160
new EFP (P, 584, 0xca28a291859bbf93L, 0x7d7b8f7L << 36), //<10^(16^1*11)=1.00000000000000000000000000000e+176
new EFP (P, 637, 0xe070f78d3927556aL, 0x85bbe25L << 36), //<10^(16^1*12)=1.00000000000000000000000000000e+192
new EFP (P, 690, 0xf92e0c3537826145L, 0xa7709a5L << 36), //<10^(16^1*13)=1.00000000000000000000000000000e+208
new EFP (P, 744, 0x8a5296ffe33cc92fL, 0x82bd6b7L << 36), //<10^(16^1*14)=1.00000000000000000000000000000e+224
new EFP (P, 797, 0x9991a6f3d6bf1765L, 0xacca6daL << 36), //<10^(16^1*15)=1.00000000000000000000000000000e+240
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(16^2*0)=1.00000000000000000000000000000
new EFP (P, 850, 0xaa7eebfb9df9de8dL, 0xddbb902L << 36), //>10^(16^2*1)=1.00000000000000000000000000000e+256
new EFP (P, 1700, 0xe319a0aea60e91c6L, 0xcc655c5L << 36), //<10^(16^2*2)=1.00000000000000000000000000000e+512
new EFP (P, 2551, 0x973f9ca8cd00a68cL, 0x6c8d3fdL << 36), //>10^(16^2*3)=1.00000000000000000000000000000e+768
new EFP (P, 3401, 0xc976758681750c17L, 0x650d3d3L << 36), //>10^(16^2*4)=1.00000000000000000000000000000e+1024
new EFP (P, 4252, 0x862c8c0eeb856ecbL, 0x085bccdL << 36), //<10^(16^2*5)=1.00000000000000000000000000000e+1280
new EFP (P, 5102, 0xb2b8353b3993a7e4L, 0x4257ac4L << 36), //>10^(16^2*6)=1.00000000000000000000000000000e+1536
new EFP (P, 5952, 0xee0ddd84924ab88cL, 0x2d4070fL << 36), //<10^(16^2*7)=1.00000000000000000000000000000e+1792
new EFP (P, 6803, 0x9e8b3b5dc53d5de4L, 0xa74d28dL << 36), //>10^(16^2*8)=1.00000000000000000000000000000e+2048
new EFP (P, 7653, 0xd32e203241f4806fL, 0x3f50c80L << 36), //<10^(16^2*9)=1.00000000000000000000000000000e+2304
new EFP (P, 8504, 0x8ca554c020a1f0a6L, 0x5dfed0aL << 36), //>10^(16^2*10)=1.00000000000000000000000000000e+2560
new EFP (P, 9354, 0xbb570a9a9bd977ccL, 0x4c80875L << 36), //<10^(16^2*11)=1.00000000000000000000000000000e+2816
new EFP (P, 10204, 0xf9895d25d88b5a8aL, 0xfdd08c5L << 36), //>10^(16^2*12)=1.00000000000000000000000000000e+3072
new EFP (P, 11055, 0xa630ef7d5699fe45L, 0x50e3660L << 36), //<10^(16^2*13)=1.00000000000000000000000000000e+3328
new EFP (P, 11905, 0xdd5dc8a2bf27f3f7L, 0x95aa119L << 36), //>10^(16^2*14)=1.00000000000000000000000000000e+3584
new EFP (P, 12756, 0x936e07737dc64f6dL, 0x8c474bbL << 36), //<10^(16^2*15)=1.00000000000000000000000000000e+3840
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(16^3*0)=1.00000000000000000000000000000
new EFP (P, 13606, 0xc46052028a20979aL, 0xc94c154L << 36), //>10^(16^3*1)=1.00000000000000000000000000000e+4096
new EFP (P, 27213, 0x96a3a1d17faf211aL, 0x0c7c289L << 36), //<10^(16^3*2)=1.00000000000000000000000000000e+8192
};
public final EFP[] EFP_TEN_M16QR = {
// echo read("efp.gp");for(i=0,50,q=eval("i>>4");r=bitand(i,15);efpmem([Str("10^(-16^",q,"*",r,")")])) | gp -q
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(-16^0*0)=1.00000000000000000000000000000
new EFP (P, -4, 0xccccccccccccccccL, 0xccccccdL << 36), //>10^(-16^0*1)=0.100000000000000000000000000000
new EFP (P, -7, 0xa3d70a3d70a3d70aL, 0x3d70a3dL << 36), //<10^(-16^0*2)=0.0100000000000000000000000000000
new EFP (P, -10, 0x83126e978d4fdf3bL, 0x645a1cbL << 36), //>10^(-16^0*3)=0.00100000000000000000000000000000
new EFP (P, -14, 0xd1b71758e219652bL, 0xd3c3611L << 36), //<10^(-16^0*4)=1.00000000000000000000000000000e-4
new EFP (P, -17, 0xa7c5ac471b478423L, 0x0fcf80eL << 36), //>10^(-16^0*5)=1.00000000000000000000000000000e-5
new EFP (P, -20, 0x8637bd05af6c69b5L, 0xa63f9a5L << 36), //>10^(-16^0*6)=1.00000000000000000000000000000e-6
new EFP (P, -24, 0xd6bf94d5e57a42bcL, 0x3d32907L << 36), //<10^(-16^0*7)=1.00000000000000000000000000000e-7
new EFP (P, -27, 0xabcc77118461cefcL, 0xfdc20d3L << 36), //>10^(-16^0*8)=1.00000000000000000000000000000e-8
new EFP (P, -30, 0x89705f4136b4a597L, 0x31680a9L << 36), //>10^(-16^0*9)=1.00000000000000000000000000000e-9
new EFP (P, -34, 0xdbe6fecebdedd5beL, 0xb573441L << 36), //>10^(-16^0*10)=1.00000000000000000000000000000e-10
new EFP (P, -37, 0xafebff0bcb24aafeL, 0xf78f69aL << 36), //<10^(-16^0*11)=1.00000000000000000000000000000e-11
new EFP (P, -40, 0x8cbccc096f5088cbL, 0xf93f87bL << 36), //<10^(-16^0*12)=1.00000000000000000000000000000e-12
new EFP (P, -44, 0xe12e13424bb40e13L, 0x2865a5fL << 36), //<10^(-16^0*13)=1.00000000000000000000000000000e-13
new EFP (P, -47, 0xb424dc35095cd80fL, 0x538484cL << 36), //<10^(-16^0*14)=1.00000000000000000000000000000e-14
new EFP (P, -50, 0x901d7cf73ab0acd9L, 0x0f9d370L << 36), //<10^(-16^0*15)=1.00000000000000000000000000000e-15
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(-16^1*0)=1.00000000000000000000000000000
new EFP (P, -54, 0xe69594bec44de15bL, 0x4c2ebe7L << 36), //>10^(-16^1*1)=1.00000000000000000000000000000e-16
new EFP (P, -107, 0xcfb11ead453994baL, 0x67de18fL << 36), //>10^(-16^1*2)=1.00000000000000000000000000000e-32
new EFP (P, -160, 0xbb127c53b17ec159L, 0x5560c02L << 36), //>10^(-16^1*3)=1.00000000000000000000000000000e-48
new EFP (P, -213, 0xa87fea27a539e9a5L, 0x3f2398dL << 36), //<10^(-16^1*4)=1.00000000000000000000000000000e-64
new EFP (P, -266, 0x97c560ba6b0919a5L, 0xdccd87aL << 36), //>10^(-16^1*5)=1.00000000000000000000000000000e-80
new EFP (P, -319, 0x88b402f7fd75539bL, 0x11dbcb0L << 36), //<10^(-16^1*6)=1.00000000000000000000000000000e-96
new EFP (P, -373, 0xf64335bcf065d37dL, 0x4d4617bL << 36), //<10^(-16^1*7)=1.00000000000000000000000000000e-112
new EFP (P, -426, 0xddd0467c64bce4a0L, 0xac7cb3fL << 36), //<10^(-16^1*8)=1.00000000000000000000000000000e-128
new EFP (P, -479, 0xc7caba6e7c5382c8L, 0xfe64a53L << 36), //>10^(-16^1*9)=1.00000000000000000000000000000e-144
new EFP (P, -532, 0xb3f4e093db73a093L, 0x59ed216L << 36), //<10^(-16^1*10)=1.00000000000000000000000000000e-160
new EFP (P, -585, 0xa21727db38cb002fL, 0xb8ada01L << 36), //>10^(-16^1*11)=1.00000000000000000000000000000e-176
new EFP (P, -638, 0x91ff83775423cc06L, 0x7b6306aL << 36), //<10^(-16^1*12)=1.00000000000000000000000000000e-192
new EFP (P, -691, 0x8380dea93da4bc60L, 0x4247cbaL << 36), //>10^(-16^1*13)=1.00000000000000000000000000000e-208
new EFP (P, -745, 0xece53cec4a314ebdL, 0xa4f8bf5L << 36), //<10^(-16^1*14)=1.00000000000000000000000000000e-224
new EFP (P, -798, 0xd5605fcdcf32e1d6L, 0xfb1e4aaL << 36), //>10^(-16^1*15)=1.00000000000000000000000000000e-240
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(-16^2*0)=1.00000000000000000000000000000
new EFP (P, -851, 0xc0314325637a1939L, 0xfa91115L << 36), //<10^(-16^2*1)=1.00000000000000000000000000000e-256
new EFP (P, -1701, 0x9049ee32db23d21cL, 0x7132d33L << 36), //<10^(-16^2*2)=1.00000000000000000000000000000e-512
new EFP (P, -2552, 0xd8a66d4a505de96bL, 0x5ae1b26L << 36), //>10^(-16^2*3)=1.00000000000000000000000000000e-768
new EFP (P, -3402, 0xa2a682a5da57c0bdL, 0x87a6016L << 36), //>10^(-16^2*4)=1.00000000000000000000000000000e-1024
new EFP (P, -4253, 0xf4385d0975edbabeL, 0x1f4bf66L << 36), //<10^(-16^2*5)=1.00000000000000000000000000000e-1280
new EFP (P, -5103, 0xb759449f52a711b2L, 0x68e1eb7L << 36), //<10^(-16^2*6)=1.00000000000000000000000000000e-1536
new EFP (P, -5953, 0x89a63ba4c497b50eL, 0x6c83ad1L << 36), //<10^(-16^2*7)=1.00000000000000000000000000000e-1792
new EFP (P, -6804, 0xceae534f34362de4L, 0x492512dL << 36), //<10^(-16^2*8)=1.00000000000000000000000000000e-2048
new EFP (P, -7654, 0x9b2a840f28a1638fL, 0xe393a9cL << 36), //<10^(-16^2*9)=1.00000000000000000000000000000e-2304
new EFP (P, -8505, 0xe8fb7dc2dec0a404L, 0x598eec8L << 36), //>10^(-16^2*10)=1.00000000000000000000000000000e-2560
new EFP (P, -9355, 0xaee973911228abcaL, 0xe3187c3L << 36), //<10^(-16^2*11)=1.00000000000000000000000000000e-2816
new EFP (P, -10205, 0x8350bf3c91575a87L, 0xe79e237L << 36), //>10^(-16^2*12)=1.00000000000000000000000000000e-3072
new EFP (P, -11056, 0xc52ba8a6aeb15d92L, 0x9e98cbaL << 36), //>10^(-16^2*13)=1.00000000000000000000000000000e-3328
new EFP (P, -11906, 0x9406af8f83fd6265L, 0x4b4de35L << 36), //>10^(-16^2*14)=1.00000000000000000000000000000e-3584
new EFP (P, -12757, 0xde42ff8d37cad87fL, 0x1463ef5L << 36), //>10^(-16^2*15)=1.00000000000000000000000000000e-3840
new EFP (P, 0, 0x8000000000000000L, 0x0000000L << 36), //=10^(-16^3*0)=1.00000000000000000000000000000
new EFP (P, -13607, 0xa6dd04c8d2ce9fdeL, 0x2de3812L << 36), //<10^(-16^3*1)=1.00000000000000000000000000000e-4096
new EFP (P, -27214, 0xd986c20b686da869L, 0x5d1d4feL << 36), //>10^(-16^3*2)=1.00000000000000000000000000000e-8192
};
// echo read("efp.gp");efppub(["TENTO28","10^28"]) | gp -q
public final EFP TENTO28 = new EFP (P, 93, 0x813f3978f8940984L, 0x4000000L << 36); //=10^28=10000000000000000000000000000.0
//========================================================================
//$$EFP 92bit浮動小数点数
// class EFP
//
// フラグ flg
// bit31 M -
// bit30 Z ±0
// bit29 I ±Inf
// bit28 N NaN
// flg==P +x
// flg==M -x
// flg==(P|Z) +0
// flg==(M|Z) -0
// flg==(P|I) +Inf
// flg==(M|I) -Inf
// flg==N NaN
// flg==0 +x
// flg!=0 -x,±0,±Inf,NaN
// flg>=0 +x,+0,+Inf,NaN
// flg<0 -x,-0,-Inf
// flg<<1==0 ±x
// flg<<1!=0 ±0,±Inf,NaN
// flg<<1>=0 ±x,±Inf,NaN
// flg<<1<0 ±0
// flg<<2==0 ±x,±0
// flg<<2!=0 ±Inf,NaN
// flg<<2>=0 ±x,±0,NaN
// flg<<2<0 ±Inf
// flg<<3==0 ±x,±0,±Inf
// flg<<3!=0 NaN
// flg<<3>=0 ±x,±0,±Inf
// flg<<3<0 NaN
// インスタンスのフラグがコンディションコードを兼ねる
// ±0,±Inf,NaNの表現を仮数部に組み込まない理由
// ±0,±Inf,NaNをflg<<1!=0でまとめて分離することで±0,±Inf,NaN以外の処理のオーバーヘッドを減らす
// ±0,±Inf,NaNの仮数部を不定にすることで±0,±Inf,NaNを返す処理を短くする
// -NaNを設けない理由
// 例外的な値のためにコードを冗長にしたくない
// doubleの場合
// 負符号でNaNの符号が反転しない場合と反転する場合がある
// System.out.printf("%016x\n",Double.doubleToRawLongBits(Double.NaN));
// 7ff8000000000000
// System.out.printf("%016x\n",Double.doubleToRawLongBits(-Double.NaN));
// 7ff8000000000000
// System.out.printf("%016x\n",Double.doubleToRawLongBits(-Double.longBitsToDouble(0x7ff8000000000000L)));
// fff8000000000000
// 加算で片方がNaNのときはその符号が使用される
// System.out.printf("%016x\n",Double.doubleToRawLongBits(Double.longBitsToDouble(0xfff8000000000000L)+0.0));
// fff8000000000000
// System.out.printf("%016x\n",Double.doubleToRawLongBits(0.0+Double.longBitsToDouble(0xfff8000000000000L)));
// fff8000000000000
// 加算で両方がNaNのときは後者の符号が使用される
// System.out.printf("%016x\n",Double.doubleToRawLongBits(Double.NaN+Double.longBitsToDouble(0xfff8000000000000L)));
// fff8000000000000
// System.out.printf("%016x\n",Double.doubleToRawLongBits(Double.longBitsToDouble(0xfff8000000000000L)+Double.NaN));
// 7ff8000000000000
//
// 指数部 epp
// 符号あり16bit(-32768~32767)
// 内部32bit
// 高速化のため内部では指数部が符号あり16bitに収まっているかどうかを確認せずに処理を進める
// 浮動小数点数の値が1のとき指数部は0
// ±0,±Inf,NaNのときは不定
// 下駄履き16bitゼロ拡張ではなくて16bit符号拡張にする理由
// 乗算、除算、累乗などで下駄が邪魔にならない
// オーバーフローまたはアンダーフローの判定は(short)epp!=eppでできる
// 下駄履き16bitゼロ拡張のときのepp>>16!=0または(char)epp!=eppと比較しても大きく遅くなることはない
//
// 仮数部 dvl,cvl
// LEN=92bit
// (92bitに限定する必要がない場所では65bit<=LEN<=95bitの範囲で調整できるようにする)
// 整数部は1bitで常に1
// ±0,±Inf,NaN以外はすべて正規化数であり、仮数部について非正規化数は存在しない
// 小数部は91bit
// 2個のlongに左詰めで格納する
// 余った領域は0で埋める
// 表現できる正規化数の範囲は2^-32768から(2-2^(1-LEN))*2^32767まで
// 2^-32768 = 10^-9864.1508979173358047637961023321875012
// (2-2^(1-92))*2^32767 = 10^9864.1508979173358047637961023320997960
// 連続して正確に表現できる整数の範囲は-2^92から2^92まで。10進数で27桁まで
// 2^92 = 4951760157141521099596496896
// = 10^27.694759601086269959663978314653358463
// 26桁まで出力する
// 単一の演算では26桁までは正確であることを期待できる
// ±0,±Inf,NaNのときは不定
// 65bit以上にする理由
// 64bit以下では超越関数などでextendedの精度を確保できない
// 92bit以下にする理由
// 乗算を効率よく行える
// 32bit,30bit,30bitに3分割して掛けると中間の加算が最大で62bit*2+60bit*3となって64bitに収まるのでキャリーの処理が簡単になる
// 91bit以下にする理由
// 除算を効率よく行える
// 91bitの被除数を右に1bitずらしてから基数2^31で3分割して割ると
// 2^29<=被除数の1桁目(30bit)<2^30<=除数の1桁目(31bit)<2^31
// なので3回の操作で92bitまたは93bitの商が得られる
// 商に92bit目のguard bitが含まれるので丸めの処理が簡単になる
// 整数部を1に固定する(非正規化数を設けない)理由
// 非正規化数を設けないことで正規化数の処理のオーバーヘッドを減らす
// float,double,extendedの非正規化数はEFPでは正規化数として表現できる
// extendedの指数部は15bit
//
// 丸めの処理
// 演算結果を最も近い表現可能な値に丸める
// 演算結果に最も近い表現可能な値が2つあるときはLSBが0の方(最近接偶数)に丸める
// 他の丸めはfloat,double,extendedへ変換するときだけ用いる
// 最近接偶数への丸めにする理由
// 最近接偶数への丸めは符号を考慮する必要がないので高速
// 丸めてから符号反転したときと符号反転してから丸めたときの結果が異なるのは気持ち悪い
// 条件
// 65bit<=LEN<=95bitであること
// 演算結果がze,zd,zc,zbに入っているとする
// ze 指数部
// zd 仮数部の上位(64bit)
// zc 仮数部の下位(1~31bit),guard bit(1bit),round bit(1bit),sticky bit(61~31bit)
// zb sticky bit(64bit)
// 手順
// guard bitが0またはLSBとround bitとsticky bitがすべて0のときは切り捨てる
// guard bitが1かつLSBとround bitとsticky bitのいずれかが0でないときは切り上げて、溢れたときはMSBだけセットして指数部を1増やす
// コード
// if ((zc << LEN - 64 | zb) != 0L) { //端数が0でないとき
// this.epbFpsr |= X2; //不正確な結果
// if (zc << LEN - 64 >= 0L || (zc & (LSB | RBM | SBM) | zb) == 0L) { //guard bitが0またはLSBとround bitとsticky bitがすべて0のとき
// zc &= -LSB; //切り捨てる
// } else if ((zc = zc + LSB & -LSB) == 0L && ++zd == 0L) { //切り上げて、溢れたとき
// zd = MSB; //MSBだけセットして
// ze++; //指数部を1増やす
// }
// }
//
// 超越関数の多項式展開
// テイラー展開
// f(x) = sum[n=0..∞]{f'n(a)/n!*(x-a)^n}
// a=0のとき(マクローリン展開)
// f(x) = sum[n=0..∞]{f'n(0)/n!*x^n}
// 偶関数の奇数次の係数と奇関数の偶数次の係数は自動的に0になる
// cosの多倍角の公式
// cos(0*t) = 1
// cos(1*t) = cos(t)
// cos(n*t) = 2*cos(t)*cos((n-1)*t)-cos((n-2)*t)
// チェビシェフ多項式
// T(0,x) = 1
// T(1,x) = x
// T(n,x) = 2*x*T(n-1,x)-T(n-2,x)
// = ((x-sqrt(x^2-1))^n+(x+sqrt(x^2-1))^n)/2
// echo for(n=0,10,printf("T(%d,x) = %s\n",n,polchebyshev(n))) | gp -q
// T(0,x) = 1
// T(1,x) = x
// T(2,x) = 2*x^2 - 1
// T(3,x) = 4*x^3 - 3*x
// T(4,x) = 8*x^4 - 8*x^2 + 1
// T(5,x) = 16*x^5 - 20*x^3 + 5*x
// T(6,x) = 32*x^6 - 48*x^4 + 18*x^2 - 1
// T(7,x) = 64*x^7 - 112*x^5 + 56*x^3 - 7*x
// T(8,x) = 128*x^8 - 256*x^6 + 160*x^4 - 32*x^2 + 1
// T(9,x) = 256*x^9 - 576*x^7 + 432*x^5 - 120*x^3 + 9*x
// T(10,x) = 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
// チェビシェフ展開
// f(x) = sum[k=0..∞]{(k==0?1:2)/pi*int[t=0..pi]{cos(k*t)*f(cos(t))}*T(k,x)}
// 定義域が[-1,1]なので目的の関数に応じて変数変換を行う
// 偶関数の奇数次の係数と奇関数の偶数次の係数は自動的に0になる
// 台形積分を用いる場合
// f(x) ≒ sum[k=0..n]{(k==0?1:2)/n*sum[j=0..n]{(j==0||j==n?1/2:1)*cos(pi*j*k/n)*f(cos(pi*j/n))}*T(k,x)}
// テイラー展開vsチェビシェフ展開
// 多項式近似の所要時間は項数と各項の次数と係数の有無が同じであれば係数の値は関係ない
// 係数の値を調整することで真の値と一致する桁数を増やすことができれば同じ桁数を得るのに必要な項数が少なくて済む分所要時間が短くなる
// 無限に続けることが前提のテイラー展開を途中で打ち切った多項式よりも項数を任意に設定できるチェビシェフ展開の方が同じ項数でも真の値と一致する桁数が多くなる
// 多項式の次数の選択
// 定義域を10000分割して10001箇所すべてで必要なbit数よりも8bit以上余分に求められる最短の多項式を選択する
// ほぼ全域で誤差が129/256ulp未満となる
// 全域で誤差を1/2ulp未満にする(常に真の値に最も近い表現可能な値を返す)多項式を構築することは困難である
// 真の値の端数が0.5に近くて近似値の端数が0.5を挟んで反対側にあるとそれらの差がどれだけ小さくても真の値から遠い方に丸められてしまう
// 例: atan()の23次のチェビシェフ展開の精度は55bitだが53bitに丸めると53bit目が真の値に最も近い表現可能な値と異なってしまう例
// echo read("efp.gp");x=dbltonum(0x3f8cf097f3a42000);y0=atan(x);y1=eval("-2722284370390831588490114173/158456325028528675187087900672*x^23 + 739739927556278187039881021/19807040628566084398385987584*x^21 - 992045672314533323023892321/19807040628566084398385987584*x^19 + 2313610503890582509205873157/39614081257132168796771975168*x^17 - 1319535373237619650487539135/19807040628566084398385987584*x^15 + 3047093318219389825184024421/39614081257132168796771975168*x^13 - 3601272632870709965040963617/39614081257132168796771975168*x^11 + 1100391082127852704923599513/9903520314283042199192993792*x^9 - 2829577229944316543631260919/19807040628566084398385987584*x^7 + 1980704062840506309069283499/9903520314283042199192993792*x^5 - 3301173438094258430826284729/9903520314283042199192993792*x^3 + 154742504910672532084711661/154742504910672534362390528*x")*1.0;printf("%.30g,%016x",y0,floor(y0*eval("2^59")+0.5));print();printf("%.30g,%016x",y1,floor(y1*eval("2^59")+0.5));print();printf("%.30g",log(abs((y1-y0)/y0))/log(2));print() | gp -q
// 0.0141298303751989210010080821653,001cf019bae04517 真の値
// 0.0141298303751989208174624059843,001cf019bae04516 近似値
// -56.0953826306895581110391156901 精度
// 真の値の端数は0.10010…なので本来は切り上げなければならないが近似値の端数が0.01110…なので切り捨てられてしまっている
//
// 多項式の計算
// 多項式の計算にはホーナー法(Horner's method)を用いる
// c(n)*x^n+c(n-1)*x^(n-1)+...+c1*x+c0 = ((c(n)*x+c(n-1))*x+...+c1)*x+c0
// c(n)*x+c(n-1)が0に近いときすなわちxが-c(n-1)/c(n)に近いとき桁落ち誤差が大きくなることに注意する
//
// 余談
// SPARC64 VIIIfx(京のプロセッサ)の三角関数補助演算命令は[-π/4,π/4]の範囲のsinを7項、cosを8項の多項式で近似している
// 特にsinは53bitの係数×7項で57bitまで一致させるという超絶技巧が使われており、この係数をどうやって選択したのか興味深い
// sin(x)=1.0000000000000000000*x-0.16666666666666615781*x^3+0.0083333333333200018678*x^5-0.00019841269828402128715*x^7
// +2.7557313299015053950e-6*x^9-2.5050705846378874749e-8*x^11+1.5894136371952154456e-10*x^13
// echo read("efp.gp");printf("%.4f%c",closeness(sin,((((((dbltonum(0X3DE5D8408868552F)*x*x+dbltonum(0XBE5AE5E2B60F7B91))*x*x+dbltonum(0X3EC71DE351F3D22B))*x*x+dbltonum(0xBF2A01A019B92FC6))*x*x+dbltonum(0x3F8111111110F30C))*x*x+dbltonum(0xBFC5555555555543))*x*x+dbltonum(0x3FF0000000000000))*x,-Pi/4,Pi/4,10000),10) | gp -q
// 57.0852
// cos(x)=1.0000000000000000000-0.50000000000000000000*x^2+0.041666666666666449248*x^4-0.0013888888888861107822*x^6
// +2.4801587283886826962e-5*x^8-2.7557313099139499305e-7*x^10+2.0875582539758721897e-9*x^12-1.1353387007200546080e-11*x^14
// echo read("efp.gp");printf("%.4f%c",closeness(cos,((((((dbltonum(0xBDA8F76380FBB401)*x*x+dbltonum(0x3E21EE96D2641B13))*x*x+dbltonum(0xBE927E4F7282F468))*x*x+dbltonum(0x3EFA01A019B1E8D8))*x*x+dbltonum(0xBF56C16C16C13A0B))*x*x+dbltonum(0x3FA5555555555536))*x*x+dbltonum(0xBFE0000000000000))*x*x+dbltonum(0x3FF0000000000000),-Pi/4,Pi/4,10000),10) | gp -q
// 56.9315
//
// 参考
// http://repository.dl.itc.u-tokyo.ac.jp/dspace/handle/2261/31404
// 研究解説 : チェビシェフ多項式による関数近似について
// http://www.made.gifu-u.ac.jp/~tanaka/LectureNote/numerical_analysis.pdf
// 基礎数値解析‐偏微分方程式の数値シミュレーション技法入門‐
// http://www.fujitsu.com/jp/solutions/business-technology/tc/catalog/
// SPARC64(TM) VIIIfx Extensions 日本語版
//
// メモ
// インスタンスを格納する変数がfinalでもフィールドは読み書き自由なので定数インスタンスのフィールドを間違って書き換えないように注意する
// 使用頻度が低い処理のための条件分岐(下位が0かどうかの場合分けなど)を使用頻度が高い場所に書くことは極力避ける
//
// 逆三角関数と逆双曲線関数の名前
// 逆三角関数と逆双曲線関数の接頭辞は1文字のa、呼び方はinverse(逆)に統一する
// ISO 80000-2:2009では逆三角関数の接頭辞はarc、逆双曲線関数の接頭辞はar
// Google Ngram Viewerによると、2008年までの逆双曲線関数の接頭辞の使用頻度はa>arc>arである
// https://books.google.com/ngrams/graph?content=acosh%2Casinh%2Catanh%2Carcosh%2Carsinh%2Cartanh%2Carccosh%2Carcsinh%2Carctanh&case_insensitive=on&year_start=1840&year_end=2008&corpus=15&smoothing=6
// ただし、ソースコードの中のasinhと数式の中のarsinhが同程度に満遍なくカウントできているのかどうかは定かではない
// 意味的に逆三角関数の返却値はarc(弧)だが逆双曲線関数の返却値はarea(面積)なのだから逆双曲線関数の接頭辞にarcを使うのは誤りということらしい
// コンピュータの関数名は双曲線関数の先頭にarcを付けたのではなく逆三角関数の末尾にhを付けたらarcが付いてきたというパターンも多いと思われる
// Mathematicaの関数名はArcTanhである
// http://reference.wolfram.com/language/ref/ArcTanh.html
// PHPのマニュアル(日本語版)のatanhの説明にカタカナでアークハイパボリックタンジェントと書かれている
// http://php.net/manual/ja/function.atanh.php
// 英語版はinverseとしか書かれていない
// http://php.net/manual/en/function.atanh.php
// MC68881UMのFATANHのページにはhyperbolic arc tangentと書かれている
// http://cache.freescale.com/files/32bit/doc/ref_manual/MC68881UM.pdf
// MZ-1500用のHuBASIC Ver2.0のマニュアルにもarc-hyperbolic tangentと書かれていた
// Wikipediaのノートにいろいろな意見がある
// https://en.wikipedia.org/wiki/Talk:Inverse_hyperbolic_function
//
// 累乗は冪乗またはべき乗とも書くがここでは累乗とする
//
public class EFP implements Comparable<EFP> {
//------------------------------------------------------------------------
//定数
// サイズ
public static final int LEN = 92; //仮数部のbit数。65<=LEN<=95
public static final long MSB = 1L << 63; //dの最上位bit。整数部
public static final long LSB = 1L << 128 - LEN; //cの最下位bit。ulp
public static final long GBM = LSB >>> 1; //cのguard bit。1/2*ulp。丸めの処理で使う
public static final long RBM = GBM >>> 1; //cのround bit。1/4*ulp。指数部が異なる数の減算で1bit減ったときにguard bitになる
public static final long SBM = RBM - 1L; //cのsticky bitのマスク。1/4*ulp未満が0か0でないかを示す
public static final int EFP_DECIMAL_PREC = 26; //toStringの出力桁数
public static final int EFP_COTH_EPP_MAX = 5; //floor(log(log(sqrt(2^(LEN+1)+1)))/log(2))
// JavaのNaN FPCPのNaN
// 0x7ff8000000000000L 0x7fffffffffffffffL
// 0x7fc00000 0x7fffffff
public static final boolean EFP_FPCP_NAN = true; //doubleまたはfloatで取り出すときNaNをJavaのNaNではなくFPCPのNaNに変換する
//------------------------------------------------------------------------
//インスタンスフィールド
// 6666555555555544 4444444433333333 3322222222221111 1111110000000000
// 3210987654321098 7654321098765432 1098765432109876 5432109876543210
public int flg; // MZIN000000000000 0000000000000000 f フラグ
public int epp; // ssssssssssssssss seeeeeeeeeeeeeee e 指数部
public long dvl; //1ddddddddddddddd dddddddddddddddd dddddddddddddddd dddddddddddddddd d 仮数部の上位64bit
// └e==0のときの小数点の位置
public long cvl; //cccccccccccccccc cccccccccccc0000 0000000000000000 0000000000000000 c 仮数部の下位LEN-64bit
// GRSS SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS guard bit,round bit,sticky bit
//------------------------------------------------------------------------
//公開コンストラクタ
// 丸めの処理が入るので定数の構築には使用できない
//y = epb.new EFP ()
//y = epb.new EFP (d)
//y = epb.new EFP (f)
//y = epb.new EFP (i)
//y = epb.new EFP (l)
//y = epb.new EFP (s)
//y = epb.new EFP (e)
public EFP () {
this.set0 ();
} //EFP()
public EFP (double d) {
this.setd (d);
} //EFP(double)
public EFP (float f) {
this.setf (f);
} //EFP(float)
public EFP (int i) {
this.seti (i);
} //EFP(int)
public EFP (long l) {
this.setl (l);
} //EFP(long)
public EFP (String s) {
this.parse (s);
} //EFP(String)
public EFP (EFP x) {
this.sete (x);
} //EFP(EFP)
//------------------------------------------------------------------------
//内部コンストラクタ
// 定数の構築に使用するので丸めの処理を行ってはならない
// 丸めの処理が必要な場所で使う場合は後から丸めの処理を行う必要がある
public EFP (int xf, int xe, long xd, long xc) {
this.flg = xf;
this.epp = xe;
this.dvl = xd;
this.cvl = xc;
} //EFP(int,int,long,long)
//------------------------------------------------------------------------
//丸めの処理
//efp = efp.inner ()
// 一時的に、丸め桁数を92bitに、丸めモードをRNに変更する
// 関数が内部で他の関数を複数回呼び出すとき、最初の子を呼び出す『前に』実行する
// 最初の子から最大精度で丸めさせる
// EFPBoxの機能だがメソッドチェーンに挟めるようにEFPのメソッドにしてある
// EFPBoxのインスタンスが同じならばどのEFPのインスタンスで呼び出しても同じ
// inner()とouter()の数がずれないように注意すること
public final EFP inner () {
if (epbRoundingDepth++ == 0) {
epbRoundingOuterPrec = epbRoundingPrec; //丸め桁数を保存する
epbRoundingPrec = EPB_PREC_EFP; //丸め桁数を92bitに変更する
epbRoundingOuterMode = epbRoundingMode; //丸めモードを保存する
epbRoundingMode = EPB_MODE_RN; //丸めモードをRNに変更する
}
if (false) {
if (epbRoundingDepth == 10) {
System.out.println ("too many EFP.inner()\n");
}
}
return this;
} //efp.inner()
//efp = efp.outer ()
// 丸め桁数と丸めモードを元に戻す
// 関数が内部で他の関数を複数回呼び出すとき、最後の子を呼び出す『前に』実行する
// 最後の子に本来の精度で丸めさせる
// EFPBoxの機能だがメソッドチェーンに挟めるようにEFPのメソッドにしてある
// EFPBoxのインスタンスが同じならばどのEFPのインスタンスで呼び出しても同じ
// inner()とouter()の数がずれないように注意すること
public final EFP outer () {
if (--epbRoundingDepth == 0) {
epbRoundingPrec = epbRoundingOuterPrec; //丸め桁数を復元する
epbRoundingMode = epbRoundingOuterMode; //丸めモードを復元する
}
if (false) {
if (epbRoundingDepth == -1) {
System.out.println ("too many EFP.outer()\n");
}
}
return this;
} //efp.outer()
//efp = efp.finish ()
//efp = efp.finish (zf, ze, zd, zc, zb)
// 丸めの処理とオーバーフローとアンダーフローのチェックを行ってからインスタンスフィールドを設定する
// 原則としてすべての関数に設置する
// 関数が内部で他の関数を複数回呼び出すときは、最初の子を呼び出す前にinner()を、最後の子を呼び出す前にouter()を実行する
public final EFP finish () {
int zf = this.flg;
if (zf << 1 != 0) { //±0,±Inf,NaN
return this;
}
switch (epbRoundingPrec) {
case EPB_PREC_EXD:
return this.roundx (epbRoundingMode);
case EPB_PREC_SGL:
return this.roundf (epbRoundingMode);
case EPB_PREC_DBL:
case EPB_PREC_DBL3:
return this.roundd (epbRoundingMode);
case EPB_PREC_TPL:
return this.roundy (epbRoundingMode);
case EPB_PREC_XSG:
return this.roundg (epbRoundingMode);
case EPB_PREC_EFP:
default:
int ze = this.epp;
long zd = this.dvl;
long zc = this.cvl;
switch (epbRoundingMode) {
case EPB_MODE_RN:
if (zc << 28 != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zc << 28 < 0L && (zc & 0x00000017ffffffffL) != 0L && //guard bitが1かつLSBまたはguard bit以外の端数が0ではないとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RZ:
if (zc << 28 != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RM:
if (zc << 28 != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zf < 0 && //-のとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RP:
default:
if (zc << 28 != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (0 <= zf && //+のとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
}
if ((short) ze != ze) { //オーバーフローまたはアンダーフロー
if (0 <= ze) { //オーバーフロー
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = zf;
epbExceptionOperandMantissa = zd;
return this.sete (OVFL_RESULTS[EPB_PREC_EFP << 3 | EPB_MODE_RP << 1 | zf >>> 31]); //±Inf
} else { //アンダーフロー
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
epbExceptionOperandExponent = zf;
epbExceptionOperandMantissa = zd;
return this.sete (UNFL_RESULTS[EPB_PREC_EFP << 3 | EPB_MODE_RP << 1 | zf >>> 31]); //±0
}
}
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc;
return this;
} //switch epbRoundingMode
} //efp.finish()
public final EFP finish (int zf, int ze, long zd, long zc, long zb) {
if (zf << 1 != 0) { //±0,±Inf,NaN
this.flg = zf;
return this;
}
switch (epbRoundingPrec) {
case EPB_PREC_EXD:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundx (epbRoundingMode);
case EPB_PREC_SGL:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundf (epbRoundingMode);
case EPB_PREC_DBL:
case EPB_PREC_DBL3:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundd (epbRoundingMode);
case EPB_PREC_TPL:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundy (epbRoundingMode);
case EPB_PREC_XSG:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundg (epbRoundingMode);
case EPB_PREC_EFP:
default:
switch (epbRoundingMode) {
case EPB_MODE_RN:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zc << 28 < 0L && ((zc & 0x00000017ffffffffL) | zb) != 0L && //guard bitが1かつLSBまたはguard bit以外の端数が0ではないとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RZ:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RM:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zf < 0 && //-のとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RP:
default:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (0 <= zf && //+のとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
}
if ((short) ze != ze) { //オーバーフローまたはアンダーフロー
if (0 <= ze) { //オーバーフロー
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = zf;
epbExceptionOperandMantissa = zd;
return this.sete (OVFL_RESULTS[EPB_PREC_EFP << 3 | EPB_MODE_RP << 1 | zf >>> 31]); //±Inf
} else { //アンダーフロー
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
epbExceptionOperandExponent = zf;
epbExceptionOperandMantissa = zd;
return this.sete (UNFL_RESULTS[EPB_PREC_EFP << 3 | EPB_MODE_RP << 1 | zf >>> 31]); //±0
}
}
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc;
return this;
} //switch epbRoundingMode
} //finish(int,int,long,long,long)
public final EFP finish2 (int zf, int ze, long zd, long zc, long zb) {
if (zf << 1 != 0) { //±0,±Inf,NaN
this.flg = zf;
return this;
}
switch (epbRoundingPrec) {
case EPB_PREC_EXD:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundx2 (epbRoundingMode);
case EPB_PREC_SGL:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundf (epbRoundingMode);
case EPB_PREC_DBL:
case EPB_PREC_DBL3:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundd (epbRoundingMode);
case EPB_PREC_TPL:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundy2 (epbRoundingMode);
case EPB_PREC_XSG:
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc | zb >>> 32 | zb & 0xffffffffL;
return this.roundg (epbRoundingMode);
case EPB_PREC_EFP:
default:
switch (epbRoundingMode) {
case EPB_MODE_RN:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zc << 28 < 0L && ((zc & 0x00000017ffffffffL) | zb) != 0L && //guard bitが1かつLSBまたはguard bit以外の端数が0ではないとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RZ:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RM:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zf < 0 && //-のとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
case EPB_MODE_RP:
default:
if ((zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (0 <= zf && //+のとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
}
break;
}
if ((short) ze != ze) { //オーバーフローまたはアンダーフロー
if (0 <= ze) { //オーバーフロー
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = zf;
epbExceptionOperandMantissa = zd;
return this.sete (OVFL_RESULTS[EPB_PREC_EFP << 3 | EPB_MODE_RP << 1 | zf >>> 31]); //±Inf
} else { //アンダーフロー
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
epbExceptionOperandExponent = zf;
epbExceptionOperandMantissa = zd;
return this.sete (UNFL_RESULTS[EPB_PREC_EFP << 3 | EPB_MODE_RP << 1 | zf >>> 31]); //±0
}
}
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc;
return this;
} //switch epbRoundingMode
} //finish(int,int,long,long,long)
public final EFP ifinish (int zf, int ze, long zd, long zc, long zb) {
if (zf << 1 == 0 && //±0,±Inf,NaN以外で
(zc << 28 | zb) != 0L) { //端数が0でないとき
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (zc << 28 < 0L && ((zc & 0x00000017ffffffffL) | zb) != 0L && //guard bitが1かつLSBまたはguard bit以外の端数が0ではないとき
(zc += 1L << 36) >>> 36 == 0L && ++zd == 0L) { //切り上げて溢れたとき
zd = MSB;
ze++;
}
zc &= 0xfffffff000000000L; //端数を切り捨てる
} //if ±0,±Inf,NaN以外で端数が0でないとき
this.flg = zf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc;
return this;
} //ifinish(int,int,long,long,long)
//this = this.originLowerLower (x)
//this = this.originLowerUpper (x)
//this = this.originUpperLower (x)
//this = this.originUpperUpper (x)
// 原点を傾き1で通る関数で原点付近の入力と出力の大小関係に矛盾が生じていたら修正する
// x<0
// x<0でy=xよりも下(y=-Infとy=xの間)にあるもの(asin,atanh,log1p,sinh,tan)
// SGL,DBLでないときはy=xまで下げる
// RMのときはy=xの下まで下げる
// x<0でy=xよりも上(y=0とy=xの間)にあるもの(asinh,atan,expm1,sin,tanh)
// SGL,DBLでないときはy=xまで上げる
// RZ,RPのときはy=xの上まで上げる
// 0<x
// 0<xでy=xよりも下(y=0とy=xの間)にあるもの(asinh,atan,log1p,sin,tanh)
// SGL,DBLでないときはy=xまで下げる
// RZ,RMのときはy=xの下まで下げる
// 0<xでy=xよりも上(y=xとy=+Infの間)にあるもの(asin,atanh,expm1,sinh,tan)
// SGL,DBLでないときはy=xまで上げる
// RPのときはy=xの上まで上げる
public final EFP originLowerLower (EFP x) {
if (x.flg << 1 == 0 && x.epp < -16) { //0<|x|<2^-16
if (x.flg < 0) { //x<0でy=xよりも下(y=-Infとy=xの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.gt (x)) {
//SGL,DBLでないときはy=xまで下げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RM) {
if (this.ge (x)) {
//RMのときはy=xの下まで下げる
this.nextdown (x, epbRoundingPrec);
}
}
} else { //0<xでy=xよりも下(y=0とy=xの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.gt (x)) {
//SGL,DBLでないときはy=xまで下げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) {
if (this.ge (x)) {
//RZ,RMのときはy=xの下まで下げる
this.nextdown (x, epbRoundingPrec);
}
}
}
}
return this;
} //originLowerLower(EFP)
public final EFP originLowerUpper (EFP x) {
if (x.flg << 1 == 0 && x.epp < -16) { //0<|x|<2^-16
if (x.flg < 0) { //x<0でy=xよりも下(y=-Infとy=xの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.gt (x)) {
//SGL,DBLでないときはy=xまで下げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RM) {
if (this.ge (x)) {
//RMのときはy=xの下まで下げる
this.nextdown (x, epbRoundingPrec);
}
}
} else { //0<xでy=xよりも上(y=xとy=+Infの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.lt (x)) {
//SGL,DBLでないときはy=xまで上げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RP) {
if (this.le (x)) {
//RPのときはy=xの上まで上げる
this.nextup (x, epbRoundingPrec);
}
}
}
}
return this;
} //originLowerUpper(EFP)
public final EFP originUpperLower (EFP x) {
if (x.flg << 1 == 0 && x.epp < -16) { //0<|x|<2^-16
if (x.flg < 0) { //x<0でy=xよりも上(y=0とy=xの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.lt (x)) {
//SGL,DBLでないときはy=xまで上げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) {
if (this.le (x)) {
//RZ,RPのときはy=xの上まで上げる
this.nextup (x, epbRoundingPrec);
}
}
} else { //0<xでy=xよりも下(y=0とy=xの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.gt (x)) {
//SGL,DBLでないときはy=xまで下げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) {
if (this.ge (x)) {
//RZ,RMのときはy=xの下まで下げる
this.nextdown (x, epbRoundingPrec);
}
}
}
}
return this;
} //originUpperLower(EFP)
public final EFP originUpperUpper (EFP x) {
if (x.flg << 1 == 0 && x.epp < -16) { //0<|x|<2^-16
if (x.flg < 0) { //x<0でy=xよりも上(y=0とy=xの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.lt (x)) {
//SGL,DBLでないときはy=xまで上げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) {
if (this.le (x)) {
//RZ,RPのときはy=xの上まで上げる
this.nextup (x, epbRoundingPrec);
}
}
} else { //0<xでy=xよりも上(y=xとy=+Infの間)にあるもの
if (epbRoundingPrec != EPB_PREC_SGL && epbRoundingPrec != EPB_PREC_DBL) {
if (this.lt (x)) {
//SGL,DBLでないときはy=xまで上げる
this.sete (x).finish ();
}
}
if (epbRoundingMode == EPB_MODE_RP) {
if (this.le (x)) {
//RPのときはy=xの上まで上げる
this.nextup (x, epbRoundingPrec);
}
}
}
}
return this;
} //originUpperUpper(EFP)
//this = this.correctUnderflow (savedFpsr)
// 非正規化数のときUFをセット、正規化数のときUFをクリアする
public final EFP correctUnderflow (int savedFpsr) {
if (this.flg << 1 == 0) {
if (this.epp < (epbRoundingPrec == EPB_PREC_SGL ? -126 :
epbRoundingPrec == EPB_PREC_DBL || epbRoundingPrec == EPB_PREC_DBL3 ? -1022 :
-16383)) { //非正規化数のとき
epbFpsr |= EPB_FPSR_UF; //UFをセット
} else { //正規化数のとき
epbFpsr = epbFpsr & ~EPB_FPSR_UF | savedFpsr & EPB_FPSR_UF; //UFをクリア
}
}
return this;
} //correctUnderflow(int)
//------------------------------------------------------------------------
//x = x.abs ()
// x=|x|
//y = y.abs (x)
// y=|x|
// 絶対値関数 absolute value function アブソリュートバリューファンクション
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{abs($_[0])});print$g"
// echo read("efp.gp");graph(abs) | gp -q
// **--------+---------+---------+---------+---------+---------+---------+--------**
// |*** | ***|
// | *** | *** |
// | *** | *** |
// | *** | *** |
// + *** + *** +
// | *** | *** |
// | *** | *** |
// | *** | *** |
// | *** | *** |
// + *** + *** +
// | *** | *** |
// | *** | *** |
// | *** | *** |
// | *** | *** |
// + *** + *** +
// | *** | *** |
// | *** | *** |
// | *** | *** |
// | ***|*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// 0<=y<=inf
//
public final EFP abs () {
return this.finish (this.flg & ~M, this.epp, this.dvl, this.cvl, 0L);
} //efp.abs()
public final EFP iabs () {
this.flg &= ~M; //NaNでも問題ない
return this;
} //efp.abs()
public final EFP abs (EFP x) {
return this.finish (x.flg & ~M, x.epp, x.dvl, x.cvl, 0L);
} //efp.abs(EFP)
public final EFP iabs (EFP x) {
this.flg = x.flg & ~M; //NaNでも問題ない
this.epp = x.epp;
this.dvl = x.dvl;
this.cvl = x.cvl;
return this;
} //efp.abs(EFP)
//------------------------------------------------------------------------
//x = x.acos ()
// x=acos(x)
//y = y.acos (x)
// y=acos(x)
// 逆余弦 inverse cosine インバースコサイン
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{acos($_[0])});print$g"
// echo read("efp.gp");graph(acos) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | * | |
// + * + +
// | ** | |
// | ** | |
// | ** | |
// | *** | |
// + *** + +
// | ***| |
// | *** |
// | |*** |
// | | *** |
// + + ** +
// | | *** |
// | | ** |
// | | ** |
// | | * |
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -1<=x<=1
//
// 値域
// 0<=y<=pi
//
// 逆三角関数との関係
// acos(x)=atan2(sqrt(1-x^2),x)
// =atan(sqrt(1-x^2)/x)
// =pi/2-asin(x)
// =pi/2-atan2(x,sqrt(1-x^2))
// =pi/2-atan(x/sqrt(1-x^2))
//
// テイラー展開
// asinのテイラー展開を参照
// acos(x)=pi/2-asin(x)
// =pi/2-sum[m=0..inf]{prod[k=0..m-1]{2*k+1}/2^m/m!/(2*m+1)*x^(2*m+1)}
// =pi/2-(1/1/1*x^1+(1)/(2)/3*x^3+(1*3)/(2*4)/5*x^5+(1*3*5)/(2*4*6)/7*x^7+(1*3*5*7)/(2*4*6*8)/9*x^9+...)
// =pi/2-x-1/6*x^3-3/40*x^5-5/112*x^7-35/1152*x^9-...
// > coeff(sub(a=0,for n:=0:10 sum sub(x=a,df(acos(x),x,n))/factorial(n)*(x-a)^n),x);
// pi - 1 - 3 - 5 - 35
// {----,-1,0,------,0,------,0,------,0,-------}
// 2 6 40 112 1152
//
// pi/2-asin(x)で求める方法
// 浮動小数点数の場合、x=1-εで桁落ちが発生して精度が低くなるので工夫が必要
//
public final EFP acos () {
return this.acos (this);
} //efp.acos()
public final EFP acos (EFP x) {
//return this.asin (x).negsub (PI_2); //pi/2-asin(x)。x=1-εのとき桁落ちが発生するため精度が低い
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_X2; //不正確な結果
this.sete (ROUNDED_PI_2[epbRoundingMode]).finish (); //acos(±0)=pi/2
} else if (xf << 2 < 0) { //±Inf
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //acos(±Inf)=NaN
} else { //NaN
this.flg = N; //acos(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (xe >= 0) { //|x|>=1
if (xe == 0 && x.dvl == MSB && x.cvl == 0L) { //|x|==1
if (xf >= 0) {
this.flg = P | Z; //acos(+1)=+0
} else {
epbFpsr |= EPB_FPSR_X2; //不正確な結果
this.sete (ROUNDED_PI[epbRoundingMode]).finish (); //acos(-1)=pi
}
} else { //1<|x|
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf | 0x3fff + xe << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N;
}
return this;
}
//|x|<1
if (this == x) {
x = new EFP (x);
}
return this.inner ().negdec (x).imul (new EFP ().inc (x)).sqrt ().outer ().atan2 (x); //atan2(sqrt((1-x)*(1+x)),x) [91]
} //efp.acos(EFP)
//------------------------------------------------------------------------
//x = x.acosh ()
// x=acosh(x)
//y = y.acosh (x)
// y=acosh(x)
// 逆双曲線余弦 inverse hyperbolic cosine インバースハイパボリックコサイン
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{acosh($_[0])});print$g"
// echo read("efp.gp");graph(acosh) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + *******
// | | ******* |
// | | ***** |
// | | ***** |
// | | **** |
// + + **** +
// | | ** |
// | | *** |
// | | ** |
// | | * |
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// 1<=x<=inf
//
// 値域
// 0<=y<=inf
//
// 対数関数との関係
// acosh(x)=log(x+sqrt(x^2-1))
// =log1p(x-1+sqrt((x-1)*(x+1)))
// =log1p(x-1+sqrt((x-1)^2+2*(x-1)))
// x^2-1=(x-1+1)^2-1
// =(x-1)^2+2*(x-1)+1-1
// =(x-1)^2+2*(x-1)
// acoshの定義域は1<=xなのでx-1で誤差が増えることはない
//
public final EFP acosh () {
return this.acosh (this);
} //efp.acosh()
public final EFP acosh (EFP x) {
int xf = x.flg;
if (xf != 0) { //-x,±0,±Inf,NaN
if (xf < 0 || xf << 1 < 0) { //-x,±0,-Inf
epbFpsr |= EPB_FPSR_OE;
if (xf << 1 < 0) { //±0
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else if (xf == (M | I)) { //-Inf
epbExceptionOperandExponent = M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else { //-x
epbExceptionOperandExponent = M | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
}
this.flg = N; //acosh(-x)=acosh(-Inf)=acosh(±0)=NaN
} else {
this.flg = xf == (P | I) ? P | I : N; //acosh(+Inf)=+Inf, acosh(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
if (x.epp < 0) { //0<x<1
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N; //acosh(|x|<1)=NaN
return this;
}
//1<=|x|
return this.inner ().dec (x).iadd (new EFP ().isqu (this).iadd (new EFP ().imul2 (this)).sqrt ()).outer ().log1p (); //log1p(x-1+sqrt((x-1)^2+2*(x-1)))
} //efp.acosh(EFP)
//------------------------------------------------------------------------
//x = x.acot ()
// x=acot(x)
//y = y.acot (x)
// y=acot(x)
// 逆余接 inverse cotangent インバースコタンジェント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{acot($_[0])});print$g"
// echo read("efp.gp");eval("acot(x)=atan(1/x)");graph(acot) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | ** |
// | |*** |
// | | *** |
// + + **** +
// | | ***** |
// | | ******* |
// | | *************** |
// | | *********
// +---------+---------+---------+---------+---------+---------+---------+---------+
// ********* | |
// | *************** | |
// | ******* | |
// | ***** | |
// + **** + +
// | *** | |
// | ***| |
// | ** |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// inf<=x<0
// 0<x<=inf
//
// 値域
// -pi/2<=y<0
// 0<y<=pi/2
//
// 逆三角関数との関係
// acot(x)=atan2(1/x,1)
// =atan(1/x)
//
public final EFP acot () {
return this.acot (this);
} //efp.acot()
public final EFP acot (EFP x) {
return this.inner ().rcp (x).outer ().atan (); //atan(1/x)
} //efp.acot(EFP)
//------------------------------------------------------------------------
//x = x.acoth ()
// x=acoth(x)
//y = y.acoth (x)
// y=acoth(x)
// 逆双曲線余接 inverse hyperbolic cotangent インバースハイパボリックコタンジェント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{acoth($_[0])});print$g"
// echo read("efp.gp");eval("acoth(x)=log((x+1)/(x-1))/2");graph(acoth) | gp -q
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | * |
// | | * |
// | | * |
// | | * |
// + + * +
// | | * |
// | | * |
// | | * |
// | | * |
// + + * +
// | | ** |
// | | * |
// | | ** |
// | | * |
// + + *** +
// | | **** |
// | | ****** |
// | | ************* |
// | | *******
// +---------+---------+---------+---------+---------+---------+---------+---------+
// ******* | |
// | ************* | |
// | ****** | |
// | **** | |
// + *** + +
// | * | |
// | ** | |
// | * | |
// | ** | |
// + * + +
// | * | |
// | * | |
// | * | |
// | * | |
// + * + +
// | * | |
// | * | |
// | * | |
// | * | |
// +---------+---------+---------*---------+---------+---------+---------+---------+
//
// 定義域
// inf<=x<-1
// 1<x<=inf
//
// 値域
// -inf<=y<0
// 0<y<=inf
//
// 対数関数との関係
// acoth(x)=log((x+1)/(x-1))/2
// =log(sqrt((x+1)/(x-1)))
// =log(sqrt(x+1)/sqrt(x-1))
//
public final EFP acoth () {
return this.acoth (this);
} //efp.acoth()
public final EFP acoth (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //acoth(±0)=NaN
} else {
this.flg = xf << 2 < 0 ? xf ^ (Z | I) : N; //acoth(±Inf)=±0, acoth(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
if (x.epp < 0) { //|x|<1
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N; //acoth(|x|<1)=NaN
return this;
}
if (x.epp == 0 && x.dvl == MSB && x.cvl == 0L) { //|x|==1
epbFpsr |= EPB_FPSR_DZ;
epbExceptionOperandExponent = xf & M | 0x3fff << 16;
epbExceptionOperandMantissa = 0x8000000000000000L;
this.flg = xf | I; //acoth(±1)=±Inf
return this;
}
//1<|x|
return this.inner ().iabs (x).dec ().rcp ().imul2 ().log1p ().idiv2 ().outer ().neg (xf < 0); //sgn(x)*log(1+2/(|x|-1))/2
} //efp.acoth(EFP)
//------------------------------------------------------------------------
//x = x.acsc ()
// x=acsc(x)
//y = y.acsc (x)
// y=acsc(x)
// 逆余割 inverse cosecant インバースコセカント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{acsc($_[0])});print$g"
// echo read("efp.gp");eval("acsc(x)=sign(x)*atan(1/sqrt((x-1)*(x+1)))");graph(acsc) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | * |
// | | * |
// | | ** |
// + + *** +
// | | **** |
// | | ****** |
// | | ************** |
// | | *******
// +---------+---------+---------+---------+---------+---------+---------+---------+
// ******* | |
// | ************** | |
// | ****** | |
// | **** | |
// + *** + +
// | ** | |
// | * | |
// | * | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// inf<=x<=-1
// 1<=x<=inf
//
// 値域
// -pi/2<=y<0
// 0<y<=pi/2
//
// 逆三角関数との関係
// acsc(x)=atan2(1/x,sqrt(1-1/x^2))
// =atan2(sgn(x),sqrt(x^2-1))
// =sgn(x)*atan2(1,sqrt(x^2-1))
// =sgn(x)*atan(1/sqrt(x^2-1))
// =sgn(x)*atan(1/sqrt((x-1)*(x+1)))
// =asin(1/x)
//
public final EFP acsc () {
return this.acsc (this);
} //efp.acsc()
public final EFP acsc (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //acsc(±0)=NaN
} else {
this.flg = xf << 2 < 0 ? xf ^ (Z | I) : N; //acsc(±Inf)=±0, acsc(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
if (x.epp < 0) { //|x|<1
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N; //acsc(|x|<1)=NaN
return this;
}
if (x.epp == 0 && x.dvl == MSB && x.cvl == 0L) { //|x|==1
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (xf >= 0) {
this.sete (ROUNDED_PI_2[epbRoundingMode]).finish (); //acsc(1)=pi/2
} else {
this.sete (ROUNDED_NEGPI_2[epbRoundingMode]).finish (); //acsc(-1)=-pi/2
}
return this;
}
//1<|x|
EFP t = new EFP ().inner ().inc (x);
return this.dec (x).imul (t).sqrt ().rcp ().atan ().outer ().neg (xf < 0); //sgn(x)*atan(1/sqrt((x-1)*(x+1)))
} //efp.acsc(EFP)
//------------------------------------------------------------------------
//x = x.acsch ()
// x=acsch(x)
//y = y.acsch (x)
// y=acsch(x)
// 逆双曲線余割 inverse hyperbolic cosecant インバースハイパボリックコセカント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{acsch($_[0])});print$g"
// echo read("efp.gp");eval("acsch(x)=log(1/x+sqrt(1/x^2+1))");graph(acsch) | gp -q
// +---------+---------+---------+---------*---------+---------+---------+---------+
// | * |
// | ** |
// | |* |
// | |* |
// + +* +
// | |* |
// | |** |
// | | * |
// | | * |
// + + ** +
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + **** +
// | | **** |
// | | ******* |
// | | *************** |
// | | ********
// +---------+---------+---------+---------+---------+---------+---------+---------+
// ******** | |
// | *************** | |
// | ******* | |
// | **** | |
// + **** + +
// | ** | |
// | ** | |
// | ** | |
// | ** | |
// + ** + +
// | * | |
// | * | |
// | **| |
// | *| |
// + *+ +
// | *| |
// | *| |
// | ** |
// | * |
// +---------+---------+---------+---------*---------+---------+---------+---------+
//
// 定義域
// inf<=x<0
// 0<x<=inf
//
// 値域
// -inf<=y<0
// 0<y<=inf
//
// 逆双曲線関数との関係
// acsch(x)=asinh(1/x)
//
// 対数関数との関係
// acsch(x)=log(1/x+sqrt(1/x^2+1))
// =log((1+sgn(x)*sqrt(1+x^2))/x)
// =log((sgn(x)+sqrt(1+x^2))/abs(x))
// =log(sgn(x)+sqrt(1+x^2))-log(abs(x))
//
// テイラー展開
// http://mathworld.wolfram.com/InverseHyperbolicCosecant.html
// acsch(x)=sum[n=1..inf]{(-1)^n*pochhammer(1/2,n-1)/((2*n-1)*(n-1)!)*x^(1-2*n)}
// =x^-1-1/6*x^-3+3/40*x^-5-5/112*x^-7+...
// pochhammer(x,n)=prod[k=0..n-1]{x+k} ポッホハマー記号
//
// ピュイズー展開
// http://mathworld.wolfram.com/InverseHyperbolicCosecant.html
// acsch(x)=-log(x)+log(2)+sum[n=1..inf]{(-1)^(n+1)*(2*n-1)!!/(2*n*(2*n)!!)*x^(2*n)}
// =-log(x)+log(2)+1!!/(2*2!!)*x^2-3!!/(4*4!!)*x^4+5!!/(6*6!!)*x^6-...
// =-log(x)+log(2)+1/(2*2)*x^2-1*3/(4*2*4)*x^4+1*3*5/(6*2*4*6)*x^6-...
// =-log(x)+log(2)+1/4*x^2-3/32*x^4+5/96*x^6-...
//
// 1<xのとき
// sqrt(x^2+1)-x=sum[n=0..inf]{(-1)^n*catalan(n)/(2*x)^(2*n+1)}
// =sum[n=0..inf]{(-1)^n*(2*n)!/(n!*(n+1)!)/(2*x)^(2*n+1)}
// =1/(2*x)-1/(2*x)^3+2/(2*x)^5-5/(2*x)^7+14/(2*x)^9
// -42/(2*x)^11+132/(2*x)^13-429/(2*x)^15+1430/(2*x)^17-4862/(2*x)^19
// +16796/(2*x)^21-58786/(2*x)^23...
//
// 0<=x<1のとき
// sqrt(1/x^2+1)-1/x=sum[n=0..inf]{(-1)^n*catalan(n)/2^(2*n+1)*x^(2*n+1)}
// =sum[n=0..inf]{(-1)^n*(2*n)!/(n!*(n+1)!)/2^(2*n+1)*x^(2*n+1)}
// =1/2*x-1/2^3*x^3+2/2^5*x^5-5/2^7*x^7+14/2^9*x^9
// -42/2^11*x^11+132/2^13*x^13-429/2^15*x^15+1430/2^17*x^17-4862/2^19*x^19
// +16796/2^21*x^21-58786/2^23*x^23...
// acsch(x)=log(2/x+sum[n=0..inf]{(-1)^n*catalan(n)/2^(2*n+1)*x^(2*n+1)})
// ピュイズー展開の式に似ている。x→+0でlog(2/x)に近付くのだから当然か
//
public final EFP acsch () {
return this.acsch (this);
} //efp.acsch()
public final EFP acsch (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //acsch(±0)=NaN
} else {
this.flg = xf << 2 < 0 ? xf ^ (Z | I) : N; //acsch(±Inf)=±0, acsc(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
x = new EFP ().inner ().rcp (x); //1/x
if (x.epp < -1) { //|x|<0.5
EFP x2 = new EFP ().isqu (x);
return this.imul (ASINH_C43, x2)
.iadd (ASINH_C41).imul (x2)
.iadd (ASINH_C39).imul (x2)
.iadd (ASINH_C37).imul (x2)
.iadd (ASINH_C35).imul (x2)
.iadd (ASINH_C33).imul (x2)
.iadd (ASINH_C31).imul (x2)
.iadd (ASINH_C29).imul (x2)
.iadd (ASINH_C27).imul (x2)
.iadd (ASINH_C25).imul (x2)
.iadd (ASINH_C23).imul (x2)
.iadd (ASINH_C21).imul (x2)
.iadd (ASINH_C19).imul (x2)
.iadd (ASINH_C17).imul (x2)
.iadd (ASINH_C15).imul (x2)
.iadd (ASINH_C13).imul (x2)
.iadd (ASINH_C11).imul (x2)
.iadd (ASINH_C9).imul (x2)
.iadd (ASINH_C7).imul (x2)
.iadd (ASINH_C5).imul (x2)
.iadd (ASINH_C3).imul (x2)
.iadd (ASINH_C1).outer ().mul (x);
}
//0.5<=|x|
return this.iabs (x).iadd (new EFP ().isqu (this).inc ().sqrt ()).log ().outer ().neg (xf < 0); //sgn(x)*log(|1/x|+sqrt((|1/x|)^2+1))
} //efp.acsch(EFP)
//------------------------------------------------------------------------
//x = x.add (y)
// x+=y
//z = z.add (x, y)
// z=x+y
// 加算
//
// (xn/xd)+(yn/yd)
// =((xn*yd)/(xd*yd))+((xd*yn)/(xd*yd))
// =(xn*yd+xd*yn)/(xd*yd)
//
public final EFP add (EFP y) {
int xf = this.flg;
int xe = this.epp;
long xd = this.dvl;
long xc = this.cvl;
long xb = 0L;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((xf | yf) << 3 < 0) { //どちらかがNaNのときNaN
this.flg = N;
return this;
}
if ((xf & yf) << 2 < 0 && xf != yf) { //両方±Infで符号が逆のときNaN
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = yf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N;
return this;
}
if ((xf & yf) << 1 < 0 && xf != yf) { //両方±0で符号が逆のとき
this.flg = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
return this;
}
if (xf << 1 < 0 || yf << 2 < 0) { //xが±0またはyが±Infのときy
xf = yf;
xe = y.epp;
xd = y.dvl;
xc = y.cvl;
}
//xが±Infまたはyが±0のときx
} else { //両方±0,±Inf,NaN以外
//加算なのでyの符号はそのまま
long yd = y.dvl;
long yc = y.cvl;
int o = xe - y.epp;
if (o < 0 || o == 0 && (xd < yd || xd == yd && xc >>> 1 < yc >>> 1)) { //yの方が絶対値が大きい
//xとyを入れ換える
xf = yf;
xe += o = -o; //xe=y.epp
xd = yd;
xc = yc;
yf = this.flg; //後で符号を比較するときに使う
yd = this.dvl;
yc = this.cvl;
}
//xの方が絶対値が大きいか等しい
//yを右にずらして小数点の位置を合わせる
if (0 < o) {
if (o <= 63) {
xb = yc << -o;
yc = yd << -o | yc >>> o;
yd >>>= o;
} else if (o == 64) {
xb = yc;
yc = yd;
yd = 0L;
} else if (o <= 127) {
xb = yd << -o | yc;
yc = yd >>> o;
yd = 0L;
} else {
xb = yd | yc; //絶対値減算を行うとき下位からのボローとして必要
yc = 0L;
yd = 0L;
}
}
//絶対値加算または絶対値減算を行う
if (xf == yf) { //符号が同じなので絶対値加算を行う
//yc[1]とyc[0]をsticky bitに押し出す
xb |= yc << 62;
//右にずらしてxd[63]を空ける
xc = xd << 63 | xc >>> 1;
xd >>>= 1;
yc = yd << 63 | yc >>> 1;
yd >>>= 1;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//足す
xc += yc;
xd += yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//溢れの処理
if (xd < 0L) { //溢れたとき
xe++;
} else { //溢れなかったとき
xd = xd << 1 | xc >>> 63; //左にずらしてxd[63]を詰める
xc <<= 1;
}
} else { //符号が異なるので絶対値減算を行う
//yc[0]をsticky bitに押し出す
xb |= yc << 63;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//引く
// xの方が絶対値が大きいか等しいので負になることはないが0になることがある
if (xb != 0L) {
xc--;
}
xc -= yc;
xd -= yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//正規化する
if (0L <= xd) {
if (xd != 0L) {
xe -= o = Long.numberOfLeadingZeros (xd);
xd = xd << o | xc >>> -o;
xc <<= o;
} else if (xc != 0L) {
xe -= o = 64 + Long.numberOfLeadingZeros (xc);
xd = xc << o;
xc = 0L;
} else { //0になった
xf = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
}
}
} //if 符号が同じなので絶対値加算を行う/符号が異なるので絶対値減算を行う
} //if どちらかが±0,±Inf,NaN/両方±0,±Inf,NaN以外
return this.finish (xf, xe, xd, xc, xb);
} //efp.add(EFP)
public final EFP iadd (EFP y) {
int xf = this.flg;
int xe = this.epp;
long xd = this.dvl;
long xc = this.cvl;
long xb = 0L;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((xf | yf) << 3 < 0) { //どちらかがNaNのときNaN
this.flg = N;
return this;
}
if ((xf & yf) << 2 < 0 && xf != yf) { //両方±Infで符号が逆のときNaN
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = yf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N;
return this;
}
if ((xf & yf) << 1 < 0 && xf != yf) { //両方±0で符号が逆のとき
this.flg = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
return this;
}
if (xf << 1 < 0 || yf << 2 < 0) { //xが±0またはyが±Infのときy
xf = yf;
xe = y.epp;
xd = y.dvl;
xc = y.cvl;
}
//xが±Infまたはyが±0のときx
} else { //両方±0,±Inf,NaN以外
//加算なのでyの符号はそのまま
long yd = y.dvl;
long yc = y.cvl;
int o = xe - y.epp;
if (o < 0 || o == 0 && (xd < yd || xd == yd && xc >>> 1 < yc >>> 1)) { //yの方が絶対値が大きい
//xとyを入れ換える
xf = yf;
xe += o = -o; //xe=y.epp
xd = yd;
xc = yc;
yf = this.flg; //後で符号を比較するときに使う
yd = this.dvl;
yc = this.cvl;
}
//xの方が絶対値が大きいか等しい
//yを右にずらして小数点の位置を合わせる
if (0 < o) {
if (o <= 63) {
xb = yc << -o;
yc = yd << -o | yc >>> o;
yd >>>= o;
} else if (o == 64) {
xb = yc;
yc = yd;
yd = 0L;
} else if (o <= 127) {
xb = yd << -o | yc;
yc = yd >>> o;
yd = 0L;
} else {
xb = yd | yc; //絶対値減算を行うとき下位からのボローとして必要
yc = 0L;
yd = 0L;
}
}
//絶対値加算または絶対値減算を行う
if (xf == yf) { //符号が同じなので絶対値加算を行う
//yc[1]とyc[0]をsticky bitに押し出す
xb |= yc << 62;
//右にずらしてxd[63]を空ける
xc = xd << 63 | xc >>> 1;
xd >>>= 1;
yc = yd << 63 | yc >>> 1;
yd >>>= 1;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//足す
xc += yc;
xd += yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//溢れの処理
if (xd < 0L) { //溢れたとき
xe++;
} else { //溢れなかったとき
xd = xd << 1 | xc >>> 63; //左にずらしてxd[63]を詰める
xc <<= 1;
}
} else { //符号が異なるので絶対値減算を行う
//yc[0]をsticky bitに押し出す
xb |= yc << 63;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//引く
// xの方が絶対値が大きいか等しいので負になることはないが0になることがある
if (xb != 0L) {
xc--;
}
xc -= yc;
xd -= yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//正規化する
if (0L <= xd) {
if (xd != 0L) {
xe -= o = Long.numberOfLeadingZeros (xd);
xd = xd << o | xc >>> -o;
xc <<= o;
} else if (xc != 0L) {
xe -= o = 64 + Long.numberOfLeadingZeros (xc);
xd = xc << o;
xc = 0L;
} else { //0になった
xf = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
}
}
} //if 符号が同じなので絶対値加算を行う/符号が異なるので絶対値減算を行う
} //if どちらかが±0,±Inf,NaN/両方±0,±Inf,NaN以外
return this.ifinish (xf, xe, xd, xc, xb);
} //efp.iadd(EFP)
public final EFP add (EFP x, EFP y) {
int xf = x.flg;
int xe = x.epp;
long xd = x.dvl;
long xc = x.cvl;
long xb = 0L;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((xf | yf) << 3 < 0) { //どちらかがNaNのときNaN
this.flg = N;
return this;
}
if ((xf & yf) << 2 < 0 && xf != yf) { //両方±Infで符号が逆のときNaN
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = yf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N;
return this;
}
if ((xf & yf) << 1 < 0 && xf != yf) { //両方±0で符号が逆のとき
this.flg = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
return this;
}
if (xf << 1 < 0 || yf << 2 < 0) { //xが±0またはyが±Infのときy
xf = yf;
xe = y.epp;
xd = y.dvl;
xc = y.cvl;
}
//xが±Infまたはyが±0のときx
} else { //両方±0,±Inf,NaN以外
//加算なのでyの符号はそのまま
long yd = y.dvl;
long yc = y.cvl;
int o = xe - y.epp;
if (o < 0 || o == 0 && (xd < yd || xd == yd && xc >>> 1 < yc >>> 1)) { //yの方が絶対値が大きい
//xとyを入れ換える
xf = yf;
xe += o = -o; //xe=y.epp
xd = yd;
xc = yc;
yf = x.flg; //後で符号を比較するときに使う
yd = x.dvl;
yc = x.cvl;
}
//xの方が絶対値が大きいか等しい
//yを右にずらして小数点の位置を合わせる
if (0 < o) {
if (o <= 63) {
xb = yc << -o;
yc = yd << -o | yc >>> o;
yd >>>= o;
} else if (o == 64) {
xb = yc;
yc = yd;
yd = 0L;
} else if (o <= 127) {
xb = yd << -o | yc;
yc = yd >>> o;
yd = 0L;
} else {
xb = yd | yc; //絶対値減算を行うとき下位からのボローとして必要
yc = 0L;
yd = 0L;
}
}
//絶対値加算または絶対値減算を行う
if (xf == yf) { //符号が同じなので絶対値加算を行う
//yc[1]とyc[0]をsticky bitに押し出す
xb |= yc << 62;
//右にずらしてxd[63]を空ける
xc = xd << 63 | xc >>> 1;
xd >>>= 1;
yc = yd << 63 | yc >>> 1;
yd >>>= 1;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//足す
xc += yc;
xd += yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//溢れの処理
if (xd < 0L) { //溢れたとき
xe++;
} else { //溢れなかったとき
xd = xd << 1 | xc >>> 63; //左にずらしてxd[63]を詰める
xc <<= 1;
}
} else { //符号が異なるので絶対値減算を行う
//yc[0]をsticky bitに押し出す
xb |= yc << 63;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//引く
// xの方が絶対値が大きいか等しいので負になることはないが0になることがある
if (xb != 0L) {
xc--;
}
xc -= yc;
xd -= yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//正規化する
if (0L <= xd) {
if (xd != 0L) {
xe -= o = Long.numberOfLeadingZeros (xd);
xd = xd << o | xc >>> -o;
xc <<= o;
} else if (xc != 0L) {
xe -= o = 64 + Long.numberOfLeadingZeros (xc);
xd = xc << o;
xc = 0L;
} else { //0になった
xf = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
}
}
} //if 符号が同じなので絶対値加算を行う/符号が異なるので絶対値減算を行う
} //if どちらかが±0,±Inf,NaN/両方±0,±Inf,NaN以外
return this.finish (xf, xe, xd, xc, xb);
} //efp.add(EFP,EFP)
public final EFP iadd (EFP x, EFP y) {
int xf = x.flg;
int xe = x.epp;
long xd = x.dvl;
long xc = x.cvl;
long xb = 0L;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((xf | yf) << 3 < 0) { //どちらかがNaNのときNaN
this.flg = N;
return this;
}
if ((xf & yf) << 2 < 0 && xf != yf) { //両方±Infで符号が逆のときNaN
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = yf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N;
return this;
}
if ((xf & yf) << 1 < 0 && xf != yf) { //両方±0で符号が逆のとき
this.flg = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
return this;
}
if (xf << 1 < 0 || yf << 2 < 0) { //xが±0またはyが±Infのときy
xf = yf;
xe = y.epp;
xd = y.dvl;
xc = y.cvl;
}
//xが±Infまたはyが±0のときx
} else { //両方±0,±Inf,NaN以外
//加算なのでyの符号はそのまま
long yd = y.dvl;
long yc = y.cvl;
int o = xe - y.epp;
if (o < 0 || o == 0 && (xd < yd || xd == yd && xc >>> 1 < yc >>> 1)) { //yの方が絶対値が大きい
//xとyを入れ換える
xf = yf;
xe += o = -o; //xe=y.epp
xd = yd;
xc = yc;
yf = x.flg; //後で符号を比較するときに使う
yd = x.dvl;
yc = x.cvl;
}
//xの方が絶対値が大きいか等しい
//yを右にずらして小数点の位置を合わせる
if (0 < o) {
if (o <= 63) {
xb = yc << -o;
yc = yd << -o | yc >>> o;
yd >>>= o;
} else if (o == 64) {
xb = yc;
yc = yd;
yd = 0L;
} else if (o <= 127) {
xb = yd << -o | yc;
yc = yd >>> o;
yd = 0L;
} else {
xb = yd | yc; //絶対値減算を行うとき下位からのボローとして必要
yc = 0L;
yd = 0L;
}
}
//絶対値加算または絶対値減算を行う
if (xf == yf) { //符号が同じなので絶対値加算を行う
//yc[1]とyc[0]をsticky bitに押し出す
xb |= yc << 62;
//右にずらしてxd[63]を空ける
xc = xd << 63 | xc >>> 1;
xd >>>= 1;
yc = yd << 63 | yc >>> 1;
yd >>>= 1;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//足す
xc += yc;
xd += yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//溢れの処理
if (xd < 0L) { //溢れたとき
xe++;
} else { //溢れなかったとき
xd = xd << 1 | xc >>> 63; //左にずらしてxd[63]を詰める
xc <<= 1;
}
} else { //符号が異なるので絶対値減算を行う
//yc[0]をsticky bitに押し出す
xb |= yc << 63;
//下位を右にずらしてxc[63]を空ける
yc >>>= 1;
xc >>>= 1;
//引く
// xの方が絶対値が大きいか等しいので負になることはないが0になることがある
if (xb != 0L) {
xc--;
}
xc -= yc;
xd -= yd + (xc >>> 63);
//下位を左にずらしてxc[63]を詰める
xc <<= 1;
//正規化する
if (0L <= xd) {
if (xd != 0L) {
xe -= o = Long.numberOfLeadingZeros (xd);
xd = xd << o | xc >>> -o;
xc <<= o;
} else if (xc != 0L) {
xe -= o = 64 + Long.numberOfLeadingZeros (xc);
xd = xc << o;
xc = 0L;
} else { //0になった
xf = epbRoundingMode == EPB_MODE_RM ? M | Z : P | Z; //RMのとき-0,それ以外は+0
}
}
} //if 符号が同じなので絶対値加算を行う/符号が異なるので絶対値減算を行う
} //if どちらかが±0,±Inf,NaN/両方±0,±Inf,NaN以外
return this.ifinish (xf, xe, xd, xc, xb);
} //efp.iadd(EFP,EFP)
//------------------------------------------------------------------------
//a = a.agi (b)
// a=I(a,b)
//i = i.agi (a, b)
// i=I(a,b)
// 算術幾何平均
//
// グラフ
// echo read("efp.gp");eval("f(b)=if(0<b&&b<1,Pi/(2*agm(1,b)),error())");graph(f) | gp -q
// +---------+---------+---------+---------+*--------+---------+---------+---------+
// | |* |
// | |* |
// | |* |
// | |** |
// + + * +
// | | ** |
// | | * |
// | | ** |
// | | ** |
// + + *** +
// | | *** |
// | | ** |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// 0<b<1
//
// 値域
// pi/2<i<+inf
//
// I(a,b)=int[0..pi/2]{dt/sqrt(a^2*cos(t)^2+b^2*sin(t)^2)}
// =1/2*int[-inf..inf]{dt/sqrt((a^2+t^2)*(b^2+t^2))}
// =pi/(2*M(a,b))
//
public final EFP agi (EFP be) {
return this.agi (this, be);
} //efp.agi(EFP)
public final EFP agi (EFP ae, EFP be) {
return this.agm (ae, be).rcpdiv (PI_2); //pi/(2*M(a,b))
} //efp.agi(EFP,EFP)
//------------------------------------------------------------------------
//a = a.agm (b)
// a=M(a,b)
//m = m.agm (a, b)
// m=M(a,b)
// 算術幾何平均
//
// グラフ
// echo read("efp.gp");eval("f(b)=if(0<b&&b<1,agm(1,b),error())");graph(f) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + *** +
// | | **** |
// | | **** |
// | *** |
// | * |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// 0<b<1
//
// 値域
// 0<m<1
//
// a[0]=1
// b[0]=b
// a[n+1]=(a[n]+b[n])/2
// b[n+1]=sqrt(a[n]*b[n])
// M(1,b)=lim[n=inf]{a[n]}
// =lim[n=inf]{b[n]}
//
public final EFP agm (EFP be) {
return this.agm (this, be);
} //efp.agm(EFP)
public final EFP agm (EFP ae, EFP be) {
int af = ae.flg;
int bf = be.flg;
if ((af | bf) != 0) { //どちらかが±0,±Inf,NaN,-x
this.flg = ((af | bf) << 3 < 0 || //agm(NaN,b)=agm(a,NaN)=NaN
((af | bf) & (Z | I)) == (Z | I) ? N : //agm(±0,±Inf)=agm(±Inf,±0)=NaN
(af | bf) << 1 < 0 ? P | Z : //agm(±0,b)=agm(a,±0)=+0
(af | bf) < 0 ? N : //agm(a<0,b!=0)=agm(a!=0,b<0)=NaN
P | I); //agm(+Inf,b>0)=agm(a>0,+Inf)=+Inf
return this;
}
//両方±0,±Inf,NaN,-x以外
EFP t = new EFP ();
EFP u = new EFP ();
EFP v = new EFP ();
if (ae.ge (be)) { //b<=a
//u.sete (ae);
u.flg = ae.flg;
u.epp = ae.epp;
u.dvl = ae.dvl;
u.cvl = ae.cvl;
//v.sete (be);
v.flg = be.flg;
v.epp = be.epp;
v.dvl = be.dvl;
v.cvl = be.cvl;
} else { //a<b
//u.sete (be);
u.flg = be.flg;
u.epp = be.epp;
u.dvl = be.dvl;
u.cvl = be.cvl;
//v.sete (ae);
v.flg = ae.flg;
v.epp = ae.epp;
v.dvl = ae.dvl;
v.cvl = ae.cvl;
}
// 0<b<=a
// 0<sqrt(a*b)<=(a+b)/2
this.inner ();
for (;;) {
// u=a,v=b
t.iadd (u, v).idiv2 (); //t=(a+b)/2。算術平均
if (t.ge (u)) { //0<b<aのままaとbが近付くのでaが減らなくなったら終了
return this.outer ().sete (u).finish ();
}
v.imul (u).sqrt (); //b=sqrt(a*b)。幾何平均
// t=a,v=b
u.iadd (t, v).idiv2 (); //u=(a+b)/2。算術平均
if (u.ge (t)) { //0<b<aのままaとbが近付くのでaが減らなくなったら終了
return this.outer ().sete (t).finish ();
}
v.imul (t).sqrt (); //b=sqrt(a*b)。幾何平均
}
} //efp.agm(EFP,EFP)
//------------------------------------------------------------------------
//x = x.asec ()
// x=asec(x)
//y = y.asec (x)
// y=asec(x)
// 逆正割 inverse secant インバースセカント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{asec($_[0])});print$g"
// echo read("efp.gp");eval("asec(x)=if(x>=0,atan(sqrt(x^2-1)),Pi-atan(sqrt(x^2-1)))");graph(asec) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | * | |
// + * + +
// | ** | |
// | ** | |
// | **** | |
// | ****** | |
// + ************ + +
// ********** | |
// | | |
// | | ****
// | | **************** |
// + + ******* +
// | | **** |
// | | *** |
// | | ** |
// | | * |
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// inf<=x<=1
// 1<=x<=inf
//
// 値域
// 0<=y<=pi
//
// 逆三角関数との関係
// asec(x)=atan2(sqrt(x^2-1),sgn(x))
// =x>=0?atan(sqrt(x^2-1)):pi-atan(sqrt(x^2-1))
//
public final EFP asec () {
return this.asec (this);
} //efp.asec()
public final EFP asec (EFP x) {
int xf = x.flg;
if (x.cmp1abs () < 0) { //|x|<1
epbFpsr |= EPB_FPSR_OE;
if (xf << 1 < 0) { //±0
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else { //|±x|<1
epbExceptionOperandExponent = xf & M | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
}
this.flg = N;
return this;
}
EFP t = new EFP ().inner ().dec (x);
this.inc (x).imul (t).sqrt ();
return (xf < 0 ?
this.atan ().negsub (PI).outer ().add (PIA) : //pi-atan(sqrt((x-1)*(x+1)))
this.outer ().atan ()); //atan(sqrt((x-1)*(x+1)))。x^2-1だと1+εのとき精度が低い
} //efp.asec(EFP)
//------------------------------------------------------------------------
//x = x.asech ()
// x=asech(x)
//y = y.asech (x)
// y=asech(x)
// 逆双曲線正割 inverse hyperbolic secant インバースハイパボリックセカント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{asech($_[0])});print$g"
// echo read("efp.gp");eval("asech(x)=log(1/x+sqrt(1/x^2-1))");graph(asech) | gp -q
// +---------+---------+---------+---------*---------+---------+---------+---------+
// | * |
// | ** |
// | |* |
// | |* |
// + +* +
// | |* |
// | |** |
// | | * |
// | | * |
// + + ** +
// | | ** |
// | | * |
// | | ** |
// | | ** |
// + + ** +
// | | ** |
// | | ** |
// | | ** |
// | | * |
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// 0<x<=1
//
// 値域
// 0<=y<=inf
//
// 逆双曲線関数との関係
// asech(x)=acosh(1/x)
//
// 対数関数との関係
// asech(x)=log(1/x+sqrt(1/x^2-1))
// =log1p(1/x-1+sqrt((1/x-1)*(1/x+1)))
// =log1p(1/x-1+sqrt((1/x-1)^2+2*(1/x-1)))
// =log1p((1-x)/x+sqrt(((1-x)/x)^2+2*(1-x)/x))
//
public final EFP asech () {
return this.asech (this);
} //efp.asech()
public final EFP asech (EFP x) {
//return this.rcp (x).acosh (); //1-εのとき精度が低い
int xf = x.flg;
if (xf != 0) { //-x,±0,±Inf,NaN
if (xf < 0 || xf << 2 < 0) { //-x,-0,±Inf
epbFpsr |= EPB_FPSR_OE;
if (xf == (M | Z)) { //-0
epbExceptionOperandExponent = M;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else if (xf << 2 < 0) { //±Inf
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else { //-x
epbExceptionOperandExponent = M | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
}
this.flg = N; //asech(-x)=NaN, asech(-0)=NaN, asech(±Inf)=NaN
} else { //+0,NaN
this.flg = xf << 1 < 0 ? P | I : N; //asech(+0)=+Inf, asech(NaN)=NaN
}
return this;
}
//x<0,±0,±Inf,NaN以外
if (0 <= x.epp) { //1<=|x|
if (x.epp == 0 && x.dvl == MSB && x.cvl == 0L) { //|x|==1
this.flg = P | Z; //+0
} else { //1<|x|
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N; //NaN
}
return this;
}
//|x|<1
EFP t = new EFP ().inner ().negdec (x).div (x); //(1-x)/x
return this.iadd (t, new EFP ().isqu (t).iadd (new EFP ().imul2 (t)).sqrt ()).outer ().log1p (); //log1p((1-x)/x+sqrt(((1-x)/x)^2+2*(1-x)/x))
} //efp.asech(EFP)
//------------------------------------------------------------------------
//x = x.asin ()
// x=asin(x)
//y = y.asin (x)
// y=asin(x)
// 逆正弦 inverse sine インバースサイン
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{asin($_[0])});print$g"
// echo read("efp.gp");graph(asin) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | * |
// | | * |
// | | ** |
// + + ** +
// | | *** |
// | | ** |
// | | *** |
// | |*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | ***| |
// | *** | |
// | ** | |
// | *** | |
// + ** + +
// | ** | |
// | * | |
// | * | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -1<=x<=1
//
// 値域
// -pi/2<=y<=pi/2
//
// 逆三角関数との関係
// asin(x)=atan2(x,sqrt(1-x^2))
// =atan2(x,sqrt((1-x)*(1+x)))
// =atan(x/sqrt(1-x^2))
// =atan(x/sqrt((1-x)*(1+x)))
// =pi/2-acos(x)
// =acsc(1/x)
//
// 微分
// df{asin(x)}=1/sqrt(1-x^2)
//
// 積分表示
// asin(x)=int[t=0..x]{dt/sqrt(1-t^2)}
//
// テイラー展開
// 積分表示を二項展開してから項別積分する
// 二項展開
// (1+x)^n=sum[m=0..inf]{ncm(n,m)*x^m}
// =sum[m=0..inf]{n!/(m!*(n-m)!)*x^m}
// =sum[m=0..inf]{prod[k=0..m-1]{n-k}/m!*x^m} (prodで項が1つもないときの値は1とする)
// asin(x)=int[t=0..x]{dt/sqrt(1-t^2)}
// =int[t=0..x]{(1-t^2)^(-1/2)*dt}
// 二項展開する
// =int[t=0..x]{sum[m=0..inf]{prod[k=0..m-1]{-1/2-k}/m!*(-t^2)^m}*dt}
// =int[t=0..x]{sum[m=0..inf]{(-1)^m*prod[k=0..m-1]{2*k+1}/2^m/m!*(-1)^m*t^(2*m)}*dt}
// =int[t=0..x]{sum[m=0..inf]{prod[k=0..m-1]{2*k+1}/2^m/m!*t^(2*m)}*dt}
// 項別積分する
// =sum[m=0..inf]{prod[k=0..m-1]{2*k+1}/2^m/m!*int[t=0..x]{t^(2*m)*dt}}
// =sum[m=0..inf]{prod[k=0..m-1]{2*k+1}/2^m/m!/(2*m+1)*x^(2*m+1)}
// =1/2^0/1/1*x^1+(1)/2^1/(1)/3*x^3+(1*3)/2^2/(1*2)/5*x^5+(1*3*5)/2^3/(1*2*3)/7*x^7+(1*3*5*7)/2^4/(1*2*3*4)/9*x^9+...
// =1/1/1*x^1+(1)/(2)/3*x^3+(1*3)/(2*4)/5*x^5+(1*3*5)/(2*4*6)/7*x^7+(1*3*5*7)/(2*4*6*8)/9*x^9+...
// =x+1/6*x^3+3/40*x^5+5/112*x^7+35/1152*x^9+...
// > coeff(sub(a=0,for n:=0:10 sum sub(x=a,df(asin(x),x,n))/factorial(n)*(x-a)^n),x);
// 1 3 5 35
// {0,1,0,---,0,----,0,-----,0,------}
// 6 40 112 1152
// |x|が1に近いとき収束が遅い
//
// 連分数展開
// asin(x)=x/(1-(1*x)^2/(2*3+(1*x)^2-2*3*(3*x)^2/(4*5+(3*x)^2-4*5*(5*x)^2/(6*7+(5*x)^2-6*7*(7*x)^2/(8*9+(7*x)^2-...)))))
// テイラー展開と同じ
//
public final EFP asin () {
return this.asin (this);
} //efp.asin()
public final EFP asin (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 2 < 0) { //±Inf
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //asin(±Inf)=NaN
} else { //±0,NaN
this.flg = xf; //asin(±0)=±0, asin(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (0 <= xe) { //1<=|x|
if (xe == 0 && x.dvl == MSB && x.cvl == 0L) { //|x|==1
epbFpsr |= EPB_FPSR_X2; //不正確な結果
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (0 <= xf) {
this.sete (ROUNDED_PI_2[epbRoundingMode]).finish (); //asin(1)=pi/2
} else {
this.sete (ROUNDED_NEGPI_2[epbRoundingMode]).finish (); //asin(-1)=-pi/2
}
} else { //1<|x|
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N;
}
return this;
}
//|x|<1
epbFpsr |= EPB_FPSR_X2; //不正確な結果
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (x.epp < -4) { //|x|<1/16
//atan2を使う方法はxが±0に近すぎると誤差で|asin(x)|<|x|になってしまうことがある
//±0の近くだけチェビシェフ展開を使う
int savedFpsr = epbFpsr;
this.inner ();
if (this == x) {
x = new EFP (x);
}
EFP x2 = new EFP ().isqu (x); //x^2
this.imul (ASIN_C17, x2)
.iadd (ASIN_C15).imul (x2)
.iadd (ASIN_C13).imul (x2)
.iadd (ASIN_C11).imul (x2)
.iadd (ASIN_C9).imul (x2)
.iadd (ASIN_C7).imul (x2)
.iadd (ASIN_C5).imul (x2)
.iadd (ASIN_C3).imul (x2)
.iadd (ASIN_C1).outer ().mul (x);
return this.originLowerUpper (x).correctUnderflow (savedFpsr);
}
//1/16<=|x|<1
this.inner ();
EFP t = new EFP ().negdec (x).imul (new EFP ().inc (x)).sqrt ();
return this.outer ().atan2 (x, t); //atan2(x,sqrt((1-x)*(1+x))) [90]
} //efp.asin(EFP)
//------------------------------------------------------------------------
//x = x.asinh ()
// x=asinh(x)
//y = y.asinh (x)
// y=asinh(x)
// 逆双曲線正弦 inverse hyperbolic sine インバースハイパボリックサイン
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{asinh($_[0])});print$g"
// echo read("efp.gp");graph(asinh) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + ********
// | | ******** |
// | | ****** |
// | | ***** |
// | | ***** |
// + + **** +
// | | *** |
// | | **** |
// | | *** |
// | |*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | ***| |
// | *** | |
// | **** | |
// | *** | |
// + **** + +
// | ***** | |
// | ***** | |
// | ****** | |
// | ******** | |
// ******** + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
// 対数関数との関係
// asinh(x)=sgn(x)*log(abs(x)+sqrt(x^2+1))
// =sgn(x)*log(abs(x)+sqrt((abs(x)-1)*(abs(x)+1)+2))
//
// マクローリン展開
// http://mathworld.wolfram.com/InverseHyperbolicSine.html
// |x|<1のとき
// asinh(x)=sum[n=0..inf]{(-1)^n*(2*n-1)!!/((2*n+1)*(2*n)!!)*x^(2*n+1)}
// =1!!/(1*0!!)*x^1-1!!/(3*2!!)*x^3+3!!/(5*4!!)*x^5-5!!/(7*6!!)*x^7+7!!/(9*8!!)*x^9-9!!/(11*10!!)*x^11+...
// =x-1/(3*2)*x^3+1*3/(5*2*4)*x^5-1*3*5/(7*2*4*6)*x^7+1*3*5*7/(9*2*4*6*8)*x^9-1*3*5*7*9/(11*2*4*6*8*10)*x^11+...
// =x-1/6*x^3+3/40*x^5-5/112*x^7+35/1152*x^9-63/2816*x^11+...
//
// ピュイズー展開
// http://mathworld.wolfram.com/InverseHyperbolicSine.html
// asinh(x)=-log(1/x)+log(2)+sum[n=1..inf]{(-1)^(n-1)*(2*n-1)!!/(2*n*(2*n)!!)*x^(-2*n))}
// =-log(1/x)+log(2)+1/4/x^2-3/32/x^4+5/96/x^6-...
//
// チェビシェフ展開
// 0の近くだけチェビシェフ展開を使う
// echo read("efp.gp");eval("f(x)=asinh(x)");a=-0.25;b=0.25;nmax=41;print1(" // ");forstep(n=1,nmax,2,printf("%4d",n));print();print1(" // ");forstep(n=1,nmax,2,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000))));print() | gp -q
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41
// 7 13 19 26 32 38 44 50 56 62 69 75 81 87 93 99 105 111 117 123 129
//
public final EFP asinh () {
return this.asinh (this);
} //efp.asinh()
public final EFP asinh (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
this.flg = xf; //asinh(±0), asinh(±Inf)=±Inf, asinh(NaN)=NaN
return this;
}
//±0,±Inf,NaN以外
if (x.epp < -1) { //|x|<0.5
int savedFpsr = epbFpsr;
this.inner ();
if (this == x) {
x = new EFP (x);
}
EFP x2 = new EFP ().isqu (x);
this.imul (ASINH_C43, x2)
.iadd (ASINH_C41).imul (x2)
.iadd (ASINH_C39).imul (x2)
.iadd (ASINH_C37).imul (x2)
.iadd (ASINH_C35).imul (x2)
.iadd (ASINH_C33).imul (x2)
.iadd (ASINH_C31).imul (x2)
.iadd (ASINH_C29).imul (x2)
.iadd (ASINH_C27).imul (x2)
.iadd (ASINH_C25).imul (x2)
.iadd (ASINH_C23).imul (x2)
.iadd (ASINH_C21).imul (x2)
.iadd (ASINH_C19).imul (x2)
.iadd (ASINH_C17).imul (x2)
.iadd (ASINH_C15).imul (x2)
.iadd (ASINH_C13).imul (x2)
.iadd (ASINH_C11).imul (x2)
.iadd (ASINH_C9).imul (x2)
.iadd (ASINH_C7).imul (x2)
.iadd (ASINH_C5).imul (x2)
.iadd (ASINH_C3).imul (x2)
.iadd (ASINH_C1).outer ().mul (x);
return this.originUpperLower (x).correctUnderflow (savedFpsr);
}
//0.5<=|x|
EFP t = new EFP ().inner ().iabs (x);
return this.isqu (t).inc ().sqrt ().iadd (t).log ().outer ().neg (xf < 0); //sgn(x)*log(abs(x)+sqrt(x^2+1))
} //efp.asinh(EFP)
//------------------------------------------------------------------------
//x = x.atan ()
// x=atan(x)
//y = y.atan (x)
// y=atan(x)
// 逆正接 inverse tangent インバースタンジェント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{atan($_[0])});print$g"
// echo read("efp.gp");graph(atan) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | *****
// | | ***************** |
// + + ******** +
// | | ****** |
// | | **** |
// | | *** |
// | |*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | ***| |
// | *** | |
// | **** | |
// | ****** | |
// + ******** + +
// | ***************** | |
// ***** | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -pi/2<=atan(x)<=pi/2
// 加法定理を用いるときは値域からはみ出さないように注意すること
//
// 逆三角関数との関係
// asin(x)=atan(x/sqrt(1-x^2))
// acos(x)=pi/2-atan(x/sqrt(1-x^2))
//
// 加法定理
// atan(a)+atan(b)=atan((a+b)/(1-a*b)) a*b!=1
// atan(a)-atan(b)=atan((a-b)/(1+a*b)) a*b!=-1
// 値域が-pi/2<atan(x)<=pi/2に制限されるので左辺の値と右辺の値がpiだけずれる場合があることに注意
// atan(x)+atan((1-x)/(1+x))=atan((x+(1-x)/(1+x))/(1-x*(1-x)/(1+x)))
// =atan((x*(1+x)+(1-x))/((1+x)-x*(1-x)))
// =atan((x+x^2+1-x)/(1+x-x+x^2))
// =atan((1+x^2)/(1+x^2))
// =atan(1)
// =pi/4 -1<xのとき
// -3/4*pi x<-1のとき
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{atan($_[0])+atan((1-$_[0])/(1+$_[0]))});print$g"
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | ***************************************************
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// ******************************* | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// atan(x)+atan(1/x)=sgn(x)*pi/2
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{atan($_[0])+atan(1/$_[0])});print$g"
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | *****************************************
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// ***************************************** |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 例外
// |x|<=2^(-LEN/2)のときatan(x)=xとみなす
// テイラー展開よりatan(x)=x-1/3*x^3+1/5*x^5-1/7*x^7+...である
// |x|<=2^(-LEN/2)ならば|-1/3*x^3|/|x|=1/3*x^2<=1/3*2^(-LEN)であるから、
// 仮数部がLENbitの浮動小数点数では|x|<=2^(-LEN/2)のときatan(x)とxを区別できない
// echo for(n=1,10,x=eval("10^-n");printf(" // x=%.10f atan(x)=%.10f%c",x,atan(x),10)) | gp -q
// x=0.1000000000 atan(x)=0.0996686525
// x=0.0100000000 atan(x)=0.0099996667
// x=0.0010000000 atan(x)=0.0009999997
// x=0.0001000000 atan(x)=0.0001000000
// x=0.0000100000 atan(x)=0.0000100000
// x=0.0000010000 atan(x)=0.0000010000
// x=0.0000001000 atan(x)=0.0000001000
// x=0.0000000100 atan(x)=0.0000000100
// x=0.0000000010 atan(x)=0.0000000010
// x=0.0000000001 atan(x)=0.0000000001
// |x|>=2^(LEN+1)のときatan(x)=sgn(x)*pi/2とみなす
// atan(x)+atan(1/x)=sgn(x)*pi/2よりatan(x)-sgn(x)*pi/2=atan(1/x)=1/x-1/(3*x^3)+1/(5*x^5)-1/(7*x^7)+...である
// |x|>=2^(LEN+1)ならば|1/x|<=2^(-LEN-1)であるから、
// 仮数部がLENbitの浮動小数点数では|x|>=2^(LEN+1)のときatan(x)とsgn(x)*pi/2を区別できない
// echo for(n=1,10,x=eval("10^n");printf(" // 1/x=%.10f pi/2-atan(x)=%.10f%c",1/x,Pi/2-atan(x),10)) | gp -q
// 1/x=0.1000000000 pi/2-atan(x)=0.0996686525
// 1/x=0.0100000000 pi/2-atan(x)=0.0099996667
// 1/x=0.0010000000 pi/2-atan(x)=0.0009999997
// 1/x=0.0001000000 pi/2-atan(x)=0.0001000000
// 1/x=0.0000100000 pi/2-atan(x)=0.0000100000
// 1/x=0.0000010000 pi/2-atan(x)=0.0000010000
// 1/x=0.0000001000 pi/2-atan(x)=0.0000001000
// 1/x=0.0000000100 pi/2-atan(x)=0.0000000100
// 1/x=0.0000000010 pi/2-atan(x)=0.0000000010
// 1/x=0.0000000001 pi/2-atan(x)=0.0000000001
//
// 符号除去
// 符号を付けたままだと加法定理が使いにくいので0<=xにする
// atan(x)は奇関数
// atan(x)=-atan(-x)
//
// 変数変換
// 収束を速くするために0<=x<=sqrt(2)-1にする
// 0<=x<=sqrt(2)-1のとき
// y=atan(x)
// 除算は不要
// sqrt(2)-1<x<1+sqrt(2)のとき
// x'=(1-x)/(1+x)
// y'=atan(x')
// y=pi/4-y'
// =pi/4-atan(x')
// =pi/4-atan((1-x)/(1+x))
// -1<xのときatan(x)+atan((1-x)/(1+x))=pi/4なので
// =atan(x)
// 多項式を用いるときは除算が1回必要
// 1+sqrt(2)<=xのとき
// x'=1/x
// y'=atan(x')
// y=pi/2-y'
// =pi/2-atan(x')
// =pi/2-atan(1/x)
// 0<xのときatan(x)+atan(1/x)=pi/2なので
// =atan(x)
// 多項式を用いるときは除算が1回必要
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{my$a=abs($_[0]);$a<=sqrt(2)-1?$a:$a<1+sqrt(2)?(1-$a)/(1+$a):1/$a});print$g"
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | ********** *** | *** ********** |
// ******** **** ***|*** **** ********
// +---------+---------+-------*****------***------*****-------+---------+---------+
// | ******** | ******** |
// | ****** | ****** |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$PI=4*atan(1);$g->func(sub{my$x=$_[0];my $a=abs($x);($x<=>0)*($a<=sqrt(2)-1?atan($a):$a<1+sqrt(2)?$PI/4-atan((1-$a)/(1+$a)):$PI/2-atan(1/$a))});print$g"
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | *****
// | | ***************** |
// + + ******** +
// | | ****** |
// | | **** |
// | | *** |
// | |*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | ***| |
// | *** | |
// | **** | |
// | ****** | |
// + ******** + +
// | ***************** | |
// ***** | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// テイラー展開
// atan(x)=x-1/3*x^3+1/5*x^5-1/7*x^7+...
// f(n,x)=sum(k=0,n,(-1)^k*1/(2*k+1)*x^(2*k+1))
// 収束が遅い
// 除算は不要
//
// 連分数展開
// atan(x)=x/(1+x^2/(3+4*x^2/(5+9*x^2/(7+16*x^2/(9+...n^2*x^2/(2*n+1))))))
// g(n,x,k)=k^2*x^2/(2*k+1+if(k<n,g(n,x,k+1),0))
// f(n,x)=x/(1+if(n<1,0,g(n,x,1)))
// echo eval("g(n,x,k)=k^2*x^2/(2*k+1+if(k<n,g(n,x,k+1),0))");eval("f(n,x)=x/(1+if(n<1,0,g(n,x,1)))");for(n=0,10,print(" // f(",n,",x)=",f(n,x))) | gp -q
// f(0,x)=x
// f(1,x)=3*x/(x^2 + 3)
// f(2,x)=(4*x^3 + 15*x)/(9*x^2 + 15)
// f(3,x)=(55*x^3 + 105*x)/(9*x^4 + 90*x^2 + 105)
// f(4,x)=(64*x^5 + 735*x^3 + 945*x)/(225*x^4 + 1050*x^2 + 945)
// f(5,x)=(231*x^5 + 1190*x^3 + 1155*x)/(25*x^6 + 525*x^4 + 1575*x^2 + 1155)
// f(6,x)=(256*x^7 + 5943*x^5 + 19250*x^3 + 15015*x)/(1225*x^6 + 11025*x^4 + 24255*x^2 + 15015)
// f(7,x)=(15159*x^7 + 147455*x^5 + 345345*x^3 + 225225*x)/(1225*x^8 + 44100*x^6 + 242550*x^4 + 420420*x^2 + 225225)
// f(8,x)=(16384*x^9 + 638055*x^7 + 3738735*x^5 + 6831825*x^3 + 3828825*x)/(99225*x^8 + 1455300*x^6 + 5675670*x^4 + 8108100*x^2 + 3828825)
// f(9,x)=(307835*x^9 + 4813380*x^7 + 19801782*x^5 + 29609580*x^3 + 14549535*x)/(19845*x^10 + 1091475*x^8 + 9459450*x^6 + 28378350*x^4 + 34459425*x^2 + 14549535)
// f(10,x)=(327680*x^11 + 19225635*x^9 + 175855680*x^7 + 552473922*x^5 + 698377680*x^3 + 305540235*x)/(2401245*x^10 + 52026975*x^8 + 312161850*x^6 + 758107350*x^4 + 800224425*x^2 + 305540235)
// 分子は(n|1)次(n>>1)項、分母は(n+1&~1)次(n+1>>1)項、合わせてn+2項
// テイラー展開よりも収束が速い
// 分母が定数ではないので除算が必要
// 1項ずつ除算するのは効率が悪いので通分して分子の多項式と分母の多項式をそれぞれ計算して最後に割ったほうが速い
// それでも除算が1回必要
//
// チェビシェフ展開
// テイラー展開よりも収束が速い
// 変数変換で|x|<=sqrt(2)-1にしてから展開する
// sqrt(2)-1<|x|のとき変数変換に除算が1回必要
// 変数変換の都合で符号を分離していても奇関数のまま展開した方が収束が速い
//
// tan(x)を高速に計算できる場合
// 組み込み関数を使ってatan(x)の近似値t'を求める
// tan(x)を使ってx'=tan(t')を正確に求める。これは正確なのでatan(x')=t'である
// atan(x)=atan(x')+atan((x-x')/(1+x*x'))
// =t'+atan((x-x')/(1+x*x'))
// (x-x')/(1+x*x')は小さいのでatan((x-x')/(1+x*x'))は速く収束する
//
// CORDIC
// 基本
// 座標(u[k],v[k])を向き+x→+yで角度t[k]だけ回転した座標(u[k+1],v[k+1])は
// u[k+1]=cos(t[k])*u[k]-sin(t[k])*v[k]
// v[k+1]=sin(t[k])*u[k]+cos(t[k])*v[k]
// である
// 原点から見た方向だけが必要で原点からの距離は変化しても構わないとき
// cos(t[k])=1
// sin(t[k])=tan(t[k])
// とおけば
// u[k+1]=u[k]-tan(t[k])*v[k]
// v[k+1]=v[k]+tan(t[k])*u[k]
// となる
// 向き+y→+xのときは
// v[k+1]=cos(t[k])*v[k]-sin(t[k])*u[k]
// u[k+1]=sin(t[k])*v[k]+cos(t[k])*u[k]
// であるから
// u[k+1]=u[k]+tan(t[k])*v[k]
// v[k+1]=v[k]-tan(t[k])*u[k]
// となる
// 準備
// tan(t[k])=1/2^kに固定してt[k]のテーブルを用意する
// t[k]=atan(1/2^k)
// 手順
// 座標(u[0],v[0])ただしu[0]>0が与えられたとき、
// k=0,1,2,…について
// 座標(u[k],v[k])がx軸よりも上にあるとき(v[k]>=0)
// (u[k],v[k])をt[k]だけ右回転した方向にある座標を(u[k+1],v[k+1])とする
// u[k+1]=u[k]-v[k]/2^k
// v[k+1]=v[k]+u[k]/2^k
// 座標(u[k],v[k])がx軸よりも下にあるとき(v[k]<0)
// (u[k],v[k])をt[k]だけ左回転した方向にある座標を(u[k+1],v[k+1])とする
// u[k+1]=u[k]+v[k]/2^k
// v[k+1]=v[k]-u[k]/2^k
// を繰り返すと、座標(u[k],v[k])はx軸に近付いてゆく
// 座標(u[k],v[k])とx軸のなす角はatan(v[k],u[k])であるから、kが十分に大きくなったとき
// 右回転した角度の合計-左回転した角度の合計
// は座標(u[0],v[0])とx軸のなす角、すなわちatan2(v[0],u[0])である
// 高速化1
// atan(1/2^1)≒0.463
// |x|<=sqrt(2)-1≒0.414
// atan(1/2^2)≒0.245
// であるから少なくともk=0とk=1は不要
// 指数部を見てkの開始位置を決めればよい
// k=8あたりまでと仮数部の先頭4bitくらいをテーブル参照で処理することで固定小数点の上位のビットを排除してビット数を確保する
// 高速化2
// x→0のときatan(x)≒x-x^3/3であるから、有効桁数の1/3まで回して結果にv[k]/u[k]を加えてもよい
// しかし、このままだと除算が必要
// t→0のとき1-cos(t)≒t^2/2であるから、u[0]が1などの定数のときは有効桁数の1/2まで回せばu[k]も定数になる
// u==1のときは有効桁数の1/2まで回して結果にv[k]*(1/K)を加えればよい
// 乗算の回数は少ないが加減算の回数が多い
// 1要素の固定小数点のときは速い
// 2要素以上になると固定小数点でもキャリーやボローの処理が加わるため遅くなる
//
// ガウス求積
// atan(x)は積分で表されるのでルジャンドル多項式を用いて近似式を構築することができる
// atan(x)=int[t=0..x]{1/(1+t^2)}
// =1/2*int[t=-x..x]{1/(1+t^2)}
// =x/2*int[t=-1..1]{1/(1+x^2*t^2)}
//
// AGM
// Fast multiple-precision evaluation of elementary functions (1976)
// http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.98.4721
// S=2^(-n/2)
// V=x/(1+sqrt(1+x^2))
// Q=1
// while 1-S>2^(-n) {
// Q=2*Q/(1+S)
// W=2*S*V/(1+V^2)
// W=W/(1+sqrt(1-W^2))
// W=(V+W)/(1-V*W)
// V=W/(1+sqrt(1+W^2))
// S=2*sqrt(S)/(1+S)
// }
// return Q*log((1+V)/(1-V))
// 多倍長演算用。桁数が少ないときは遅い
//
// テイラー展開
// echo read("efp.gp");eval("f(n,x)=sum(k=0,n,(-1)^k*1/(2*k+1)*x^(2*k+1))");a=1-sqrt(2);b=sqrt(2)-1;nmax=27;print1(" // ");for(n=0,nmax,printf("%4d",2*n+1));print();print1(" // ");for(n=0,nmax,printf("%4d",floor(closeness(atan,f(n,x),a,b,10000))));print() | gp -q
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
// 4 7 10 13 16 19 21 24 27 29 32 35 37 40 43 45 48 51 53 56 58 61 64 66 69 71 74 77
//
// 連分数展開
// echo read("efp.gp");eval("g(n,x,k)=k^2*x^2/(2*k+1+if(k<n,g(n,x,k+1),0))");eval("f(n,x)=x/(1+if(n<1,0,g(n,x,1)))");a=1-sqrt(2);b=sqrt(2)-1;nmax=27;print1(" // ");for(n=0,nmax,printf("%4d",2*n+1));print();print1(" // ");for(n=0,nmax,printf("%4d",floor(closeness(atan,f(n,x),a,b,10000))));print() | gp -q
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
// 4 8 13 18 22 27 31 36 41 45 50 55 59 64 69 73 78 83 87 92 97 101 106 111 115 120 125 129
//
// チェビシェフ展開
// echo read("efp.gp");a=1-sqrt(2);b=sqrt(2)-1;nmax=55;print1(" // ");forstep(n=1,nmax,2,printf("%4d",n));print();print1(" // ");forstep(n=1,nmax,2,printf("%4d",floor(closeness(atan,chebyshev(atan,a,b,n),a,b,10000))));print() | gp -q
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
// 4 9 13 18 23 27 32 37 41 46 51 55 60 65 69 74 79 83 88 93 97 102 107 111 116 121 125 130
//
public final EFP atan () {
return this.atan (this);
} //efp.atan()
public final EFP atan (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 2 >= 0) { //atan(±0)=±0,atan(NaN)=NaN
this.flg = xf;
} else {
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (xf >= 0) {
this.sete (ROUNDED_PI_2[epbRoundingMode]).finish (); //atan(+Inf)=pi/2
} else {
this.sete (ROUNDED_NEGPI_2[epbRoundingMode]).finish (); //atan(-Inf)=-pi/2
}
}
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (xe <= -LEN / 2) { //|x|<=2^(-LEN/2) --> atan(x)=x
epbFpsr |= EPB_FPSR_X2; //不正確な結果
int savedFpsr = epbFpsr;
//this.sete (x);
this.flg = xf;
this.epp = xe;
this.dvl = x.dvl;
this.cvl = x.cvl;
if (this.flg < 0) {
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) {
this.nextup (epbRoundingPrec);
}
} else {
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) {
this.nextdown (epbRoundingPrec);
}
}
return this.finish ().correctUnderflow (savedFpsr);
}
if (LEN + 1 <= xe) { //2^(LEN+1)<=|x| --> atan(x)=sgn(x)*pi/2
epbFpsr |= EPB_FPSR_X2; //不正確な結果
return this.sete (ROUNDED_PI_2[epbRoundingMode]).neg (xf < 0);
}
if (false) { //[91] 600ns
this.inner ();
EFP u = new EFP ().iabs (x); //|x|
EFP b;
EFP bw;
EFP t = new EFP ();
if (u.le (DECSQRT2)) { //0<=x<=sqrt(2)-1
b = null; //y=y'
bw = null;
} else if (u.lt (INCSQRT2)) { //sqrt(2)-1<x<1+sqrt(2)
//t.inc (u);
//u.imul2 ().div (t).negdec (); //x'=1-(2*x)/(1+x)
u.div (t.negdec (u), u.inc ()); //x'=(1-x)/(1+x)
b = PI_4; //y=pi/4-y'
bw = PI_4A;
} else { //1+sqrt(2)<=x
u.rcp (); //x'=1/x
b = PI_2; //y=pi/2-y'
bw = PI_2A;
}
if (false) { //テイラー展開
EFP x2 = new EFP (u).isqu (); //x^2
//this.set0 (); //0
this.flg = P | Z;
for (int k = 0; ; k++) {
t.divi (u, 2 * k + 1); //1/(2*k+1)*x^(2*k+1)
if ((k & 1) == 0) {
t.iadd (this, t); //(-1)^k*1/(2*k+1)*x^(2*k+1)
} else {
t.sub (this, t); //(-1)^k*1/(2*k+1)*x^(2*k+1)
}
if (this.eq (t)) {
break;
}
//this.sete (t);
this.flg = t.flg;
this.epp = t.epp;
this.dvl = t.dvl;
this.cvl = t.cvl;
u.imul (x2);
}
} else { //チェビシェフ展開
t.isqu (u); //u^2
this.imul (ATAN_C39, t)
.iadd (ATAN_C37).imul (t)
.iadd (ATAN_C35).imul (t)
.iadd (ATAN_C33).imul (t)
.iadd (ATAN_C31).imul (t)
.iadd (ATAN_C29).imul (t)
.iadd (ATAN_C27).imul (t)
.iadd (ATAN_C25).imul (t)
.iadd (ATAN_C23).imul (t)
.iadd (ATAN_C21).imul (t)
.iadd (ATAN_C19).imul (t)
.iadd (ATAN_C17).imul (t)
.iadd (ATAN_C15).imul (t)
.iadd (ATAN_C13).imul (t)
.iadd (ATAN_C11).imul (t)
.iadd (ATAN_C9).imul (t)
.iadd (ATAN_C7).imul (t)
.iadd (ATAN_C5).imul (t)
.iadd (ATAN_C3).imul (t)
.iadd (ATAN_C1).imul (u);
}
if (b != null) {
this.negsub (b).iadd (bw); //y=pi/4-y'またはy=pi/2-y'
}
return this.outer ().neg (xf < 0);
} else { //tanを使う。[91] 540ns
int savedFpsr = epbFpsr;
this.inner ();
if (this == x) {
x = new EFP (x); //必要なときだけコピーする
}
// 指数部が小さすぎる場合と大きすぎる場合は除いてあるのでこのままdoubleに変換する
// Math.atan(double)を使ってatan(x)の近似値t'を求める
long s = Double.doubleToLongBits (Math.atan (Double.longBitsToDouble ((long) (1023 + x.epp) << 52 | x.dvl << 1 >>> 12)));
EFP tt = new EFP (xf, (int) (s >>> 52) - 1023, MSB | s << 12 >>> 1, 0L); //atan(x)の近似値t'
// tanを使ってatan(x')=t'を満たすx'を求める
EFP xx = new EFP ().tan (tt); //x'=tan(t')
// atan(x)=atan(x')+atan((x-x')/(1+x*x'))を使ってatan(x)を計算する
// (x-x')/(1+x*x')は小さいので1次の項だけ加える
this.imul (x, xx).inc ().rcp ().imul (xx.negsub (x)).outer ().add (tt); //t'+(x-x')/(1+x*x')
return this.originUpperLower (x).correctUnderflow (savedFpsr);
}
} //efp.atan(EFP)
//------------------------------------------------------------------------
//y = y.atan2 (x)
// y=atan2(y,x)
//z = z.atan2 (y, x)
// z=atan2(y,x)
// 逆正接 inverse tangent インバースタンジェント
//
// atan2(y,x)=(isNaN(y)||isNaN(x)?NaN:
// isInfinite(y)&&isInfinite(x)?copySign(x>=+0?pi/4:3*pi/4,y):
// y==0||isInfinite(x)?copySign(x>=+0?0:pi,y):
// isInfinite(y)||x==0?copySign(pi/2,y):
// x>=0?atan(y/x):atan(y/x)+copySign(pi,y))
//
// 定義域
// -inf<=y<=inf
// -inf<=x<=inf
// y==0&&x==0を除く
// (y,x)=(Inf,Inf)などは感覚的にはNaNにするべきだと思うがMath.atan2はpi/4を返す
//
// 値域
// -pi<=atan2(y,x)<=pi
//
public final EFP atan2 (EFP x) {
return this.atan2 (this, x);
} //efp.atan2(EFP)
public final EFP atan2 (EFP y, EFP x) {
int yf = y.flg;
int xf = x.flg;
if ((yf | xf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((yf | xf) << 3 < 0) { //どちらかがNaN
this.flg = N;
} else if ((yf & xf) << 2 < 0) { //両方±Inf
epbFpsr |= EPB_FPSR_X2; //不正確な結果
this.sete (yf >= 0 ? xf >= 0 ? PI_4 : PI3_4 : xf >= 0 ? NEGPI_4 : NEGPI3_4).finish ();
} else if (yf << 1 < 0 || xf << 2 < 0) { //yが±0またはxが±Inf
if (xf >= 0) {
this.sete (yf >= 0 ? ZERO : NEGZERO);
} else {
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (yf >= 0) {
this.sete (ROUNDED_PI[epbRoundingMode]).finish ();
} else {
this.sete (ROUNDED_NEGPI[epbRoundingMode]).finish ();
}
}
} else { //yが±Infまたはxが±0
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (yf >= 0) {
this.sete (ROUNDED_PI_2[epbRoundingMode]).finish ();
} else {
this.sete (ROUNDED_NEGPI_2[epbRoundingMode]).finish ();
}
}
return this;
}
//両方±0,±Inf,NaN以外
return (xf < 0 ?
this.inner ().div (y, x).atan ().outer ().add (yf >= 0 ? PI : NEGPI) :
this.inner ().div (y, x).outer ().atan ());
} //efp.atan2(EFP,EFP)
//------------------------------------------------------------------------
//x = x.atanh ()
// x=atanh(x)
//y = y.atanh (x)
// y=atanh(x)
// 逆双曲線正接 inverse hyperbolic tangent インバースハイパボリックタンジェント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{atanh($_[0])});print$g"
// echo read("efp.gp");graph(atanh) | gp -q
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | * |
// | | * |
// | | * |
// | | * |
// + + * +
// | | * |
// | | * |
// | | * |
// | | * |
// + + * +
// | | ** |
// | | * |
// | | * |
// | | ** |
// + + ** +
// | | ** |
// | | ** |
// | | *** |
// | |*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | ***| |
// | *** | |
// | ** | |
// | ** | |
// + ** + +
// | ** | |
// | * | |
// | * | |
// | ** | |
// + * + +
// | * | |
// | * | |
// | * | |
// | * | |
// + * + +
// | * | |
// | * | |
// | * | |
// | * | |
// +---------+---------+---------*---------+---------+---------+---------+---------+
//
// 定義域
// -1<=x<=1
//
// 値域
// -inf<=y<=inf
//
// テイラー展開
// atanh(x)=sum[k=0..inf]{x^(2*k+1)/(2*k+1)}
// > coeff(sub(a=0,for n:=0:13 sum sub(x=a,df(atanh(x),x,n))/factorial(n)*(x-a)^n),x);
// 1 1 1 1 1 1
// {0,1,0,---,0,---,0,---,0,---,0,----,0,----}
// 3 5 7 9 11 13
//
// 対数関数との関係
// atanh(x)=x>=0?log((1+x)/(1-x))/2:-log((1-x)/(1+x))/2
//
// 変数変換1
// 次のように変形する
// atanh(x)=log((1+x)/(1-x))/2
// =(log((1+x)/(1-x))-log(2^n)+log(2^n))/2
// =log((1+x)/(2^n*(1-x)))/2+n*log(2)/2
// ここで
// (1+x)/(2^n*(1-x))=(1+t)/(1-t)
// となるようにtを定める
// atanh(x)=log((1+t)/(1-t))/2+n*log(2)/2
// =atanh(t)+n*log(2)/2
// tをxで表現する
// 1+t=(1+x)/(2^n*(1-x))*(1-t)
// (1+(1+x)/(2^n*(1-x)))*t=(1+x)/(2^n*(1-x))-1
// t=((1+x)/(2^n*(1-x))-1)/(1+(1+x)/(2^n*(1-x)))
// =((1+x)-2^n*(1-x))/(2^n*(1-x)+(1+x))
// =(1+x-2^n+2^n*x)/(2^n-2^n*x+1+x)
// =((2^n+1)*x-(2^n-1))/((2^n+1)-(2^n-1)*x)
// =(((2^n+1)*x-(2^n-1))+((2^n+1)-(2^n-1)*x))/((2^n+1)-(2^n-1)*x)-1
// =((2^n+1)*x-(2^n-1)+(2^n+1)-(2^n-1)*x)/((2^n+1)-(2^n-1)*x)-1
// =(2*x+2)/((2^n+1)-(2^n-1)*x)-1
// =2*(1+x)/((2^n+1)-(2^n-1)*x)-1
// xをtで表現する
// 1+x=2^n*(1+t)/(1-t)*(1-x)
// (1+2^n*(1+t)/(1-t))*x=2^n*(1+t)/(1-t)-1
// x=(2^n*(1+t)/(1-t)-1)/(1+2^n*(1+t)/(1-t))
// =(2^n*(1+t)-(1-t))/((1-t)+2^n*(1+t))
// =(2^n+2^n*t-1+t)/(1-t+2^n+2^n*t)
// =((2^n+1)*t+(2^n-1))/((2^n+1)+(2^n-1)*t)
// =1-(((2^n+1)+(2^n-1)*t)-((2^n+1)*t+(2^n-1)))/((2^n+1)+(2^n-1)*t)
// =1-((2^n+1)+(2^n-1)*t-(2^n+1)*t-(2^n-1))/((2^n+1)+(2^n-1)*t)
// =1-(2-2*t)/((2^n+1)+(2^n-1)*t)
// =1-2*(1-t)/((2^n+1)+(2^n-1)*t)
//
// 変数変換2
// t=0となるxで分割する
// x=1-2*(1-0)/((2^n+1)+(2^n-1)*0)
// =1-2/(2^n+1)
// したがって、|x|<1を
// 1-2/(2^n+1)={1/3,3/5,7/9,15/17,31/33,...}
// で分割すると、|t|<=1/3になる
// perl -e "use POSIX;sub log2{my($x)=@_;log($x)/log(2);}printf' // %4s%10s%10s%11s%18s%c','n','x','1-x','log2(1-x)','floor(log2(1-x))',10;for$n(0..10){$x=1-2/(2**$n+1);printf' // %4d%10.6f%10.6f%11.6f%18d%c',$n,$x,1-$x,log2(1-$x),floor(log2(1-$x)),10}"
// n x 1-x log2(1-x) floor(log2(1-x))
// 0 0.000000 1.000000 0.000000 0
// 1 0.333333 0.666667 -0.584963 -1
// 2 0.600000 0.400000 -1.321928 -2
// 3 0.777778 0.222222 -2.169925 -3
// 4 0.882353 0.117647 -3.087463 -4
// 5 0.939394 0.060606 -4.044394 -5
// 6 0.969231 0.030769 -5.022368 -6
// 7 0.984496 0.015504 -6.011227 -7
// 8 0.992218 0.007782 -7.005625 -8
// 9 0.996101 0.003899 -8.002815 -9
// 10 0.998049 0.001951 -9.001408 -10
// 手順
// n=-floor(log2(1-|x|)); //1-xの指数部を取り出して符号を反転したもの。1以上
// if(|x|<=1-2/(2^n+1)){ //1-2/(2^n+1)は高々LEN通りしかないのでテーブルに列挙しておく
// n--;
// }
// t=(1+|x|-2^n*(1-|x|))/(1+|x|+2^n*(1-|x|))
// //tで多項式を計算する
// //n*log(2)/2を加える
// //xの符号を掛ける
// x→tのグラフ
// perl -e "use POSIX;use Graph;sub log2{my($x)=@_;log($x)/log(2);}$g=new Graph(80,40,-1,1,-1,1);$g->grid();$g->func(sub{$x=$_[0];if(1<=abs($x)){$t=undef;}else{$n=-floor(log2(1-abs($x)));if(abs($x)<=1-2/(2**$n+1)){$n--;}$t=($x<=>0)*(1+abs($x)-2**$n*(1-abs($x)))/(1+abs($x)+2**$n*(1-abs($x)));}$t});print$g"
// +
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// | * * * * ***
// | *** *** ** * ****
// | *** ** ** ** ****
// | *** *** ** * ****
// | *** ** ** ** *****
// | *** *** ** ** * ***
// |*** *** ** ** * ***
// ***-**---*-----**---------**-----------***-----------**---------**-----*---**-***
// *** * ** ** *** ***|
// *** * ** ** *** *** |
// ***** ** ** ** *** |
// **** * ** *** *** |
// **** ** ** ** *** |
// **** * ** *** *** |
// *** * * * * |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// +
//
// 変数変換3
// -r<=t<=rとなるxの範囲が重ならないように分割する
// nのときt=rに対応するxとn+1のときt=-rに対応するxが等しくなるようにする
// 1-2*(1-r)/((2^n+1)+(2^n-1)*r)=1-2*(1-(-r))/((2^(n+1)+1)+(2^(n+1)-1)*(-r))
// (1-r)/((2^n+1)+(2^n-1)*r)=(1+r)/((2*2^n+1)-(2*2^n-1)*r)
// (1-r)*((2*2^n+1)-(2*2^n-1)*r)-(1+r)*((2^n+1)+(2^n-1)*r)=0
// ((2*2^n+1)-(2*2^n-1)*r)-((2*2^n+1)-(2*2^n-1)*r)*r-((2^n+1)+(2^n-1)*r)-((2^n+1)+(2^n-1)*r)*r=0
// (2*2^n+1)-(2*2^n-1)*r-(2*2^n+1)*r+(2*2^n-1)*r^2-(2^n+1)-(2^n-1)*r-(2^n+1)*r-(2^n-1)*r^2=0
// (2*2^n-1)*r^2-(2^n-1)*r^2-(2*2^n-1)*r-(2*2^n+1)*r-(2^n-1)*r-(2^n+1)*r+(2*2^n+1)-(2^n+1)=0
// (2*2^n-1-2^n+1)*r^2-(2*2^n-1+2*2^n+1+2^n-1+2^n+1)*r+(2*2^n+1-2^n-1)=0
// (2^n)*r^2-(6*2^n)*r+(2^n)=0
// r^2-6*r+1=0
// r=3+/-2*sqrt(2)
// r=3-2*sqrt(2)
// t=rのときのxは
// x=1-2*(1-r)/((2^n+1)+(2^n-1)*r)
// =1-2*(1-(3-2*sqrt(2)))/((2^n+1)+(2^n-1)*(3-2*sqrt(2)))
// =1-2*(sqrt(2)-1)/((2*2^n-1)-(2^n-1)*sqrt(2))
// =1-2*(sqrt(2)-1)*((2*2^n-1)+(2^n-1)*sqrt(2))/((2*2^n-1)-(2^n-1)*sqrt(2))/((2*2^n-1)+(2^n-1)*sqrt(2))
// =1-2*((2*2^n-1)*sqrt(2)+2*(2^n-1)-(2*2^n-1)-(2^n-1)*sqrt(2))/((2*2^n-1)^2-2*(2^n-1)^2)
// =1-2*((2*2^n-1-2^n+1)*sqrt(2)+(2*2^n-2-2*2^n+1))/(4*4^n-4*2^n+1-2*4^n+4*2^n-2)
// =1-2*(2^n*sqrt(2)-1)/(2*4^n-1)
// =1-2*(2^n*sqrt(2)-1)/((2^n*sqrt(2)-1)*(2^n*sqrt(2)+1))
// =1-2/(2^n*sqrt(2)+1)
// したがって、|x|<1を
// 1-2/(2^n*sqrt(2)+1)={3-2*sqrt(2),(9-4*sqrt(2))/7,(33-8*sqrt(2))/31,(129-16*sqrt(2))/127,(513-32*sqrt(2))/511,...}
// で分割すると、|t|<=3-2*sqrt(2)になる
// perl -e "use POSIX;sub log2{my($x)=@_;log($x)/log(2);}printf' // %4s%10s%10s%11s%18s%c','n','x','1-x','log2(1-x)','floor(log2(1-x))',10;for$n(0..10){$x=1-2/(2**$n*sqrt(2)+1);printf' // %4d%10.6f%10.6f%11.6f%18d%c',$n,$x,1-$x,log2(1-$x),floor(log2(1-$x)),10}"
// n x 1-x log2(1-x) floor(log2(1-x))
// 0 0.171573 0.828427 -0.271553 -1
// 1 0.477592 0.522408 -0.936752 -1
// 2 0.699558 0.300442 -1.734841 -2
// 3 0.837579 0.162421 -2.622193 -3
// 4 0.915353 0.084647 -3.562390 -4
// 5 0.956761 0.043239 -4.531532 -5
// 6 0.978144 0.021856 -5.515852 -6
// 7 0.989012 0.010988 -6.507948 -7
// 8 0.994491 0.005509 -7.503979 -8
// 9 0.997242 0.002758 -8.501991 -9
// 10 0.998620 0.001380 -9.500996 -10
// 手順
// if(|x|<=3-2*sqrt(2)){
// //変数変換を行わない
// //|x|<0.5に区切りが2箇所あるのでn=0を分けなければならない
// //|x|が小さすぎると1-|x|が1になってしまうので1-|x|を経由する方法では正確に計算できない
// //xで多項式を計算する
// }else{
// n=-floor(log2(1-|x|)); //1-|x|の指数部を取り出して符号を反転したもの。1以上
// if(1-2/(2^n*sqrt(2)+1)<|x|){ //1-2/(2^n*sqrt(2)+1)は高々LEN通りしかないのでテーブルに列挙しておく
// n++;
// }
// t=(1+|x|-2^n*(1-|x|))/(1+|x|+2^n*(1-|x|))
// //tで多項式を計算する
// //n*log(2)/2を加える
// //xの符号を掛ける
// }
// x→tのグラフ
// perl -e "use POSIX;use Graph;sub log2{my($x)=@_;log($x)/log(2);}$g=new Graph(80,40,-1,1,-1,1);$g->grid();$g->func(sub{my$x=$_[0];if(1<=abs($x)){$t=undef;}elsif(abs($x)<=3-2*sqrt(2)){$t=$x;}else{$n=-floor(log2(1-abs($x)));if(1-2/(2**$n*sqrt(2)+1)<abs($x)){$n++;}$t=($x<=>0)*(1+abs($x)-2**$n*(1-abs($x)))/(1+abs($x)+2**$n*(1-abs($x)));}$t});print$g"
// +
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// **** * ** *** *** | *** ** ** ** *****
// **** ** ** ** *** | *** *** ** ** * ***
// ** * * ** ** ** |*** *** ** ** * ***
// ******---*-----***--------***----------***----------***--------***-----*---******
// *** * ** ** *** ***| ** ** ** * * **
// *** * ** ** *** *** | *** ** ** ** ****
// ***** ** ** ** *** | *** *** ** * ****
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// +
//
// チェビシェフ展開
// |x|<3-2*sqrt(2)
// echo read("efp.gp");a=2*sqrt(2)-3;b=-a;nmax=55;print1(" // ");forstep(n=1,nmax,2,printf("%4d",n));print();print1(" // ");forstep(n=1,nmax,2,printf("%4d",floor(closeness(atanh,chebyshev(atanh,a,b,n),a,b,10000))));print() | gp -q
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55
// 7 14 21 28 35 42 49 56 63 70 77 84 91 98 105 113 120 127 134 141 148 155 162 169 176 183 190 197
//
// CORDIC
// atanh(y/x)のときxとyを両方入力することで除算が不要になる
// tanh(t)=sinh(t)/cosh(t)
// t=atanh(sinh(t)/cosh(t))
//
public final EFP atanh () {
return this.atanh (this);
} //efp.atanh()
public final EFP atanh (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 2 < 0) { //±Inf
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //atanh(±Inf)=NaN
} else {
this.flg = xf; //atanh(±0)=±0, atanh(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (0 <= xe) { //1<=|x|
if (xe == 0 && x.dvl == MSB && x.cvl == 0L) { //|x|==1
epbFpsr |= EPB_FPSR_DZ;
epbExceptionOperandExponent = xf | 0x3fff << 16;
epbExceptionOperandMantissa = 0x8000000000000000L;
this.flg = xf | I;
} else { //1<|x|
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
this.flg = N;
}
return this;
}
//|x|<1
if (false) { //logを使う。[89] 540ns
if (x.epp < -4) { //|x|<0.0625
EFP x2 = new EFP ().inner ().isqu (x); //x^2
return this.imul (ATANH_C19, x2)
.iadd (ATANH_C17).imul (x2)
.iadd (ATANH_C15).imul (x2)
.iadd (ATANH_C13).imul (x2)
.iadd (ATANH_C11).imul (x2)
.iadd (ATANH_C9).imul (x2)
.iadd (ATANH_C7).imul (x2)
.iadd (ATANH_C5).imul (x2)
.iadd (ATANH_C3).imul (x2)
.iadd (ATANH_C1).outer ().mul (x);
}
//0.0625<=|x|
this.inner ().iabs (x); //|x|
EFP t = new EFP ().negdec (this); //1-|x|
return this.inc ().div (t).log ().idiv2 ().outer ().neg (xf < 0); //sgn(x)*log((1+|x|)/(1-|x|))/2
} else { //|x|<3-2*sqrt(2)に畳む。[90] 425ns
int savedFpsr = epbFpsr;
this.inner ();
long xd = x.dvl;
long xc = x.cvl;
if (xe <= -3 && (xe < -3 || xd <= 0xafb0ccc06219b7baL)) { //|x|<=3-2*sqrt(2)。xcの比較は省略
if (this == x) {
x = new EFP (x); //必要なときだけコピーする
}
EFP x2 = new EFP ().isqu (x); //x^2
/*
return this.imul (ATH_C25, x2)
.iadd (ATH_C23).imul (x2)
.iadd (ATH_C21).imul (x2)
.iadd (ATH_C19).imul (x2)
.iadd (ATH_C17).imul (x2)
.iadd (ATH_C15).imul (x2)
.iadd (ATH_C13).imul (x2)
.iadd (ATH_C11).imul (x2)
.iadd (ATH_C9).imul (x2)
.iadd (ATH_C7).imul (x2)
.iadd (ATH_C5).imul (x2)
.iadd (ATH_C3).imul (x2)
.iadd (ATH_C1).outer ().mul (x);
*/
this.imul (ATH_C27, x2)
.iadd (ATH_C25).imul (x2)
.iadd (ATH_C23).imul (x2)
.iadd (ATH_C21).imul (x2)
.iadd (ATH_C19).imul (x2)
.iadd (ATH_C17).imul (x2)
.iadd (ATH_C15).imul (x2)
.iadd (ATH_C13).imul (x2)
.iadd (ATH_C11).imul (x2)
.iadd (ATH_C9).imul (x2)
.iadd (ATH_C7).imul (x2)
.iadd (ATH_C5).imul (x2)
.iadd (ATH_C3).imul (x2)
.iadd (ATH_C1).outer ().mul (x);
return this.originLowerUpper (x).correctUnderflow (savedFpsr);
}
EFP a = new EFP (P, xe, xd, xc); //|x|
EFP t = new EFP ().negdec (a); //1-|x|
int n = -t.epp; //-floor(log2(1-|x|))
if (ATH_T[n].lt (a)) { //1-2/(2^n*sqrt(2)+1)<|x|
n++;
}
EFP u = new EFP ().iadd (a.inc (), t.shl (n));
t.negsub (a).div (u); //(1+|x|-2^n*(1-|x|))/(1+|x|+2^n*(1-|x|))
a.isqu (t); //t^2
/*
return this.imul (ATH_C25, a)
.iadd (ATH_C23).imul (a)
.iadd (ATH_C21).imul (a)
.iadd (ATH_C19).imul (a)
.iadd (ATH_C17).imul (a)
.iadd (ATH_C15).imul (a)
.iadd (ATH_C13).imul (a)
.iadd (ATH_C11).imul (a)
.iadd (ATH_C9).imul (a)
.iadd (ATH_C7).imul (a)
.iadd (ATH_C5).imul (a)
.iadd (ATH_C3).imul (a)
.iadd (ATH_C1).imul (t).iadd (t.muli (LOG_2_2, n)).outer ().neg (xf < 0); //+n*log(2)/2
*/
return this.imul (ATH_C27, a)
.iadd (ATH_C25).imul (a)
.iadd (ATH_C23).imul (a)
.iadd (ATH_C21).imul (a)
.iadd (ATH_C19).imul (a)
.iadd (ATH_C17).imul (a)
.iadd (ATH_C15).imul (a)
.iadd (ATH_C13).imul (a)
.iadd (ATH_C11).imul (a)
.iadd (ATH_C9).imul (a)
.iadd (ATH_C7).imul (a)
.iadd (ATH_C5).imul (a)
.iadd (ATH_C3).imul (a)
.iadd (ATH_C1).imul (t).iadd (t.muli (LOG_2_2, n)).outer ().neg (xf < 0); //+n*log(2)/2
}
} //efp.atanh(EFP)
//------------------------------------------------------------------------
//x = x.cbrt ()
// x=x^(1/3)
//y = y.cbrt (x)
// y=x^(1/3)
// 1/3乗(立方根)
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{($_[0]<=>0)*abs($_[0])**(1/3)});print$g"
// echo read("efp.gp");eval("cbrt(x)=sign(x)*abs(x)^(1/3)");graph(cbrt) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | *******
// | | ************* |
// | | ********** |
// + + ******* +
// | | ***** |
// | |*** |
// | ** |
// | * |
// +---------+---------+---------+---------*---------+---------+---------+---------+
// | * |
// | ** |
// | ***| |
// | ***** | |
// + ******* + +
// | ********** | |
// | ************* | |
// ******* | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
// ニュートン法
// f(t)=t^3-x
// f'(t)=3*t^2
// t'=t-f(t)/f'(t)
// =t-(t^3-x)/(3*t^2)
// =(2*t^3+x)/(3*t^2)
// =(2*t+x/t^2)/3
//
public final EFP cbrt () {
return this.cbrt (this);
} //efp.cbrt()
public final EFP cbrt (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
this.flg = xf;
return this;
}
//±0,±Inf,NaN以外
if (false) { //ニュートン法。[90] 1095.4ns
this.inner ();
EFP s = new EFP ().sgn (x);
EFP a = new EFP ().iabs (x);
EFP t = new EFP ().iadd (TWO, a).div3 (); //t=(2+a)/3
EFP w = new EFP ();
do {
//this.sete (t);
this.flg = t.flg;
this.epp = t.epp;
this.dvl = t.dvl;
this.cvl = t.cvl;
w.isqu (t).mul3 (); //3*t^2
t.cub ().imul2 ().iadd (a).div (w); //t=(2*t^3+a)/(3*t^2)
} while (this.gt (t));
return this.outer ().mul (s);
} else { //Math.cbrtを使う。[91] 214ns
this.inner ();
int xe = x.epp; //-32768..32767
int xe3 = (int) (xe * 43691L >> 17); //xe / 3
long s = Double.doubleToLongBits (Math.cbrt (Double.longBitsToDouble ((long) (1023 + (xe - xe3 * 3)) << 52 | x.dvl << 1 >>> 12)));
EFP t = new EFP (P, (int) (s >>> 52) - 1023 + xe3, MSB | s << 12 >>> 1, 0L);
EFP t2 = new EFP ().imul2 (t);
t2.flg |= xf;
return this.iadd (t2, t.isqu ().rcpdiv (x)).outer ().div3 (); //(2*t+x/t^2)/3
}
} //efp.cbrt(EFP)
//------------------------------------------------------------------------
//x = x.ceil ()
// x=ceil(x)
//y = y.ceil (x)
// y=ceil(x)
// 天井関数 ceiling function
//
// グラフ
// perl -e "use POSIX;use Graph;$g=new Graph();$g->grid();$g->func(sub{ceil($_[0])});print$g"
// echo read("efp.gp");graph(ceil) | gp -q
// +---------+---------+---------+---------+---------+---------+---------***********
// | | |
// | | |
// | | |
// | | |
// + + *********** +
// | | |
// | | |
// | | |
// | | |
// + + *********** +
// | | |
// | | |
// | | |
// | | |
// + *********** +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------***********---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + *********** + +
// | | |
// | | |
// | | |
// | | |
// + *********** + +
// | | |
// | | |
// | | |
// | | |
// *********** + +
// | | |
// | | |
// | | |
// | | |
// *---------+---------+---------+---------+---------+---------+---------+---------+
//
public final EFP ceil () {
return this.ceil (this);
} //efp.ceil()
public final EFP ceil (EFP x) { //2.8ns
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
this.flg = xf;
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (xe < 0) { //すべて小数部
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (xf < 0) { //ceil(-1<x<0)=-0
this.flg = M | Z;
} else { //ceil(0<x<1)=+1
this.flg = P;
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
}
return this;
}
//整数部がある
long xd = x.dvl;
long xc = x.cvl;
long m = MSB >> xe; //整数部のマスク。符号に注意
if (xf < 0) { //ceil(x<0)=trunc(x)。小数部を切り捨てる
if (xe <= 63) { //0..63。dの途中または末尾まで整数部
if ((xd & ~m | xc) != 0L) { //小数部が0ではない
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xd &= m; //小数部を切り捨てる
xc = 0L;
}
} else if (xe <= LEN - 2) { //64..90。cの途中まで整数部
if ((xc & ~m) != 0L) { //小数部が0ではない
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xc &= m; //小数部を切り捨てる
}
}
//すべて整数部のときはそのまま
} else { //ceil(0<x)。小数部を切り捨てる。小数部が0でなかったときは絶対値に1を加える
if (xe <= 63) { //0..63。dの途中または末尾まで整数部
long t = xd; //保存して
xd &= m; //小数部を切り捨てる
if (((t ^ xd) | xc) != 0L) { //小数部が0でなかった
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xd -= m; //絶対値に1を加える。符号に注意
if (xd >= 0L) { //dから溢れた
xd = MSB;
xe++;
if ((short) xe != xe) { //オーバーフローした
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = xf;
epbExceptionOperandMantissa = xd;
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | xf >>> 31]).finish (); //±Inf
}
}
xc = 0L;
}
//小数部が0のときはそのまま
} else if (xe <= LEN - 2) { //64..90。cの途中まで整数部
long t = xc; //保存して
xc &= m; //小数部を切り捨てる
if ((t ^ xc) != 0L) { //小数部が0でなかった
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xc -= m; //絶対値に1を加える。符号に注意
if ((t ^ xc) < 0L) { //cから溢れた
xd++;
if (xd >= 0L) { //dから溢れた
xd = MSB;
xe++;
if ((short) xe != xe) { //オーバーフローした
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = xf;
epbExceptionOperandMantissa = xd;
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | xf >>> 31]).finish (); //±Inf
}
}
}
}
}
//すべて整数部のときはそのまま
}
return this.finish (xf, xe, xd, xc, 0L);
} //efp.ceil(EFP)
//------------------------------------------------------------------------
//s = x.cmp (y)
// s=x<=>y
// 比較
//
// -Inf==-Inf<-x<-0==+0<+x<+Inf==+Inf
//
// NaNの扱い
// どちらかがNaNのときは0を返す
// どちらかがNaNのときにNaNを返すのはx.sgnsub(y)
//
// ±0の扱い
// 両方が±0のときは符号に関係なく0を返す
//
// 関係演算子および等価演算子との違い
// doubleのNaNはNaNを含むすべての数と等しくなく大きくなく小さくもないので-1,0,1に分類できない
//
// x.compareTo(y)との違い
// x.compareTo(y)はx.equals(y)と一貫性を保つためにNaNを含むすべての数について大小関係が定められている
// -Inf==-Inf<x<-0<+0<+x<+Inf==+Inf<NaN
// ((Double)x).compareTo(y)とDouble.compare(double,double)も同様
//
// xn/xd<=>yn/yd
// =xn*yd<=>xd*yn (xd>0,yd>0)
//
public int cmp (EFP y) {
int xf = this.flg;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
//return ((xf | yf) << 3 < 0 || (xf & yf) << 1 < 0 || xf == yf ? 0 : //どちらかがNaNまたは両方±0または両方-Infまたは両方+Inf
// (xf ^ yf) < 0 ? xf >= 0 ? 1 : -1 : //両方NaN以外でどちらかが±0,±Infで符号が違う
// xf == (P | I) || yf == (P | Z) || xf == (M | Z) || yf == (M | I) ? 1 : -1); //両方NaN以外でどちらかが±0,±Infで符号が同じ
return EFP_CMP_TABLE[xf >>> 28] << (yf >>> 28 - 1) >> 30;
}
//両方±0,±Inf,NaN以外
if (xf != yf) { //両方±0,±Inf,NaN以外で符号が違う
return xf >= 0 ? 1 : -1;
}
//両方±0,±Inf,NaN以外で符号が同じ
int s;
long t;
return (xf >= 0 ? 1 : -1) * ((s = this.epp - y.epp) != 0 ? s >= 0 ? 1 : -1 :
(t = this.dvl - y.dvl) != 0L ? t >= 0L ? 1 : -1 :
(t = (this.cvl >>> 1) - (y.cvl >>> 1)) != 0L ? t >= 0L ? 1 : -1 :
0);
} //efp.cmp(EFP)
//------------------------------------------------------------------------
//s = x.cmp0 ()
// s=x<=>0
// 0との比較
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]<=>0});print$g"
// echo read("efp.gp");graph(sign) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + *****************************************
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------*---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// ***************************************** +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// x.cmp(0)と同じ
//
public int cmp0 () {
int xf = this.flg;
return xf << 3 < 0 || xf << 1 < 0 ? 0 : xf >= 0 ? 1 : -1;
} //efp.cmp0()
//------------------------------------------------------------------------
//s = x.cmp1 ()
// s=x<=>1
// 1との比較
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]<=>1});print$g"
// echo read("efp.gp");eval("cmp1(x)=sign(x-1)");graph(cmp1) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + *******************************
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------*---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// *************************************************** +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// x.cmp(1)と同じ
//
public int cmp1 () {
int xf = this.flg;
if (xf != 0) { //-x,±0,±Inf,NaN
return xf << 3 < 0 ? 0 : (xf | xf << 1) < 0 ? -1 : 1;
}
//+x
int xe = this.epp; //xの指数
return xe < 0 ? -1 : xe == 0 && this.dvl == MSB && this.cvl == 0L ? 0 : 1;
} //efp.cmp1()
//------------------------------------------------------------------------
//s = x.cmp1abs ()
// s=|x|<=>1
// 絶対値と1の比較
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{abs($_[0])<=>1});print$g"
// echo read("efp.gp");eval("cmp1abs(x)=sign(abs(x)-1)");graph(cmp1abs) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// ******************************* + *******************************
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------*---------+---------*---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + ********************* +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// t.abs(x).cmp1()と同じ
//
public int cmp1abs () {
int xf = this.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
return xf << 3 < 0 ? 0 : xf << 1 < 0 ? -1 : 1;
}
//±0,±Inf,NaN以外
int xe = this.epp; //xの指数
return xe < 0 ? -1 : xe == 0 && this.dvl == MSB && this.cvl == 0L ? 0 : 1;
} //efp.cmp1abs()
//------------------------------------------------------------------------
//s = x.cmpabs (y)
// s=|x|<=>|y|
// 絶対値比較
//
public int cmpabs (EFP y) {
int xf = this.flg & ~M;
int yf = y.flg & ~M;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
return EFP_CMP_TABLE[xf >>> 28] << (yf >>> 28 - 1) >> 30;
}
//両方±0,±Inf,NaN以外
int s;
long t;
return ((s = this.epp - y.epp) != 0 ? s >= 0 ? 1 : -1 :
(t = this.dvl - y.dvl) != 0L ? t >= 0L ? 1 : -1 :
(t = (this.cvl >>> 1) - (y.cvl >>> 1)) != 0L ? t >= 0L ? 1 : -1 :
0);
} //efp.cmpabs(EFP)
//------------------------------------------------------------------------
//s = x.compareTo (y)
// s=x<=>y
// 比較
//
// -Inf==-Inf<-x<-0<+0<+x<+Inf==+Inf<NaN==NaN
//
// equalsであるオブジェクトはcompareToが0であることが強く推奨される
// 同じクラスだがequalsでないオブジェクトはcompareToが0でないことが強く推奨される
//
@Override public int compareTo (EFP y) {
EFP x = this;
int xf = x.flg;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
//return (xf == yf ? 0 : //両方-Infまたは両方-0または両方+0または両方+Infまたは両方NaN
// (xf | yf) << 3 < 0 ? xf << 3 < 0 ? 1 : -1 : //どちらか一方がNaN
// (xf ^ yf) < 0 ? xf >= 0 ? 1 : -1 : //両方NaN以外でどちらかが±0,±Infで符号が違う
// xf == (P | I) || yf == (P | Z) || xf == (M | Z) || yf == (M | I) ? 1 : -1); //両方NaN以外でどちらかが±0,±Infで符号が同じ
return EFP_COMPARE_TABLE[xf >>> 28] << (yf >>> 28 - 1) >> 30;
}
//両方±0,±Inf,NaN以外
if (xf != yf) { //両方±0,±Inf,NaN以外で符号が違う
return xf >= 0 ? 1 : -1;
}
//両方±0,±Inf,NaN以外で符号が同じ
int s;
long t;
return (xf >= 0 ? 1 : -1) * ((s = x.epp - y.epp) != 0 ? s >= 0 ? 1 : -1 :
(t = x.dvl - y.dvl) != 0L ? t >= 0L ? 1 : -1 :
(t = (x.cvl >>> 1) - (y.cvl >>> 1)) != 0L ? t >= 0L ? 1 : -1 :
0);
} //efp.compareTo(EFP)
//------------------------------------------------------------------------
//x = x.cos ()
// x=cos(x)
//y = y.cos (x)
// y=cos(x)
// 余弦 cosine コサイン
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{cos($_[0])});print$g"
// echo read("efp.gp");graph(cos) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + *********** +
// | **** | **** |
// | *** | *** |
// | **** | **** |
// | *** | *** |
// +---------+---------+--***----+---------+---------+----***--+---------+---------+
// | *** | *** |
// | *** | *** |
// ** *** | *** **
// |**** ***** | ***** ****|
// + ********** + ********** +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -1<=y<=1
//
// 三角関数のとの関係
// cos(x)=(1-tan(x/2)^2)/(1+tan(x/2)^2)
//
// 変数変換
// 収束を速くするために|x|<=pi/4にする
// cos(x)=-sin(x-pi/2)
// =-cos(x-pi)
// =sin(x-3*pi/2)
// =cos(x-2*pi)
// -sin(x-pi/2)
// k=1
// │ ←
// k=2↓\ │ /
// \ │ /
// \│/
// -cos(x-pi) ────・──── cos(x)
// /│\
// / │ \
// / │ \↑k=0
// → │
// k=3
// sin(x-3*pi/2)
//
// メモ
// k=round(x/(pi/2))としてx-k*pi/2を計算するとき、pi/2の近似値3217/2048を用いて
// x-k*pi/2=x-k*(3217/2048+(pi/2-3217/2048))
// =x-k*3217/2048+k*(pi/2-3217/2048)
// を計算するという方法がある
// kは普通は桁数の少ない整数で2048は2の累乗なのでk*3217/2048は正確に計算できる
// xとk*3217/2048はほぼ同じ値なのでx-k*3217/2048は桁落ちを発生させながら正確に計算できる
// k*(pi/2-3217/2048)で発生する誤差は小さい
// echo Pi/2-3217/2048 | gp -q
// -4.4544551033807686783083602485579023568 E-6
//
// テイラー展開
// cos(x)=1-x^2/2!+x^4/4!-x^6/6!+...
// f(n,x)=sum(k=0,n,(-1)^k*x^(2*k)/(2*k)!)
// echo read("efp.gp");eval("f(h,x)=sum(k=0,h,(-1)^k/(2*k)!*x^(2*k))");a=-Pi/4;b=-a;hmax=27;print1(" // ");for(h=0,hmax,n=2*h;printf("%4d",n));print();print1(" // ");for(h=0,hmax,n=2*h;printf("%4d",floor(closeness(cos,f(h,x),a,b,10000))));print() | gp -q
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
// 1 5 11 17 24 32 40 49 58 67 77 86 96 107 117 128 139 150 161 172 184 195 207 219 231 243 255 267
//
// チェビシェフ展開
// echo read("efp.gp");a=-Pi/4;b=-a;hmax=27;print1(" // ");for(h=0,hmax,n=2*h;printf("%4d",n));print();print1(" // ");for(h=0,hmax,n=2*h;printf("%4d",floor(closeness(cos,chebyshev(cos,a,b,n),a,b,10000))));print() | gp -q
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
// 2 8 16 24 33 43 53 64 75 86 98 109 121 134 146 159 172 185 198 211 225 238 252 266 280 294 308 322
//
public final EFP cos () {
return this.cos (this);
} //efp.cos()
public final EFP cos (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
this.flg = P; //cos(±0)=1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else if (xf << 2 < 0) { //±Inf
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //cos(±Inf)=NaN
} else { //NaN
this.flg = N; //cos(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
this.inner ();
EFP u = new EFP ();
EFP u2 = new EFP ();
int k = u.ieeerempi2 (x); //-pi/2<=u<=pi/2。kはx-uの象限
if (false) { //テイラー展開
EFP s = new EFP ();
EFP t = new EFP ();
u2.isqu (u); //u^2
if ((k & 1) != 0) { //sin
//s.sete (u); //(-1)^k*x^(2*k+1)/(2*k+1)!
s.flg = u.flg;
s.epp = u.epp;
s.dvl = u.dvl;
s.cvl = u.cvl;
//t.set0 ();
t.flg = P | Z;
//this.sete (s);
this.flg = s.flg;
this.epp = s.epp;
this.dvl = s.dvl;
this.cvl = s.cvl;
for (int twok1 = 3; this.ne (t); twok1 += 2) { //2*k+1
s.imul (u2).divi ((1 - twok1) * twok1); //(-1)^k*x^(2*k+1)/(2*k+1)!
//t.sete (this);
t.flg = this.flg;
t.epp = this.epp;
t.dvl = this.dvl;
t.cvl = this.cvl;
this.iadd (s);
}
} else { //cos
//s.set1 (); //(-1)^k*x^(2*k)/(2*k)!
s.flg = P;
s.epp = 0;
s.dvl = MSB;
s.cvl = 0L;
//t.set0 ();
t.flg = P | Z;
//this.sete (s);
this.flg = s.flg;
this.epp = s.epp;
this.dvl = s.dvl;
this.cvl = s.cvl;
for (int twok = 2; this.ne (t); twok += 2) { //2*k
s.imul (u2).divi ((1 - twok) * twok); //(-1)^k*x^(2*k)/(2*k)!
//t.sete (this);
t.flg = this.flg;
t.epp = this.epp;
t.dvl = this.dvl;
t.cvl = this.cvl;
this.iadd (s);
}
}
} else { //チェビシェフ展開
if ((k & 1) != 0) { //sin
u2.isqu (u); //u^2
this.imul (SIN_C21, u2)
.iadd (SIN_C19).imul (u2)
.iadd (SIN_C17).imul (u2)
.iadd (SIN_C15).imul (u2)
.iadd (SIN_C13).imul (u2)
.iadd (SIN_C11).imul (u2)
.iadd (SIN_C9).imul (u2)
.iadd (SIN_C7).imul (u2)
.iadd (SIN_C5).imul (u2)
.iadd (SIN_C3).imul (u2)
.iadd (SIN_C1).imul (u);
} else { //cos
u2.isqu (u); //u^2
this.imul (COS_C20, u2)
.iadd (COS_C18).imul (u2)
.iadd (COS_C16).imul (u2)
.iadd (COS_C14).imul (u2)
.iadd (COS_C12).imul (u2)
.iadd (COS_C10).imul (u2)
.iadd (COS_C8).imul (u2)
.iadd (COS_C6).imul (u2)
.iadd (COS_C4).imul (u2)
.iadd (COS_C2).imul (u2)
.iadd (COS_C0);
}
}
// 0123
this.outer ().neg (0b0110 << 28 << k < 0);
// n*pi/2はn==0を除いて正確に表現できないので、
// RZまたはRPでsin(x)およびcos(x)が-1になることはあり得ない
// RZまたはRMでsin(x)およびcos(x)がcos(0)以外で+1になることはあり得ない
if (this.flg << 1 == 0 && this.epp == 0) { //結果が±1
if (this.flg < 0) { //結果が-1
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) { //RZまたはRPで結果が-1
this.sete (NEXTUP_MINUSONE[epbRoundingPrec]);
}
} else { //結果が+1
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) { //RZまたはRMで結果が+1
this.sete (NEXTDOWN_PLUSONE[epbRoundingPrec]);
}
}
}
return this;
} //efp.cos(EFP)
//------------------------------------------------------------------------
//x = x.cosh ()
// x=cosh(x)
//y = y.cosh (x)
// y=cosh(x)
// 双曲線余弦 hyperbolic cosine ハイパボリックコサイン
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{cosh($_[0])});print$g"
// echo read("efp.gp");graph(cosh) | gp -q
// +---------+--------**---------+---------+---------+---------**--------+---------+
// | * | * |
// | ** | ** |
// | * | * |
// | ** | ** |
// + ** + ** +
// | * | * |
// | ** | ** |
// | ** | ** |
// | ** | ** |
// + ** + ** +
// | *** | *** |
// | ** | ** |
// | *** | *** |
// | ***** | ***** |
// + ********* +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// 1<=y<=inf
//
// 指数関数との関係
// cosh(x)=(e^x+e^-x)/2
// =((e^x)^2+1)/(2*e^x)
//
// テイラー展開
// cosh(x)=1+x^2/2!+x^4/4!+x^6/6!+...
// f(n,x)=sum(k=0,n,x^(2*k)/(2*k)!)
// echo read("efp.gp");eval("f(h,x)=sum(k=0,h,1/(2*k)!*x^(2*k))");a=-1;b=-a;hmax=27;print1(" // ");for(h=0,hmax,n=2*h;printf("%4d",n));print();print1(" // ");for(h=0,hmax,n=2*h;printf("%4d",floor(closeness(cosh,f(h,x),a,b,10000))));print() | gp -q
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
// 1 5 10 15 22 29 36 44 53 61 70 79 89 98 108 118 128 138 149 159 170 181 192 203 214 226 237 249
//
// チェビシェフ展開
// echo read("efp.gp");a=-1;b=-a;nmax=54;print1(" // ");forstep(n=0,nmax,2,printf("%4d",n));print();print1(" // ");forstep(n=0,nmax,2,printf("%4d",floor(closeness(cosh,chebyshev(cosh,a,b,n),a,b,10000))));print() | gp -q
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
// 2 7 14 22 30 39 49 59 69 80 90 102 113 124 136 148 160 173 185 198 210 223 236 249 263 276 290 303
//
public final EFP cosh () {
return this.cosh (this);
} //efp.cosh()
public final EFP cosh (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //cosh(±0)=1
//this.set1 ();
this.flg = P;
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else if (xf << 2 < 0) { //cosh(±Inf)=+Inf
this.flg = P | I;
} else { //cosh(NaN)=NaN
this.flg = N;
}
return this;
}
//±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_X2; //不正確な結果。オーバーフローまたはアンダーフローのときもセットされる
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (15 <= x.epp) { //x<=-32768||32768<=x。cosh(-big)=+Inf,cosh(+big)=+Inf
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+Inf
}
if (x.epp < -3) { //|x|<0.125
EFP x2 = new EFP ().inner ().isqu (x); //x^2
return this.imul (COSH_C14, x2)
.iadd (COSH_C12).imul (x2)
.iadd (COSH_C10).imul (x2)
.iadd (COSH_C8).imul (x2)
.iadd (COSH_C6).imul (x2)
.iadd (COSH_C4).imul (x2)
.iadd (COSH_C2).imul (x2)
.outer ().add (COSH_C0);
}
//0.125<=|x|
// xが絶対値の大きい負数のときそのままe^xを計算するとアンダーフローして0になりさらに1/e^xがゼロ除算になる
// オーバーフローだけセットさせるためにxの符号を取ってからe^xを計算する
this.inner ().abs (x).exp (); //e^|x|
this.iadd (new EFP ().rcp (this)).outer ().div2 (); //(e^|x|+e^-|x|)/2
if (this.flg << 2 < 0) {
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | this.flg >>> 31]).finish (); //±Inf
}
return this;
} //efp.cosh(EFP)
//------------------------------------------------------------------------
//x = x.cot ()
// x=cot(x)
//y = y.cot (x)
// y=cot(x)
// 余接 cotangent コタンジェント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{cot($_[0])});print$g"
// echo read("../misc/efp.gp");graph(cotan) | gp -q
// +---------+*--------+---------+---------+-**------+---------+---------+---*-----+
// | * | * * |
// | * | * * |
// | ** | * * |
// | * | * ** |
// + * + * * +
// | * | ** * |
// | * | * * |
// | ** | * ** |
// | * | * * |
// + * + ** * +
// | ** | * ** |
// | * | ** * |
// | ** | ** ** |
// | ** | * **|
// + ** + ** **
// | ** | *** *
// | *** | ** |
// | ** | *** |
// | *** | *** |
// +---------+---------+--***----+---------+---------+----***--+---------+---------+
// | *** | *** |
// | *** | ** |
// | ** | *** |
// * *** | ** |
// ** ** + ** +
// |** * | ** |
// | ** ** | ** |
// | * ** | * |
// | ** * | ** |
// + * ** + * +
// | * * | * |
// | ** * | ** |
// | * * | * |
// | * ** | * |
// + * * + * +
// | ** * | * |
// | * * | ** |
// | * * | * |
// | * * | * |
// +-----*---+---------+---------+------**-+---------+---------+--------*+---------+
//
// 定義域
// -inf<=x<=inf
// n*piを除く
//
// 値域
// -inf<=cot(x)<=inf
//
// 三角関数との関係
// cot(x)=1/tan(x)
// =cos(x)/sin(x)
// =tan(pi/2-x)
//
public final EFP cot () {
return this.cot (this);
} //efp.cot()
public final EFP cot (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //cot(±0)=NaN
} else if (xf << 2 < 0) { //±Inf
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //cot(±Inf)=NaN
} else { //NaN
this.flg = N; //cot(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
if (false) { //cos(x)/sin(x)。[90] 810ns
EFP s = new EFP ().inner ().sin (x); //sin(x)
return this.cos (x).outer ().div (s); //cos(x)/sin(x)
} else if (false) { //tan(pi/2-x)。[38]
return this.inner ().sub (PI_2, x).iadd (PI_2A).outer ().tan (); //cot(x)=tan(pi/2-x)
} else if (false) { //1/tan(x)。[90] 415ns
return this.inner ().tan (x).outer ().rcp (); //cot(x)=1/tan(x)
} else { //128分割。[90] 340ns
if (15 <= x.epp) { //|x|が大きすぎる
EFP s = new EFP ().inner ().sin (x); //sin(x)
return this.cos (x).outer ().div (s); //cos(x)/sin(x)
}
this.inner ();
EFP s = new EFP ();
EFP t = new EFP ();
EFP u = new EFP ().iabs (x); //|x|
EFP u2 = new EFP ();
s.iadd (u, TAN7_X).imul (TAN7_Y).trunc (); //|x|+pi/256をpi/128で割った商
// |x|をpi/128で割った余りを求めるとき|x|がpi/128の整数倍に近いと桁落ちが発生するので倍精度で計算する
u.sub (t.imulw (u2, s, TAN7_Z)).sub (u2).sub (t.imul (s, TAN7_ZA)); //|x|をpi/128で割った余り。[-pi/256,pi/256]
int k = s.geti () & 127; //|x|+pi/256をpi/128で割った商の下位7bit
u2.isqu (u); //u^2
this.imul (TAN7_C11, u2)
.iadd (TAN7_C9).imul (u2)
.iadd (TAN7_C7).imul (u2)
.iadd (TAN7_C5).imul (u2)
.iadd (TAN7_C3).imul (u2)
.iadd (TAN7_C1).imul (u);
if (k == 0) {
this.rcp (); //1/tan(x)
} else if (k <= 63) {
t = TAN7_T[k];
s.iadd (this, t);
this.imul (t).negdec ().div (s); //(1-tan(k*pi/128)*t)/(tan(x-k*pi/128)+t)
} else if (k == 64) {
this.ineg (); //-tan(x-pi/2)
} else {
t = TAN7_T[128 - k];
s.sub (this, t);
this.imul (t).inc ().div (s); //(1+tan((128-k)*pi/128)*t)/(tan(x-(128-k)*pi/128)-t)
}
return this.outer ().neg (xf < 0); //cotは奇関数なのでxの符号を掛ける
}
} //efp.cot(EFP)
//------------------------------------------------------------------------
//x = x.coth ()
// x=coth(x)
//y = y.coth (x)
// y=coth(x)
// 双曲線余接 hyperbolic cotangent ハイパボリックコタンジェント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{coth($_[0])});print$g"
// echo read("../misc/efp.gp");eval("coth(x)=1/tanh(x)");graph(coth) | gp -q
// +---------+---------+---------+---------+-**------+---------+---------+---------+
// | | * |
// | | * |
// | | * |
// | | * |
// + + ** +
// | | * |
// | | * |
// | | ** |
// | | * |
// + + ** +
// | | ** |
// | | ** |
// | | *** |
// | | ****** |
// + + **************************
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// ************************** + +
// | ****** | |
// | *** | |
// | ** | |
// | ** | |
// + ** + +
// | * | |
// | ** | |
// | * | |
// | * | |
// + ** + +
// | * | |
// | * | |
// | * | |
// | * | |
// +---------+---------+---------+------**-+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<0
// 0<x<=inf
//
// 値域
// -inf<=y<1
// 1<y<=inf
//
// 双曲線関数との関係
// coth(x)=1/tanh(x)
// =cosh(x)/sinh(x)
//
// 指数関数との関係
// coth(x)=(e^x+e^(-x))/(e^x-e^(-x))
// =1+2*e^(-x)/(e^x-e^(-x))
// =((e^x)^2+1)/((e^x)^2-1)
//
// 定義域の制限
// x=log(sqrt(2^(n+1)+1))
// のとき
// (e^x)^2=2^(n+1)+1
// coth(x)=((e^x)^2+1)/((e^x)^2-1)
// =(2^(n+1)+1+1)/(2^(n+1)+1-1)
// =(2^(n+1)+2)/2^(n+1)
// =1+1/2^n
// したがって、仮数部がnbitのとき
// log(sqrt(2^(n+1)+1))<x
// ならばcoth(x)と1を区別できない(cothは奇関数なので負のときも同様)
// > log(sqrt(2^(53+1)+1));
// 18.714973875118523382020842894999680078257317575103
// > log(sqrt(2^(92+1)+1));
// 32.231343896037456887901293647855697513444901003298
// cosh(x)/sinh(x)ではxの絶対値が大きすぎるとInf/Infで結果がNaNになってしまうので途中で打ち切って1にする必要がある
//
public final EFP coth () {
return this.coth (this);
} //efp.coth()
public final EFP coth (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //coth(±0)=NaN
} else if (xf << 2 < 0) { //±Inf
this.flg = xf & M; //coth(±Inf)=±1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else { //NaN
this.flg = N; //coth(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
// e^xを経由する方法はオーバーフローを発生させずに計算できる範囲が狭いので|x|が大きい場合を分ける必要がある
int xe = x.epp;
if (xe < -2) { //|x|<0.25
EFP x2 = new EFP ().inner ().isqu (x); //x^2
return this.imul (TANH_C27, x2)
.iadd (TANH_C25).imul (x2)
.iadd (TANH_C23).imul (x2)
.iadd (TANH_C21).imul (x2)
.iadd (TANH_C19).imul (x2)
.iadd (TANH_C17).imul (x2)
.iadd (TANH_C15).imul (x2)
.iadd (TANH_C13).imul (x2)
.iadd (TANH_C11).imul (x2)
.iadd (TANH_C9).imul (x2)
.iadd (TANH_C7).imul (x2)
.iadd (TANH_C5).imul (x2)
.iadd (TANH_C3).imul (x2)
.iadd (TANH_C1).imul (x).outer ().rcp ();
}
//0.25<=|x|
if (false) { //cosh/sinh
EFP s = new EFP ().inner ().sinh (x); //sinh(x)
return this.cosh (x).outer ().div (s); //cosh(x)/sinh(x)
} else if (EFP_COTH_EPP_MAX < xe) {
this.flg = xf & M; //±1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
return this;
} else {
EFP t = new EFP ().inner ().imul2 (x).exp (); //e^(2*x)
return this.inc (t).outer ().div (t.dec ()); //(e^(2*x)+1)/(e^(2*x)-1)
}
} //efp.coth(EFP)
//------------------------------------------------------------------------
//x = x.csc ()
// x=csc(x)
//y = y.csc (x)
// y=csc(x)
// 余割 cosecant コセカント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{csc($_[0])});print$g"
// echo read("../misc/efp.gp");eval("csc(x)=1/sin(x)");graph(csc) | gp -q
// +-----*---+---------+---------+---------+-**------+---------+--------*+---------+
// | * | * * |
// | * | * * |
// | * | * ** |
// | ** | * * |
// + * + ** * +
// | * | * * |
// | ** | * ** |
// | * | * * |
// | * | ** ** |
// + ** + ** * +
// | ** | * ** |
// |** | ** ** |
// ** | *** ** |
// | | *** **** |
// + + ********** +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + ********** + +
// | **** *** | |
// | ** *** | **
// | ** ** | **|
// | ** * | ** |
// + * ** + ** +
// | ** ** | * |
// | * * | * |
// | ** * | ** |
// | * * | * |
// + * ** + * +
// | * * | ** |
// | ** * | * |
// | * * | * |
// | * * | * |
// +---------+*--------+---------+------**-+---------+---------+---------+---*-----+
//
// 定義域
// -inf<=x<=inf
// n*piを除く
//
// 値域
// -inf<=y<=-1
// 1<=y<=inf
//
// 三角関数との関係
// csc(x)=1/sin(x)
//
public final EFP csc () {
return this.csc (this);
} //efp.csc()
public final EFP csc (EFP x) {
return this.inner ().sin (x).outer ().rcp (); //1/sin(x)
} //efp.csc(EFP)
//------------------------------------------------------------------------
//x = x.csch ()
// x=csch(x)
//y = y.csch (x)
// y=csch(x)
// 双曲線余割 hyperbolic cosecant ハイパボリックコセカント
//
// グラフ
// perl -e "use Math::Trig;use Graph;$g=new Graph();$g->grid();$g->func(sub{csch($_[0])});print$g"
// echo read("../misc/efp.gp");eval("csch(x)=1/sinh(x)");graph(csch) | gp -q
// +---------+---------+---------+---------+-**------+---------+---------+---------+
// | | * |
// | | * |
// | | * |
// | | * |
// + + * +
// | | ** |
// | | * |
// | | * |
// | | ** |
// + + * +
// | | ** |
// | | * |
// | | ** |
// | | ** |
// + + *** +
// | | *** |
// | | *** |
// | | ****** |
// | | ************ |
// ***********---------+---------+---------+---------+---------+---------***********
// | ************ | |
// | ****** | |
// | *** | |
// | *** | |
// + *** + +
// | ** | |
// | ** | |
// | * | |
// | ** | |
// + * + +
// | ** | |
// | * | |
// | * | |
// | ** | |
// + * + +
// | * | |
// | * | |
// | * | |
// | * | |
// +---------+---------+---------+------**-+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<0
// 0<x<=inf
//
// 値域
// -inf<=y<0
// 0<y<=inf
//
// 双曲線関数との関係
// csch(x)=1/sinh(x)
//
// 指数関数との関係
// csch(x)=2/(e^x-e^-x)
// =2*e^x/((e^x)^2-1)
//
public final EFP csch () {
return this.csch (this);
} //efp.csch()
public final EFP csch (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //csch(±0)=NaN
} else { //±Inf,NaN
this.flg = xf << 2 < 0 ? xf ^ (Z | I) : N; //csch(±Inf)=±0, csch(NaN)=NaN
}
return this;
}
//±0,±Inf,NaN以外
if (true) {
return this.inner ().sinh (x).outer ().rcp (); //1/sinh(x) [88] 89以上が多いが88も出ることがある
} else if (false) {
this.inner ().exp (x); //e^x
return this.sub (new EFP ().rcp (this)).outer ().rcp ().outer ().mul2 (); //2/(e^x-e^-x) [87]
} else {
return this.sub (new EFP ().inner ().exp (x), new EFP ().ineg (x).exp ()).rcp ().outer ().mul2 (); //2/(e^x-e^-x) [88]
}
} //efp.csch(EFP)
//------------------------------------------------------------------------
//x = x.cub ()
// x*=x^2
//y = y.cub (x)
// y=x^3
// 3乗
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]**3});print$g"
// echo read("../misc/efp.gp");eval("cub(x)=x^3");graph(cub) | gp -q
// +---------+---------+---------+---------+---------+-----*---+---------+---------+
// | | ** |
// | | * |
// | | * |
// | | * |
// + + ** +
// | | * |
// | | * |
// | | ** |
// | | * |
// + + ** +
// | | * |
// | | ** |
// | | * |
// | | ** |
// + + * +
// | | ** |
// | | ** |
// | | ** |
// | | *** |
// +---------+---------+---------+----***********----+---------+---------+---------+
// | *** | |
// | ** | |
// | ** | |
// | ** | |
// + * + +
// | ** | |
// | * | |
// | ** | |
// | * | |
// + ** + +
// | * | |
// | ** | |
// | * | |
// | * | |
// + ** + +
// | * | |
// | * | |
// | * | |
// | ** | |
// +---------+---------+---*-----+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
// (a*x^2+b*x+c)^3 = a^3*x^6 + 3*a^2*b*x^5 + (3*a^2*c + 3*a*b^2)*x^4 + (6*a*b*c + b^3)*x^3 + (3*a*c^2 + 3*b^2*c)*x^2 + 3*b*c^2*x + c^3
//
public final EFP cub () {
return this.mul (new EFP ().isqu (this)); //x*x^2
} //efp.cub()
public final EFP cub (EFP x) {
return this.mul (x, new EFP ().isqu (x)); //x*x^2
} //efp.cub(EFP)
//------------------------------------------------------------------------
//x = x.dec ()
// x-=1
//y = y.dec (x)
// y=x-1
// 1を引く(デクリメント)
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]-1});print$g"
// echo read("../misc/efp.gp");eval("dec(x)=x-1");graph(dec) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + **
// | | ***|
// | | *** |
// | | *** |
// | | *** |
// + + *** +
// | | *** |
// | | *** |
// | | *** |
// | | *** |
// + + *** +
// | | *** |
// | | *** |
// | | *** |
// | | *** |
// +---------+---------+---------+---------+--------***--------+---------+---------+
// | | *** |
// | | *** |
// | | *** |
// | |*** |
// + *** +
// | ***| |
// | *** | |
// | *** | |
// | *** | |
// + *** + +
// | *** | |
// | *** | |
// | *** | |
// | *** | |
// + *** + +
// | *** | |
// | *** | |
// | *** | |
// | *** | |
// +--------***--------+---------+---------+---------+---------+---------+---------+
//
public final EFP dec () {
return this.dec (this);
} //efp.dec()
public final EFP dec (EFP x) {
//return this.sub (x, ONE); //7.4ns
//6.1ns
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
this.flg = M; //-1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else { //±Inf,NaN
this.flg = xf;
}
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (xe < -LEN) { //..-LEN-1。xの先頭がguard bitよりも右
//絶対値は1の方が大きいのでxを右にシフトするがxの絶対値が小さすぎるので-1になる
epbFpsr |= EPB_FPSR_X2; //不正確な結果
this.flg = M; //-1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
return this;
}
long xd = x.dvl;
long xc = x.cvl;
if (LEN < xe) { //LEN+1..。1がguard bitよりも右
//絶対値はxの方が大きいので1を右にシフトするが1の絶対値が小さすぎるのでxになる
epbFpsr |= EPB_FPSR_X2; //不正確な結果
return this.finish (xf, xe, xd, xc, 0L); //x
}
long xb = 0L;
if (xe == 0) { //0。xの最上位bitと1が重なる
//絶対値はxの方が大きいか等しいが小数点の位置は同じ
if (xf < 0) { //-x
//絶対値に1を加える
xb = xc << -1;
xc = xd << -1 | xc >>> 1;
xd = (xd >>> 1) + (MSB >>> 1);
xe++;
} else { //+x
//絶対値から1を引く
xd -= MSB;
}
} else if (0 < xe) { //1..LEN
//絶対値はxの方が大きいので1を右にシフトする
if (xf < 0) { //-x
//絶対値に1を加える
if (xe <= 63) { //1..63。xの上位と1が重なる
if ((xd += MSB >>> xe) >>> ~xe == 0L) { //絶対値に1を加えたら加えたbitから上がすべて0になって溢れた
xb = xc << -1;
xc = xd << -1 | xc >>> 1;
xd = MSB | xd >>> 1;
xe++;
}
} else { //64..LEN。xの下位またはguard bitと1が重なる
if ((xc += MSB >>> xe) >>> ~xe == 0L && ++xd == 0L) { //絶対値に1を加えたら加えたbitから上がすべて0になって溢れた
xb = xc << -1;
xc = xc >>> 1;
xd = MSB;
xe++;
}
}
} else { //+x
//絶対値から1を引く
if (xe <= 63) { //1..63。xの上位の2bit目以降と1が重なる
xd -= MSB >>> xe; //最上位bitが1なのでボローはなく0にもならない
} else { //64..LEN。xの下位またはguard bitと1が重なる
if (xc >>> ~xe != 0L) { //下位の引く位置から上が0ではない。下位だけで引ける
xc -= MSB >>> xe;
} else { //下位の引く位置から上が0なのでボローが発生する
xc |= MSB >> xe; //下位の引く位置から上は-1になる
xd--; //ボローを上位から引く
}
}
}
} else { //-LEN..-1
//絶対値は1の方が大きいのでxを右にシフトする
if (-63 <= xe) { //-63..-1。xの先頭が1の右隣から上位の最下位bitまで
xb = xc << xe;
xc = xd << xe | xc >>> -xe;
xd >>>= -xe;
} else if (-64 == xe) { //-64。xの先頭が下位の最上位bit
xb = xc;
xc = xd;
xd = 0L;
} else { //-LEN..-65。xの先頭が下位の上から2bit目からguard bitまで
xb = xd << xe | xc >>> -xe;
xc = xd >>> -xe;
xd = 0L;
}
xe = 0;
if (xf < 0) { //-x
//絶対値に1を加える
xd |= MSB;
} else { //+x
//絶対値を1から引く
if (xb != 0L) {
xb = -xb;
xc = -1L - xc;
xd = MSB - 1L - xd;
} else if (xc != 0L) {
xc = -xc;
xd = MSB - 1L - xd;
} else {
xd = MSB - xd;
}
xf ^= M; //符号反転
}
}
//正規化する
if (xd >= 0L) {
if (xd != 0L) {
int o = Long.numberOfLeadingZeros (xd); //1..63。左にシフトするbit数
xe -= o;
xd = xd << o | xc >>> -o;
xc = xc << o | xb >>> -o;
xb <<= o;
} else if (xc < 0L) {
xe -= 64;
xd = xc;
xc = xb;
xb = 0L;
} else if (xc != 0L) {
int o = 64 + Long.numberOfLeadingZeros (xc); //65..127。左にシフトするbit数
xe -= o;
xd = xc << o | xb >>> -o;
xc = xb << o;
xb = 0L;
} else if (xb < 0L) {
xe -= 128;
xd = xb;
xc = 0L;
xb = 0L;
} else if (xb != 0L) {
int o = 128 + Long.numberOfLeadingZeros (xb); //129..191。左にシフトするbit数
xe -= o;
xd = xb << o;
xc = 0L;
xb = 0L;
} else {
this.flg = P | Z; //-1+1=+0
return this;
}
}
return this.finish (xf, xe, xd, xc, xb);
} //efp.dec(EFP)
//------------------------------------------------------------------------
//x = x.deg ()
// x*=180/pi
//y = y.deg (x)
// y=x*180/pi
// 180/pi倍(デグリー)
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{45/atan2(1,1)*$_[0]});print$g"
// echo read("../misc/efp.gp");eval("deg(x)=x*180/Pi");graph(deg) | gp -q
// +---------+---------+---------+---------+*--------+---------+---------+---------+
// | |* |
// | |* |
// | |* |
// | |* |
// + +* +
// | ** |
// | * |
// | * |
// | * |
// + * +
// | * |
// | * |
// | * |
// | * |
// + * +
// | * |
// | * |
// | * |
// | * |
// +---------+---------+---------+---------*---------+---------+---------+---------+
// | * |
// | * |
// | * |
// | * |
// + * +
// | * |
// | * |
// | * |
// | * |
// + * +
// | * |
// | * |
// | * |
// | ** |
// + *+ +
// | *| |
// | *| |
// | *| |
// | *| |
// +---------+---------+---------+--------*+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
public final EFP deg () {
return this.deg (this);
} //efp.deg()
public final EFP deg (EFP x) {
return this.mul (x, TO_DEG); //x*180/pi
} //efp.deg(EFP)
//------------------------------------------------------------------------
//x = x.div (y)
// x/=y
//z = z.div (x, y)
// z=x/y
// 除算
//
// (xn/xd)/(yn/yd)
// =(xn*yd)/(xd*yn)
//
public final EFP div (EFP y) {
return this.div (this, y);
} //efp.div(EFP)
public final EFP div (EFP x, EFP y) {
int xf = x.flg;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((xf | yf) << 3 != 0) { //どちらかがNaNのときNaN
this.flg = N;
} else if ((xf & yf & (Z | I)) != 0) { //±0/±0または±Inf/±InfのときNaN
epbFpsr |= EPB_FPSR_OE;
if (yf << 1 < 0) { //±0/±0
epbExceptionOperandExponent = yf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else { //±Inf/±Inf
epbExceptionOperandExponent = yf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
}
this.flg = N;
} else if (xf << 1 == 0 && yf << 1 < 0) { //(±0,NaN以外)/±0のとき±Inf
epbFpsr |= EPB_FPSR_DZ;
epbExceptionOperandExponent = yf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = (xf ^ yf) & M | I;
} else { //±0/(±0,NaN以外)または(±Inf,NaN以外)/±Infのとき±0、±Inf/(±Inf,NaN以外)のとき±Inf
this.flg = (xf ^ yf) & M | ((xf & Z | yf & I) != 0 ? Z : I);
}
return this;
}
//±0,±Inf,NaN以外
long r01 = x.dvl;
long y01 = y.dvl;
long r2 = (r01 << -2 | x.cvl >>> 2) >>> 33;
long y2 = (y01 << -2 | y.cvl >>> 2) >>> 33;
r01 >>>= 2;
y01 >>>= 2;
long y0 = y01 >>> 31;
long y1 = y01 & 0x7fffffffL;
//先頭1bit
boolean qq;
if (r01 < y01 || (r01 == y01 && r2 < y2)) { //x<y
qq = false;
} else {
qq = true;
r2 -= y2;
r01 -= y01;
if (r2 < 0L) {
r2 += 0x80000000L;
r01--;
}
}
//1桁目
long q0 = r01 >> 31 == y0 ? 0x7fffffffL : r01 / y0;
r01 = (r01 - q0 * y0 << 31) + r2 - q0 * y1;
if (r01 < 0L) {
q0--;
r01 += y01;
}
r2 = q0 * y2 + 0x7fffffffL;
r01 -= r2 >> 31;
r2 = ~r2 & 0x7fffffffL; //~(r2 | ~0x7fffffffL)
if (r01 < 0L) {
q0--;
r2 += y2;
r01 += y01 + (r2 >> 31);
r2 &= 0x7fffffffL;
}
//2桁目
long q1 = r01 >> 31 == y0 ? 0x7fffffffL : r01 / y0;
r01 = (r01 - q1 * y0 << 31) + r2 - q1 * y1;
if (r01 < 0L) {
q1--;
r01 += y01;
}
r2 = q1 * y2 + 0x7fffffffL;
r01 -= r2 >> 31;
r2 = ~r2 & 0x7fffffffL; //~(r2 | ~0x7fffffffL)
if (r01 < 0L) {
q1--;
r2 += y2;
r01 += y01 + (r2 >> 31);
r2 &= 0x7fffffffL;
}
//3桁目
long q2 = r01 >> 31 == y0 ? 0x7fffffffL : r01 / y0;
r01 = (r01 - q2 * y0 << 31) + r2 - q2 * y1;
if (r01 < 0L) {
q2--;
r01 += y01;
}
r2 = q2 * y2 + 0x7fffffffL;
r01 -= r2 >> 31;
r2 = ~r2 & 0x7fffffffL; //~(r2 | ~0x7fffffffL)
if (r01 < 0L) {
q2--;
r2 += y2;
r01 += y01 + (r2 >> 31);
r2 &= 0x7fffffffL;
}
//商 (((qq ? MSB : 0) | q0) << 31 | q1) << 31 | q2
//余り r01 << 31 | r2
//正規化する
int ze = x.epp - y.epp;
if (qq) { //商は94bit
q0 = MSB | q0 << 32 | q1 << 1 | q2 >>> 30;
q2 <<= -30;
} else { //商は93bit
ze--;
q0 = q0 << -31 | q1 << 2 | q2 >>> 29;
q2 <<= -29;
}
return this.finish2 (xf ^ yf, ze, q0, q2, r01 | r2);
} //efp.div(EFP,EFP)
//------------------------------------------------------------------------
//x = x.div2 ()
// x/=2
//y = y.div2 (x)
// y=x/2
// 1/2倍
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]/2});print$g"
// echo read("../misc/efp.gp");eval("div2(x)=x/2");graph(div2) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + ***
// | | ***** |
// | | ***** |
// | | ***** |
// | | ***** |
// + + ***** +
// | | ***** |
// | | ***** |
// | | ***** |
// | | ***** |
// +---------+---------+---------+-------*****-------+---------+---------+---------+
// | ***** | |
// | ***** | |
// | ***** | |
// | ***** | |
// + ***** + +
// | ***** | |
// | ***** | |
// | ***** | |
// | ***** | |
// *** + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
public final EFP div2 () {
return this.finish (this.flg, this.epp - 1, this.dvl, this.cvl, 0L);
} //efp.div2()
public final EFP idiv2 () {
this.epp--;
return this;
} //efp.idiv2()
public final EFP div2 (EFP x) {
return this.finish (x.flg, x.epp - 1, x.dvl, x.cvl, 0L);
} //efp.div2(EFP)
public final EFP idiv2 (EFP x) {
this.flg = x.flg;
this.epp = x.epp - 1;
this.dvl = x.dvl;
this.cvl = x.cvl;
return this;
} //efp.idiv2(EFP)
//------------------------------------------------------------------------
//x = x.div3 ()
// x/=3
//y = y.div3 (x)
// y=x/3
// 1/3倍
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]/3});print$g"
// echo read("../misc/efp.gp");eval("div3(x)=x/3");graph(div3) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | **
// | | *******|
// + + ******* +
// | | ******* |
// | | ******* |
// | | ******* |
// | | ******* |
// +---------+---------+---------+------*******------+---------+---------+---------+
// | ******* | |
// | ******* | |
// | ******* | |
// | ******* | |
// + ******* + +
// |******* | |
// ** | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
public final EFP div3 () {
return this.div3 (this);
} //efp.div3()
public final EFP div3 (EFP x) {
//return this.divi (x, 3); //x/3
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
this.flg = xf;
return this;
}
//±0,±Inf,NaN以外
//2分割して割る
int ze = x.epp;
long zc = x.dvl;
long zb = x.cvl;
zb = (zc << -1 | zb >>> 1) >>> 3; //被除数の下位61bit
zc >>>= 1; //被除数の上位63bit
long zd = zc / 3L; //商の上位61..62bit
zb |= zc - zd * 3L << -3; //上位の余りを下位に連結する
zc = zb / 3L; //商の下位61bit
zb -= zc * 3L; //余り
zc <<= 3;
//正規化する
if (zd << 2 < 0L) { //1bit減った
ze--;
zd = zd << 2 | zc >>> -2;
zc <<= 2;
} else { //2bit減った
ze -= 2;
zd = zd << 3 | zc >>> -3;
zc <<= 3;
}
return this.finish (xf, ze, zd, zc, zb);
} //efp.div3(EFP)
//------------------------------------------------------------------------
//x = x.divi (n)
// x/=n
//z = z.divi (x, n)
// z=x/n
// int除算
//
public final EFP divi (int n) {
return this.divi (this, n);
} //efp.divi(int)
public final EFP divi (EFP x, int n) {
//return this.div (x, new EFP (n)); //x/n
int xf = x.flg;
if (n == 0) { //yが0
if (xf << 1 != 0) { //xが±0,±Inf,NaN
if (xf << 1 < 0) { //xが±0
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = P;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = N; //±0/0=NaN
} else {
this.flg = xf; //NaN/0=NaN, ±Inf/0=±Inf
}
} else { //xが±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_DZ;
epbExceptionOperandExponent = P;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = (xf & M) | I; //±x/0=±Inf
}
return this;
}
if (xf << 1 != 0) { //xが±0,±Inf,NaN
this.flg = xf << 3 < 0 ? N : xf ^ (n & M); //NaN/±n=NaN, ±Inf/±n=±Inf, ±0/±n=±0
return this;
}
//両方±0,±Inf,NaN以外
int ze = x.epp;
long zd = x.dvl;
long zc = x.cvl;
long zb = 0L;
if (n < 0) { //yが負
xf ^= M;
//0x80000000を取り除く
if (n == 0x80000000) {
ze -= 31;
if ((short) ze != ze) { //アンダーフロー
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
epbExceptionOperandExponent = xf;
epbExceptionOperandMantissa = zd;
return this.sete (UNFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | xf >>> 31]).finish (); //±0
}
this.flg = xf;
this.epp = ze;
this.dvl = zd;
this.cvl = zc;
return this;
}
n = -n;
}
if (n != 1) { //0x80000000を取り除いていない場合はn>1は不可
long y = (long) n; //0x80000000を取り除いていない場合は&0xffffffffLが必要
if (n >>> 16 == 0) { //除数が2..16bit
//2分割して割る
zb = (zd << -1 | zc >>> 1) >>> 17; //被除数の下位47bit
zc = zd >>> 1; //被除数の上位63bit
zd = zc / y; //商の上位47..62bit
zb |= zc - zd * y << 47; //上位の余り16bitと被除数の下位47bitを連結する
zc = zb / y; //商の下位47bit。上位の余り16bitは除数よりも小さいので47bit以内に収まる
zb -= zc * y; //余り16bit
zc <<= 17;
} else { //除数が17..32bit
//3分割して割る
zb = (zd << -1 | zc >>> 1) >>> 33; //被除数の中位31bit
zc = zd >>> 1; //被除数の上位63bit
zd = zc / y; //商の上位31..47bit
zb |= zc - zd * y << 31; //上位の余り32bitと被除数の中位31bitを連結する
zc = zb / y; //商の中位31bit。上位の余り32bitは除数よりも小さいので31bit以内に収まる
zb = zb - zc * y << 31; //中位の余り32bitと被除数の下位31bit(0)を連結する
long t = zb / y; //商の下位31bit
zc = (zc << 31 | t) << 2; //商の下位62bit
zb -= t * y; //余り
}
//正規化する
int o = Long.numberOfLeadingZeros (zd);
ze -= o - 1;
zd = zd << o | zc >>> -o;
zc <<= o;
} //n!=1
return this.finish (xf, ze, zd, zc, zb);
} //efp.divi(EFP,int)
//------------------------------------------------------------------------
//x = x.divpi ()
// x/=pi
//y = y.divpi (x)
// y=x/pi
// 1/pi倍
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]/(4*atan2(1,1))});print$g"
// echo read("../misc/efp.gp");eval("divpi(x)=x/Pi");graph(divpi) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | ******
// + + ******** +
// | | ******* |
// | | ******* |
// | | ******** |
// | | ******* |
// +---------+---------+---------+------*******------+---------+---------+---------+
// | ******* | |
// | ******** | |
// | ******* | |
// | ******* | |
// + ******** + +
// ****** | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -inf<=y<=inf
//
public final EFP divpi () {
return this.mul (this, ONE_PI); //x*1/pi
} //efp.divpi()
public final EFP divpi (EFP x) {
return this.mul (x, ONE_PI); //x*1/pi
} //efp.divpi(EFP)
//------------------------------------------------------------------------
//x = x.divrz (y)
// x/=y
//z = z.divrz (x, y)
// z=x/y
// 除算(RZ)
//
public final EFP divrz (EFP y) {
return this.divrz (this, y);
} //efp.divrz(EFP)
public final EFP divrz (EFP x, EFP y) {
int xf = x.flg;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
if ((xf | yf) << 3 != 0) { //どちらかがNaNのときNaN
this.flg = N;
} else if ((xf & yf & (Z | I)) != 0) { //±0/±0または±Inf/±InfのときNaN
epbFpsr |= EPB_FPSR_OE;
if (yf << 1 < 0) { //±0/±0
epbExceptionOperandExponent = yf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
} else { //±Inf/±Inf
epbExceptionOperandExponent = yf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
}
this.flg = N;
} else if (xf << 1 == 0 && yf << 1 < 0) { //(±0,NaN以外)/±0のとき±Inf
epbFpsr |= EPB_FPSR_DZ;
epbExceptionOperandExponent = yf & M;
epbExceptionOperandMantissa = 0x0000000000000000L;
this.flg = (xf ^ yf) & M | I;
} else { //±0/(±0,NaN以外)または(±Inf,NaN以外)/±Infのとき±0、±Inf/(±Inf,NaN以外)のとき±Inf
this.flg = (xf ^ yf) & M | ((xf & Z | yf & I) != 0 ? Z : I);
}
return this;
}
//±0,±Inf,NaN以外
long r01 = x.dvl;
long y01 = y.dvl;
long r2 = (r01 << -2 | x.cvl >>> 2) >>> 33;
long y2 = (y01 << -2 | y.cvl >>> 2) >>> 33;
r01 >>>= 2;
y01 >>>= 2;
long y0 = y01 >>> 31;
long y1 = y01 & 0x7fffffffL;
//先頭1bit
boolean qq;
if (r01 < y01 || (r01 == y01 && r2 < y2)) { //x<y
qq = false;
} else {
qq = true;
r2 -= y2;
r01 -= y01;
if (r2 < 0L) {
r2 += 0x80000000L;
r01--;
}
}
//1桁目
long q0 = r01 >> 31 == y0 ? 0x7fffffffL : r01 / y0;
r01 = (r01 - q0 * y0 << 31) + r2 - q0 * y1;
if (r01 < 0L) {
q0--;
r01 += y01;
}
r2 = q0 * y2 + 0x7fffffffL;
r01 -= r2 >> 31;
r2 = ~r2 & 0x7fffffffL; //~(r2 | ~0x7fffffffL)
if (r01 < 0L) {
q0--;
r2 += y2;
r01 += y01 + (r2 >> 31);
r2 &= 0x7fffffffL;
}
//2桁目
long q1 = r01 >> 31 == y0 ? 0x7fffffffL : r01 / y0;
r01 = (r01 - q1 * y0 << 31) + r2 - q1 * y1;
if (r01 < 0L) {
q1--;
r01 += y01;
}
r2 = q1 * y2 + 0x7fffffffL;
r01 -= r2 >> 31;
r2 = ~r2 & 0x7fffffffL; //~(r2 | ~0x7fffffffL)
if (r01 < 0L) {
q1--;
r2 += y2;
r01 += y01 + (r2 >> 31);
r2 &= 0x7fffffffL;
}
//3桁目
long q2 = r01 >> 31 == y0 ? 0x7fffffffL : r01 / y0;
r01 = (r01 - q2 * y0 << 31) + r2 - q2 * y1;
if (r01 < 0L) {
q2--;
r01 += y01;
}
r2 = q2 * y2 + 0x7fffffffL;
r01 -= r2 >> 31;
r2 = ~r2 & 0x7fffffffL; //~(r2 | ~0x7fffffffL)
if (r01 < 0L) {
q2--;
r2 += y2;
r01 += y01 + (r2 >> 31);
r2 &= 0x7fffffffL;
}
//商 (((qq ? MSB : 0) | q0) << 31 | q1) << 31 | q2
//余り r01 << 31 | r2
//正規化する
int ze = x.epp - y.epp;
if (qq) { //商は94bit
q0 = MSB | q0 << 32 | q1 << 1 | q2 >>> 30;
q2 <<= -30;
} else { //商は93bit
ze--;
q0 = q0 << -31 | q1 << 2 | q2 >>> 29;
q2 <<= -29;
}
return this.finish (xf ^ yf, ze, q0, q2, r01 | r2);
} //efp.divrz(EFP,EFP)
//------------------------------------------------------------------------
//b = x.eq (y)
// b=x==y
// 等しいか
//
// -Inf==-Inf<-x<-0==+0<+x<+Inf==+Inf
//
// NaNの扱い
// どちらかがNaNのときはfalseを返す
//
public boolean eq (EFP y) {
int xf = this.flg;
int yf = y.flg;
return ((xf | yf) << 1 != 0 ? //どちらかが±0,±Inf,NaN
EFP_EQ_TABLE[xf >>> 28] << (yf >>> 28 - 1) < 0
: //両方±0,±Inf,NaN以外
xf == yf && this.epp == y.epp && this.dvl == y.dvl && this.cvl == y.cvl);
} //efp.eq(EFP)
//------------------------------------------------------------------------
//b = x.equals (y)
// b=x==y
// 一致
//
// equalsであるオブジェクトはクラスと内容の両方が一致していなければならない
// equalsであるオブジェクトはhashCodeが同じでなければならない
// equalsでないオブジェクトはhashCodeがなるべく違う方がよい
// equalsであるオブジェクトはcompareToが0であることが強く推奨される
// equalsでないオブジェクトはcompareToが0でないことが強く推奨される
//
@Override public boolean equals (Object yo) {
if (yo instanceof EFP) {
EFP x = this;
EFP y = (EFP) yo;
return (x.flg == y.flg &&
x.epp == y.epp &&
x.dvl == y.dvl &&
x.cvl == y.cvl);
}
return false;
} //efp.equals(Object)
//------------------------------------------------------------------------
//x = x.exp ()
// x=e^x
//y = y.exp (x)
// y=e^x
// 指数関数 exponential
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{exp($_[0])});print$g"
// echo read("../misc/efp.gp");graph(exp) | gp -q
// +---------+---------+---------+---------+---------+---*-----+---------+---------+
// | | ** |
// | | * |
// | | ** |
// | | ** |
// + + * +
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + ** +
// | | ** |
// | | ** |
// | | ** |
// | |*** |
// + *** +
// | ****| |
// | **** | |
// | ****** | |
// | ************ | |
// ******************--+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// 0<y<=inf
//
// テイラー展開
// e^x=1+1/1!*x+1/2!*x^2+1/3!*x^3+1/4!*x^4+1/5!*x^5+1/6!*x^6+...
// f(n,x)=sum(k=0,n,1/k!*x^k)
//
// 対数関数との関係
// e^log(x)=x
// log(e^x)=x
//
// 双曲線関数との関係
// e^x=cosh(x)+sinh(x)
// e^-x=cosh(x)-sinh(x)
// cosh(x)=(e^x+e^-x)/2
// sinh(x)=(e^x-e^-x)/2
//
public final EFP exp () {
return this.exp (this);
} //efp.exp()
public final EFP exp (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //e^±0=1
//this.set1 ();
this.flg = P;
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else {
this.flg = (xf == (P | I) ? P | I : //e^+Inf=+Inf。オーバーフローはセットされない
xf == (M | I) ? P | Z : //e^-Inf=+0。アンダーフローはセットされない
N); //e^NaN=NaN
}
return this;
}
//±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_X2; //不正確な結果。オーバーフローまたはアンダーフローのときもセットされる
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (15 <= x.epp) { //x<=-32768||32768<=x
if (xf < 0) { //x<=-32768。exp(-big)=+0
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
return this.sete (UNFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+0
} else { //32768<=x。exp(+big)=+Inf
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+Inf
}
}
if (false) { //テイラー展開 [71]
this.inner ();
EFP s = new EFP (1); //x^k/k!
EFP t = new EFP (0);
EFP u = new EFP (x); //thisが破壊されるのでxをコピーしておく
//this.sete (s);
this.flg = s.flg;
this.epp = s.epp;
this.dvl = s.dvl;
this.cvl = s.cvl;
for (int k = 1; this.ne (t); k++) {
s.imul (u).divi (k); //x^k/k!
//t.sete (this);
t.flg = this.flg;
t.epp = this.epp;
t.dvl = this.dvl;
t.cvl = this.cvl;
this.iadd (s);
}
return this.outer ().finish ();
} else if (false) { //powを使う。powがexpを使っている場合は不可
return this.pow (E, x); //e^x [89]
} else if (true) { //exp2を使う。exp2がexpを使っている場合は不可 [85] 228ns
this.inner ();
if (this == x) {
x = new EFP (x);
}
if (x.epp < -32) { //|x|<2^-32
this.imul (x, ONE_3).inc ().imul (x).idiv2 ().inc ().imul (x).outer ().inc (); //e^x=1+x*(1+x/2*(1+x/3))
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) {
if (xf < 0) {
//x<0のときe^x<1なのでRZ,RMで1<=yとなってはならない
if (this.flg << 1 == 0 && 0 <= this.epp) {
this.set1 ().nextdown (epbRoundingPrec);
}
}
} else if (epbRoundingMode == EPB_MODE_RP) {
//x!=0のとき1+x<e^xなのでRPでy<=1+xとなってはならない
if (new EFP (this.flg, this.epp, this.dvl, this.cvl).dec ().le (x)) { //y-1<=x
this.inner ().inc(x).outer ().nextup (epbRoundingPrec); //y=nextup(1+x)
}
}
} else {
this.imul (LOG2_E, x).outer ().exp2 (); //e^x=2^(log2(e)*x)
}
return this;
} else if (false) { //小数部分だけexp2を使う。[90] 257ns
int xe = x.epp;
if (xe < 0) { //|x|<1
return this.inner ().imul (LOG2_E, x).outer ().exp2 ();
}
//1<=|x|
this.inner ();
int o = (int) (x.dvl >>> ~xe); //整数部分
this.frac (x).imul (LOG2_E).exp2 ();
EFP[] a = xf >= 0 ? EXP_P_I : EXP_M_I;
for (int i = 0; o != 0; i++) {
if ((o & 1) != 0) {
this.imul (a[i]);
}
o >>>= 1;
}
return this.outer ().finish ();
} else { //64分割。[90] 270ns
int xe = x.epp;
this.inner ();
long xd = x.dvl; //整数部分は高々16bit
long xc = x.cvl;
EFP u;
if (false) {
u = new EFP ().shl (x, 6).frac ().shr (6); //xの小数点以下7桁目以降
} else {
int uf = xf;
int ue;
long ud;
long uc;
int o = xe + 7;
if (o <= 0) {
ue = xe;
ud = xd;
uc = xc;
} else if (o <= 63) {
ue = -7;
ud = xd << o | xc >>> -o;
uc = xc << o;
} else if (o <= LEN - 1) {
ue = -7;
ud = xc << o;
uc = 0L;
} else {
ue = 0;
ud = 0L;
uc = 0L;
}
if (ud >= 0L) {
if (ud != 0L) {
o = Long.numberOfLeadingZeros (ud);
ue -= o;
ud = ud << o | uc >>> -o;
uc <<= o;
} else if (uc != 0L) {
o = 64 + Long.numberOfLeadingZeros (uc);
ue -= o;
ud = uc << o;
uc = 0L;
} else {
uf |= Z;
}
}
u = new EFP (uf, ue, ud, uc); //xの小数点以下7桁目以降
}
this.imul (EXP_C10, u)
.iadd (EXP_C9).imul (u)
.iadd (EXP_C8).imul (u)
.iadd (EXP_C7).imul (u)
.iadd (EXP_C6).imul (u)
.iadd (EXP_C5).imul (u)
.iadd (EXP_C4).imul (u)
.iadd (EXP_C3).imul (u)
.iadd (EXP_C2).imul (u)
.iadd (EXP_C1).imul (u)
//.iadd (EXP_C0);
.inc ();
if (xf >= 0) {
if (xe >= 0) {
this.imul (EXP_P_T[(int) (xd << xe + 1 >>> -6)]);
int o = (int) (xd >>> ~xe); //整数部分
for (int i = 0; o != 0; i++) {
if ((o & 1) != 0) {
this.imul (EXP_P_I[i]);
}
o >>>= 1;
}
} else if (xe >= -6) {
this.imul (EXP_P_T[(int) (xd >>> ~xe - 6)]);
}
} else {
if (xe >= 0) {
this.imul (EXP_M_T[(int) (xd << xe + 1 >>> -6)]);
int o = (int) (xd >>> ~xe); //整数部分
for (int i = 0; o != 0; i++) {
if ((o & 1) != 0) {
this.imul (EXP_M_I[i]);
}
o >>>= 1;
}
} else if (xe >= -6) {
this.imul (EXP_M_T[(int) (xd >>> ~xe - 6)]);
}
}
return this.outer ().finish ();
}
} //efp.exp(EFP)
//------------------------------------------------------------------------
//x = x.exp10 ()
// x=10^x
//y = y.exp10 (x)
// y=10^x
// 底が10の指数関数 exponential with base 10
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{10**$_[0]});print$g"
// echo read("../misc/efp.gp");eval("exp10(x)=10^x");graph(exp10) | gp -q
// +---------+---------+---------+---------+-----*---+---------+---------+---------+
// | | * |
// | | ** |
// | | * |
// | | * |
// + + * +
// | | ** |
// | | * |
// | | * |
// | | ** |
// + + * +
// | | ** |
// | | * |
// | |** |
// | ** |
// + * +
// | *** |
// | ** | |
// | *** | |
// | ****** | |
// *******************************---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// 0<y<=inf
//
// 指数関数との関係
// 10^x=(e^log(10))^x
// =e^(log(10)*x)
//
// チェビシェフ展開1
// 10^x=10^(trunc(x)+frac(x))
// =10^trunc(x)*10^frac(x)
// xの整数部分は10^(±2^k),0<=k<=13のテーブルを参照して後から掛ける
// 以下は-1<x<1とする
// echo read("../misc/efp.gp");eval("f(x)=10^x");a=-1;b=1;for(n=0,31,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// -5 -4 -3 -1 1 3 6 9 12 15 18 22 25 29 32 36 40 44 48 52 56 61 65 69 74 78 83 87 92 97 102 106
//
// チェビシェフ展開2
// 偶関数と奇関数に分けてそれぞれ展開する
// 10^x=(10^x+10^-x)/2+(10^x-10^-x)/2
// echo read("../misc/efp.gp");eval("f(x)=(10^x+10^-x)/2");a=-1;b=1;forstep(n=0,30,2,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
// -1 2 7 12 18 25 32 39 47 55 64 73 82 91 100 110
// echo read("../misc/efp.gp");eval("f(x)=(10^x-10^-x)/2");a=-1;b=1;forstep(n=1,31,2,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
// 0 3 8 13 19 26 33 40 48 56 65 74 83 92 101 111
// 評価が高くなったように見えるが係数は同じなので偶関数と奇関数に分ける意味はない
//
public final EFP exp10 () {
return this.exp10 (this);
} //efp.exp10()
public final EFP exp10 (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //10^±0=1
//this.set1 ();
this.flg = P;
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else {
this.flg = (xf == (P | I) ? P | I : //10^+Inf=+Inf。オーバーフローはセットされない
xf == (M | I) ? P | Z : //10^-Inf=+0。アンダーフローはセットされない
N); //10^NaN=NaN
}
return this;
}
//±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_X2; //不正確な結果。オーバーフローまたはアンダーフローのときもセットされる
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (15 <= x.epp) { //x<=-32768||32768<=x
if (xf < 0) { //x<=-32768。exp10(-big)=+0
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
return this.sete (UNFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+0
} else { //32768<=x。exp10(+big)=+Inf
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+Inf
}
}
if (false) { //powを使う。powがexp10を使っている場合は不可
return this.pow (TEN, x); //10^x
} else if (false) { //expを使う。expがexp10を使っている場合は不可
return this.inner ().imul (LOG_10, x).outer ().exp (); //10^x=e^(log(10)*x)
} else if (true) { //exp2を使う
// 10^x=(2^log2(10))^x
// =2^(log2(10)*x)
return this.inner ().imul (LOG2_10, x).outer ().exp2 ();
} else if (false) { //exp2とexp2m1と高精度のlog2(10)を使う
// 10^x=(2^log2(10))^x
// =2^(log2(10)*x)
// =2^((log2(10)-ε+ε)*x)
// =2^((log2(10)-ε)*x+ε*x)
// =2^((log2(10)-ε)*x)*(1+2^(ε*x)-1)
// =2^((log2(10)-ε)*x)+2^((log2(10)-ε)*x)*(2^(ε*x)-1)
this.inner ();
EFP t = new EFP ().imul (LOG2_10A, x).exp2m1 ();
this.imul (LOG2_10, x).exp2 ();
t.imul (this);
return this.outer ().add (t);
} else if (false) { //小数部分だけexp2を使う。[90] 258ns
int xe = x.epp;
this.inner ();
if (xe < 0) { //|x|<1
this.imul (LOG2_10, x).exp2 ();
} else {
int o = (int) (x.dvl >>> ~xe); //整数部分
this.frac (x).imul (LOG2_10).exp2 ();
EFP[] a = xf >= 0 ? EXP10_P_I : EXP10_M_I;
for (int i = 0; o != 0; i++) {
if ((o & 1) != 0) {
this.imul (a[i]);
}
o >>>= 1;
}
}
return this.outer ().finish ();
} else { //64分割。[90] 315ns
int xe = x.epp;
this.inner ();
long xd = x.dvl; //整数部分は高々16bit
long xc = x.cvl;
EFP u;
if (false) {
u = new EFP ().shl (x, 6).frac ().shr (6); //xの小数点以下7桁目以降
} else {
int uf = xf;
int ue;
long ud;
long uc;
int o = xe + 7;
if (o <= 0) {
ue = xe;
ud = xd;
uc = xc;
} else if (o <= 63) {
ue = -7;
ud = xd << o | xc >>> -o;
uc = xc << o;
} else if (o <= LEN - 1) {
ue = -7;
ud = xc << o;
uc = 0L;
} else {
ue = 0;
ud = 0L;
uc = 0L;
}
if (ud >= 0L) {
if (ud != 0L) {
o = Long.numberOfLeadingZeros (ud);
ue -= o;
ud = ud << o | uc >>> -o;
uc <<= o;
} else if (uc != 0L) {
o = 64 + Long.numberOfLeadingZeros (uc);
ue -= o;
ud = uc << o;
uc = 0L;
} else {
uf |= Z;
}
}
u = new EFP (uf, ue, ud, uc); //xの小数点以下7桁目以降
}
this.imul (EXP10_C11, u)
.iadd (EXP10_C10).imul (u)
.iadd (EXP10_C9).imul (u)
.iadd (EXP10_C8).imul (u)
.iadd (EXP10_C7).imul (u)
.iadd (EXP10_C6).imul (u)
.iadd (EXP10_C5).imul (u)
.iadd (EXP10_C4).imul (u)
.iadd (EXP10_C3).imul (u)
.iadd (EXP10_C2).imul (u)
.iadd (EXP10_C1).imul (u)
//.iadd (EXP10_C0);
.inc ();
if (xf >= 0) {
if (xe >= 0) {
this.imul (EXP10_P_T[(int) (xd << xe + 1 >>> -6)]);
int o = (int) (xd >>> ~xe); //整数部分
for (int i = 0; o != 0; i++) {
if ((o & 1) != 0) {
this.imul (EXP10_P_I[i]);
}
o >>>= 1;
}
} else if (xe >= -6) {
this.imul (EXP10_P_T[(int) (xd >>> ~xe - 6)]);
}
this.outer ().finish ();
if (epbRoundingMode == EPB_MODE_RP) {
//0<xのとき1<10^xなのでRPでy<=1となってはならない
if (this.flg << 1 == 0 && (this.epp < 0 ||
this.epp == 0 && this.dvl == MSB && this.cvl == 0L)) {
this.set1 ().nextup (epbRoundingPrec);
}
}
} else {
if (xe >= 0) {
this.imul (EXP10_M_T[(int) (xd << xe + 1 >>> -6)]);
int o = (int) (xd >>> ~xe); //整数部分
for (int i = 0; o != 0; i++) {
if ((o & 1) != 0) {
this.imul (EXP10_M_I[i]);
}
o >>>= 1;
}
} else if (xe >= -6) {
this.imul (EXP10_M_T[(int) (xd >>> ~xe - 6)]);
}
this.outer ().finish ();
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) {
//x<0のとき10^x<1なのでRZ,RMで1<=yとなってはならない
if (this.flg << 1 == 0 && 0 <= this.epp) {
this.set1 ().nextdown (epbRoundingPrec);
}
}
}
return this;
}
} //efp.exp10(EFP)
//------------------------------------------------------------------------
//x = x.exp2 ()
// x=2^x
//y = y.exp2 (x)
// y=2^x
// 底が2の指数関数 exponential with base 2
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{2**$_[0]});print$g"
// echo read("../misc/efp.gp");eval("exp2(x)=2^x");graph(exp2) | gp -q
// +---------+---------+---------+---------+---------+---------*---------+---------+
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + ** +
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + *** +
// | | ** |
// | | *** |
// | | *** |
// | |**** |
// + **** +
// | **** | |
// | ****** | |
// | ******** | |
// | ***************** | |
// ********--+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// 0<y<=inf
//
// 指数関数との関係
// 2^x=(e^log(2))^x
// =e^(log(2)*x)
// e^x=(2^log2(e))^x
// =2^(log2(e)*x)
//
// 手順
// abs(x)<2^-LENのときは1を返す
// x→0のとき2^x→1+log(2)*x≒1+0.693*xなので1+xが情報落ちで1になるときは2^xも1になる
// xを整数部と小数部に分ける
// 整数部はそのまま指数部にする
// 小数部はチェビシェフ展開を行う
//
// exp2(x)
// echo read("../misc/efp.gp");eval("f(n,x)=sum(k=0,n,log(2)^k/k!*x^k)");eval("g(x)=2^x");for(n=0,26,printf("%4d",floor(closeness(g,f(n,x),-1,1,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=-1;b=0;for(n=0,26,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0;b=1;for(n=0,26,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// 次数 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// テイラー展開 0 1 3 5 8 11 15 18 22 26 30 34 38 42 47 51 56 61 65 70 75 80 85 90 95 101 106
// チェビシェフ展開
// [-1,0] 1 4 8 13 18 23 38 34 39 45 51 57 63 70 76 83 89 96 103 110 117 124 131 138 145 152 159
// [0,1] 1 4 8 13 18 23 38 34 39 45 51 57 63 70 76 83 89 96 103 110 117 124 131 138 145 152 159
//
// 累乗の方法
// 例
// 2^1.375=2^(1+1/4+1/8)
// =2^1*2^(1/4)*2^(1/8)
// 2^(1/4)や2^(1/8)をテーブルに展開しておいて必要なものを掛けるだけ
// 1bitずつやると効率が悪いので数bitずつまとめる
// bit ブロック サイズ
// 1 92 1*92=92
// 2 46 3*46=138
// 3 31 7*31=217
// 4 23 15*23=345
//
// チェビシェフ展開
// [0,1]を8分割
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0;b=0.125;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.125;b=0.25;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.25;b=0.375;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.375;b=0.5;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.5;b=0.625;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.625;b=0.75;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.75;b=0.875;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// echo read("../misc/efp.gp");eval("f(x)=2^x");a=0.875;b=1;for(n=0,25,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// [0,0.125] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.125,0.25] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.25,0.375] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.375,0.5] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.5,0.625] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.625,0.75] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.75,0.875] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
// [0.875,1] 4 11 18 25 33 41 49 58 67 76 85 94 103 112 122 131 141 150 160 170 180 190 200 210 220 231
//
public final EFP exp2 () {
return this.exp2 (this);
} //efp.exp2()
public final EFP exp2 (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //2^±0=1
//this.set1 ();
this.flg = P;
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else {
this.flg = (xf == (P | I) ? P | I : //2^+Inf=+Inf。オーバーフローはセットされない
xf == (M | I) ? P | Z : //2^-Inf=+0。アンダーフローはセットされない
N); //2^NaN=NaN
}
return this;
}
//±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_X2; //不正確な結果。オーバーフローまたはアンダーフローのときもセットされる
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (15 <= x.epp) { //x<=-32768||32768<=x
if (xf < 0) { //x<=-32768。exp2(-big)=+0
epbFpsr |= EPB_FPSR_UF; //アンダーフロー
return this.sete (UNFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+0
} else { //32768<=x。exp2(+big)=+Inf
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+Inf
}
}
if (false) { //powを使う。powがexp2を使っている場合は不可
return this.pow (TWO, x); //2^x
} else if (false) { //expを使う。expがexp2を使っている場合は不可
return this.inner ().imul (LOG_2, x).outer ().exp (); //2^x=e^(log(2)*x)
} else { //64分割。[91] 205ns
int xe = x.epp;
long xd = x.dvl; //整数部分は高々16bit
long xc = x.cvl;
this.inner ();
EFP u;
if (false) {
u = new EFP ().shl (x, 6).frac ().shr (6); //xの小数点以下7桁目以降
} else {
int uf = xf;
int ue;
long ud;
long uc;
int o = xe + 7;
if (o <= 0) {
ue = xe;
ud = xd;
uc = xc;
} else if (o <= 63) {
ue = -7;
ud = xd << o | xc >>> -o;
uc = xc << o;
} else if (o <= LEN - 1) {
ue = -7;
ud = xc << o;
uc = 0L;
} else {
ue = 0;
ud = 0L;
uc = 0L;
}
if (ud >= 0L) {
if (ud != 0L) {
o = Long.numberOfLeadingZeros (ud);
ue -= o;
ud = ud << o | uc >>> -o;
uc <<= o;
} else if (uc != 0L) {
o = 64 + Long.numberOfLeadingZeros (uc);
ue -= o;
ud = uc << o;
uc = 0L;
} else {
uf |= Z;
}
}
u = new EFP (uf, ue, ud, uc); //xの小数点以下7桁目以降
}
if (xf >= 0) {
this.imul (EXP2P_C8, u)
.iadd (EXP2P_C7).imul (u)
.iadd (EXP2P_C6).imul (u)
.iadd (EXP2P_C5).imul (u)
.iadd (EXP2P_C4).imul (u)
.iadd (EXP2P_C3).imul (u)
.iadd (EXP2P_C2).imul (u)
.iadd (EXP2P_C1).imul (u)
//.iadd (EXP2P_C0);
.inc ();
if (xe >= 0) {
this.imul (EXP2P_T[(int) (xd << xe + 1 >>> -6)]).shl ((int) (xd >>> ~xe));
} else if (xe >= -6) {
this.imul (EXP2P_T[(int) (xd >>> ~xe - 6)]);
}
this.outer ().finish ();
if (epbRoundingMode == EPB_MODE_RP) {
//0<xのとき1<2^xなのでRPでy<=1となってはならない
if (this.flg << 1 == 0 && (this.epp < 0 ||
this.epp == 0 && this.dvl == MSB && this.cvl == 0L)) {
this.set1 ().nextup (epbRoundingPrec);
}
}
} else {
this.imul (EXP2M_C8, u)
.iadd (EXP2M_C7).imul (u)
.iadd (EXP2M_C6).imul (u)
.iadd (EXP2M_C5).imul (u)
.iadd (EXP2M_C4).imul (u)
.iadd (EXP2M_C3).imul (u)
.iadd (EXP2M_C2).imul (u)
.iadd (EXP2M_C1).imul (u)
//.iadd (EXP2M_C0);
.inc ();
if (xe >= 0) {
this.imul (EXP2M_T[(int) (xd << xe + 1 >>> -6)]).shr ((int) (xd >>> ~xe));
} else if (xe >= -6) {
this.imul (EXP2M_T[(int) (xd >>> ~xe - 6)]);
}
this.outer ().finish ();
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RM) {
//x<0のとき2^x<1なのでRZ,RMで1<=yとなってはならない
if (this.flg << 1 == 0 && 0 <= this.epp) {
this.set1 ().nextdown (epbRoundingPrec);
}
}
}
return this;
}
} //efp.exp2(EFP)
//------------------------------------------------------------------------
//x = x.exp2m1 ()
// x=2^x-1
//y = y.exp2m1 (x)
// y=2^x-1
// 0に近い数の底が2の指数関数 exponential of number being close to 0 with base 2
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{my($x)=@_;2**$x-1});print$g"
// echo read("../misc/efp.gp");eval("f(x)=2^x-1");graph(f) | gp -q
// +---------+---------+---------+---------+---------+---------+--**-----+---------+
// | | ** |
// | | * |
// | | ** |
// | | ** |
// + + * +
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + ** +
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + *** +
// | | ** |
// | | *** |
// | | *** |
// | |**** |
// +---------+---------+---------+-------****--------+---------+---------+---------+
// | **** | |
// | ****** | |
// | ******** | |
// | ***************** | |
// ******** + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -1<y<=inf
//
// メモ
// |x|が0に極端に近いとき、exp2(x)-1を計算しようとすると情報落ちで1になってしまうが、exp2m1(x)は真の値に近い結果を返す
//
// 加算
// 2^(x+y)-1=(2^x-1)*(2^y-1)+(2^x-1)+(2^y-1)
//
// テイラー展開
// > coeff(sub(a=0,for n:=0:4 sum sub(x=a,df(2^x-1,x,n))/factorial(n)*(x-a)^n),x);
// {0,
// log(2),
// 2
// log(2)
// ---------,
// 2
// 3
// log(2)
// ---------,
// 6
// 4
// log(2)
// ---------}
// 24
//
// チェビシェフ展開
// [0,1]を8分割する
// echo read("../misc/efp.gp");eval("f(x)=2^x-1");for(s=0,7,a=s/8;b=(s+1)/8;printf(" // [%6.3f,%6.3f]",a,b);for(n=0,15,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000))));print()) | gp -q
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// [ 0.000, 0.125] -13 -6 1 8 16 24 33 41 50 59 68 77 86 95 105 114
// [ 0.125, 0.250] 0 7 14 22 29 38 46 54 63 72 81 90 99 109 118 128
// [ 0.250, 0.375] 1 8 15 22 30 38 47 55 64 73 82 91 100 110 119 128
// [ 0.375, 0.500] 2 8 15 23 31 39 47 56 65 73 82 91 101 110 119 129
// [ 0.500, 0.625] 2 9 16 23 31 39 48 56 65 74 83 92 101 110 120 129
// [ 0.625, 0.750] 2 9 16 24 31 40 48 56 65 74 83 92 101 111 120 130
// [ 0.750, 0.875] 3 9 16 24 32 40 48 57 65 74 83 92 102 111 120 130
// [ 0.875, 1.000] 3 9 16 24 32 40 48 57 66 74 83 92 102 111 120 130
//
public final EFP exp2m1 () {
return this.exp2m1 (this);
} //efp.exp2m1()
public final EFP exp2m1 (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf == (M | I)) { //exp2m1(-Inf)=-1
this.flg = M; //-1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else { //exp2m1(±0)=±0, exp2m1(+Inf)=+Inf, exp2m1(NaN)=NaN
this.flg = xf; //x
}
return this;
}
//±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_X2; //不正確な結果。オーバーフローまたはアンダーフローのときもセットされる
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (xf < 0) { //x<0
if (8 <= x.epp) { //x<=-256。exp2m1(-big)=-1
//exp2(-big).dec()だとアンダーフローがセットされてしまう場合がある
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) {
return this.sete (NEXTUP_MINUSONE[epbRoundingPrec]).finish (); //-1
} else {
return this.negset1 ().finish (); //-1
}
}
} else { //0<x
if (15 <= x.epp) { //32768<=x。exp2m1(+big)=+Inf
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+Inf
}
}
int xe = x.epp;
if (xe < -2) { //|x|<1/4
this.inner ();
if (this == x) {
x = new EFP (x); //必要なときだけコピーする
}
return this.imul (EXP2M1_C17, x)
.iadd (EXP2M1_C16).imul (x)
.iadd (EXP2M1_C15).imul (x)
.iadd (EXP2M1_C14).imul (x)
.iadd (EXP2M1_C13).imul (x)
.iadd (EXP2M1_C12).imul (x)
.iadd (EXP2M1_C11).imul (x)
.iadd (EXP2M1_C10).imul (x)
.iadd (EXP2M1_C9).imul (x)
.iadd (EXP2M1_C8).imul (x)
.iadd (EXP2M1_C7).imul (x)
.iadd (EXP2M1_C6).imul (x)
.iadd (EXP2M1_C5).imul (x)
.iadd (EXP2M1_C4).imul (x)
.iadd (EXP2M1_C3).imul (x)
.iadd (EXP2M1_C2).imul (x)
.iadd (EXP2M1_C1).outer ().mul (x);
}
int savedFpsr = epbFpsr;
this.inner ().exp2 (x).outer ().dec ();
//exp2(x).dec()だとRZ,RPのとき-1になってしまう場合がある
if (this.flg << 1 == 0 && (this.flg < 0 && 0 <= this.epp)) { //this<=-1
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) {
this.sete (NEXTUP_MINUSONE[epbRoundingPrec]).finish (); //-1
}
}
return this.correctUnderflow (savedFpsr);
} //efp.exp2m1(EFP)
//------------------------------------------------------------------------
//x = x.expm1 ()
// x=e^x-1
//y = y.expm1 (x)
// y=e^x-1
// 0に近い数の指数関数 exponential of number being close to 0
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{my($x)=@_;exp($x)-1});print$g"
// echo read("../misc/efp.gp");graph(expm1) | gp -q
// +---------+---------+---------+---------+---------+-----*---+---------+---------+
// | | ** |
// | | * |
// | | * |
// | | ** |
// + + * +
// | | ** |
// | | * |
// | | ** |
// | | ** |
// + + * +
// | | ** |
// | | ** |
// | | ** |
// | | ** |
// + + ** +
// | | ** |
// | | ** |
// | | ** |
// | |*** |
// +---------+---------+---------+--------***--------+---------+---------+---------+
// | ****| |
// | **** | |
// | ****** | |
// | ************ | |
// ****************** + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// 定義域
// -inf<=x<=inf
//
// 値域
// -1<y<=inf
//
// メモ
// |x|が0に極端に近いとき、exp(x)-1を計算しようとすると情報落ちで1になってしまうが、expm1(x)は真の値に近い結果を返す
// e^x-e^-xは|x|が0に極端に近いときexp(x)-exp(-x)よりもexpm1(x)-expm1(-x)の方が正確
//
// 加算
// e^(x+y)-1=(e^x-1)*(e^y-1)+(e^x-1)+(e^y-1)
//
// テイラー展開
// e^x-1=1/1!*x+1/2!*x^2+1/3!*x^3+1/4!*x^4+1/5!*x^5+1/6!*x^6+...
// f(n,x)=sum(k=1,n,1/k!*x^k)
// > coeff(sub(a=0,for n:=0:8 sum sub(x=a,df(e^x-1,x,n))/factorial(n)*(x-a)^n),x);
// 1 1 1 1 1 1 1
// {0,1,---,---,----,-----,-----,------,-------}
// 2 6 24 120 720 5040 40320
// e^xのテイラー展開から定数項の1を除いたもの
//
// チェビシェフ展開
// echo read("../misc/efp.gp");eval("f(x)=expm1(x)");a=-1;b=1;forstep(n=0,30,2,printf("%4d",floor(closeness(f,chebyshev(f,a,b,n),a,b,10000)))) | gp -q
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
// -11 -5 2 9 18 27 36 46 57 67 78 89 100 112 123 135
//
public final EFP expm1 () {
return this.expm1 (this);
} //efp.expm1()
public final EFP expm1 (EFP x) {
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf == (M | I)) { //expm1(-Inf)=-1
this.flg = M; //-1
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
} else { //expm1(±0)=±0, expm1(+Inf)=+Inf, expm1(NaN)=NaN
this.flg = xf; //x
}
return this;
}
//±0,±Inf,NaN以外
epbFpsr |= EPB_FPSR_X2; //不正確な結果。オーバーフローまたはアンダーフローのときもセットされる
epbExceptionOperandExponent = xf | 0x3fff + x.epp << 16;
epbExceptionOperandMantissa = x.dvl;
if (xf < 0) { //x<0
if (8 <= x.epp) { //x<=-256。expm1(-big)=-1
//exp(-big).dec()だとアンダーフローがセットされてしまう場合がある
if (epbRoundingMode == EPB_MODE_RZ || epbRoundingMode == EPB_MODE_RP) {
return this.sete (NEXTUP_MINUSONE[epbRoundingPrec]).finish (); //-1
} else {
return this.negset1 ().finish (); //-1
}
}
} else { //0<x
if (15 <= x.epp) { //32768<=x。expm1(+big)=+Inf
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1]).finish (); //+Inf
}
}
int savedFpsr = epbFpsr;
this.inner ();
if (x.epp < -2) { //|x|<1/4
if (this == x) {
x = new EFP (x);
}
this.imul (EXPM1_C18, x)
.iadd (EXPM1_C17).imul (x)
.iadd (EXPM1_C16).imul (x)
.iadd (EXPM1_C15).imul (x)
.iadd (EXPM1_C14).imul (x)
.iadd (EXPM1_C13).imul (x)
.iadd (EXPM1_C12).imul (x)
.iadd (EXPM1_C11).imul (x)
.iadd (EXPM1_C10).imul (x)
.iadd (EXPM1_C9).imul (x)
.iadd (EXPM1_C8).imul (x)
.iadd (EXPM1_C7).imul (x)
.iadd (EXPM1_C6).imul (x)
.iadd (EXPM1_C5).imul (x)
.iadd (EXPM1_C4).imul (x)
.iadd (EXPM1_C3).imul (x)
.iadd (EXPM1_C2).imul (x)
.iadd (EXPM1_C1).outer ().mul (x);
return this.originUpperUpper (x).correctUnderflow (savedFpsr);
}
return this.imul (LOG2_E, x).outer ().exp2m1 ();
} //efp.expm1(EFP)
//------------------------------------------------------------------------
//x = x.floor ()
// x=floor(x)
//y = y.floor (x)
// y=floor(x)
// 床関数 floor function
//
// グラフ
// perl -e "use POSIX;use Graph;$g=new Graph();$g->grid();$g->func(sub{floor($_[0])});print$g"
// echo read("../misc/efp.gp");graph(floor) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------*
// | | |
// | | |
// | | |
// | | |
// + + ***********
// | | |
// | | |
// | | |
// | | |
// + + *********** +
// | | |
// | | |
// | | |
// | | |
// + + *********** +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------***********---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + *********** +
// | | |
// | | |
// | | |
// | | |
// + *********** + +
// | | |
// | | |
// | | |
// | | |
// + *********** + +
// | | |
// | | |
// | | |
// | | |
// ***********---------+---------+---------+---------+---------+---------+---------+
//
// x以下で最大の整数を返す
// +0<=x<1のときは+0を返す
// x==-0のときだけ-0を返す
// floor(x)==-ceil(-x)
//
public final EFP floor () {
return this.floor (this);
} //efp.floor()
public final EFP floor (EFP x) { //2.7ns
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
this.flg = xf;
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (xe < 0) { //すべて小数部
epbFpsr |= EPB_FPSR_X2; //不正確な結果
if (xf >= 0) { //floor(0<x<1)=+0
this.flg = P | Z;
} else { //floor(-1<x<0)=-1
this.flg = M;
this.epp = 0;
this.dvl = MSB;
this.cvl = 0L;
}
return this;
}
//整数部がある
long xd = x.dvl;
long xc = x.cvl;
long m = MSB >> xe; //整数部のマスク。符号に注意
if (xf >= 0) { //floor(0<x)=trunc(x)。小数部を切り捨てる
if (xe <= 63) { //0..63。dの途中または末尾まで整数部
if ((xd & ~m | xc) != 0L) { //小数部が0ではない
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xd &= m; //小数部を切り捨てる
xc = 0L;
}
} else if (xe <= LEN - 2) { //64..90。cの途中まで整数部
if ((xc & ~m) != 0L) { //小数部が0ではない
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xc &= m; //小数部を切り捨てる
}
}
//すべて整数部のときはそのまま
} else { //floor(x<0)。小数部を切り捨てる。小数部が0でなかったときは絶対値に1を加える
if (xe <= 63) { //0..63。dの途中または末尾まで整数部
long t = xd; //保存して
xd &= m; //小数部を切り捨てる
if (((t ^ xd) | xc) != 0L) { //小数部が0でなかった
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xd -= m; //絶対値に1を加える。符号に注意
if (xd >= 0L) { //dから溢れた
xd = MSB;
xe++;
if ((short) xe != xe) { //オーバーフローした
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = xf;
epbExceptionOperandMantissa = xd;
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | 1]).finish (); //-Inf
}
}
xc = 0L;
}
//小数部が0のときはそのまま
} else if (xe <= LEN - 2) { //64..90。cの途中まで整数部
long t = xc; //保存して
xc &= m; //小数部を切り捨てる
if ((t ^ xc) != 0L) { //小数部が0でなかった
epbFpsr |= EPB_FPSR_X2; //不正確な結果
xc -= m; //絶対値に1を加える。符号に注意
if ((t ^ xc) < 0L) { //cから溢れた
xd++;
if (xd >= 0L) { //dから溢れた
xd = MSB;
xe++;
if ((short) xe != xe) { //オーバーフローした
epbFpsr |= EPB_FPSR_OF; //オーバーフロー
epbExceptionOperandExponent = xf;
epbExceptionOperandMantissa = xd;
return this.sete (OVFL_RESULTS[epbRoundingPrec << 3 | epbRoundingMode << 1 | 1]).finish (); //-Inf
}
}
}
}
}
//すべて整数部のときはそのまま
}
return this.finish (xf, xe, xd, xc, 0L);
} //efp.floor(EFP)
//------------------------------------------------------------------------
//x = x.frac ()
// x=frac(x)
//y = y.frac (x)
// y=frac(x)
// 小数部 fractional part
//
// グラフ
// perl -e "use Graph;$g=new Graph();$g->grid();$g->func(sub{$_[0]-int$_[0]});print$g"
// echo read("../misc/efp.gp");eval("f(x)=x-truncate(x)");graph(f) | gp -q
// +---------+---------+---------+---------+---------+---------+---------+---------+
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + ** ** ** **
// | | *** *** *** ***|
// | | *** *** *** *** |
// | | *** *** *** *** |
// | |*** *** *** *** |
// *--------**--------**--------**--------***--------**--------**--------**--------*
// | *** *** *** ***| |
// | *** *** *** *** | |
// | *** *** *** *** | |
// |*** *** *** *** | |
// ** ** ** ** + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// + + +
// | | |
// | | |
// | | |
// | | |
// +---------+---------+---------+---------+---------+---------+---------+---------+
//
// frac(x)=(t=x-trunc(x))==0?copySign(0,x):t
//
// 整数部を切り捨てて符号と小数部だけ残す
//
// doubleの場合
// frac(x)=Double.doubleToLongBits(x)>=0L?x-Math.floor(x):-(-x-Math.floor(-x))
// 符号の判別がx>=+0.0でない理由
// doubleの比較演算子は-0.0と+0.0を区別しないのでx>=+0.0だとfrac(-0.0)が+0.0になってしまう
// Double.compare(x,+0.0)>=+0.0でも-0.0と+0.0を区別できるがDouble.doubleToLongBits(x)>=0Lの方が速そう
// 負のときの式がx-Math.ceil(x)でない理由
// doubleの(-1.0)-(-1.0)は+0.0なのでx-ceil(x)だとfrac(-1.0)が+0.0になってしまう
//
public final EFP frac () {
return this.frac (this);
} //efp.frac()
public final EFP frac (EFP x) { //5.6ns
int xf = x.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
this.flg = xf << 2 != 0 ? N : xf; //frac(±Inf)=frac(NaN)=NaN,frac(±0)=±0
return this;
}
//±0,±Inf,NaN以外
int xe = x.epp;
if (xe >= LEN - 1) { //91..。すべて整数部
this.flg = xf | Z; //±0
return this;
}
long xd = x.dvl;
long xc = x.cvl;
if (xe >= 0) { //0..90。整数部がある
if (xe < 63) { //0..62。dの途中まで整数部
xe++; //整数部のbit数
xd = xd << xe | xc >>> -xe; //整数部を押し出す
xc <<= xe;
if (xd != 0L) { //小数部の上位64bitが0でない
xe = Long.numberOfLeadingZeros (xd);
if (xe > 0) {
xd = xd << xe | xc >>> -xe;
xc <<= xe;
}
xe = ~xe; //xe=-1-xe
} else if (xc != 0L) { //小数部の上位64bitが0で続く64bitが0でない
xe = Long.numberOfLeadingZeros (xc);
xd = xc << xe;
xc = 0L;
xe = -65 - xe;
} else { //小数部がすべて0
this.flg = xf | Z; //±0
return this;
}
} else { //63..90。cの先頭または途中まで整数部
xe++; //整数部のbit数
xc <<= xe; //xc<<=xe-64
if (xc != 0L) { //小数部が0でない
xe = Long.numberOfLeadingZeros (xc);
xd = xc << xe;
xc = 0L;
xe = ~xe; //xe=-1-xe
} else { //小数部がすべて0
this.flg = xf | Z; //±0
return this;
}
}
}
this.flg = xf;
this.epp = xe;
this.dvl = xd;
this.cvl = xc;
return this;
} //efp.frac(EFP)
//------------------------------------------------------------------------
//b = x.ge (y)
// b=x>=y
// より大きいか等しいか
//
// -Inf==-Inf<-x<-0==+0<+x<+Inf==+Inf
//
// NaNの扱い
// どちらかがNaNのときはfalseを返す
//
public boolean ge (EFP y) {
int xf = this.flg;
int yf = y.flg;
if ((xf | yf) << 1 != 0) { //どちらかが±0,±Inf,NaN
return EFP_GE_TABLE[xf >>> 28] << (yf >>> 28 - 1) < 0;
}
//両方±0,±Inf,NaN以外
if (xf != yf) { //両方±0,±Inf,NaN以外で符号が違う
return xf > yf;
}
//両方±0,±Inf,NaN以外で符号が同じ
int s;
long t;
return (xf >= 0 ? 1 : -1) * ((s = this.epp - y.epp) != 0 ? s >= 0 ? 1 : -1 :
(t = this.dvl - y.dvl) != 0L ? t >= 0L ? 1 : -1 :
(t = (this.cvl >>> 1) - (y.cvl >>> 1)) != 0L ? t >= 0L ? 1 : -1 :
0) >= 0;
} //efp.ge(EFP)
//------------------------------------------------------------------------
//i = x.getb ()
//i = x.getb (roundingMode)
// byte値
//
// 丸めモードを省略したときは小数点以下を切り捨てる(RZ)
// 2^7-1よりも大きい数は2^7-1に、-2^7よりも小さい数は-2^7に変換する(飽和変換)
// NaNは-1に変換する
//
// Javaのdoubleからbyteへのキャストは飽和変換ではない(intに飽和変換してから下位8bitを取り出す)ことに注意
//
public int getb () {
int xf = this.flg;
if (xf << 1 != 0) { //±0,±Inf,NaN
if (xf << 1 < 0) { //±0
return 0;
} else if (xf << 2 < 0) { //±Inf
epbFpsr |= EPB_FPSR_OE;
epbExceptionOperandExponent = xf & M | 0x7fff << 16;
epbExceptionOperandMantissa = 0x0000000000000000L;
return xf >> 31 ^ 0x0000007f; //+Infは0x0000007f,-Infは0xffffff80
} else { //NaN
epbFpsr |= EPB_FPSR_OE | EPB_FPSR_AV;
epbExceptionOperandExponent = 0x7fff << 16;
epbExceptionOperandMantissa = 0xffffffffffffffffL;
return -1; //NaNは-1
}
}
//±0,±Inf,NaN以外
int xe = this.epp;
long xd = this.dvl;
long xc = this.cvl;
if (xe < 0) { //0<|x|<1
if (false) {
epbFpsr |= EPB_FPSR_X2; //不正確な結果
epbExceptionOperandExponent = xf | 0x3fff + xe << 16;
epbExceptionOperandMantissa = xd;
}
return 0;
}
//1<=|x|
if (xe < 7) { //1<=|x|<2^7