File indexing completed on 2026-06-02 08:17:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include "lisk.hpp"
0024 #include <string>
0025 #include <cmath>
0026 #include <cassert>
0027 #include <type_traits>
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <typename numtype>
0039 LiSK<numtype>::LiSK(const size_t n, const size_t prec) :
0040 _prec{prec<17 ? 17:prec},
0041 _constants_clR{n},
0042 _constants{n},
0043 _iep_d{0.,std::pow(10,-(17-_offset))},
0044 _iep_clN{cln::complex(0,cln::cl_F(("1.e-"+std::to_string(prec-_offset)+"_"+std::to_string(prec)).c_str()))}
0045 {
0046
0047
0048 if (!std::is_same<numtype, cp_d>::value && !std::is_same<numtype, cln::cl_N>::value) {
0049 throw std::runtime_error("Momentarily LiSK only supports 'std::complex<double>' and 'cln::cl_N' as types!");
0050 }
0051
0052
0053 std::unordered_map<std::string, size_t> default_max_values = {
0054 {"nHarmNum",3},{"nPosZeta",4},{"nNegZeta",100},{"nFactorials",100},{"nBernNum",100},{"nLiCij",100},{"nLiBn_eq59",50}};
0055
0056 for (auto x : _user_max_values) {
0057 default_max_values[x.first] = std::max(default_max_values[x.first], x.second);
0058 }
0059
0060 _init(default_max_values);
0061
0062 }
0063
0064 template <typename numtype>
0065 template <typename T>
0066 LiSK<numtype>::constants<T>::constants(const size_t Li_n) {
0067
0068 max_values["nweight"] = Li_n;
0069
0070
0071
0072
0073 LiCij.resize(Li_n);
0074 LiBn_eq59.resize(3);
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084 template <typename numtype>
0085 numtype LiSK<numtype>::Li(const size_t n, const numtype x) {
0086
0087 assert(n>0);
0088 switch (n) {
0089 case 1:
0090 return _Li1(_add_iep(x));
0091
0092 case 2:
0093 return _Li2(_add_iep(x));
0094
0095 case 3:
0096 return _Li3(_add_iep(x));
0097
0098 case 4:
0099 return _Li4(_add_iep(x));
0100
0101 default:
0102 return _Lin_basis(n, _add_iep(x));
0103 }
0104 }
0105
0106 template <typename numtype> inline
0107 numtype LiSK<numtype>::Li1(const numtype x) {
0108 return _Li1(_add_iep(x));
0109 }
0110
0111 template <typename numtype> inline
0112 numtype LiSK<numtype>::Li2(const numtype x) {
0113 return _Li2(_add_iep(x));
0114 }
0115
0116 template <typename numtype> inline
0117 numtype LiSK<numtype>::Li3(const numtype x) {
0118 return _Li3(_add_iep(x));
0119 }
0120
0121 template <typename numtype> inline
0122 numtype LiSK<numtype>::Li4(const numtype x) {
0123 return _Li4(_add_iep(x));
0124 }
0125
0126
0127
0128
0129 template <typename numtype>
0130 numtype LiSK<numtype>::Li22(const numtype x, const numtype y) {
0131
0132 const auto one = Re((numtype)1);
0133 const numtype tx = _add_iep(x), ty = _add_iep(y);
0134
0135
0136 if (is_zero(x) || is_zero(y)) return 0;
0137
0138 if (is_zero(x-one) && is_zero(y-one)) return (((numtype)3)*_constants.PosZeta[4])/((numtype)4);
0139 if (is_zero(x+one) && is_zero(y+one)) return -(((numtype)3)*_constants.PosZeta[4])/((numtype)16);
0140
0141 if (is_zero(one/x-y)) {
0142
0143
0144
0145 if (abs(x)<=1) {
0146 const numtype lmty = log(-ty), Li2 = _Li2(ty), &zeta2 = _constants.PosZeta[2];
0147 return ((numtype)3)*_Li4(ty) - Li2*(Li2 + lmty*lmty + ((numtype)6)*zeta2)/((numtype)2) - (((numtype)2)*zeta2*zeta2)/((numtype)5);
0148
0149 } else {
0150
0151 const numtype lmtx = log(-tx), Li2x = _Li2(tx), &zeta2 = _constants.PosZeta[2];
0152 const numtype Li22_yx = ((numtype)3)*_Li4(tx) - Li2x*(Li2x + lmtx*lmtx + ((numtype)6)*zeta2)/((numtype)2)
0153 - (((numtype)2)*zeta2*zeta2)/((numtype)5);
0154
0155 return -Li22_yx - _Li4(tx*ty) + Li2x*_Li2(ty);
0156 }
0157 }
0158
0159 return _Li22(tx, ty);
0160 }
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 template <typename numtype>
0171 template <typename T>
0172 T LiSK<numtype>::_vec_max(const std::vector<T> v) const {
0173
0174 T tmp = (v.size()==0 ? T() : v[0]);
0175 for(auto i : v) tmp = std::max(tmp, i);
0176 return tmp;
0177 }
0178
0179
0180 template <typename numtype>
0181 void LiSK<numtype>::_HarmNum_extend(){
0182
0183
0184 auto &v = _constants_clR.HarmNum;
0185 const size_t nstart = v.size();
0186 const size_t nend = _vec_max<size_t>({_constants_clR.max_values["nHarmNum"]+1,nstart});
0187
0188 for(size_t n=nstart; n<nend; ++n){
0189 cln::cl_RA tmp = 0;
0190 if(n>0){
0191 for(size_t k=1;k<=n; ++k){
0192 tmp += cln::cl_R("1")/k;
0193 }
0194 }
0195 v.push_back(tmp);
0196 }
0197 }
0198
0199
0200 template <typename numtype>
0201 void LiSK<numtype>::_PosZeta_extend() {
0202
0203
0204 auto &v = _constants_clR.PosZeta;
0205 const size_t nstart = v.size();
0206 const size_t nend = _vec_max<size_t>({_constants_clR.max_values["nPosZeta"]+1,nstart});
0207
0208 for (size_t n=nstart; n<nend; ++n) {
0209 if(n==0) v.push_back(-cln::cl_R("1/2"));
0210 else if (n==1) v.push_back(0);
0211 else v.push_back(cln::zeta((int)n, cln::float_format(_prec)));
0212 }
0213 }
0214
0215
0216 template <typename numtype>
0217 void LiSK<numtype>::_Factorials_extend() {
0218
0219
0220 auto &v = _constants_clR.Factorials;
0221 const size_t nstart = v.size();
0222 const size_t nend = _vec_max<size_t>({_constants_clR.max_values["nFactorials"]+1,nstart});
0223
0224 for (size_t n=nstart; n<nend; ++n) {
0225 v.push_back(cln::factorial((uintL)n));
0226 }
0227 }
0228
0229
0230 template <typename numtype>
0231 void LiSK<numtype>::_BernNum_extend() {
0232
0233
0234 auto &v = _constants_clR.BernNum;
0235 const size_t nstart = v.size();
0236 const size_t nend = _vec_max<size_t>({_constants_clR.max_values["nBernNum"]+1,nstart});
0237
0238 for (size_t n=nstart; n<nend; ++n) {
0239 if (n==0) v.push_back(cln::cl_I(1));
0240 else{
0241 cln::cl_R tmp = 0;
0242 for (size_t k=0; k<n; ++k) {
0243 tmp += cln::binomial((uintL)n+1, (uintL)k)*v[k];
0244 }
0245 v.push_back(-tmp/(n+1));
0246 }
0247 }
0248 }
0249
0250
0251 template <typename numtype>
0252 void LiSK<numtype>::_NegZeta_extend() {
0253
0254 auto &v = _constants_clR.NegZeta;
0255 const size_t nmax = _constants_clR.max_values["nNegZeta"];
0256 if (nmax==0) throw std::runtime_error("nmax==0 not allowed in NegZeta. Set nmax>0!");
0257
0258
0259 const size_t nstart = v.size()+1;
0260 const size_t nend = _vec_max<size_t>({nmax+1,nstart});
0261
0262 for (size_t n=nstart; n<nend; ++n) {
0263 v.push_back(-_constants_clR.BernNum[n+1]/(n+1));
0264 }
0265 }
0266
0267
0268 template <typename numtype>
0269 void LiSK<numtype>::_LiCij_extend() {
0270
0271
0272 auto &v = _constants_clR.LiCij;
0273 const size_t nweight = _constants_clR.max_values["nweight"];
0274 if (nweight>v.size()){
0275 _constants_clR.LiCij.resize(nweight);
0276 _constants.LiCij.resize(nweight);
0277 }
0278
0279
0280 for (size_t i=0; i<nweight; ++i) {
0281
0282
0283 const size_t nstart = v[i].size();
0284 const size_t nend = _vec_max<size_t>({_constants_clR.max_values["nLiCij"]+1,nstart});
0285
0286 for (size_t j=nstart; j<nend; ++j) {
0287 if (!i) (j==0 ? v[0].push_back(cln::cl_I(1)) : v[0].push_back(0));
0288 else {
0289
0290 cln::cl_R tmp = 0;
0291 for (size_t k=0; k<=j; ++k) {
0292
0293 tmp += cln::binomial((uintL)j, (uintL)k)*_constants_clR.BernNum[j-k]*v[i-1][k]/(k+1)*_constants_clR.Factorials[k+1];
0294 }
0295 v[i].push_back(tmp/_constants_clR.Factorials[j+1]);
0296 }
0297 }
0298 }
0299 }
0300
0301
0302 template <typename numtype>
0303 void LiSK<numtype>::_LiBn_eq59_extend() {
0304
0305
0306 auto &v = _constants_clR.LiBn_eq59;
0307 const size_t nmax = _constants_clR.max_values["nLiBn_eq59"];
0308 for (size_t m=0; m<3; ++m) {
0309
0310 const size_t nstart = v[m].size()+1;
0311 const size_t nend = _vec_max<size_t>({nmax+1,nstart});
0312
0313 for (size_t n=nstart; n<nend ; ++n) {
0314 v[m].push_back(_constants_clR.BernNum[2*n]/(2*n)/_constants_clR.Factorials[2*n+m+1]);
0315 }
0316 }
0317 }
0318
0319
0320
0321
0322 template <typename numtype>
0323 void LiSK<numtype>::_init(const std::unordered_map<std::string, size_t> max_values) {
0324
0325
0326 std::unordered_map<std::string, size_t> &mv = _constants_clR.max_values;
0327 for (auto x : max_values) {
0328 if (mv.count(x.first)>0) mv[x.first] = x.second;
0329 else mv.insert(x);
0330 }
0331
0332 mv["nBernNum"] = _vec_max<size_t>({mv["nBernNum"],mv["nLiCij"],mv["nNegZeta"]+1,2*mv["nLiBn_eq59"]});
0333 mv["nFactorials"] = _vec_max<size_t>({mv["nFactorials"],mv["nLiCij"]+1,2*mv["nLiBn_eq59"]+3,mv["nweight"]});
0334 mv["nPosZeta"] = _vec_max<size_t>({mv["nPosZeta"],mv["nweight"]});
0335 mv["nHarmNum"] = _vec_max<size_t>({mv["nHarmNum"],mv["nweight"]-1});
0336
0337
0338 _HarmNum_extend(); _PosZeta_extend(); _Factorials_extend(); _BernNum_extend();
0339 _NegZeta_extend(); _LiCij_extend(); _LiBn_eq59_extend();
0340
0341
0342 _constants.max_values = _constants_clR.max_values;
0343
0344 for (size_t i=_constants.HarmNum.size(); i<_constants_clR.HarmNum.size(); ++i) {
0345 _constants.HarmNum.push_back(convert(_constants_clR.HarmNum[i]));
0346 }
0347 for (size_t i=_constants.PosZeta.size(); i<_constants_clR.PosZeta.size(); ++i) {
0348 _constants.PosZeta.push_back(convert(_constants_clR.PosZeta[i]));
0349 }
0350 for (size_t i=_constants.Factorials.size(); i<_constants_clR.Factorials.size(); ++i) {
0351 _constants.Factorials.push_back(convert(_constants_clR.Factorials[i]));
0352 }
0353 for (size_t i=_constants.BernNum.size(); i<_constants_clR.BernNum.size(); ++i) {
0354 _constants.BernNum.push_back(convert(_constants_clR.BernNum[i]));
0355 }
0356 for (size_t i=_constants.NegZeta.size(); i<_constants_clR.NegZeta.size(); ++i) {
0357 _constants.NegZeta.push_back(convert(_constants_clR.NegZeta[i]));
0358 }
0359 for (size_t i=0; i<_constants_clR.LiCij.size(); ++i) {
0360 for (size_t j=_constants.LiCij[i].size(); j<_constants_clR.LiCij[i].size(); ++j) {
0361 _constants.LiCij[i].push_back(convert(_constants_clR.LiCij[i][j]));
0362 }
0363 }
0364 for (size_t i=0; i<_constants_clR.LiBn_eq59.size(); ++i) {
0365 for (size_t j=_constants.LiBn_eq59[i].size(); j<_constants_clR.LiBn_eq59[i].size(); ++j) {
0366 _constants.LiBn_eq59[i].push_back(convert(_constants_clR.LiBn_eq59[i][j]));
0367 }
0368 }
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378 template <typename numtype> inline
0379 numtype LiSK<numtype>::_Li1(const numtype& x){
0380 return -log(((numtype)1)-x);
0381 }
0382
0383 template <typename numtype>
0384 numtype LiSK<numtype>::_Li2(const numtype& x){
0385
0386 const auto one = Re((numtype)1);
0387
0388 if (Re(x)<=one/2 && abs(x)<=one) {
0389 const numtype al = -log(one-x), res = al - al*al/((numtype)4);
0390 return _Li_sumBn(res, al, 2,true);
0391 }
0392 else if (Re(x)>one/2 && abs(x-one)<=one){
0393 const numtype al = -log(x), res = _constants.PosZeta[2]-al-al*al/((numtype)4)+al*log(al);
0394 return _Li_sumBn(res, al, 2);
0395 }
0396 else{
0397
0398
0399 return -Li2(one/x) - log(-x)*log(-x)/((numtype)2)-_constants.PosZeta[2];
0400 }
0401 }
0402
0403 template <typename numtype>
0404 numtype LiSK<numtype>::_Li3(const numtype& x){
0405
0406 const auto one = Re((numtype)1);
0407 const numtype two = 2, three = 3, four = 4;
0408
0409 if (Re(x)<=one/2 && abs(x)<=one) {
0410 return _Lin_1mexpal(3, x);
0411 }
0412 else if (Re(x)>one/2 && abs(x-one)<=one){
0413 const numtype al = -log(x), alsq(al*al);
0414 const numtype res = _constants.PosZeta[3]-_constants.PosZeta[2]*al+(three*alsq)/four+alsq*al/(three*four)-alsq/two*log(al);
0415 return _Li_sumBn(res, al, 3,false,true);
0416 }
0417 else{
0418
0419
0420 const numtype lx = log(-x);
0421 return Li3(one/x) - Pow(lx, 3)/(two*three) - _constants.PosZeta[2]*lx;
0422 }
0423 }
0424
0425 template <typename numtype>
0426 numtype LiSK<numtype>::_Li4(const numtype& x){
0427
0428 const auto one = Re((numtype)1);
0429 const numtype two = 2, four = 4, six = 6, eight = 8, eleven = 11;
0430
0431 if (Re(x)<=one/2 && abs(x)<=one) {
0432 return _Lin_1mexpal(4, x);
0433 }
0434 else if (Re(x)>one/2 && abs(x-one)<=one){
0435 const numtype al = -log(x), alsq(al*al);
0436 const numtype res = _constants.PosZeta[4] - _constants.PosZeta[3]*al + _constants.PosZeta[2]/two*alsq - (eleven*alsq*al)/(six*six)
0437 - alsq*alsq/(six*eight) + alsq*al/six*log(al);
0438 return _Li_sumBn(res, al, 4);
0439 }
0440 else{
0441
0442
0443 const numtype lxsq = log(-x)*log(-x), &zeta2 = _constants.PosZeta[2];
0444 return -Li4(one/x) - lxsq*lxsq/(four*six) - zeta2/two*lxsq - (((numtype)7)*zeta2*zeta2)/((numtype)10);
0445 }
0446 }
0447
0448 template <typename numtype>
0449 numtype LiSK<numtype>::_Lin_basis(const size_t n, const numtype& x){
0450
0451 const auto one = Re((numtype)1);
0452
0453 if (Re(x)<=one/2 && abs(x)<=one) {
0454 return _Lin_1mexpal(n, x);
0455 }
0456 else if (Re(x)>one/2 && abs(x-one)<=one){
0457 return _Lin_expal(n, x);
0458 }
0459 else{
0460
0461
0462 return _Lin_inverse(n, x);
0463 }
0464 }
0465
0466
0467
0468
0469 template <typename numtype>
0470 numtype LiSK<numtype>::_Lin_1mexpal(const size_t n, const numtype& x){
0471
0472 assert(n>0);
0473 const auto one = Re((numtype)1);
0474 const numtype al = -log(one-x);
0475 numtype alpow(al), res = 0, tmp = 0, prev_res = 0;
0476 size_t j = 0;
0477
0478
0479 if (n>_constants_clR.max_values["nweight"]) {
0480 _constants_clR.max_values["nweight"] = n;
0481 _init(_constants_clR.max_values);
0482 }
0483
0484 do {
0485
0486 if (j>_constants_clR.max_values["nLiCij"]){
0487 _constants_clR.max_values["nLiCij"] = j + _step;
0488 _init(_constants_clR.max_values);
0489 }
0490 prev_res = res;
0491 tmp = _constants.LiCij[n-1][j]*alpow;
0492 res += tmp;
0493 alpow *= al;
0494 j++;
0495 } while ( _ErrorEstimate(res, prev_res, tmp) );
0496
0497 return res;
0498 }
0499
0500
0501
0502
0503 template <typename numtype>
0504 numtype LiSK<numtype>::_Lin_expal(const size_t n, const numtype& x){
0505
0506 assert(n>0);
0507 const numtype al = -log(x);
0508 numtype alpow = 1, tmp = 0, res = 0, prev_res = 0;
0509 numtype sgn = 1; size_t m = 0;
0510 auto &mv = _constants_clR.max_values;
0511
0512
0513 if (n-1>mv["nHarmNum"] || n-1>mv["nFactorials"] || n>mv["nPosZeta"]) {
0514 mv["nHarmNum"] = mv["nFactorials"] = n-1;
0515 mv["nPosZeta"] = n;
0516 _init(mv);
0517 }
0518
0519 res = (Pow(-((numtype)1), (int)n-1)/_constants.Factorials[n-1])*Pow(al, (int)n-1)*(_constants.HarmNum[n-1]-log(al));
0520
0521 do {
0522
0523 if (m>mv["nFactorials"] || std::abs((int)(n-m))>mv["nNegZeta"]){
0524 mv["nFactorials"] = m + _step;
0525 mv["nNegZeta"] = std::abs((int)(n-m)) + _step;
0526 _init(mv);
0527 }
0528
0529 prev_res = res;
0530 const long ndiff = n-m;
0531 if (m==n-1) {
0532 tmp = 0;
0533 } else {
0534 tmp = (ndiff>=0 ? _constants.PosZeta[ndiff] : _constants.NegZeta[-ndiff-1])/_constants.Factorials[m]*sgn*alpow;
0535 }
0536 res += tmp;
0537 alpow *= al;
0538 sgn *= -1;
0539 m++;
0540 } while ( _ErrorEstimate(res, prev_res, tmp) );
0541
0542 return res;
0543 }
0544
0545
0546
0547
0548 template <typename numtype>
0549 numtype LiSK<numtype>::_Lin_inverse(const size_t n, const numtype &x) {
0550
0551 assert(n>=2);
0552 const auto one = Re((numtype)1), two = Re((numtype)2);
0553 const numtype sgn = ((n-1)%2) ? -1 : 1;
0554 const numtype lx = log(-x);
0555 numtype res = 0;
0556
0557
0558 if (n>_constants_clR.max_values["nweight"]) {
0559 _constants_clR.max_values["nweight"] = n;
0560 _init(_constants_clR.max_values);
0561 }
0562
0563 for (int r=1; r<=n/2; ++r) {
0564 res += ((Pow(((numtype)2), 1-2*r)-one)*_constants.PosZeta[2*r]/_constants.Factorials[n-2*r])*Pow(lx, (int)n-2*r);
0565 }
0566
0567
0568 return sgn*_Lin_1mexpal(n, one/x) - Pow(lx, (int)n)/_constants.Factorials[n] + two*res;
0569 }
0570
0571
0572
0573
0574 template <typename numtype>
0575 numtype LiSK<numtype>::_Li_sumBn(const numtype &precal, const numtype &al, const size_t n, const bool fac_2n, const bool sign){
0576
0577 assert(n>=2 && n<=4);
0578 const auto one = Re((numtype)1), two = Re((numtype)2);
0579 const numtype alsq(al*al), alfac(Pow(al,(int)n-1));
0580 numtype alpow(alsq), tmp = 0, res(precal), prev_res = 0;
0581 size_t m = 1;
0582
0583 do {
0584
0585 if (m>_constants_clR.max_values["nLiBn_eq59"]){
0586 _constants_clR.max_values["nLiBn_eq59"] = m + _step;
0587 _init(_constants_clR.max_values);
0588 }
0589
0590 prev_res = res;
0591 tmp = _constants.LiBn_eq59[n-2][m-1];
0592 if (fac_2n) tmp *= two*m;
0593 if (sign) tmp *= -one;
0594 tmp *= alpow*alfac;
0595 res += tmp;
0596 alpow *= alsq;
0597 m++;
0598 } while (_ErrorEstimate(res, prev_res, tmp));
0599
0600 return res;
0601 }
0602
0603
0604
0605
0606
0607
0608
0609
0610 template <typename numtype>
0611 numtype LiSK<numtype>::_Li22(const numtype& x, const numtype& y) {
0612
0613 const auto one = Re((numtype)1);
0614 const auto ax = abs(x), axy = abs(x*y);
0615
0616 if (ax<one && axy<one) {
0617 return _Li22_orig(x, y);
0618 }
0619 else if (ax>=one && axy>=one){
0620 return _Li22_inversion(x, y);
0621 }
0622 else{
0623 return _Li22_stuffle(x, y);
0624 }
0625 }
0626
0627
0628
0629
0630
0631 template <typename numtype>
0632 numtype LiSK<numtype>::_Li22_orig(const numtype &x, const numtype &y) const {
0633
0634
0635 numtype xpow = x*x, ypow = y, res = xpow*ypow/((numtype)4), tmp = 0, prev_res = 0;
0636
0637 numtype prev_y = ypow;
0638 size_t i = 3;
0639
0640 do {
0641 xpow *= x;
0642 ypow *= y;
0643 prev_y += ypow/((numtype)((i-1)*(i-1)));
0644
0645
0646 tmp = xpow*prev_y/((numtype)(i*i));
0647 prev_res = res;
0648 res += tmp;
0649 i++;
0650
0651 } while (_ErrorEstimate(res, prev_res, tmp));
0652
0653 return res;
0654 }
0655
0656
0657
0658
0659
0660 template <typename numtype> inline
0661 numtype LiSK<numtype>::_Li22_stuffle(const numtype &x, const numtype &y) {
0662 return -_Li22(y, x) - _Li4(x*y) + _Li2(x)*_Li2(y);
0663 }
0664
0665
0666
0667
0668
0669 template <typename numtype>
0670 numtype LiSK<numtype>::_Li22_inversion(const numtype &x, const numtype &y) {
0671
0672 const auto one = Re((numtype)1);
0673 const numtype &Pisq_6 = _constants.PosZeta[2], mxy = -x*y, invx = one/x, lmxy = log(mxy), lmxy2 = lmxy*lmxy, lx2 = Pow(log(-x),2);
0674
0675 return _Li22(invx, one/y) - _Li4(-mxy) + ((numtype)3)*(_Li4(invx)+_Li4(y)) + ((numtype)2)*(_Li3(invx)-_Li3(y))*lmxy
0676 + _Li2(invx)*(Pisq_6+lmxy2/((numtype)2)) + _Li2(y)*(lmxy2-lx2)/((numtype)2);
0677 }
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691 template <> inline
0692 cp_d LiSK<cp_d>::convert(const cln::cl_R &x) const {
0693 return {cln::double_approx(x),0};
0694 }
0695
0696
0697
0698
0699 template <> inline
0700 cp_d LiSK<cp_d>::_add_iep(const cp_d &x) const {
0701 return x - _iep_d;
0702 }
0703
0704
0705
0706
0707
0708 template <> inline
0709 bool LiSK<cp_d>::_ErrorEstimate(const cp_d& res, const cp_d& prev_res, const cp_d& current) const{
0710 return res!=prev_res || cln::zerop((cln::cl_R)abs(current));
0711 }
0712
0713
0714
0715
0716 template <> inline
0717 cp_d LiSK<cp_d>::Pow(const cp_d &x, const int n) const{
0718 return std::pow(x,n);
0719 }
0720
0721
0722
0723
0724 template <> inline
0725 bool LiSK<cp_d>::is_zero(const cp_d &x) const{
0726 return cln::zerop(cln::complex(x.real(), x.imag()));
0727 }
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737 template <> inline
0738 cln::cl_N LiSK<cln::cl_N>::convert(const cln::cl_R &x) const {
0739 return _cln_tofloat ? cln::cl_float(x, cln::float_format(_prec)) : x;
0740 }
0741
0742
0743
0744
0745 template<> inline
0746 cln::cl_N LiSK<cln::cl_N>::_adjustDigits(const cln::cl_N &x) const{
0747
0748 const auto prec = cln::float_format(_prec);
0749 const cln::cl_F r = cln::cl_float(cln::realpart(x), prec);
0750 const cln::cl_F i = cln::cl_float(cln::imagpart(x), prec);
0751
0752 return cln::complex(r, i);
0753 }
0754
0755
0756
0757
0758 template <> inline
0759 cln::cl_N LiSK<cln::cl_N>::_add_iep(const cln::cl_N &x) const {
0760 return _adjustDigits(x) - _iep_clN;
0761 }
0762
0763
0764
0765
0766 template <> inline
0767 bool LiSK<cln::cl_N>::is_zero(const cln::cl_N &x) const{
0768 return cln::zerop(x);
0769 }
0770
0771
0772
0773
0774 template <> inline
0775 bool LiSK<cln::cl_N>::_ErrorEstimate(const cln::cl_N& res, const cln::cl_N& prev_res, const cln::cl_N& current) const{
0776 return res!=prev_res || is_zero(current);
0777 }
0778
0779
0780
0781
0782 template <> inline
0783 cln::cl_N LiSK<cln::cl_N>::Pow(const cln::cl_N &x, const int n) const{
0784 return cln::expt(x, (cln::cl_I)n);
0785 }