加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ldouble.c 51.76 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
/*******************************************
* SPDX-License-Identifier: MIT *
* Copyright (C) 2019-.... Jing Leng *
* Contact: Jing Leng <lengjingzju@163.com> *
* URL: https://github.com/lengjingzju/json *
*******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#define DIY_SIGNIFICAND_SIZE 64 /* Symbol: 1 bit, Exponent, 11 bits, Mantissa, 52 bits */
#define DP_SIGNIFICAND_SIZE 52 /* Mantissa, 52 bits */
#define DP_EXPONENT_OFFSET 0x3FF /* Exponent offset is 0x3FF */
#define DP_EXPONENT_MAX 0x7FF /* Max Exponent value */
#define DP_EXPONENT_MASK 0x7FF0000000000000 /* Exponent Mask, 11 bits */
#define DP_SIGNIFICAND_MASK 0x000FFFFFFFFFFFFF /* Mantissa Mask, 52 bits */
#define DP_HIDDEN_BIT 0x0010000000000000 /* Integer bit for Mantissa */
#ifndef USE_FLOAT_MUL_CONVERT
#define USE_FLOAT_MUL_CONVERT 0
#endif
#ifndef LSHIFT_RESERVED_BIT
#define LSHIFT_RESERVED_BIT 11 /* The value should be less than or equal to 11 */
#endif
#ifndef APPROX_TAIL_CMP_VAL
#define APPROX_TAIL_CMP_VAL 2 /* The value should be less than or equal to 4 */
#endif
static const unsigned int s_tail_cmp = (APPROX_TAIL_CMP_VAL << 1) + 1;
typedef struct {
uint64_t f;
int32_t e;
} diy_fp_t;
#if !USE_FLOAT_MUL_CONVERT
typedef struct {
uint32_t hi;
uint32_t lo;
} u32x2_t;
typedef struct {
uint32_t hi;
uint32_t lo;
int32_t e;
} pow9x2_t;
#else
static inline uint64_t u128_calc(uint64_t x, uint64_t y)
{
const uint64_t div = 10000000000000000000llu;
uint64_t hi, lo, ret;
double val;
#if defined(_MSC_VER) && defined(_M_AMD64)
lo = _umul128(x, y, &hi);
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __clang_major__ >= 9) && (__WORDSIZE == 64)
__extension__ typedef unsigned __int128 uint128;
const uint128 p = (uint128)x * (uint128)y;
hi = (uint64_t)(p >> 64);
lo = (uint64_t)p;
#else
const uint64_t M32 = 0XFFFFFFFF;
const uint64_t a = x >> 32;
const uint64_t b = x & M32;
const uint64_t c = y >> 32;
const uint64_t d = y & M32;
const uint64_t ac = a * c;
const uint64_t bc = b * c;
const uint64_t ad = a * d;
const uint64_t bd = b * d;
const uint64_t mid1 = ad + (bd >> 32);
const uint64_t mid2 = bc + (mid1 & M32);
hi = ac + (mid1 >> 32) + (mid2 >> 32);
lo = (bd & M32) | (mid2 & M32) << 32;
#endif
val = hi * 1.8446744073709551616; /* 1<<64 = 18446744073709551616 */
ret = (uint64_t)val + 1;
if (lo >= div)
++ret;
return ret;
}
#endif
static inline int32_t u64_pz_get(uint64_t f)
{
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
return 63 - index;
#elif defined(__GNUC__) || defined(__clang__)
return __builtin_clzll(f);
#else
int32_t index = DP_SIGNIFICAND_SIZE; /* max value of f is smaller than pow(2, 53) */
while (!(f & ((uint64_t)1 << index)))
--index;
return 63 - index;
#endif
}
#if !USE_FLOAT_MUL_CONVERT
/*
# python to get lut
def print_pow_array(unit, index, end, positive):
cmp_value = 1000000000000000000 # ULONG_MAX = 18446744073709551615
base_lut = []
index_lut = []
for i in range(end + 1):
a = unit ** i
b = a
j = 0
if a < cmp_value:
while b < cmp_value:
j += 1
b = a * (10 ** j)
j -= 1
b = a * (10 ** j)
j = i * index + j
else:
while b >= cmp_value:
j += 1
b = a // (10 ** j)
b = a // (10 ** j)
if b != cmp_value:
b += 1;
j = i * index - j
#print('%-3d: %d 0x%016x %d' % (i, j, b, b))
base_lut.append(b)
index_lut.append(j)
print('static const u32x2_t %s_base_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 4 == 0:
print()
print(' ', end='')
hi = base_lut[i] // 1000000000;
lo = base_lut[i] - hi * 1000000000;
print('{%9d,%9d}' % (hi, lo), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
print()
print('static const int8_t %s_index_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 20 == 0:
print()
print(' ', end='')
print('%-3d' % (index_lut[i]), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
def print_positive_array():
# 1 * (2 ** 4) = 1.6 * (10 ** 1)
# 16 = 1.6 * (10 ** 1)
# 243 = (1023 - 52 - (11 - x)) / 4 + 1
print_pow_array(16, 1, 243, True)
def print_negative_array():
# 1 * (2 ** -4) = 0.625 * (10 ** -1)
# 625 = 0.625 * (10 ** 3)
# 285 = (1022 + 52 + (63 - (11 - x))) / 4 + 1
print_pow_array(625, 3, 285, False)
print_positive_array()
print()
print_negative_array()
*/
static inline pow9x2_t positive_diy_fp(int32_t e)
{
static const u32x2_t positive_base_lut[244] = {
{100000000, 0}, {160000000, 0}, {256000000, 0}, {409600000, 0},
{655360000, 0}, {104857600, 0}, {167772160, 0}, {268435456, 0},
{429496729,600000000}, {687194767,360000000}, {109951162,777600000}, {175921860,444160000},
{281474976,710656000}, {450359962,737049600}, {720575940,379279360}, {115292150,460684698},
{184467440,737095517}, {295147905,179352826}, {472236648,286964522}, {755578637,259143235},
{120892581,961462918}, {193428131,138340668}, {309485009,821345069}, {495176015,714152110},
{792281625,142643376}, {126765060, 22822941}, {202824096, 36516705}, {324518553,658426727},
{519229685,853482763}, {830767497,365572421}, {132922799,578491588}, {212676479,325586540},
{340282366,920938464}, {544451787, 73501542}, {871122859,317602467}, {139379657,490816395},
{223007451,985306232}, {356811923,176489971}, {570899077, 82383953}, {913438523,331814324},
{146150163,733090292}, {233840261,972944467}, {374144419,156711148}, {598631070,650737836},
{957809713, 41180537}, {153249554, 86588886}, {245199286,538542218}, {392318858,461667548},
{627710173,538668077}, {100433627,766186893}, {160693804,425899028}, {257110087, 81438445},
{411376139,330301511}, {658201822,928482417}, {105312291,668557187}, {168499666,669691499},
{269599466,671506398}, {431359146,674410237}, {690174634,679056379}, {110427941,548649021},
{176684706,477838433}, {282695530,364541493}, {452312848,583266389}, {723700557,733226222},
{115792089,237316196}, {185267342,779705913}, {296427748,447529461}, {474284397,516047137},
{758855036, 25675419}, {121416805,764108067}, {194266889,222572908}, {310827022,756116652},
{497323236,409786643}, {795717178,255658628}, {127314748,520905381}, {203703597,633448609},
{325925756,213517774}, {521481209,941628439}, {834369935,906605501}, {133499189,745056881},
{213598703,592091009}, {341757925,747345614}, {546812681,195752982}, {874900289,913204770},
{139984046,386112764}, {223974474,217780422}, {358359158,748448674}, {573374653,997517878},
{917399446,396028605}, {146783911,423364577}, {234854258,277383323}, {375766813,243813317},
{601226901,190101307}, {961963041,904162091}, {153914086,704665935}, {246262538,727465496},
{394020061,963944793}, {630432099,142311668}, {100869135,862769867}, {161390617,380431787},
{258224987,808690859}, {413159980,493905375}, {661055968,790248599}, {105768955, 6439776},
{169230328, 10303642}, {270768524,816485827}, {433229639,706377322}, {693167423,530203715},
{110906787,764832595}, {177450860,423732152}, {283921376,677971442}, {454274202,684754307},
{726838724,295606891}, {116294195,887297103}, {186070713,419675364}, {297713141,471480583},
{476341026,354368932}, {762145642,166990291}, {121943302,746718447}, {195109284,394749515},
{312174855, 31599224}, {499479768, 50558758}, {799167628,880894012}, {127866820,620943042},
{204586912,993508867}, {327339060,789614188}, {523742497,263382700}, {837987995,621412319},
{134078079,299425971}, {214524926,879081554}, {343239883, 6530486}, {549183812,810448778},
{878694100,496718044}, {140591056, 79474887}, {224945689,727159820}, {359913103,563455711},
{575860965,701529137}, {921377545,122446620}, {147420407,219591460}, {235872651,551346335},
{377396242,482154136}, {603833987,971446617}, {966134380,754314587}, {154581500,920690334},
{247330401,473104535}, {395728642,356967255}, {633165827,771147608}, {101306532,443383618},
{162090451,909413788}, {259344723, 55062060}, {414951556,888099296}, {663922491, 20958874},
{106227598,563353420}, {169964157,701365472}, {271942652,322184755}, {435108243,715495608},
{696173189,944792972}, {111387710,391166876}, {178220336,625867001}, {285152538,601387202},
{456244061,762219522}, {729990498,819551235}, {116798479,811128198}, {186877567,697805117},
{299004108,316488186}, {478406573,306381098}, {765450517,290209756}, {122472082,766433561},
{195955332,426293698}, {313528531,882069916}, {501645651, 11311866}, {802633041,618098985},
{128421286,658895838}, {205474058,654233341}, {328758493,846773345}, {526013590,154837351},
{841621744,247739762}, {134659479, 79638362}, {215455166,527421379}, {344728266,443874207},
{551565226,310198730}, {882504362, 96317968}, {141200697,935410875}, {225921116,696657400},
{361473786,714651840}, {578358058,743442944}, {925372893,989508710}, {148059663, 38321394},
{236895460,861314230}, {379032737,378102768}, {606452379,804964428}, {970323807,687943085},
{155251809,230070894}, {248402894,768113430}, {397444631,628981488}, {635911410,606370380},
{101745825,697019261}, {162793321,115230818}, {260469313,784369308}, {416750902, 54990893},
{666801443,287985428}, {106688230,926077669}, {170701169,481724270}, {273121871,170758832},
{436994993,873214130}, {699191990,197142608}, {111870718,431542818}, {178993149,490468508},
{286389039,184749613}, {458222462,695599380}, {733155940,312959007}, {117304950,450073442},
{187687920,720117506}, {300300673,152188010}, {480481077, 43500815}, {768769723,269601304},
{123003155,723136209}, {196805049,157017934}, {314888078,651228694}, {503820925,841965911},
{806113481,347145457}, {128978157, 15543274}, {206365051,224869237}, {330184081,959790779},
{528294531,135665247}, {845271249,817064395}, {135243399,970730304}, {216389439,953168485},
{346223103,925069576}, {553956966,280111322}, {886331146, 48178115}, {141812983,367708499},
{226900773,388333598}, {363041237,421333756}, {580865979,874134009}, {929385567,798614415},
{148701690,847778307}, {237922705,356445291}, {380676328,570312465}, {609082125,712499943},
{974531401,139999909}, {155925024,182399986}, {249480038,691839977}, {399168061,906943963}
};
static const int8_t positive_index_lut[244] = {
17 , 17 , 17 , 17 , 17 , 16 , 16 , 16 , 16 , 16 , 15 , 15 , 15 , 15 , 15 , 14 , 14 , 14 , 14 , 14 ,
13 , 13 , 13 , 13 , 13 , 12 , 12 , 12 , 12 , 12 , 11 , 11 , 11 , 11 , 11 , 10 , 10 , 10 , 10 , 10 ,
9 , 9 , 9 , 9 , 9 , 8 , 8 , 8 , 8 , 7 , 7 , 7 , 7 , 7 , 6 , 6 , 6 , 6 , 6 , 5 ,
5 , 5 , 5 , 5 , 4 , 4 , 4 , 4 , 4 , 3 , 3 , 3 , 3 , 3 , 2 , 2 , 2 , 2 , 2 , 1 ,
1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , -1 , -1 , -1 , -1 , -1 , -2 , -2 , -2 , -2 , -3 , -3 ,
-3 , -3 , -3 , -4 , -4 , -4 , -4 , -4 , -5 , -5 , -5 , -5 , -5 , -6 , -6 , -6 , -6 , -6 , -7 , -7 ,
-7 , -7 , -7 , -8 , -8 , -8 , -8 , -8 , -9 , -9 , -9 , -9 , -9 , -10, -10, -10, -10, -10, -11, -11,
-11, -11, -11, -12, -12, -12, -12, -13, -13, -13, -13, -13, -14, -14, -14, -14, -14, -15, -15, -15,
-15, -15, -16, -16, -16, -16, -16, -17, -17, -17, -17, -17, -18, -18, -18, -18, -18, -19, -19, -19,
-19, -19, -20, -20, -20, -20, -20, -21, -21, -21, -21, -21, -22, -22, -22, -22, -23, -23, -23, -23,
-23, -24, -24, -24, -24, -24, -25, -25, -25, -25, -25, -26, -26, -26, -26, -26, -27, -27, -27, -27,
-27, -28, -28, -28, -28, -28, -29, -29, -29, -29, -29, -30, -30, -30, -30, -30, -31, -31, -31, -31,
-31, -32, -32, -32
};
const pow9x2_t v = { .hi = positive_base_lut[e].hi, .lo = positive_base_lut[e].lo, .e = positive_index_lut[e] };
return v;
}
static inline pow9x2_t negative_diy_fp(int32_t e)
{
static const u32x2_t negative_base_lut[286] = {
{100000000, 0}, {625000000, 0}, {390625000, 0}, {244140625, 0},
{152587890,625000000}, {953674316,406250000}, {596046447,753906250}, {372529029,846191407},
{232830643,653869629}, {145519152,283668519}, {909494701,772928238}, {568434188,608080149},
{355271367,880050093}, {222044604,925031309}, {138777878, 78144568}, {867361737,988403548},
{542101086,242752218}, {338813178,901720136}, {211758236,813575085}, {132348898, 8484428},
{827180612,553027675}, {516987882,845642297}, {323117426,778526436}, {201948391,736579023},
{126217744,835361889}, {788860905,221011806}, {493038065,763132379}, {308148791,101957737},
{192592994,438723586}, {120370621,524202241}, {752316384,526264006}, {470197740,328915004},
{293873587,705571877}, {183670992,315982424}, {114794370,197489015}, {717464813,734306341},
{448415508,583941463}, {280259692,864963415}, {175162308, 40602134}, {109476442,525376334},
{684227765,783602086}, {427642353,614751304}, {267276471, 9219565}, {167047794,380762228},
{104404871,487976393}, {652530446,799852453}, {407831529,249907783}, {254894705,781192365},
{159309191,113245228}, {995682444,457782674}, {622301527,786114171}, {388938454,866321357},
{243086534,291450848}, {151929083,932156780}, {949556774,575979875}, {593472984,109987422},
{370920615, 68742139}, {231825384,417963837}, {144890865,261227398}, {905567907,882671237},
{565979942,426669523}, {353737464, 16668452}, {221085915, 10417783}, {138178696,881511115},
{863616855,509444463}, {539760534,693402790}, {337350334,183376744}, {210843958,864610465},
{131777474,290381541}, {823609214,314884627}, {514755758,946802892}, {321722349,341751808},
{201076468,338594880}, {125672792,711621800}, {785454954,447636249}, {490909346,529772656},
{306818341,581107910}, {191761463,488192444}, {119850914,680120278}, {749068216,750751733},
{468167635,469219833}, {292604772,168262396}, {182877982,605163998}, {114298739,128227499},
{714367119,551421864}, {446479449,719638665}, {279049656, 74774166}, {174406035, 46733854},
{109003771,904208659}, {681273574,401304116}, {425795984, 815072}, {266122490, 509420},
{166326556,250318388}, {103954097,656448993}, {649713110,352806202}, {406070693,970503876},
{253794183,731564923}, {158621364,832228077}, {991383530,201425478}, {619614706,375890924},
{387259191,484931828}, {242036994,678082393}, {151273121,673801496}, {945457010,461259344},
{590910631,538287090}, {369319144,711429432}, {230824465,444643395}, {144265290,902902122},
{901658068,143138260}, {563536292,589461413}, {352210182,868413383}, {220131364,292758365},
{137582102,682973978}, {859888141,768587361}, {537430088,605367101}, {335893805,378354438},
{209933628,361471524}, {131208517,725919703}, {820053235,786998139}, {512533272,366873837},
{320333295,229296148}, {200208309,518310093}, {125130193,448943808}, {782063709, 55898799},
{488789818,159936750}, {305493636,349960469}, {190933522,718725293}, {119333451,699203308},
{745834073,120020675}, {466146295,700012922}, {291341434,812508076}, {182088396,757817548},
{113805247,973635968}, {711282799,835224795}, {444551749,897015497}, {277844843,685634686},
{173653027,303521679}, {108533142, 64701049}, {678332137,904381557}, {423957586,190238473},
{264973491,368899046}, {165608432,105561904}, {103505270, 65976190}, {646907937,912351186},
{404317461,195219491}, {252698413,247012182}, {157936508,279382614}, {987103176,746141335},
{616939485,466338335}, {385587178,416461459}, {240991986,510288412}, {150619991,568930258},
{941374947,305814109}, {588359342, 66133818}, {367724588,791333637}, {229827867,994583523},
{143642417,496614702}, {897765109,353841886}, {561103193,346151179}, {350689495,841344487},
{219180934,900840304}, {136988084,313025190}, {856175526,956407438}, {535109704,347754649},
{334443565,217346656}, {209027228,260841660}, {130642017,663026038}, {816512610,393912733},
{510320381,496195458}, {318950238,435122162}, {199343899, 21951351}, {124589936,888719595},
{778687105,554497464}, {486679440,971560915}, {304174650,607225572}, {190109156,629515983},
{118818222,893447489}, {742613893, 84046807}, {464133683,177529254}, {290083551,985955784},
{181302219,991222365}, {113313887,494513978}, {708211796,840712363}, {442632373, 25445227},
{276645233,140903267}, {172903270,713064542}, {108064544,195665339}, {675403401,222908366},
{422127125,764317729}, {263829453,602698581}, {164893408,501686613}, {103058380,313554133},
{644114876,959713331}, {402571798, 99820832}, {251607373,812388020}, {157254608,632742513},
{982841303,954640703}, {614275814,971650440}, {383922384,357281525}, {239951490,223300953},
{149969681,389563096}, {937310508,684769347}, {585819067,927980842}, {366136917,454988027},
{228835573,409367517}, {143022233,380854698}, {893888958,630341861}, {558680599,143963663},
{349175374,464977290}, {218234609, 40610806}, {136396630,650381754}, {852478941,564885961},
{532799338,478053726}, {332999586,548783579}, {208124741,592989737}, {130077963,495618586},
{812987271,847616158}, {508117044,904760099}, {317573153, 65475062}, {198483220,665921914},
{124052012,916201196}, {775325080,726257475}, {484578175,453910922}, {302861359,658694327},
{189288349,786683954}, {118305218,616677472}, {739407616,354234195}, {462129760,221396372},
{288831100,138372733}, {180519437,586482958}, {112824648,491551849}, {705154053, 72199054},
{440721283,170124409}, {275450801,981327756}, {172156751,238329847}, {107597969,523956155},
{672487309,524725965}, {420304568,452953728}, {262690355,283096080}, {164181472, 51935050},
{102613420, 32459407}, {641333875,202871289}, {400833672, 1794556}, {250521045, 1121598},
{156575653,125700999}, {978597832, 35631240}, {611623645, 22269525}, {382264778,138918453},
{238915486,336824034}, {149322178,960515021}, {933263618,503218879}, {583289761,564511800},
{364556100,977819875}, {227847563,111137422}, {142404726,944460889}, {890029543,402880554},
{556268464,626800346}, {347667790,391750217}, {217292368,994843886}, {135807730,621777429},
{848798316,386108927}, {530498947,741318079}, {331561842,338323800}, {207226151,461452375},
{129516344,663407735}, {809477154,146298338}, {505923221,341436462}, {316202013,338397789},
{197626258,336498618}, {123516411,460311637}, {771977571,626947726}, {482485982,266842329},
{301553738,916776456}, {188471086,822985285}, {117794429,264365803}, {736215182,902286268},
{460134489,313928918}, {287584055,821205574}, {179740034,888253484}, {112337521,805158428},
{702109511,282240170}, {438818444,551400106}, {274261527,844625067}, {171413454,902890667},
{107133409,314306667}, {669583808,214416666}
};
static const int8_t negative_index_lut[286] = {
17 , 18 , 18 , 18 , 18 , 19 , 19 , 19 , 19 , 19 , 20 , 20 , 20 , 20 , 20 , 21 , 21 , 21 , 21 , 21 ,
22 , 22 , 22 , 22 , 22 , 23 , 23 , 23 , 23 , 23 , 24 , 24 , 24 , 24 , 24 , 25 , 25 , 25 , 25 , 25 ,
26 , 26 , 26 , 26 , 26 , 27 , 27 , 27 , 27 , 28 , 28 , 28 , 28 , 28 , 29 , 29 , 29 , 29 , 29 , 30 ,
30 , 30 , 30 , 30 , 31 , 31 , 31 , 31 , 31 , 32 , 32 , 32 , 32 , 32 , 33 , 33 , 33 , 33 , 33 , 34 ,
34 , 34 , 34 , 34 , 35 , 35 , 35 , 35 , 35 , 36 , 36 , 36 , 36 , 36 , 37 , 37 , 37 , 37 , 38 , 38 ,
38 , 38 , 38 , 39 , 39 , 39 , 39 , 39 , 40 , 40 , 40 , 40 , 40 , 41 , 41 , 41 , 41 , 41 , 42 , 42 ,
42 , 42 , 42 , 43 , 43 , 43 , 43 , 43 , 44 , 44 , 44 , 44 , 44 , 45 , 45 , 45 , 45 , 45 , 46 , 46 ,
46 , 46 , 46 , 47 , 47 , 47 , 47 , 48 , 48 , 48 , 48 , 48 , 49 , 49 , 49 , 49 , 49 , 50 , 50 , 50 ,
50 , 50 , 51 , 51 , 51 , 51 , 51 , 52 , 52 , 52 , 52 , 52 , 53 , 53 , 53 , 53 , 53 , 54 , 54 , 54 ,
54 , 54 , 55 , 55 , 55 , 55 , 55 , 56 , 56 , 56 , 56 , 56 , 57 , 57 , 57 , 57 , 58 , 58 , 58 , 58 ,
58 , 59 , 59 , 59 , 59 , 59 , 60 , 60 , 60 , 60 , 60 , 61 , 61 , 61 , 61 , 61 , 62 , 62 , 62 , 62 ,
62 , 63 , 63 , 63 , 63 , 63 , 64 , 64 , 64 , 64 , 64 , 65 , 65 , 65 , 65 , 65 , 66 , 66 , 66 , 66 ,
66 , 67 , 67 , 67 , 67 , 68 , 68 , 68 , 68 , 68 , 69 , 69 , 69 , 69 , 69 , 70 , 70 , 70 , 70 , 70 ,
71 , 71 , 71 , 71 , 71 , 72 , 72 , 72 , 72 , 72 , 73 , 73 , 73 , 73 , 73 , 74 , 74 , 74 , 74 , 74 ,
75 , 75 , 75 , 75 , 75 , 76
};
const pow9x2_t v = { .hi = negative_base_lut[e].hi, .lo = negative_base_lut[e].lo, .e = negative_index_lut[e] };
return v;
}
static inline void ldouble_convert(diy_fp_t *v)
{
uint64_t f = v->f;
int32_t e = v->e, t = v->e;
pow9x2_t x;
uint64_t hi, lo;
e >>= 2;
t -= e << 2;
if (t) {
++e;
f >>= 4 - t;
}
x = e >= 0 ? positive_diy_fp(e) : negative_diy_fp(-e);
hi = f / 1000000000;
lo = f - hi * 1000000000;
if (x.lo && lo) {
f = x.hi * hi + (x.hi * lo + x.lo * hi + (x.lo * lo) / 1000000000) / 1000000000;
} else {
f = x.hi * hi + (x.hi * lo + x.lo * hi) / 1000000000;
}
#if LSHIFT_RESERVED_BIT > 10
v->f = f;
v->e = e - x.e + 18;
#elif LSHIFT_RESERVED_BIT > 7
v->f = f / 10;
v->e = e - x.e + 19;
#elif LSHIFT_RESERVED_BIT > 4
v->f = f / 100;
v->e = e - x.e + 20;
#else
v->f = f / 1000;
v->e = e - x.e + 21;
#endif
}
#else
/*
# python to get lut
def print_pow_array(unit, index, end, positive):
cmp_value = 10000000000000000000 # ULONG_MAX = 18446744073709551615
base_lut = []
index_lut = []
for i in range(end + 1):
a = unit ** i
b = a
j = 0
if a < cmp_value:
while b < cmp_value:
j += 1
b = a * (10 ** j)
j -= 1
b = a * (10 ** j)
j = i * index + j
else:
while b >= cmp_value:
j += 1
b = a // (10 ** j)
b = a // (10 ** j)
if b != cmp_value:
b += 1;
j = i * index - j
#print('%-3d: %d 0x%016x %d' % (i, j, b, b))
base_lut.append(b)
index_lut.append(j)
print('static const uint64_t %s_base_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 4 == 0:
print()
print(' ', end='')
print('0x%016x' % (base_lut[i]), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
print()
print('static const int8_t %s_index_lut[%d] = {' % ('positive' if positive else 'negative', end + 1), end='')
for i in range(end + 1):
if i % 20 == 0:
print()
print(' ', end='')
print('%-3d' % (index_lut[i]), end='')
if i != end:
print(', ', end='');
else:
print()
print('};')
def print_positive_array():
# 1 * (2 ** 4) = 1.6 * (10 ** 1)
# 16 = 1.6 * (10 ** 1)
# 243 = (1023 - 52 - (11 - x)) / 4 + 1
print_pow_array(16, 1, 243, True)
def print_negative_array():
# 1 * (2 ** -4) = 0.625 * (10 ** -1)
# 625 = 0.625 * (10 ** 3)
# 285 = (1022 + 52 + (63 - (11 - x))) / 4 + 1
print_pow_array(625, 3, 285, False)
print_positive_array()
print()
print_negative_array()
*/
static inline diy_fp_t positive_diy_fp(int32_t e)
{
static const uint64_t positive_base_lut[244] = {
0x0de0b6b3a7640000, 0x16345785d8a00000, 0x2386f26fc1000000, 0x38d7ea4c68000000,
0x5af3107a40000000, 0x0e8d4a5100000000, 0x174876e800000000, 0x2540be4000000000,
0x3b9aca0000000000, 0x5f5e100000000000, 0x0f42400000000000, 0x186a000000000000,
0x2710000000000000, 0x3e80000000000000, 0x6400000000000000, 0x1000000000000000,
0x199999999999999a, 0x28f5c28f5c28f5c3, 0x4189374bc6a7ef9e, 0x68db8bac710cb296,
0x10c6f7a0b5ed8d37, 0x1ad7f29abcaf4858, 0x2af31dc4611873c0, 0x44b82fa09b5a52cc,
0x6df37f675ef6eae0, 0x119799812dea111a, 0x1c25c268497681c3, 0x2d09370d42573604,
0x480ebe7b9d58566d, 0x734aca5f6226f0ae, 0x12725dd1d243aba1, 0x1d83c94fb6d2ac35,
0x2f394219248446bb, 0x4b8ed0283a6d3df8, 0x78e480405d7b9659, 0x1357c299a88ea76b,
0x1ef2d0f5da7dd8ab, 0x318481895d962777, 0x4f3a68dbc8f03f25, 0x7ec3daf941806507,
0x14484bfeebc29f87, 0x2073accb12d0ff3e, 0x33ec47ab514e652f, 0x5313a5dee87d6eb1,
0x84ec3c97da624ab5, 0x154484932d2e725b, 0x22073a8515171d5e, 0x3671f73b54f1c896,
0x571cbec554b60dbc, 0x0df01e85f912e37b, 0x164cfda3281e38c4, 0x23ae629ea696c139,
0x391704310a8acec2, 0x5b5806b4ddaae469, 0x0e9d71b689dde71b, 0x17624f8a762fd82c,
0x256a18dd89e626ac, 0x3bdcf495a9703de0, 0x5fc7edbc424d2fcc, 0x0f53304714d9265e,
0x18851a0b548ea3ca, 0x273b5cdeedb10610, 0x3ec56164af81a34c, 0x646f023ab2690546,
0x1011c2eaabe7d7e3, 0x19b604aaaca62637, 0x29233aaaadd6a38b, 0x41d1f7777c8a9f45,
0x694ff258c7443208, 0x10d9976a5d52975e, 0x1af5bf109550f22f, 0x2b22cb4dbbb4b6b2,
0x4504787c5f878ab6, 0x6e6d8d93cc0c1123, 0x11ab20e472914a6c, 0x1c45016d841baa47,
0x2d3b357c0692aa0b, 0x485ebbf9a41ddcdd, 0x73cac65c39c96162, 0x1286d80ec190dc62,
0x1da48ce468e7c703, 0x2f6dae3a4172d804, 0x4be2b05d35848cd3, 0x796ab3c855a0e152,
0x136d3b7c36a919d0, 0x1f152bf9f10e8fb3, 0x31bb798fe8174c51, 0x4f925c1973587a1c,
0x7f50935bebc0c35f, 0x145ecfe5bf520ac8, 0x2097b309321cde0c, 0x3425eb41e9c7c9ad,
0x536fdecfdc72dc48, 0x857fcae62d8493a6, 0x155c2076bf9a5511, 0x222d00bdff5d54e7,
0x36ae679665622172, 0x577d728a3bd03582, 0x0dff9772470297ec, 0x1665bf1d3e6a8cad,
0x23d5fe9530aa7aae, 0x39566421e7772ab0, 0x5bbd6d030bf1dde6, 0x0eadab0aba3b2dbf,
0x177c44ddf6c515fe, 0x2593a163246e8996, 0x3c1f689ea0b0dc23, 0x603240fdcde7c69d,
0x0f64335bcf065d38, 0x18a0522c7e709527, 0x2766e9e0ca4dbb71, 0x3f0b0fce107c5f1a,
0x64de7fb01a60982a, 0x1023998cd1053711, 0x19d28f47b4d524e8, 0x2950e53f87bb6e40,
0x421b0865a5f8b066, 0x69c4da3c3cc11a3d, 0x10ec4be0ad8f8952, 0x1b13ac9aaf4c0ee9,
0x2b52adc44bace4a8, 0x45511606df7b0773, 0x6ee8233e325e7251, 0x11bebdf578b2f392,
0x1c6463225ab7ec1d, 0x2d6d6b6a2abfe02f, 0x48af1243779966b1, 0x744b506bf28f0ab4,
0x129b69070816e2fe, 0x1dc574d80cf16b30, 0x2fa2548ce182451a, 0x4c36edae359d3b5c,
0x79f17c49ef61f894, 0x1382cc34ca2427c6, 0x1f37ad21436d0c70, 0x31f2ae9b9f14e0b3,
0x4feab0f8fe87cdea, 0x7fdde7f4ca72e310, 0x14756ccb01abfb5f, 0x20bbe144cf799232,
0x345fced47f28e9e9, 0x53cc7e20cb74a974, 0x8613fd0145877586, 0x1573d68f903ea22a,
0x2252f0e5b39769dd, 0x36eb1b091f58a961, 0x57de91a832277568, 0x0e0f218b8d25088c,
0x167e9c127b6e7413, 0x23fdc683f8b0b9b8, 0x39960a6cc11ac2bf, 0x5c2343e134f79dfe,
0x0ebdf661791d60f6, 0x179657025b6234bc, 0x25bd5803c569edfa, 0x3c62266c6f0fe329,
0x609d0a4718196b74, 0x0f7549530e188c13, 0x18bba884e35a79b8, 0x2792a73b055d8f8c,
0x3f510b91a22f4c13, 0x654e78e9037ee01e, 0x103583fc527ab338, 0x19ef3993b72ab85a,
0x297ec285f1ddf3c3, 0x42646a6fe9631f9e, 0x6a3a43e642383296, 0x10ff151a99f482fa,
0x1b31bb5dc320d18f, 0x2b82c562d1ce1c18, 0x459e089e1c7cf9c0, 0x6f6340fcfa618f99,
0x11d270cc51055ea8, 0x1c83e7ad4e6efdda, 0x2d9fd9154a4b2fc3, 0x48ffc1bbaa11e604,
0x74cc692c434fd66c, 0x12b010d3e1cf5582, 0x1de6815302e5559d, 0x2fd735519e3bbc2e,
0x4c8b888296c5f9e3, 0x7a78da6a8ad65c9e, 0x139874ddd8c6234d, 0x1f5a549627a36bae,
0x322a20f03f6bdf7d, 0x504367e6cbdfcbfa, 0x806bd9714632dff7, 0x148c22ca71a1bd70,
0x20e037aa4f692f19, 0x3499f2aa18a84b5a, 0x542984435aa6def6, 0x86a8d39ef77164bd,
0x158ba6fab6f36c48, 0x22790b2abe5246d9, 0x372811ddfd50715a, 0x58401c96621a4ef7,
0x0e1ebce4dc7f16e0, 0x169794a160cb57cd, 0x2425ba9bce122614, 0x39d5f75fb01d09ba,
0x5c898bcc4cfb42c3, 0x0ece53cec4a314ec, 0x17b08617a104ee47, 0x25e73cf29b3b16d7,
0x3ca52e50f85e8af2, 0x61084a1b26fdab1c, 0x0f867241c8cc6d4d, 0x18d71d360e13e214,
0x27be952349b969b9, 0x3f97550542c242c1, 0x65beee6ed136d135, 0x1047824f2bb6d9cb,
0x1a0c03b1df8af612, 0x29acd2b63277f01c, 0x42ae1df050bfe694, 0x6ab02fe6e79970ec,
0x1111f32f2f4bc026, 0x1b4feb7eb212cd0a, 0x2bb31264501e14dc, 0x45eb50a08030215f,
0x6fdee76733803565, 0x11e6398126f5cb1b, 0x1ca38f350b22de91, 0x2dd27ebb4504974e,
0x4950cac53b3a8bb0, 0x754e113b91f745e6, 0x12c4cf8ea6b6ec77, 0x1e07b27dd78b13f2,
0x300c50c958de864f, 0x4ce0814227ca707e, 0x7b00ced03faa4d96, 0x13ae3591f5b4d937,
0x1f7d228322baf525, 0x3261d0d1d12b21d4, 0x509c814fb511cfba, 0x80fa687f881c7f8f,
0x14a2f1ffecd15c17, 0x2104b66647b56025, 0x34d4570a0c5566a1, 0x5486f1a9ad557102,
0x873e4f75e2224e69, 0x15a391d56bdc876d, 0x229f4fbbdfc73f15, 0x37654c5fcc71fe88
};
static const int8_t positive_index_lut[244] = {
18 , 18 , 18 , 18 , 18 , 17 , 17 , 17 , 17 , 17 , 16 , 16 , 16 , 16 , 16 , 15 , 15 , 15 , 15 , 15 ,
14 , 14 , 14 , 14 , 14 , 13 , 13 , 13 , 13 , 13 , 12 , 12 , 12 , 12 , 12 , 11 , 11 , 11 , 11 , 11 ,
10 , 10 , 10 , 10 , 10 , 9 , 9 , 9 , 9 , 8 , 8 , 8 , 8 , 8 , 7 , 7 , 7 , 7 , 7 , 6 ,
6 , 6 , 6 , 6 , 5 , 5 , 5 , 5 , 5 , 4 , 4 , 4 , 4 , 4 , 3 , 3 , 3 , 3 , 3 , 2 ,
2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , -1 , -1 , -1 , -1 , -2 , -2 ,
-2 , -2 , -2 , -3 , -3 , -3 , -3 , -3 , -4 , -4 , -4 , -4 , -4 , -5 , -5 , -5 , -5 , -5 , -6 , -6 ,
-6 , -6 , -6 , -7 , -7 , -7 , -7 , -7 , -8 , -8 , -8 , -8 , -8 , -9 , -9 , -9 , -9 , -9 , -10, -10,
-10, -10, -10, -11, -11, -11, -11, -12, -12, -12, -12, -12, -13, -13, -13, -13, -13, -14, -14, -14,
-14, -14, -15, -15, -15, -15, -15, -16, -16, -16, -16, -16, -17, -17, -17, -17, -17, -18, -18, -18,
-18, -18, -19, -19, -19, -19, -19, -20, -20, -20, -20, -20, -21, -21, -21, -21, -22, -22, -22, -22,
-22, -23, -23, -23, -23, -23, -24, -24, -24, -24, -24, -25, -25, -25, -25, -25, -26, -26, -26, -26,
-26, -27, -27, -27, -27, -27, -28, -28, -28, -28, -28, -29, -29, -29, -29, -29, -30, -30, -30, -30,
-30, -31, -31, -31
};
const diy_fp_t v = { .f = positive_base_lut[e], .e = positive_index_lut[e] };
return v;
}
static inline diy_fp_t negative_diy_fp(int32_t e)
{
static const uint64_t negative_base_lut[286] = {
0x0de0b6b3a7640000, 0x56bc75e2d6310000, 0x3635c9adc5dea000, 0x21e19e0c9bab2400,
0x152d02c7e14af680, 0x84595161401484a0, 0x52b7d2dcc80cd2e4, 0x33b2e3c9fd0803cf,
0x204fce5e3e250262, 0x1431e0fae6d7217d, 0x7e37be2022c0914c, 0x4ee2d6d415b85acf,
0x314dc6448d9338c2, 0x1ed09bead87c0379, 0x13426172c74d822c, 0x785ee10d5da46d91,
0x4b3b4ca85a86c47b, 0x2f050fe938943acd, 0x1d6329f1c35ca4c0, 0x125dfa371a19e6f8,
0x72cb5bd86321e38d, 0x47bf19673df52e38, 0x2cd76fe086b93ce3, 0x1c06a5ec5433c60e,
0x118427b3b4a05bc9, 0x6d79f82328ea3da7, 0x446c3b15f9926688, 0x2ac3a4edbbfb8015,
0x1aba4714957d300e, 0x10b46c6cdd6e3e09, 0x6867a5a867f103b3, 0x4140c78940f6a250,
0x28c87cb5c89a2572, 0x197d4df19d605768, 0x0fee50b7025c36a1, 0x63917877cec0556c,
0x3e3aeb4ae1383563, 0x26e4d30eccc3215e, 0x184f03e93ff9f4db, 0x0f316271c7fc3909,
0x5ef4a74721e86477, 0x3b58e88c75313eca, 0x25179157c93ec73f, 0x172ebad6ddc73c87,
0x0e7d34c64a9c85d5, 0x5a8e89d75252446f, 0x3899162693736ac6, 0x235fadd81c2822bc,
0x161bcca7119915b6, 0x8a2dbf142dfcc7ac, 0x565c976c9cbdfccc, 0x35f9dea3e1f6bdff,
0x21bc2b266d3a36c0, 0x15159af804446238, 0x83c7088e1aab65dc, 0x525c6558d0ab1faa,
0x3379bf57826af3ca, 0x202c1796b182d85f, 0x141b8ebe2ef1c73b, 0x7dac3c24a5671d30,
0x4e8ba596e760723e, 0x3117477e509c4767, 0x1eae8caef261aca1, 0x132d17ed577d0be5,
0x77d9d58b62cd8a52, 0x4ae825771dc07673, 0x2ed1176a72984a08, 0x1d42aea2879f2e45,
0x1249ad2594c37cec, 0x724c7a2ae1c5ccbe, 0x476fcc5acd1b9ff7, 0x2ca5dfb8c03143fa,
0x1be7abd3781eca7d, 0x1170cb642b133e8e, 0x6d00f7320d3846f5, 0x44209a7f48432c5a,
0x2a94608f8d29fbb8, 0x1a9cbc59b83a3d53, 0x10a1f5b813246654, 0x67f43fbe77a37f8c,
0x40f8a7d70ac62fb8, 0x289b68e666bbddd3, 0x1961219000356aa4, 0x0fdcb4fa002162a7,
0x63236b1a80d0a88f, 0x3df622f09082695a, 0x26b9d5d65a5181d8, 0x183425a5f872f127,
0x0f209787bb47d6b9, 0x5e8bb3105280fe00, 0x3b174fea33909ec0, 0x24ee91f2603a6338,
0x17151b377c247e03, 0x0e6d3102ad96cec2, 0x5a2a7250bcee8c3c, 0x385a8772761517a6,
0x233894a789cd2ec8, 0x16035ce8b6203d3d, 0x899504ae72497ebb, 0x55fd22ed076def35,
0x35be35d424a4b581, 0x2196e1a496e6f171, 0x14fe4d06de5056e7, 0x8335616aed761f20,
0x52015ce2d469d374, 0x3340da0dc4c22429, 0x200888489af9569a, 0x1405552d60dbd620,
0x7d21545b9d5dfa47, 0x4e34d4b9425abc6c, 0x30e104f3c978b5c4, 0x1e8ca3185deb719b,
0x1317e5ef3ab32701, 0x77555d172edfb3c3, 0x4a955a2e7d4bd05a, 0x2e9d585d0e4f6238,
0x1d22573a28f19d63, 0x123576845997025e, 0x71ce24bb2fefcecb, 0x4720d6f4fdf5e13f,
0x2c7486591eb9acc8, 0x1bc8d3f7b3340bfd, 0x115d847ad000877e, 0x6c887bff94034ed3,
0x43d54d7fbc821144, 0x2a65506fd5d14acb, 0x1a7f5245e5a2cebf, 0x108f936baf85c137,
0x678159610903f798, 0x40b0d7dca5a27abf, 0x286e86e9e7858cb8, 0x1945145230b377f3,
0x0fcb2cb35e702af8, 0x62b5d7610e3d0c8c, 0x3db1a69ca8e627d7, 0x268f0821e98fd8e7,
0x1819651531f9e790, 0x0f0fdf2d3f3c30ba, 0x5e2332dacb38308b, 0x3ad5ffc8bf031e57,
0x24c5bfdd7761f2f7, 0x16fb97ea6a9d37da, 0x0e5d3ef282a242e9, 0x59c6c96bb076222b,
0x381c3de34e49d55b, 0x2311a6ae10ee2559, 0x15eb082cca94d758, 0x88fcf317f22241e3,
0x559e17eef755692e, 0x3582cef55a9561bd, 0x2171c159589d5d16, 0x14e718d7d7625a2e,
0x82a45b450226b39d, 0x51a6b90b21583043, 0x330833a6f4d71e2a, 0x1fe52048590672da,
0x13ef342d37a407c9, 0x7c97061a9bc130a3, 0x4dde63d0a158be66, 0x30aafe6264d77700,
0x1e6adefd7f06aa60, 0x1302cb5e6f642a7c, 0x76d1770e38320987, 0x4a42ea68e31f45f4,
0x2e69d2818df38bb9, 0x1d022390f8b83754, 0x1221563a9b732295, 0x71505aee4b8f981e,
0x46d238d4ef39bf13, 0x2c4363851584176c, 0x1baa1e332d728ea4, 0x114a52dffc679926,
0x6c1085f7e9877d2e, 0x438a53baf1f4ae3d, 0x2a367454d738ece6, 0x1a6208b506839410,
0x107d457124123c8a, 0x670ef2032171fa5d, 0x40695741f4e73c7a, 0x2841d689391085cd,
0x19292615c3aa53a0, 0x0fb9b7cd9a4a7444, 0x6248bcc5045156a8, 0x3d6d75fb22b2d629,
0x266469bcf5afc5da, 0x17fec216198ddba8, 0x0eff394dcff8a949, 0x5dbb262653d22208,
0x3a94f7d7f4635545, 0x249d1ae6f8be154c, 0x16e230d05b76cd4f, 0x0e4d5e82392a4052,
0x59638eade54811fd, 0x37de392caf4d0b3e, 0x22eae3bbed902707, 0x15d2ce55747a1865,
0x8865899617fb1872, 0x553f75fdcefcef47, 0x3547a9bea15e158d, 0x214cca1724dacd78,
0x14cffe4e7708c06b, 0x8213f56a67f6b29c, 0x514c796280fa2fa2, 0x32cfcbdd909c5dc5,
0x1fc1df6a7a61ba9b, 0x13d92ba28c7d14a1, 0x7c0d50b7ee0dc0ee, 0x4d885272f4c89895,
0x30753387d8fd5f5d, 0x1e494034e79e5b9a, 0x12edc82110c2f941, 0x764e22cea8c295d2,
0x49f0d5c129799da3, 0x2e368598b9ec0286, 0x1ce2137f74338194, 0x120d4c2fa8a030fd,
0x70d31c29dde93229, 0x4683f19a2ab1bf5a, 0x2c1277005aaf1798, 0x1b8b8a6038ad6ebf,
0x1137367c236c6538, 0x6b991487dd65789a, 0x433facd4ea5f6b61, 0x2a07cc05127ba31d,
0x1a44df832b8d45f2, 0x106b0bb1fb384bb7, 0x669d0918621fd938, 0x402225af3d53e7c3,
0x2815578d865470da, 0x190d56b873f4c689, 0x0fa856334878fc16, 0x61dc1ac084f42784,
0x3d2990b8531898b3, 0x2639fa7333ef5f70, 0x17e43c8800759ba6, 0x0eeea5d500498148,
0x5d538c7341cb67ff, 0x3a5437c8091f2100, 0x2474a2dd05b374a0, 0x16c8e5ca239028e4,
0x0e3d8f9e563a198f, 0x5900c19d9aeb1fba, 0x37a0790280d2f3d4, 0x22c44ba19083d865,
0x15baaf44fa52673f, 0x87cec76f1c830549, 0x54e13ca571d1e34e, 0x350cc5e767232e11,
0x2127fbb0a075fccb, 0x14b8fd4e6449bdff, 0x81842f29f2cce376, 0x50f29d7a37c00e2a,
0x3297a26c62d808db, 0x1f9ec583bdc70589, 0x13c33b72569c6376, 0x7b84338a9d516d9d,
0x4d32a036a252e482, 0x303fa4222573ced2, 0x1e27c69557686143, 0x12d8dc1d56a13cca,
0x75cb5fb75d6fbbed, 0x499f1bd29a65d574, 0x2e037163a07fa569, 0x1cc226de444fc762,
0x11f9584aeab1dc9d, 0x705667d43ad7a2d4, 0x463600e4a4c6c5c5, 0x2be1c08ee6fc3b9b,
0x1b6d1859505da541, 0x11242f37d23a8749, 0x6b22271ce1edcd85, 0x42f558720d34a073,
0x29d957474840e448, 0x1a27d68c8d288ead, 0x1058e617d839592d, 0x662b9e1507666d54,
0x3fdb42cd24a00455, 0x27e909c036e402b5, 0x18f1a618224e81b1, 0x0f9707cf1571110f,
0x616ff0ce4602aa9b, 0x3ce5f680ebc1aaa1, 0x260fba1093590aa5, 0x17c9d44a5c17a6a7,
0x0ede24ae798ec829, 0x5cec654277bc62fc
};
static const int8_t negative_index_lut[286] = {
18 , 19 , 19 , 19 , 19 , 20 , 20 , 20 , 20 , 20 , 21 , 21 , 21 , 21 , 21 , 22 , 22 , 22 , 22 , 22 ,
23 , 23 , 23 , 23 , 23 , 24 , 24 , 24 , 24 , 24 , 25 , 25 , 25 , 25 , 25 , 26 , 26 , 26 , 26 , 26 ,
27 , 27 , 27 , 27 , 27 , 28 , 28 , 28 , 28 , 29 , 29 , 29 , 29 , 29 , 30 , 30 , 30 , 30 , 30 , 31 ,
31 , 31 , 31 , 31 , 32 , 32 , 32 , 32 , 32 , 33 , 33 , 33 , 33 , 33 , 34 , 34 , 34 , 34 , 34 , 35 ,
35 , 35 , 35 , 35 , 36 , 36 , 36 , 36 , 36 , 37 , 37 , 37 , 37 , 37 , 38 , 38 , 38 , 38 , 39 , 39 ,
39 , 39 , 39 , 40 , 40 , 40 , 40 , 40 , 41 , 41 , 41 , 41 , 41 , 42 , 42 , 42 , 42 , 42 , 43 , 43 ,
43 , 43 , 43 , 44 , 44 , 44 , 44 , 44 , 45 , 45 , 45 , 45 , 45 , 46 , 46 , 46 , 46 , 46 , 47 , 47 ,
47 , 47 , 47 , 48 , 48 , 48 , 48 , 49 , 49 , 49 , 49 , 49 , 50 , 50 , 50 , 50 , 50 , 51 , 51 , 51 ,
51 , 51 , 52 , 52 , 52 , 52 , 52 , 53 , 53 , 53 , 53 , 53 , 54 , 54 , 54 , 54 , 54 , 55 , 55 , 55 ,
55 , 55 , 56 , 56 , 56 , 56 , 56 , 57 , 57 , 57 , 57 , 57 , 58 , 58 , 58 , 58 , 59 , 59 , 59 , 59 ,
59 , 60 , 60 , 60 , 60 , 60 , 61 , 61 , 61 , 61 , 61 , 62 , 62 , 62 , 62 , 62 , 63 , 63 , 63 , 63 ,
63 , 64 , 64 , 64 , 64 , 64 , 65 , 65 , 65 , 65 , 65 , 66 , 66 , 66 , 66 , 66 , 67 , 67 , 67 , 67 ,
67 , 68 , 68 , 68 , 68 , 69 , 69 , 69 , 69 , 69 , 70 , 70 , 70 , 70 , 70 , 71 , 71 , 71 , 71 , 71 ,
72 , 72 , 72 , 72 , 72 , 73 , 73 , 73 , 73 , 73 , 74 , 74 , 74 , 74 , 74 , 75 , 75 , 75 , 75 , 75 ,
76 , 76 , 76 , 76 , 76 , 77
};
const diy_fp_t v = { .f = negative_base_lut[e], .e = negative_index_lut[e] };
return v;
}
static inline void ldouble_convert(diy_fp_t *v)
{
uint64_t f = v->f;
int32_t e = v->e, t = v->e;
diy_fp_t x;
e >>= 2;
t -= e << 2;
if (t) {
++e;
f >>= 4 - t;
}
x = e >= 0 ? positive_diy_fp(e) : negative_diy_fp(-e);
f = u128_calc(x.f, f);
#if LSHIFT_RESERVED_BIT > 10
v->f = f;
v->e = e - x.e + 19;
#elif LSHIFT_RESERVED_BIT > 7
v->f = f / 10;
v->e = e - x.e + 20;
#elif LSHIFT_RESERVED_BIT > 4
v->f = f / 100;
v->e = e - x.e + 21;
#else
v->f = f / 1000;
v->e = e - x.e + 22;
#endif
}
#endif
static const char ch_100_lut[200] = {
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9',
};
static const uint8_t tz_100_lut[100] = {
2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define FAST_DIV10(n) (ch_100_lut[(n) << 1] - '0') /* 0 <= n < 100 */
#define FAST_DIV100(n) (((n) * 5243) >> 19) /* 0 <= n < 10000 */
#define FAST_DIV10000(n) ((uint32_t)(((uint64_t)(n) * 109951163) >> 40)) /* 0 <= n < 100000000 */
static inline int32_t fill_1_4_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100) {
if (digits >= 10) {
*ptz = tz_100_lut[digits];
memcpy(s, &ch_100_lut[digits<<1], 2);
s += 2;
} else {
*ptz = 0;
*s++ = digits + '0';
}
} else {
uint32_t q = FAST_DIV100(digits);
uint32_t r = digits - q * 100;
if (q >= 10) {
*ptz = tz_100_lut[q];
memcpy(s, &ch_100_lut[q<<1], 2);
s += 2;
} else {
*ptz = 0;
*s++ = q + '0';
}
if (!r) {
*ptz += 2;
memset(s, '0', 2);
s += 2;
} else {
*ptz = tz_100_lut[r];
memcpy(s, &ch_100_lut[r<<1], 2);
s += 2;
}
}
return s - buffer;
}
static inline int32_t fill_t_4_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
uint32_t q = FAST_DIV100(digits);
uint32_t r = digits - q * 100;
memcpy(s, &ch_100_lut[q<<1], 2);
memcpy(s + 2, &ch_100_lut[r<<1], 2);
if (!r) {
*ptz = tz_100_lut[q] + 2;
} else {
*ptz = tz_100_lut[r];
}
return 4;
}
static inline int32_t fill_1_8_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000) {
return fill_1_4_digits(s, digits, ptz);
} else {
uint32_t q = FAST_DIV10000(digits);
uint32_t r = digits - q * 10000;
s += fill_1_4_digits(s, q, ptz);
if (!r) {
*ptz += 4;
memset(s, '0', 4);
s += 4;
} else {
s += fill_t_4_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_t_8_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000) {
memset(s, '0', 4);
fill_t_4_digits(s + 4, digits, ptz);
} else {
uint32_t q = FAST_DIV10000(digits);
uint32_t r = digits - q * 10000;
fill_t_4_digits(s, q, ptz);
if (!r) {
memset(s + 4, '0', 4);
*ptz += 4;
} else {
fill_t_4_digits(s + 4, r, ptz);
}
}
return 8;
}
static inline int32_t fill_1_16_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100000000llu) {
return fill_1_8_digits(s, (uint32_t)digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
s += fill_1_8_digits(s, q, ptz);
if (!r) {
*ptz += 8;
memset(s, '0', 8);
s += 8;
} else {
s += fill_t_8_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_t_16_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100000000llu) {
memset(s, '0', 8);
fill_t_8_digits(s + 8, digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
fill_t_8_digits(s, q, ptz);
if (!r) {
memset(s + 8, '0', 8);
*ptz += 8;
} else {
fill_t_8_digits(s + 8, r, ptz);
}
}
return 16;
}
static inline int32_t fill_1_20_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000000000000000llu) {
return fill_1_16_digits(s, digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 10000000000000000llu);
uint64_t r = (digits - (uint64_t)q * 10000000000000000llu);
s += fill_1_4_digits(s, q, ptz);
if (!r) {
memset(s, '0', 16);
s += 16;
*ptz += 16;
} else {
s += fill_t_16_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_a_4_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
uint32_t q = FAST_DIV100(digits);
uint32_t r = digits - q * 100;
memcpy(s, &ch_100_lut[q<<1], 2);
memcpy(s + 2, &ch_100_lut[r<<1], 2);
if (r < s_tail_cmp) {
*ptz = tz_100_lut[q] + 2;
} else {
if (s[3] < (char)s_tail_cmp + '0') {
s[3] = '0';
*ptz = 1;
} else {
s[3] -= APPROX_TAIL_CMP_VAL;
*ptz = 0;
}
}
return 4;
}
static inline int32_t fill_a_8_digits(char *buffer, uint32_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 10000) {
memset(s, '0', 4);
fill_a_4_digits(s + 4, digits, ptz);
} else {
uint32_t q = FAST_DIV10000(digits);
uint32_t r = digits - q * 10000;
fill_t_4_digits(s, q, ptz);
if (r < s_tail_cmp) {
memset(s + 4, '0', 4);
*ptz += 4;
} else {
fill_a_4_digits(s + 4, r, ptz);
}
}
return 8;
}
static inline int32_t fill_a_16_digits(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
if (digits < 100000000llu) {
memset(s, '0', 8);
fill_a_8_digits(s + 8, digits, ptz);
} else {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
fill_t_8_digits(s, q, ptz);
if (r < s_tail_cmp) {
memset(s + 8, '0', 8);
*ptz += 8;
} else {
fill_a_8_digits(s + 8, r, ptz);
}
}
return 16;
}
static inline int32_t fill_significand(char *buffer, uint64_t digits, int32_t *ptz)
{
char *s = buffer;
digits += APPROX_TAIL_CMP_VAL;
if (digits < 10000000000000000llu) {
uint32_t q = (uint32_t)(digits / 100000000);
uint32_t r = (uint32_t)(digits - (uint64_t)q * 100000000);
s += fill_1_8_digits(s, q, ptz);
if (r < s_tail_cmp) {
*ptz += 8;
memset(s, '0', 8);
s += 8;
} else {
s += fill_a_8_digits(s, r, ptz);
}
} else {
uint32_t q = (uint32_t)(digits / 10000000000000000llu);
uint64_t r = (digits - (uint64_t)q * 10000000000000000llu);
s += fill_1_4_digits(s, q, ptz);
if (r < s_tail_cmp) {
memset(s, '0', 16);
s += 16;
*ptz += 16;
} else {
s += fill_a_16_digits(s, r, ptz);
}
}
return s - buffer;
}
static inline int32_t fill_exponent(int32_t K, char* buffer)
{
int32_t i = 0, k = 0;
if (K < 0) {
buffer[i++] = '-';
K = -K;
} else {
buffer[i++] = '+';
}
if (K < 100) {
if (K < 10) {
buffer[i++] = '0' + K;
} else {
memcpy(&buffer[i], &ch_100_lut[K<<1], 2);
i += 2;
}
} else {
k = FAST_DIV100(K);
K -= k * 100;
buffer[i++] = '0' + k;
memcpy(&buffer[i], &ch_100_lut[K<<1], 2);
i += 2;
}
return i;
}
static inline char* ldouble_format(char* buffer, uint64_t digits, int32_t decimal_exponent)
{
int32_t num_digits, trailing_zeros, vnum_digits, decimal_point;
num_digits = fill_significand(buffer + 1, digits, &trailing_zeros);
vnum_digits = num_digits - trailing_zeros;
decimal_point = num_digits + decimal_exponent;
switch (decimal_point) {
case -6: case -5: case -4: case -3: case -2: case -1: case 0:
/* 0.[000]digits */
memmove(buffer + 2 - decimal_point, buffer + 1, vnum_digits);
memset(buffer, '0', 2 - decimal_point);
buffer[1] = '.';
buffer += 2 - decimal_point + vnum_digits;
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17:
if (decimal_point < vnum_digits) {
/* dig.its */
memmove(buffer, buffer + 1, decimal_point);
buffer[decimal_point] = '.';
buffer += vnum_digits + 1;
} else {
/* digits[000] */
memmove(buffer, buffer + 1, decimal_point);
buffer += decimal_point;
memcpy(buffer, ".0", 2);
buffer += 2;
}
break;
default:
buffer[0] = buffer[1];
++buffer;
if (vnum_digits != 1) {
/* d.igitsE+123 */
*buffer = '.';
buffer += vnum_digits;
} else {
/* dE+123 */
}
*buffer++ = 'e';
buffer += fill_exponent(decimal_point - 1, buffer);
break;
}
*buffer = '\0';
return buffer;
}
int ldouble_dtoa(double value, char* buffer)
{
diy_fp_t v;
char *s = buffer;
int32_t lshiftbit = 11 - LSHIFT_RESERVED_BIT;
union {double d; uint64_t n;} u = {.d = value};
int32_t signbit = u.n >> (DIY_SIGNIFICAND_SIZE - 1);
int32_t exponent = (u.n & DP_EXPONENT_MASK) >> DP_SIGNIFICAND_SIZE; /* Exponent */
uint64_t significand = u.n & DP_SIGNIFICAND_MASK; /* Mantissa */
if (signbit) {
*s++ = '-';
}
switch (exponent) {
case DP_EXPONENT_MAX:
if (significand) {
memcpy(buffer, "nan", 4);
return 3;
} else {
memcpy(s, "inf", 4);
return signbit + 3;
}
break;
case 0:
if (!significand) {
/* no-normalized double */
v.f = significand; /* Non-normalized double doesn't have a extra integer bit for Mantissa */
v.e = 1 - DP_EXPONENT_OFFSET - DP_SIGNIFICAND_SIZE; /* Fixed Exponent: -1022, divisor of Mantissa: pow(2,52) */
lshiftbit = u64_pz_get(v.f) - LSHIFT_RESERVED_BIT;
v.f <<= lshiftbit;
v.e -= lshiftbit; /* The smallest e is (-1022 - 52 - (63 - LSHIFT_RESERVED_BIT)) */
} else {
memcpy(s, "0.0", 4);
return signbit + 3;
}
break;
default:
/* normalized double */
v.f = significand + DP_HIDDEN_BIT; /* Normalized double has a extra integer bit for Mantissa */
v.e = exponent - DP_EXPONENT_OFFSET - DP_SIGNIFICAND_SIZE; /* Exponent offset: -1023, divisor of Mantissa: pow(2,52) */
if (0 <= -v.e && -v.e <= DP_SIGNIFICAND_SIZE && ((v.f & (((uint64_t)1 << -v.e) - 1)) == 0)) {
/* small integer. */
int32_t tz, n;
n = fill_1_20_digits(s, v.f >> -v.e, &tz);
memcpy(s + n, ".0", 3);
return n + 2 + signbit;
} else {
v.f <<= lshiftbit;
v.e -= lshiftbit; /* The largest e is (1023 - 52 - (11 - LSHIFT_RESERVED_BIT)) */
}
break;
}
ldouble_convert(&v);
s = ldouble_format(s, v.f, v.e);
return s - buffer;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化