Skip to content

Instantly share code, notes, and snippets.

@maxint
Created July 4, 2014 02:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maxint/0172c1dcd075d3589eeb to your computer and use it in GitHub Desktop.
Save maxint/0172c1dcd075d3589eeb to your computer and use it in GitHub Desktop.
Fast Exp calculation: possible to improve accuracy without losing too much performance?
// x ~ (-1, 0)
// It's slower than system std::exp() in android NDK.
static double fast_exp(double x)
{
static double ExpAdjustment[] = {
1.04070848547586,1.04009060846346,1.03945435963673,1.03884515889925,1.03824021815052,1.03763944558270,1.03704295680744,1.03645059259355,1.03586240137854,1.03527831512575,1.03469840149188,1.03412251023128,1.03355074779371,1.03298296727100,1.03241929516751,1.03183892933538,1.03128335809127,1.03073176709173,1.03018410274259,1.02964039971006,1.02910058394928,1.02856467003324,1.02803260508207,1.02750442366190,1.02698005301085,1.02645952638791,1.02594275638492,1.02542979170181,1.02490179082401,1.02439640847484,1.02389482719960,1.02339687921152,1.02290267688865,1.02241207333728,1.02192519791699,1.02144188682589,1.02096225009002,1.02048614419477,1.02001369563484,1.01954476213512,1.01907941470823,1.01860052392423,1.01814228962482,1.01768762156337,1.01723639117398,1.01678864295365,1.01634430115608,1.01590345952391,1.01546599234047,1.01503194376712,1.01460123930548,1.01417397084375,1.01375001543751,1.01332941692768,1.01289674935462,1.01248288390935,1.01207234077774,1.01166505590082,1.01126104834081,1.01086026996390,1.01046275492830,1.01006844002563,1.00967734480311,1.00928942146734,1.00890470418160,1.00852313055064,1.00814472060665,1.00775560721999,1.00738355373701,1.00701464530543,1.00664877626587,1.00628605166103,1.00592634018642,1.00556973242023,1.00521611226515,1.00486558241890,1.00451801465626,1.00417349768753,1.00383191799893,1.00349337599118,1.00314539005733,1.00281283618677,1.00248324184194,1.00215654984705,1.00183281638877,1.00151195029359,1.00119399327336,1.00087888038648,1.00056668818722,1.00025731622485,0.999950806010605,0.999647093444429,0.999346253608152,0.999037216360937,0.998742042729300,0.998449681924816,0.998160074414331,0.997873267724746,0.997589182653224,0.997307854057204,0.997029236108705,0.996753363380387,0.996480179474874,0.996209708915315,0.995941905975963,0.995676805307982,0.995404693538552,0.995144985166988,0.994887954194090,0.994633521761414,0.994381755493227,0.994132567566337,0.993886015811345,0.993642031912292,0.993400663212142,0.993161825995872,0.992925601408350,0.992691889068032,0.992460760593132,0.992223725979549,0.991997720101343,0.991774258793868,0.991553280742882,0.991334820038226,0.991118824112209,0.990905335082368,0.990694292345731,0.990485737381084,0.990279596255090,0.990075939682900,0.989874686711884,0.989675877368326,0.989479454551388,0.989285479878243,0.989086836187912,0.988897702621443,0.988710974628500,0.988526597974102,0.988344616414097,0.988164956498162,0.987987668163020,0.987812697566973,0.987640088164821,0.987469774293189,0.987301791925496,0.987136095454028,0.986972720646750,0.986805704071422,0.986646960356815,0.986490518321478,0.986336312033559,0.986184397353498,0.986034703005843,0.985887278892685,0.985742060167113,0.985599101669180,0.985458333534452,0.985319809809382,0.985183457322962,0.985049333750007,0.984912537481659,0.984782840079448,0.984655343374599,0.984529992279347,0.984406822704953,0.984285784588775,0.984166918337197,0.984050169353797,0.983935573746747,0.983823081611089,0.983712733231884,0.983604474486344,0.983498345339260,0.983390485590376,0.983288598800556,0.983188823689312,0.983091098543810,0.982995468216504,0.982901881701432,0.982810380119717,0.982720902882206,0.982633494358344,0.982548103770581,0.982464772033224,0.982383439656231,0.982304150537479,0.982224045599121,0.982148829040707,0.982075641319582,0.982004423139252,0.981935218662025,0.981867971926130,0.981802729179452,0.981739432280605,0.981678124839945,0.981618751739653,0.981561358387062,0.981505887772183,0.981452382965189,0.981398928213436,0.981349338878064,0.981301697260840,0.981255950657232,0.981212140404415,0.981170215688532,0.981130214580527,0.981092088062991,0.981055875612388,0.981021526748112,0.980989079765855,0.980958485689049,0.980929783937988,0.980901976912786,0.980877044321070,0.980853988547040,0.980832757683368,0.980813394490741,0.980795845334532,0.980780151407448,0.980766263471036,0.980754220870683,0.980743973259480,0.980735560656569,0.980728933933794,0.980724132301728,0.980721040150820,0.980719873669722,0.980720517349567,0.980722922189567,0.980727127575060,0.980733084745789,0.980740832412423,0.980750323031038,0.980761594625752,0.980774599663698,0.980789376714874,0.980805878283077,0.980824141948768,0.980844905143897,0.980866681274760,0.980890205744794,0.980915431320003,0.980942396944371,0.980971056916417,0.981001447183621,0.981033519785144,0.981067317404551,0.981102789931184,0.981139976508402,0.981178829396097,0.981219389324642,0.981263213425383,0.981307170616572,0.981352817725092,0.981400113154611,0.981452903962228,0.981499570700151,0.981551863010307,0.981605784704342,0.981661375726928,0.981718588701275,0.981777461550776,0.981837947920528,0.981901255685625,0.981966238968649,0.982031669117081,0.982098741890462,0.982167407680270,0.982237707682701,0.982309593934973,0.982383108667497,0.982458199120364,0.982534911026350,0.982613193549862,0.982693092237399,0.982774548027333,0.982857613099273,0.982943828686503,0.983031666603621,0.983119517058891,0.983208911492633,0.983299897161189,0.983392417812943,0.983486521482634,0.983582154462718,0.983679364030274,0.983778095698705,0.983878397553897,0.983980216265579,0.984083597048478,0.984190453342224,0.984298888625163,0.984406921381419,0.984516449593999,0.984627526178100,0.984740093313886,0.984854204890771,0.984969798204411,0.985086927908891,0.985205534711155,0.985325672035049,0.985447279845662,0.985570414629623,0.985695008861867,0.985823472883640,0.985953466611536,0.986082578156624,0.986213202495727,0.986345272299683,0.986478846952453,0.986613863132913,0.986750381168917,0.986888332077216,0.987027776926451,0.987168648384883,0.987311016182895,0.987454799358619,0.987602768701164,0.987752232470003,0.987900420895319,0.988050079334099,0.988201148608466,0.988353690952110,0.988507632875332,0.988663040016361,0.988819843713918,0.988978110533810,0.989137765373181,0.989298875505779,0.989461370869173,0.989628362219838,0.989796811041012,0.989963596864345,0.990131834990275,0.990301435309621,0.990472477115908,0.990644884853298,0.990818729542384,0.990993931681845,0.991170562996954,0.991348549610806,0.991527964139777,0.991708725506750,0.991894286583130,0.992081277127788,0.992266230178536,0.992452603420269,0.992640310482869,0.992829430117082,0.993019875016557,0.993211728202277,0.993404908575353,0.993599493104923,0.993795396413649,0.993992696156981,0.994191313333970,0.994395035521592,0.994600152098997,0.994802873382264,0.995006977094071,0.995212393709713,0.995419188788004,0.995627284676950,0.995836758786088,0.996047529124365,0.996259673797058,0.996473110127170,0.996687920877021,0.996904014917217,0.997125507519437,0.997348368548017,0.997568486611427,0.997789961766336,0.998012704856460,0.998236821563769,0.998462201932737,0.998688936080314,0.998916933540563,0.999146293693713,0.999376904633322,0.999608866429790,0.999842087313280,1.00008100389753,1.00032125738496,1.00055841642429,1.00079692647757,1.00103667234554,1.00127776160962,1.00152008689249,1.00176375237488,1.00200864982496,1.00225488427740,1.00250235121251,1.00275114302683,1.00300116790172,1.00325717337584,1.00351449423893,1.00376839002994,1.00402360741689,1.00428004372212,1.00453779389954,1.00479676388429,1.00505704945444,1.00531854172528,1.00558134657104,1.00584536874944,1.00611069107437,1.00637722234066,1.00665001969507,1.00692410876659,1.00719444017088,1.00746607906888,1.00773891814879,1.00801304716636,1.00828836784759,1.00856499063292,1.00884280677475,1.00912190727198,1.00940218749661,1.00968377479596,1.00996653855319,1.01025584569917,1.01054643243626,1.01083293546698,1.01112072899338,1.01140969051690,1.01169994536174,1.01199135969959,1.01228405963959,1.01257792108817,1.01287307112655,1.01316937415697,1.01346695262498,1.01376569709936,1.01407126952976,1.01437809614767,1.01468052402566,1.01498422699007,1.01528907736679,1.01559520059967,1.01590247381897,1.01621100652271,1.01652069183911,1.01683164005134,1.01714373240579,1.01745707977985,1.01777157408074,1.01809317310617,1.01841600171458,1.01873413396424,1.01905352161752,1.01937403763719,1.01969580694619,1.02001871940591,1.02034287146202,1.02066815218861,1.02099468813197,1.02132235609600,1.02165125953805,1.02198128632391,1.02231256453072,1.02265115465216,1.02299094603593,1.02332581277569,1.02366179640428,1.02399902078311,1.02433735335845,1.02467693098185,1.02501761427755,1.02535954087860,1.02570257062141,1.02604684822699,1.02639222027285,1.02673883223045,1.02709301283259,1.02744840852685,1.02779856692509,1.02814981348473,1.02850230221942,1.02885588956780,1.02921070475320,1.02956660977573,1.02989040966361,1.03028154840181,1.03064097108078,1.03100154749948,1.03136327817166,1.03172617421657,1.03210373307721,1.03246896384844,1.03283537288195,1.03320290218232,1.03357160895937,1.03394144604957,1.03431245992505,1.03468460241530,1.03505790597793,1.03543233634404,1.03580794016235,1.03618466913980,1.03656255573884,1.03695563339951,1.03733584081499,1.03771719305502,1.03809969092098,1.03848331747202,1.03886808810570,1.03925398666544,1.03964104034831,1.04002923492485,1.04041854143143,1.04080900176813
};
int64_t tmp = (int64_t)(1512775 * x + 1072632447);
int index = (int)(tmp >> 11) & 0x01FF;
tmp <<= 32;
return (*(double*)(&tmp)) * ExpAdjustment[index];
}
t = ceil(1072632447 + 1512775 * [-1:0.0001:0]);
% t = 1072632447+[0:ceil(1512775*pi*0.1)];
x = (t - 1072632447)/1512775;
ex = exp(x);
t = uint64(t);
import java.lang.Double;
et = arrayfun( @(n) java.lang.Double.longBitsToDouble(bitshift(n,32)), t );
figure(1), plot(x, et./ex);
index = bitshift(bitand(t,uint64(2^20-2^11)),-11) + 1;
relerrfix = ex./et;
num = 512;
adjust = NaN(1,num);
for i=1:num; adjust(i) = mean(relerrfix(index == i)); end;
et2 = et .* adjust(index);
figure(2), plot(x, et2./ex);
figure(3), plot(x, ex, 'r')
hold on;
plot(x, et, 'g')
plot(x, et2, 'b')
hold off;