1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050 |
- /*
- ******************************************************************
- * C++ Mathematical Expression Toolkit Library *
- * *
- * Author: Arash Partow (1999-2020) *
- * URL: http://www.partow.net/programming/exprtk/index.html *
- * *
- * Copyright notice: *
- * Free use of the C++ Mathematical Expression Toolkit Library is *
- * permitted under the guidelines and in accordance with the most *
- * current version of the MIT License. *
- * http://www.opensource.org/licenses/MIT *
- * *
- * Example expressions: *
- * (00) (y + x / y) * (x - y / x) *
- * (01) (x^2 / sin(2 * pi / y)) - x / 2 *
- * (02) sqrt(1 - (x^2)) *
- * (03) 1 - sin(2 * x) + cos(pi / y) *
- * (04) a * exp(2 * t) + c *
- * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) *
- * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x *
- * (07) z := x + sin(2 * pi / y) *
- * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
- * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) *
- * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) *
- * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) *
- * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] *
- * *
- ******************************************************************
- */
- #ifndef INCLUDE_EXPRTK_HPP
- #define INCLUDE_EXPRTK_HPP
- #include <algorithm>
- #include <cctype>
- #include <cmath>
- #include <complex>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <deque>
- #include <exception>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <list>
- #include <map>
- #include <set>
- #include <stack>
- #include <stdexcept>
- #include <string>
- #include <utility>
- #include <vector>
- namespace exprtk
- {
- #ifdef exprtk_enable_debugging
- #define exprtk_debug(params) printf params
- #else
- #define exprtk_debug(params) (void)0
- #endif
- #define exprtk_error_location \
- "exprtk.hpp:" + details::to_str(__LINE__) \
- #if defined(__GNUC__) && (__GNUC__ >= 7)
- #define exprtk_disable_fallthrough_begin \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
- #define exprtk_disable_fallthrough_end \
- _Pragma ("GCC diagnostic pop") \
- #else
- #define exprtk_disable_fallthrough_begin (void)0;
- #define exprtk_disable_fallthrough_end (void)0;
- #endif
- namespace details
- {
- typedef unsigned char uchar_t;
- typedef char char_t;
- typedef uchar_t* uchar_ptr;
- typedef char_t* char_ptr;
- typedef uchar_t const* uchar_cptr;
- typedef char_t const* char_cptr;
- typedef unsigned long long int _uint64_t;
- typedef long long int _int64_t;
- inline bool is_whitespace(const char_t c)
- {
- return (' ' == c) || ('\n' == c) ||
- ('\r' == c) || ('\t' == c) ||
- ('\b' == c) || ('\v' == c) ||
- ('\f' == c) ;
- }
- inline bool is_operator_char(const char_t c)
- {
- return ('+' == c) || ('-' == c) ||
- ('*' == c) || ('/' == c) ||
- ('^' == c) || ('<' == c) ||
- ('>' == c) || ('=' == c) ||
- (',' == c) || ('!' == c) ||
- ('(' == c) || (')' == c) ||
- ('[' == c) || (']' == c) ||
- ('{' == c) || ('}' == c) ||
- ('%' == c) || (':' == c) ||
- ('?' == c) || ('&' == c) ||
- ('|' == c) || (';' == c) ;
- }
- inline bool is_letter(const char_t c)
- {
- return (('a' <= c) && (c <= 'z')) ||
- (('A' <= c) && (c <= 'Z')) ;
- }
- inline bool is_digit(const char_t c)
- {
- return ('0' <= c) && (c <= '9');
- }
- inline bool is_letter_or_digit(const char_t c)
- {
- return is_letter(c) || is_digit(c);
- }
- inline bool is_left_bracket(const char_t c)
- {
- return ('(' == c) || ('[' == c) || ('{' == c);
- }
- inline bool is_right_bracket(const char_t c)
- {
- return (')' == c) || (']' == c) || ('}' == c);
- }
- inline bool is_bracket(const char_t c)
- {
- return is_left_bracket(c) || is_right_bracket(c);
- }
- inline bool is_sign(const char_t c)
- {
- return ('+' == c) || ('-' == c);
- }
- inline bool is_invalid(const char_t c)
- {
- return !is_whitespace (c) &&
- !is_operator_char(c) &&
- !is_letter (c) &&
- !is_digit (c) &&
- ('.' != c) &&
- ('_' != c) &&
- ('$' != c) &&
- ('~' != c) &&
- ('\'' != c);
- }
- #ifndef exprtk_disable_caseinsensitivity
- inline void case_normalise(std::string& s)
- {
- for (std::size_t i = 0; i < s.size(); ++i)
- {
- s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
- }
- }
- inline bool imatch(const char_t c1, const char_t c2)
- {
- return std::tolower(c1) == std::tolower(c2);
- }
- inline bool imatch(const std::string& s1, const std::string& s2)
- {
- if (s1.size() == s2.size())
- {
- for (std::size_t i = 0; i < s1.size(); ++i)
- {
- if (std::tolower(s1[i]) != std::tolower(s2[i]))
- {
- return false;
- }
- }
- return true;
- }
- return false;
- }
- struct ilesscompare
- {
- inline bool operator() (const std::string& s1, const std::string& s2) const
- {
- const std::size_t length = std::min(s1.size(),s2.size());
- for (std::size_t i = 0; i < length; ++i)
- {
- const char_t c1 = static_cast<char>(std::tolower(s1[i]));
- const char_t c2 = static_cast<char>(std::tolower(s2[i]));
- if (c1 > c2)
- return false;
- else if (c1 < c2)
- return true;
- }
- return s1.size() < s2.size();
- }
- };
- #else
- inline void case_normalise(std::string&)
- {}
- inline bool imatch(const char_t c1, const char_t c2)
- {
- return c1 == c2;
- }
- inline bool imatch(const std::string& s1, const std::string& s2)
- {
- return s1 == s2;
- }
- struct ilesscompare
- {
- inline bool operator() (const std::string& s1, const std::string& s2) const
- {
- return s1 < s2;
- }
- };
- #endif
- inline bool is_valid_sf_symbol(const std::string& symbol)
- {
- // Special function: $f12 or $F34
- return (4 == symbol.size()) &&
- ('$' == symbol[0]) &&
- imatch('f',symbol[1]) &&
- is_digit(symbol[2]) &&
- is_digit(symbol[3]);
- }
- inline const char_t& front(const std::string& s)
- {
- return s[0];
- }
- inline const char_t& back(const std::string& s)
- {
- return s[s.size() - 1];
- }
- inline std::string to_str(int i)
- {
- if (0 == i)
- return std::string("0");
- std::string result;
- if (i < 0)
- {
- for ( ; i; i /= 10)
- {
- result += '0' + char(-(i % 10));
- }
- result += '-';
- }
- else
- {
- for ( ; i; i /= 10)
- {
- result += '0' + char(i % 10);
- }
- }
- std::reverse(result.begin(), result.end());
- return result;
- }
- inline std::string to_str(std::size_t i)
- {
- return to_str(static_cast<int>(i));
- }
- inline bool is_hex_digit(const std::string::value_type digit)
- {
- return (('0' <= digit) && (digit <= '9')) ||
- (('A' <= digit) && (digit <= 'F')) ||
- (('a' <= digit) && (digit <= 'f')) ;
- }
- inline uchar_t hex_to_bin(uchar_t h)
- {
- if (('0' <= h) && (h <= '9'))
- return (h - '0');
- else
- return static_cast<unsigned char>(std::toupper(h) - 'A');
- }
- template <typename Iterator>
- inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
- {
- if (
- (end != (itr )) &&
- (end != (itr + 1)) &&
- (end != (itr + 2)) &&
- (end != (itr + 3)) &&
- ('0' == *(itr )) &&
- (
- ('x' == *(itr + 1)) ||
- ('X' == *(itr + 1))
- ) &&
- (is_hex_digit(*(itr + 2))) &&
- (is_hex_digit(*(itr + 3)))
- )
- {
- result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
- hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
- itr += 3;
- }
- else
- result = '\0';
- }
- inline void cleanup_escapes(std::string& s)
- {
- typedef std::string::iterator str_itr_t;
- str_itr_t itr1 = s.begin();
- str_itr_t itr2 = s.begin();
- str_itr_t end = s.end ();
- std::size_t removal_count = 0;
- while (end != itr1)
- {
- if ('\\' == (*itr1))
- {
- ++removal_count;
- if (end == ++itr1)
- break;
- else if ('\\' != (*itr1))
- {
- switch (*itr1)
- {
- case 'n' : (*itr1) = '\n'; break;
- case 'r' : (*itr1) = '\r'; break;
- case 't' : (*itr1) = '\t'; break;
- case '0' : parse_hex(itr1, end, (*itr1));
- removal_count += 3;
- break;
- }
- continue;
- }
- }
- if (itr1 != itr2)
- {
- (*itr2) = (*itr1);
- }
- ++itr1;
- ++itr2;
- }
- s.resize(s.size() - removal_count);
- }
- class build_string
- {
- public:
- build_string(const std::size_t& initial_size = 64)
- {
- data_.reserve(initial_size);
- }
- inline build_string& operator << (const std::string& s)
- {
- data_ += s;
- return (*this);
- }
- inline build_string& operator << (char_cptr s)
- {
- data_ += std::string(s);
- return (*this);
- }
- inline operator std::string () const
- {
- return data_;
- }
- inline std::string as_string() const
- {
- return data_;
- }
- private:
- std::string data_;
- };
- static const std::string reserved_words[] =
- {
- "break", "case", "continue", "default", "false", "for",
- "if", "else", "ilike", "in", "like", "and", "nand", "nor",
- "not", "null", "or", "repeat", "return", "shl", "shr",
- "swap", "switch", "true", "until", "var", "while", "xnor",
- "xor", "&", "|"
- };
- static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
- static const std::string reserved_symbols[] =
- {
- "abs", "acos", "acosh", "and", "asin", "asinh", "atan",
- "atanh", "atan2", "avg", "break", "case", "ceil", "clamp",
- "continue", "cos", "cosh", "cot", "csc", "default",
- "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp",
- "expm1", "false", "floor", "for", "frac", "grad2deg",
- "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
- "like", "log", "log10", "log2", "logn", "log1p", "mand",
- "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
- "not", "not_equal", "null", "or", "pow", "rad2deg",
- "repeat", "return", "root", "round", "roundn", "sec", "sgn",
- "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
- "switch", "tan", "tanh", "true", "trunc", "until", "var",
- "while", "xnor", "xor", "&", "|"
- };
- static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
- static const std::string base_function_list[] =
- {
- "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
- "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
- "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
- "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
- "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
- "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
- "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
- "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
- "rad2deg", "grad2deg"
- };
- static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
- static const std::string logic_ops_list[] =
- {
- "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
- };
- static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
- static const std::string cntrl_struct_list[] =
- {
- "if", "switch", "for", "while", "repeat", "return"
- };
- static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
- static const std::string arithmetic_ops_list[] =
- {
- "+", "-", "*", "/", "%", "^"
- };
- static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
- static const std::string assignment_ops_list[] =
- {
- ":=", "+=", "-=",
- "*=", "/=", "%="
- };
- static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
- static const std::string inequality_ops_list[] =
- {
- "<", "<=", "==",
- "=", "!=", "<>",
- ">=", ">"
- };
- static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
- inline bool is_reserved_word(const std::string& symbol)
- {
- for (std::size_t i = 0; i < reserved_words_size; ++i)
- {
- if (imatch(symbol, reserved_words[i]))
- {
- return true;
- }
- }
- return false;
- }
- inline bool is_reserved_symbol(const std::string& symbol)
- {
- for (std::size_t i = 0; i < reserved_symbols_size; ++i)
- {
- if (imatch(symbol, reserved_symbols[i]))
- {
- return true;
- }
- }
- return false;
- }
- inline bool is_base_function(const std::string& function_name)
- {
- for (std::size_t i = 0; i < base_function_list_size; ++i)
- {
- if (imatch(function_name, base_function_list[i]))
- {
- return true;
- }
- }
- return false;
- }
- inline bool is_control_struct(const std::string& cntrl_strct)
- {
- for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
- {
- if (imatch(cntrl_strct, cntrl_struct_list[i]))
- {
- return true;
- }
- }
- return false;
- }
- inline bool is_logic_opr(const std::string& lgc_opr)
- {
- for (std::size_t i = 0; i < logic_ops_list_size; ++i)
- {
- if (imatch(lgc_opr, logic_ops_list[i]))
- {
- return true;
- }
- }
- return false;
- }
- struct cs_match
- {
- static inline bool cmp(const char_t c0, const char_t c1)
- {
- return (c0 == c1);
- }
- };
- struct cis_match
- {
- static inline bool cmp(const char_t c0, const char_t c1)
- {
- return (std::tolower(c0) == std::tolower(c1));
- }
- };
- template <typename Iterator, typename Compare>
- inline bool match_impl(const Iterator pattern_begin,
- const Iterator pattern_end ,
- const Iterator data_begin ,
- const Iterator data_end ,
- const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
- const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
- {
- const Iterator null_itr(0);
- Iterator d_itr = data_begin;
- Iterator p_itr = pattern_begin;
- Iterator tb_p_itr = null_itr;
- Iterator tb_d_itr = null_itr;
- while (d_itr != data_end)
- {
- if (zero_or_more == *p_itr)
- {
- while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
- {
- ++p_itr;
- }
- if (pattern_end == p_itr)
- return true;
- const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
- while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
- {
- ++d_itr;
- }
- tb_p_itr = p_itr;
- tb_d_itr = d_itr;
- continue;
- }
- else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
- {
- if (null_itr == tb_d_itr)
- return false;
- d_itr = tb_d_itr++;
- p_itr = tb_p_itr;
- continue;
- }
- ++p_itr;
- ++d_itr;
- }
- while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
- {
- ++p_itr;
- }
- return (pattern_end == p_itr);
- }
- inline bool wc_match(const std::string& wild_card,
- const std::string& str)
- {
- return match_impl<char_cptr,cs_match>(wild_card.data(),
- wild_card.data() + wild_card.size(),
- str.data(),
- str.data() + str.size(),
- '*',
- '?');
- }
- inline bool wc_imatch(const std::string& wild_card,
- const std::string& str)
- {
- return match_impl<char_cptr,cis_match>(wild_card.data(),
- wild_card.data() + wild_card.size(),
- str.data(),
- str.data() + str.size(),
- '*',
- '?');
- }
- inline bool sequence_match(const std::string& pattern,
- const std::string& str,
- std::size_t& diff_index,
- char_t& diff_value)
- {
- if (str.empty())
- {
- return ("Z" == pattern);
- }
- else if ('*' == pattern[0])
- return false;
- typedef std::string::const_iterator itr_t;
- itr_t p_itr = pattern.begin();
- itr_t s_itr = str .begin();
- itr_t p_end = pattern.end();
- itr_t s_end = str .end();
- while ((s_end != s_itr) && (p_end != p_itr))
- {
- if ('*' == (*p_itr))
- {
- const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
- if ('*' == target)
- {
- diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
- diff_value = static_cast<char>(std::toupper(*p_itr));
- return false;
- }
- else
- ++p_itr;
- while (s_itr != s_end)
- {
- if (target != std::toupper(*s_itr))
- break;
- else
- ++s_itr;
- }
- continue;
- }
- else if (
- ('?' != *p_itr) &&
- std::toupper(*p_itr) != std::toupper(*s_itr)
- )
- {
- diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
- diff_value = static_cast<char>(std::toupper(*p_itr));
- return false;
- }
- ++p_itr;
- ++s_itr;
- }
- return (
- (s_end == s_itr) &&
- (
- (p_end == p_itr) ||
- ('*' == *p_itr)
- )
- );
- }
- static const double pow10[] = {
- 1.0,
- 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
- 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
- 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
- 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
- };
- static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
- namespace numeric
- {
- namespace constant
- {
- static const double e = 2.71828182845904523536028747135266249775724709369996;
- static const double pi = 3.14159265358979323846264338327950288419716939937510;
- static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
- static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
- static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
- static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
- static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
- static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
- static const double log2 = 0.69314718055994530941723212145817656807550013436026;
- static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
- }
- namespace details
- {
- struct unknown_type_tag { unknown_type_tag() {} };
- struct real_type_tag { real_type_tag () {} };
- struct complex_type_tag { complex_type_tag() {} };
- struct int_type_tag { int_type_tag () {} };
- template <typename T>
- struct number_type
- {
- typedef unknown_type_tag type;
- number_type() {}
- };
- #define exprtk_register_real_type_tag(T) \
- template<> struct number_type<T> \
- { typedef real_type_tag type; number_type() {} }; \
- #define exprtk_register_complex_type_tag(T) \
- template<> struct number_type<std::complex<T> > \
- { typedef complex_type_tag type; number_type() {} }; \
- #define exprtk_register_int_type_tag(T) \
- template<> struct number_type<T> \
- { typedef int_type_tag type; number_type() {} }; \
- exprtk_register_real_type_tag(double )
- exprtk_register_real_type_tag(long double)
- exprtk_register_real_type_tag(float )
- exprtk_register_complex_type_tag(double )
- exprtk_register_complex_type_tag(long double)
- exprtk_register_complex_type_tag(float )
- exprtk_register_int_type_tag(short )
- exprtk_register_int_type_tag(int )
- exprtk_register_int_type_tag(_int64_t )
- exprtk_register_int_type_tag(unsigned short)
- exprtk_register_int_type_tag(unsigned int )
- exprtk_register_int_type_tag(_uint64_t )
- #undef exprtk_register_real_type_tag
- #undef exprtk_register_int_type_tag
- template <typename T>
- struct epsilon_type
- {
- static inline T value()
- {
- const T epsilon = T(0.0000000001);
- return epsilon;
- }
- };
- template <>
- struct epsilon_type <float>
- {
- static inline float value()
- {
- const float epsilon = float(0.000001f);
- return epsilon;
- }
- };
- template <>
- struct epsilon_type <long double>
- {
- static inline long double value()
- {
- const long double epsilon = (long double)(0.000000000001);
- return epsilon;
- }
- };
- template <typename T>
- inline bool is_nan_impl(const T v, real_type_tag)
- {
- return std::not_equal_to<T>()(v,v);
- }
- template <typename T>
- inline int to_int32_impl(const T v, real_type_tag)
- {
- return static_cast<int>(v);
- }
- template <typename T>
- inline _int64_t to_int64_impl(const T v, real_type_tag)
- {
- return static_cast<_int64_t>(v);
- }
- template <typename T>
- inline bool is_true_impl(const T v)
- {
- return std::not_equal_to<T>()(T(0),v);
- }
- template <typename T>
- inline bool is_false_impl(const T v)
- {
- return std::equal_to<T>()(T(0),v);
- }
- template <typename T>
- inline T abs_impl(const T v, real_type_tag)
- {
- return ((v < T(0)) ? -v : v);
- }
- template <typename T>
- inline T min_impl(const T v0, const T v1, real_type_tag)
- {
- return std::min<T>(v0,v1);
- }
- template <typename T>
- inline T max_impl(const T v0, const T v1, real_type_tag)
- {
- return std::max<T>(v0,v1);
- }
- template <typename T>
- inline T equal_impl(const T v0, const T v1, real_type_tag)
- {
- const T epsilon = epsilon_type<T>::value();
- return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
- }
- inline float equal_impl(const float v0, const float v1, real_type_tag)
- {
- const float epsilon = epsilon_type<float>::value();
- return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
- }
- template <typename T>
- inline T equal_impl(const T v0, const T v1, int_type_tag)
- {
- return (v0 == v1) ? 1 : 0;
- }
- template <typename T>
- inline T expm1_impl(const T v, real_type_tag)
- {
- // return std::expm1<T>(v);
- if (abs_impl(v,real_type_tag()) < T(0.00001))
- return v + (T(0.5) * v * v);
- else
- return std::exp(v) - T(1);
- }
- template <typename T>
- inline T expm1_impl(const T v, int_type_tag)
- {
- return T(std::exp<double>(v)) - T(1);
- }
- template <typename T>
- inline T nequal_impl(const T v0, const T v1, real_type_tag)
- {
- typedef real_type_tag rtg;
- const T epsilon = epsilon_type<T>::value();
- return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
- }
- inline float nequal_impl(const float v0, const float v1, real_type_tag)
- {
- typedef real_type_tag rtg;
- const float epsilon = epsilon_type<float>::value();
- return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
- }
- template <typename T>
- inline T nequal_impl(const T v0, const T v1, int_type_tag)
- {
- return (v0 != v1) ? 1 : 0;
- }
- template <typename T>
- inline T modulus_impl(const T v0, const T v1, real_type_tag)
- {
- return std::fmod(v0,v1);
- }
- template <typename T>
- inline T modulus_impl(const T v0, const T v1, int_type_tag)
- {
- return v0 % v1;
- }
- template <typename T>
- inline T pow_impl(const T v0, const T v1, real_type_tag)
- {
- return std::pow(v0,v1);
- }
- template <typename T>
- inline T pow_impl(const T v0, const T v1, int_type_tag)
- {
- return std::pow(static_cast<double>(v0),static_cast<double>(v1));
- }
- template <typename T>
- inline T logn_impl(const T v0, const T v1, real_type_tag)
- {
- return std::log(v0) / std::log(v1);
- }
- template <typename T>
- inline T logn_impl(const T v0, const T v1, int_type_tag)
- {
- return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
- }
- template <typename T>
- inline T log1p_impl(const T v, real_type_tag)
- {
- if (v > T(-1))
- {
- if (abs_impl(v,real_type_tag()) > T(0.0001))
- {
- return std::log(T(1) + v);
- }
- else
- return (T(-0.5) * v + T(1)) * v;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <typename T>
- inline T log1p_impl(const T v, int_type_tag)
- {
- if (v > T(-1))
- {
- return std::log(T(1) + v);
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <typename T>
- inline T root_impl(const T v0, const T v1, real_type_tag)
- {
- if (v1 < T(0))
- return std::numeric_limits<T>::quiet_NaN();
- const std::size_t n = static_cast<std::size_t>(v1);
- if ((v0 < T(0)) && (0 == (n % 2)))
- return std::numeric_limits<T>::quiet_NaN();
- return std::pow(v0, T(1) / n);
- }
- template <typename T>
- inline T root_impl(const T v0, const T v1, int_type_tag)
- {
- return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
- }
- template <typename T>
- inline T round_impl(const T v, real_type_tag)
- {
- return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
- }
- template <typename T>
- inline T roundn_impl(const T v0, const T v1, real_type_tag)
- {
- const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
- const T p10 = T(pow10[index]);
- if (v0 < T(0))
- return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
- else
- return T(std::floor((v0 * p10) + T(0.5)) / p10);
- }
- template <typename T>
- inline T roundn_impl(const T v0, const T, int_type_tag)
- {
- return v0;
- }
- template <typename T>
- inline T hypot_impl(const T v0, const T v1, real_type_tag)
- {
- return std::sqrt((v0 * v0) + (v1 * v1));
- }
- template <typename T>
- inline T hypot_impl(const T v0, const T v1, int_type_tag)
- {
- return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
- }
- template <typename T>
- inline T atan2_impl(const T v0, const T v1, real_type_tag)
- {
- return std::atan2(v0,v1);
- }
- template <typename T>
- inline T atan2_impl(const T, const T, int_type_tag)
- {
- return 0;
- }
- template <typename T>
- inline T shr_impl(const T v0, const T v1, real_type_tag)
- {
- return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
- }
- template <typename T>
- inline T shr_impl(const T v0, const T v1, int_type_tag)
- {
- return v0 >> v1;
- }
- template <typename T>
- inline T shl_impl(const T v0, const T v1, real_type_tag)
- {
- return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
- }
- template <typename T>
- inline T shl_impl(const T v0, const T v1, int_type_tag)
- {
- return v0 << v1;
- }
- template <typename T>
- inline T sgn_impl(const T v, real_type_tag)
- {
- if (v > T(0)) return T(+1);
- else if (v < T(0)) return T(-1);
- else return T( 0);
- }
- template <typename T>
- inline T sgn_impl(const T v, int_type_tag)
- {
- if (v > T(0)) return T(+1);
- else if (v < T(0)) return T(-1);
- else return T( 0);
- }
- template <typename T>
- inline T and_impl(const T v0, const T v1, real_type_tag)
- {
- return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
- }
- template <typename T>
- inline T and_impl(const T v0, const T v1, int_type_tag)
- {
- return v0 && v1;
- }
- template <typename T>
- inline T nand_impl(const T v0, const T v1, real_type_tag)
- {
- return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
- }
- template <typename T>
- inline T nand_impl(const T v0, const T v1, int_type_tag)
- {
- return !(v0 && v1);
- }
- template <typename T>
- inline T or_impl(const T v0, const T v1, real_type_tag)
- {
- return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
- }
- template <typename T>
- inline T or_impl(const T v0, const T v1, int_type_tag)
- {
- return (v0 || v1);
- }
- template <typename T>
- inline T nor_impl(const T v0, const T v1, real_type_tag)
- {
- return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
- }
- template <typename T>
- inline T nor_impl(const T v0, const T v1, int_type_tag)
- {
- return !(v0 || v1);
- }
- template <typename T>
- inline T xor_impl(const T v0, const T v1, real_type_tag)
- {
- return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
- }
- template <typename T>
- inline T xor_impl(const T v0, const T v1, int_type_tag)
- {
- return v0 ^ v1;
- }
- template <typename T>
- inline T xnor_impl(const T v0, const T v1, real_type_tag)
- {
- const bool v0_true = is_true_impl(v0);
- const bool v1_true = is_true_impl(v1);
- if ((v0_true && v1_true) || (!v0_true && !v1_true))
- return T(1);
- else
- return T(0);
- }
- template <typename T>
- inline T xnor_impl(const T v0, const T v1, int_type_tag)
- {
- const bool v0_true = is_true_impl(v0);
- const bool v1_true = is_true_impl(v1);
- if ((v0_true && v1_true) || (!v0_true && !v1_true))
- return T(1);
- else
- return T(0);
- }
- #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
- #define exprtk_define_erf(TT,impl) \
- inline TT erf_impl(TT v) { return impl(v); } \
- exprtk_define_erf( float,::erff)
- exprtk_define_erf( double,::erf )
- exprtk_define_erf(long double,::erfl)
- #undef exprtk_define_erf
- #endif
- template <typename T>
- inline T erf_impl(T v, real_type_tag)
- {
- #if defined(_MSC_VER) && (_MSC_VER < 1900)
- // Credits: Abramowitz & Stegun Equations 7.1.25-28
- static const T c[] = {
- T( 1.26551223), T(1.00002368),
- T( 0.37409196), T(0.09678418),
- T(-0.18628806), T(0.27886807),
- T(-1.13520398), T(1.48851587),
- T(-0.82215223), T(0.17087277)
- };
- const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
- T result = T(1) - t * std::exp((-v * v) -
- c[0] + t * (c[1] + t *
- (c[2] + t * (c[3] + t *
- (c[4] + t * (c[5] + t *
- (c[6] + t * (c[7] + t *
- (c[8] + t * (c[9]))))))))));
- return (v >= T(0)) ? result : -result;
- #else
- return erf_impl(v);
- #endif
- }
- template <typename T>
- inline T erf_impl(T v, int_type_tag)
- {
- return erf_impl(static_cast<double>(v),real_type_tag());
- }
- #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
- #define exprtk_define_erfc(TT,impl) \
- inline TT erfc_impl(TT v) { return impl(v); } \
- exprtk_define_erfc( float,::erfcf)
- exprtk_define_erfc( double,::erfc )
- exprtk_define_erfc(long double,::erfcl)
- #undef exprtk_define_erfc
- #endif
- template <typename T>
- inline T erfc_impl(T v, real_type_tag)
- {
- #if defined(_MSC_VER) && (_MSC_VER < 1900)
- return T(1) - erf_impl(v,real_type_tag());
- #else
- return erfc_impl(v);
- #endif
- }
- template <typename T>
- inline T erfc_impl(T v, int_type_tag)
- {
- return erfc_impl(static_cast<double>(v),real_type_tag());
- }
- template <typename T>
- inline T ncdf_impl(T v, real_type_tag)
- {
- T cnd = T(0.5) * (T(1) + erf_impl(
- abs_impl(v,real_type_tag()) /
- T(numeric::constant::sqrt2),real_type_tag()));
- return (v < T(0)) ? (T(1) - cnd) : cnd;
- }
- template <typename T>
- inline T ncdf_impl(T v, int_type_tag)
- {
- return ncdf_impl(static_cast<double>(v),real_type_tag());
- }
- template <typename T>
- inline T sinc_impl(T v, real_type_tag)
- {
- if (std::abs(v) >= std::numeric_limits<T>::epsilon())
- return(std::sin(v) / v);
- else
- return T(1);
- }
- template <typename T>
- inline T sinc_impl(T v, int_type_tag)
- {
- return sinc_impl(static_cast<double>(v),real_type_tag());
- }
- template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
- template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
- template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
- template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
- template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
- template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
- template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
- template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
- template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
- template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
- template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
- template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
- template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
- template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
- template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
- template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
- template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
- template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
- template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
- template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
- template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
- template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
- template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
- template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
- template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
- template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
- template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
- template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
- template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
- template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
- template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
- template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
- template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); }
- template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
- template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
- template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
- template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
- template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
- template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
- template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
- template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
- template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
- template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
- template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
- template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
- template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
- template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
- template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T>
- inline bool is_integer_impl(const T& v, real_type_tag)
- {
- return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
- }
- template <typename T>
- inline bool is_integer_impl(const T&, int_type_tag)
- {
- return true;
- }
- }
- template <typename Type>
- struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
- template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
- template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
- template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
- template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
- template <typename T>
- inline int to_int32(const T v)
- {
- const typename details::number_type<T>::type num_type;
- return to_int32_impl(v, num_type);
- }
- template <typename T>
- inline _int64_t to_int64(const T v)
- {
- const typename details::number_type<T>::type num_type;
- return to_int64_impl(v, num_type);
- }
- template <typename T>
- inline bool is_nan(const T v)
- {
- const typename details::number_type<T>::type num_type;
- return is_nan_impl(v, num_type);
- }
- template <typename T>
- inline T min(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return min_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T max(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return max_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T equal(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return equal_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T nequal(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return nequal_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T modulus(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return modulus_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T pow(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return pow_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T logn(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return logn_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T root(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return root_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T roundn(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return roundn_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T hypot(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return hypot_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T atan2(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return atan2_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T shr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return shr_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T shl(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return shl_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T and_opr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return and_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T nand_opr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return nand_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T or_opr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return or_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T nor_opr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return nor_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T xor_opr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return xor_impl(v0, v1, num_type);
- }
- template <typename T>
- inline T xnor_opr(const T v0, const T v1)
- {
- const typename details::number_type<T>::type num_type;
- return xnor_impl(v0, v1, num_type);
- }
- template <typename T>
- inline bool is_integer(const T v)
- {
- const typename details::number_type<T>::type num_type;
- return is_integer_impl(v, num_type);
- }
- template <typename T, unsigned int N>
- struct fast_exp
- {
- static inline T result(T v)
- {
- unsigned int k = N;
- T l = T(1);
- while (k)
- {
- if (k & 1)
- {
- l *= v;
- --k;
- }
- v *= v;
- k >>= 1;
- }
- return l;
- }
- };
- template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
- template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
- template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
- template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
- template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
- template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
- template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
- template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
- template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
- template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
- template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
- #define exprtk_define_unary_function(FunctionName) \
- template <typename T> \
- inline T FunctionName (const T v) \
- { \
- const typename details::number_type<T>::type num_type; \
- return FunctionName##_impl(v,num_type); \
- } \
- exprtk_define_unary_function(abs )
- exprtk_define_unary_function(acos )
- exprtk_define_unary_function(acosh)
- exprtk_define_unary_function(asin )
- exprtk_define_unary_function(asinh)
- exprtk_define_unary_function(atan )
- exprtk_define_unary_function(atanh)
- exprtk_define_unary_function(ceil )
- exprtk_define_unary_function(cos )
- exprtk_define_unary_function(cosh )
- exprtk_define_unary_function(exp )
- exprtk_define_unary_function(expm1)
- exprtk_define_unary_function(floor)
- exprtk_define_unary_function(log )
- exprtk_define_unary_function(log10)
- exprtk_define_unary_function(log2 )
- exprtk_define_unary_function(log1p)
- exprtk_define_unary_function(neg )
- exprtk_define_unary_function(pos )
- exprtk_define_unary_function(round)
- exprtk_define_unary_function(sin )
- exprtk_define_unary_function(sinc )
- exprtk_define_unary_function(sinh )
- exprtk_define_unary_function(sqrt )
- exprtk_define_unary_function(tan )
- exprtk_define_unary_function(tanh )
- exprtk_define_unary_function(cot )
- exprtk_define_unary_function(sec )
- exprtk_define_unary_function(csc )
- exprtk_define_unary_function(r2d )
- exprtk_define_unary_function(d2r )
- exprtk_define_unary_function(d2g )
- exprtk_define_unary_function(g2d )
- exprtk_define_unary_function(notl )
- exprtk_define_unary_function(sgn )
- exprtk_define_unary_function(erf )
- exprtk_define_unary_function(erfc )
- exprtk_define_unary_function(ncdf )
- exprtk_define_unary_function(frac )
- exprtk_define_unary_function(trunc)
- #undef exprtk_define_unary_function
- }
- template <typename T>
- inline T compute_pow10(T d, const int exponent)
- {
- static const double fract10[] =
- {
- 0.0,
- 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
- 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
- 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
- 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
- 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
- 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
- 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
- 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
- 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
- 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
- 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
- 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
- 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
- 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
- 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
- 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
- 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
- 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
- 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
- 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
- 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
- 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
- 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
- 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
- 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
- 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
- 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
- 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
- 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
- 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
- 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
- };
- static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
- const int e = std::abs(exponent);
- if (exponent >= std::numeric_limits<T>::min_exponent10)
- {
- if (e < fract10_size)
- {
- if (exponent > 0)
- return T(d * fract10[e]);
- else
- return T(d / fract10[e]);
- }
- else
- return T(d * std::pow(10.0, 10.0 * exponent));
- }
- else
- {
- d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
- return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
- }
- }
- template <typename Iterator, typename T>
- inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
- {
- if (itr == end)
- return false;
- const bool negative = ('-' == (*itr));
- if (negative || ('+' == (*itr)))
- {
- if (end == ++itr)
- return false;
- }
- static const uchar_t zero = static_cast<uchar_t>('0');
- while ((end != itr) && (zero == (*itr))) ++itr;
- bool return_result = true;
- unsigned int digit = 0;
- const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
- if (length <= 4)
- {
- exprtk_disable_fallthrough_begin
- switch (length)
- {
- #ifdef exprtk_use_lut
- #define exprtk_process_digit \
- if ((digit = details::digit_table[(int)*itr++]) < 10) \
- result = result * 10 + (digit); \
- else \
- { \
- return_result = false; \
- break; \
- } \
- #else
- #define exprtk_process_digit \
- if ((digit = (*itr++ - zero)) < 10) \
- result = result * T(10) + digit; \
- else \
- { \
- return_result = false; \
- break; \
- } \
- #endif
- case 4 : exprtk_process_digit
- case 3 : exprtk_process_digit
- case 2 : exprtk_process_digit
- case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
- #undef exprtk_process_digit
- }
- exprtk_disable_fallthrough_end
- }
- else
- return_result = false;
- if (length && return_result)
- {
- result = result * 10 + static_cast<T>(digit);
- ++itr;
- }
- result = negative ? -result : result;
- return return_result;
- }
- template <typename Iterator, typename T>
- static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
- {
- typedef typename std::iterator_traits<Iterator>::value_type type;
- static const std::size_t nan_length = 3;
- if (std::distance(itr,end) != static_cast<int>(nan_length))
- return false;
- if (static_cast<type>('n') == (*itr))
- {
- if (
- (static_cast<type>('a') != *(itr + 1)) ||
- (static_cast<type>('n') != *(itr + 2))
- )
- {
- return false;
- }
- }
- else if (
- (static_cast<type>('A') != *(itr + 1)) ||
- (static_cast<type>('N') != *(itr + 2))
- )
- {
- return false;
- }
- t = std::numeric_limits<T>::quiet_NaN();
- return true;
- }
- template <typename Iterator, typename T>
- static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
- {
- static const char_t inf_uc[] = "INFINITY";
- static const char_t inf_lc[] = "infinity";
- static const std::size_t inf_length = 8;
- const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
- if ((3 != length) && (inf_length != length))
- return false;
- char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
- while (end != itr)
- {
- if (*inf_itr == static_cast<char>(*itr))
- {
- ++itr;
- ++inf_itr;
- continue;
- }
- else
- return false;
- }
- if (negative)
- t = -std::numeric_limits<T>::infinity();
- else
- t = std::numeric_limits<T>::infinity();
- return true;
- }
- template <typename Iterator, typename T>
- inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
- {
- if (end == itr_external) return false;
- Iterator itr = itr_external;
- T d = T(0);
- const bool negative = ('-' == (*itr));
- if (negative || '+' == (*itr))
- {
- if (end == ++itr)
- return false;
- }
- bool instate = false;
- static const char_t zero = static_cast<uchar_t>('0');
- #define parse_digit_1(d) \
- if ((digit = (*itr - zero)) < 10) \
- { d = d * T(10) + digit; } \
- else \
- { break; } \
- if (end == ++itr) break; \
- #define parse_digit_2(d) \
- if ((digit = (*itr - zero)) < 10) \
- { d = d * T(10) + digit; } \
- else { break; } \
- ++itr; \
- if ('.' != (*itr))
- {
- const Iterator curr = itr;
- while ((end != itr) && (zero == (*itr))) ++itr;
- unsigned int digit;
- while (end != itr)
- {
- // Note: For 'physical' superscalar architectures it
- // is advised that the following loop be: 4xPD1 and 1xPD2
- #ifdef exprtk_enable_superscalar
- parse_digit_1(d)
- parse_digit_1(d)
- #endif
- parse_digit_1(d)
- parse_digit_1(d)
- parse_digit_2(d)
- }
- if (curr != itr) instate = true;
- }
- int exponent = 0;
- if (end != itr)
- {
- if ('.' == (*itr))
- {
- const Iterator curr = ++itr;
- unsigned int digit;
- T tmp_d = T(0);
- while (end != itr)
- {
- #ifdef exprtk_enable_superscalar
- parse_digit_1(tmp_d)
- parse_digit_1(tmp_d)
- parse_digit_1(tmp_d)
- #endif
- parse_digit_1(tmp_d)
- parse_digit_1(tmp_d)
- parse_digit_2(tmp_d)
- }
- if (curr != itr)
- {
- instate = true;
- d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
- }
- #undef parse_digit_1
- #undef parse_digit_2
- }
- if (end != itr)
- {
- typename std::iterator_traits<Iterator>::value_type c = (*itr);
- if (('e' == c) || ('E' == c))
- {
- int exp = 0;
- if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
- {
- if (end == itr)
- return false;
- else
- c = (*itr);
- }
- exponent += exp;
- }
- if (end != itr)
- {
- if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
- ++itr;
- else if ('#' == c)
- {
- if (end == ++itr)
- return false;
- else if (('I' <= (*itr)) && ((*itr) <= 'n'))
- {
- if (('i' == (*itr)) || ('I' == (*itr)))
- {
- return parse_inf(itr, end, t, negative);
- }
- else if (('n' == (*itr)) || ('N' == (*itr)))
- {
- return parse_nan(itr, end, t);
- }
- else
- return false;
- }
- else
- return false;
- }
- else if (('I' <= (*itr)) && ((*itr) <= 'n'))
- {
- if (('i' == (*itr)) || ('I' == (*itr)))
- {
- return parse_inf(itr, end, t, negative);
- }
- else if (('n' == (*itr)) || ('N' == (*itr)))
- {
- return parse_nan(itr, end, t);
- }
- else
- return false;
- }
- else
- return false;
- }
- }
- }
- if ((end != itr) || (!instate))
- return false;
- else if (exponent)
- d = compute_pow10(d,exponent);
- t = static_cast<T>((negative) ? -d : d);
- return true;
- }
- template <typename T>
- inline bool string_to_real(const std::string& s, T& t)
- {
- const typename numeric::details::number_type<T>::type num_type;
- char_cptr begin = s.data();
- char_cptr end = s.data() + s.size();
- return string_to_real(begin, end, t, num_type);
- }
- template <typename T>
- struct functor_t
- {
- /*
- Note: The following definitions for Type, may require tweaking
- based on the compiler and target architecture. The benchmark
- should provide enough information to make the right choice.
- */
- //typedef T Type;
- //typedef const T Type;
- typedef const T& Type;
- typedef T& RefType;
- typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
- typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
- typedef T (*bfunc_t)(Type t0, Type t1);
- typedef T (*ufunc_t)(Type t0);
- };
- } // namespace details
- namespace lexer
- {
- struct token
- {
- enum token_type
- {
- e_none = 0, e_error = 1, e_err_symbol = 2,
- e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
- e_eof = 6, e_number = 7, e_symbol = 8,
- e_string = 9, e_assign = 10, e_addass = 11,
- e_subass = 12, e_mulass = 13, e_divass = 14,
- e_modass = 15, e_shr = 16, e_shl = 17,
- e_lte = 18, e_ne = 19, e_gte = 20,
- e_swap = 21, e_lt = '<', e_gt = '>',
- e_eq = '=', e_rbracket = ')', e_lbracket = '(',
- e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
- e_lcrlbracket = '{', e_comma = ',', e_add = '+',
- e_sub = '-', e_div = '/', e_mul = '*',
- e_mod = '%', e_pow = '^', e_colon = ':',
- e_ternary = '?'
- };
- token()
- : type(e_none),
- value(""),
- position(std::numeric_limits<std::size_t>::max())
- {}
- void clear()
- {
- type = e_none;
- value = "";
- position = std::numeric_limits<std::size_t>::max();
- }
- template <typename Iterator>
- inline token& set_operator(const token_type tt,
- const Iterator begin, const Iterator end,
- const Iterator base_begin = Iterator(0))
- {
- type = tt;
- value.assign(begin,end);
- if (base_begin)
- position = static_cast<std::size_t>(std::distance(base_begin,begin));
- return (*this);
- }
- template <typename Iterator>
- inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
- {
- type = e_symbol;
- value.assign(begin,end);
- if (base_begin)
- position = static_cast<std::size_t>(std::distance(base_begin,begin));
- return (*this);
- }
- template <typename Iterator>
- inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
- {
- type = e_number;
- value.assign(begin,end);
- if (base_begin)
- position = static_cast<std::size_t>(std::distance(base_begin,begin));
- return (*this);
- }
- template <typename Iterator>
- inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
- {
- type = e_string;
- value.assign(begin,end);
- if (base_begin)
- position = static_cast<std::size_t>(std::distance(base_begin,begin));
- return (*this);
- }
- inline token& set_string(const std::string& s, const std::size_t p)
- {
- type = e_string;
- value = s;
- position = p;
- return (*this);
- }
- template <typename Iterator>
- inline token& set_error(const token_type et,
- const Iterator begin, const Iterator end,
- const Iterator base_begin = Iterator(0))
- {
- if (
- (e_error == et) ||
- (e_err_symbol == et) ||
- (e_err_number == et) ||
- (e_err_string == et) ||
- (e_err_sfunc == et)
- )
- {
- type = et;
- }
- else
- type = e_error;
- value.assign(begin,end);
- if (base_begin)
- position = static_cast<std::size_t>(std::distance(base_begin,begin));
- return (*this);
- }
- static inline std::string to_str(token_type t)
- {
- switch (t)
- {
- case e_none : return "NONE";
- case e_error : return "ERROR";
- case e_err_symbol : return "ERROR_SYMBOL";
- case e_err_number : return "ERROR_NUMBER";
- case e_err_string : return "ERROR_STRING";
- case e_eof : return "EOF";
- case e_number : return "NUMBER";
- case e_symbol : return "SYMBOL";
- case e_string : return "STRING";
- case e_assign : return ":=";
- case e_addass : return "+=";
- case e_subass : return "-=";
- case e_mulass : return "*=";
- case e_divass : return "/=";
- case e_modass : return "%=";
- case e_shr : return ">>";
- case e_shl : return "<<";
- case e_lte : return "<=";
- case e_ne : return "!=";
- case e_gte : return ">=";
- case e_lt : return "<";
- case e_gt : return ">";
- case e_eq : return "=";
- case e_rbracket : return ")";
- case e_lbracket : return "(";
- case e_rsqrbracket : return "]";
- case e_lsqrbracket : return "[";
- case e_rcrlbracket : return "}";
- case e_lcrlbracket : return "{";
- case e_comma : return ",";
- case e_add : return "+";
- case e_sub : return "-";
- case e_div : return "/";
- case e_mul : return "*";
- case e_mod : return "%";
- case e_pow : return "^";
- case e_colon : return ":";
- case e_ternary : return "?";
- case e_swap : return "<=>";
- default : return "UNKNOWN";
- }
- }
- inline bool is_error() const
- {
- return (
- (e_error == type) ||
- (e_err_symbol == type) ||
- (e_err_number == type) ||
- (e_err_string == type) ||
- (e_err_sfunc == type)
- );
- }
- token_type type;
- std::string value;
- std::size_t position;
- };
- class generator
- {
- public:
- typedef token token_t;
- typedef std::vector<token_t> token_list_t;
- typedef std::vector<token_t>::iterator token_list_itr_t;
- typedef details::char_t char_t;
- generator()
- : base_itr_(0),
- s_itr_ (0),
- s_end_ (0)
- {
- clear();
- }
- inline void clear()
- {
- base_itr_ = 0;
- s_itr_ = 0;
- s_end_ = 0;
- token_list_.clear();
- token_itr_ = token_list_.end();
- store_token_itr_ = token_list_.end();
- }
- inline bool process(const std::string& str)
- {
- base_itr_ = str.data();
- s_itr_ = str.data();
- s_end_ = str.data() + str.size();
- eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
- token_list_.clear();
- while (!is_end(s_itr_))
- {
- scan_token();
- if (!token_list_.empty() && token_list_.back().is_error())
- return false;
- }
- return true;
- }
- inline bool empty() const
- {
- return token_list_.empty();
- }
- inline std::size_t size() const
- {
- return token_list_.size();
- }
- inline void begin()
- {
- token_itr_ = token_list_.begin();
- store_token_itr_ = token_list_.begin();
- }
- inline void store()
- {
- store_token_itr_ = token_itr_;
- }
- inline void restore()
- {
- token_itr_ = store_token_itr_;
- }
- inline token_t& next_token()
- {
- if (token_list_.end() != token_itr_)
- {
- return *token_itr_++;
- }
- else
- return eof_token_;
- }
- inline token_t& peek_next_token()
- {
- if (token_list_.end() != token_itr_)
- {
- return *token_itr_;
- }
- else
- return eof_token_;
- }
- inline token_t& operator[](const std::size_t& index)
- {
- if (index < token_list_.size())
- return token_list_[index];
- else
- return eof_token_;
- }
- inline token_t operator[](const std::size_t& index) const
- {
- if (index < token_list_.size())
- return token_list_[index];
- else
- return eof_token_;
- }
- inline bool finished() const
- {
- return (token_list_.end() == token_itr_);
- }
- inline void insert_front(token_t::token_type tk_type)
- {
- if (
- !token_list_.empty() &&
- (token_list_.end() != token_itr_)
- )
- {
- token_t t = *token_itr_;
- t.type = tk_type;
- token_itr_ = token_list_.insert(token_itr_,t);
- }
- }
- inline std::string substr(const std::size_t& begin, const std::size_t& end)
- {
- const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
- const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_;
- return std::string(begin_itr,end_itr);
- }
- inline std::string remaining() const
- {
- if (finished())
- return "";
- else if (token_list_.begin() != token_itr_)
- return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
- else
- return std::string(base_itr_ + token_itr_->position, s_end_);
- }
- private:
- inline bool is_end(details::char_cptr itr)
- {
- return (s_end_ == itr);
- }
- inline bool is_comment_start(details::char_cptr itr)
- {
- #ifndef exprtk_disable_comments
- const char_t c0 = *(itr + 0);
- const char_t c1 = *(itr + 1);
- if ('#' == c0)
- return true;
- else if (!is_end(itr + 1))
- {
- if (('/' == c0) && ('/' == c1)) return true;
- if (('/' == c0) && ('*' == c1)) return true;
- }
- #endif
- return false;
- }
- inline void skip_whitespace()
- {
- while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
- {
- ++s_itr_;
- }
- }
- inline void skip_comments()
- {
- #ifndef exprtk_disable_comments
- // The following comment styles are supported:
- // 1. // .... \n
- // 2. # .... \n
- // 3. /* .... */
- struct test
- {
- static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
- {
- mode = 0;
- if ('#' == c0) { mode = 1; incr = 1; }
- else if ('/' == c0)
- {
- if ('/' == c1) { mode = 1; incr = 2; }
- else if ('*' == c1) { mode = 2; incr = 2; }
- }
- return (0 != mode);
- }
- static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
- {
- if (
- ((1 == mode) && ('\n' == c0)) ||
- ((2 == mode) && ( '*' == c0) && ('/' == c1))
- )
- {
- mode = 0;
- return true;
- }
- else
- return false;
- }
- };
- int mode = 0;
- int increment = 0;
- if (is_end(s_itr_))
- return;
- else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
- return;
- details::char_cptr cmt_start = s_itr_;
- s_itr_ += increment;
- while (!is_end(s_itr_))
- {
- if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
- {
- ++s_itr_;
- return;
- }
- if ((2 == mode))
- {
- if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
- {
- s_itr_ += 2;
- return;
- }
- }
- ++s_itr_;
- }
- if (2 == mode)
- {
- token_t t;
- t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
- token_list_.push_back(t);
- }
- #endif
- }
- inline void scan_token()
- {
- if (details::is_whitespace(*s_itr_))
- {
- skip_whitespace();
- return;
- }
- else if (is_comment_start(s_itr_))
- {
- skip_comments();
- return;
- }
- else if (details::is_operator_char(*s_itr_))
- {
- scan_operator();
- return;
- }
- else if (details::is_letter(*s_itr_))
- {
- scan_symbol();
- return;
- }
- else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
- {
- scan_number();
- return;
- }
- else if ('$' == (*s_itr_))
- {
- scan_special_function();
- return;
- }
- #ifndef exprtk_disable_string_capabilities
- else if ('\'' == (*s_itr_))
- {
- scan_string();
- return;
- }
- #endif
- else if ('~' == (*s_itr_))
- {
- token_t t;
- t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
- token_list_.push_back(t);
- ++s_itr_;
- return;
- }
- else
- {
- token_t t;
- t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
- token_list_.push_back(t);
- ++s_itr_;
- }
- }
- inline void scan_operator()
- {
- token_t t;
- const char_t c0 = s_itr_[0];
- if (!is_end(s_itr_ + 1))
- {
- const char_t c1 = s_itr_[1];
- if (!is_end(s_itr_ + 2))
- {
- const char_t c2 = s_itr_[2];
- if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
- {
- t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
- token_list_.push_back(t);
- s_itr_ += 3;
- return;
- }
- }
- token_t::token_type ttype = token_t::e_none;
- if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
- else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
- else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
- else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
- else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
- else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
- else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
- else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
- else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
- else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
- else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
- else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
- else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
- if (token_t::e_none != ttype)
- {
- t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
- token_list_.push_back(t);
- s_itr_ += 2;
- return;
- }
- }
- if ('<' == c0)
- t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
- else if ('>' == c0)
- t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
- else if (';' == c0)
- t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
- else if ('&' == c0)
- t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
- else if ('|' == c0)
- t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
- else
- t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
- token_list_.push_back(t);
- ++s_itr_;
- }
- inline void scan_symbol()
- {
- details::char_cptr initial_itr = s_itr_;
- while (!is_end(s_itr_))
- {
- if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
- {
- if ('.' != (*s_itr_))
- break;
- /*
- Permit symbols that contain a 'dot'
- Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
- Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
- */
- if (
- (s_itr_ != initial_itr) &&
- !is_end(s_itr_ + 1) &&
- !details::is_letter_or_digit(*(s_itr_ + 1)) &&
- ('_' != (*(s_itr_ + 1)))
- )
- break;
- }
- ++s_itr_;
- }
- token_t t;
- t.set_symbol(initial_itr,s_itr_,base_itr_);
- token_list_.push_back(t);
- }
- inline void scan_number()
- {
- /*
- Attempt to match a valid numeric value in one of the following formats:
- (01) 123456
- (02) 123456.
- (03) 123.456
- (04) 123.456e3
- (05) 123.456E3
- (06) 123.456e+3
- (07) 123.456E+3
- (08) 123.456e-3
- (09) 123.456E-3
- (00) .1234
- (11) .1234e3
- (12) .1234E+3
- (13) .1234e+3
- (14) .1234E-3
- (15) .1234e-3
- */
- details::char_cptr initial_itr = s_itr_;
- bool dot_found = false;
- bool e_found = false;
- bool post_e_sign_found = false;
- bool post_e_digit_found = false;
- token_t t;
- while (!is_end(s_itr_))
- {
- if ('.' == (*s_itr_))
- {
- if (dot_found)
- {
- t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- dot_found = true;
- ++s_itr_;
- continue;
- }
- else if ('e' == std::tolower(*s_itr_))
- {
- const char_t& c = *(s_itr_ + 1);
- if (is_end(s_itr_ + 1))
- {
- t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- else if (
- ('+' != c) &&
- ('-' != c) &&
- !details::is_digit(c)
- )
- {
- t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- e_found = true;
- ++s_itr_;
- continue;
- }
- else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
- {
- if (post_e_sign_found)
- {
- t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- post_e_sign_found = true;
- ++s_itr_;
- continue;
- }
- else if (e_found && details::is_digit(*s_itr_))
- {
- post_e_digit_found = true;
- ++s_itr_;
- continue;
- }
- else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
- break;
- else
- ++s_itr_;
- }
- t.set_numeric(initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- inline void scan_special_function()
- {
- details::char_cptr initial_itr = s_itr_;
- token_t t;
- // $fdd(x,x,x) = at least 11 chars
- if (std::distance(s_itr_,s_end_) < 11)
- {
- t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- if (
- !(('$' == *s_itr_) &&
- (details::imatch ('f',*(s_itr_ + 1))) &&
- (details::is_digit(*(s_itr_ + 2))) &&
- (details::is_digit(*(s_itr_ + 3))))
- )
- {
- t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- s_itr_ += 4; // $fdd = 4chars
- t.set_symbol(initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- #ifndef exprtk_disable_string_capabilities
- inline void scan_string()
- {
- details::char_cptr initial_itr = s_itr_ + 1;
- token_t t;
- if (std::distance(s_itr_,s_end_) < 2)
- {
- t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- ++s_itr_;
- bool escaped_found = false;
- bool escaped = false;
- while (!is_end(s_itr_))
- {
- if (!escaped && ('\\' == *s_itr_))
- {
- escaped_found = true;
- escaped = true;
- ++s_itr_;
- continue;
- }
- else if (!escaped)
- {
- if ('\'' == *s_itr_)
- break;
- }
- else if (escaped)
- {
- if (!is_end(s_itr_) && ('0' == *(s_itr_)))
- {
- /*
- Note: The following 'awkward' conditional is
- due to various broken msvc compilers.
- */
- #if defined(_MSC_VER) && (_MSC_VER == 1600)
- const bool within_range = !is_end(s_itr_ + 2) &&
- !is_end(s_itr_ + 3) ;
- #else
- const bool within_range = !is_end(s_itr_ + 1) &&
- !is_end(s_itr_ + 2) &&
- !is_end(s_itr_ + 3) ;
- #endif
- const bool x_seperator = ('x' == *(s_itr_ + 1)) ||
- ('X' == *(s_itr_ + 1)) ;
- const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
- details::is_hex_digit(*(s_itr_ + 3)) ;
- if (!within_range || !x_seperator || !both_digits)
- {
- t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- else
- s_itr_ += 3;
- }
- escaped = false;
- }
- ++s_itr_;
- }
- if (is_end(s_itr_))
- {
- t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
- token_list_.push_back(t);
- return;
- }
- if (!escaped_found)
- t.set_string(initial_itr, s_itr_, base_itr_);
- else
- {
- std::string parsed_string(initial_itr,s_itr_);
- details::cleanup_escapes(parsed_string);
- t.set_string(
- parsed_string,
- static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
- }
- token_list_.push_back(t);
- ++s_itr_;
- return;
- }
- #endif
- private:
- token_list_t token_list_;
- token_list_itr_t token_itr_;
- token_list_itr_t store_token_itr_;
- token_t eof_token_;
- details::char_cptr base_itr_;
- details::char_cptr s_itr_;
- details::char_cptr s_end_;
- friend class token_scanner;
- friend class token_modifier;
- friend class token_inserter;
- friend class token_joiner;
- };
- class helper_interface
- {
- public:
- virtual void init() { }
- virtual void reset() { }
- virtual bool result() { return true; }
- virtual std::size_t process(generator&) { return 0; }
- virtual ~helper_interface() { }
- };
- class token_scanner : public helper_interface
- {
- public:
- virtual ~token_scanner()
- {}
- explicit token_scanner(const std::size_t& stride)
- : stride_(stride)
- {
- if (stride > 4)
- {
- throw std::invalid_argument("token_scanner() - Invalid stride value");
- }
- }
- inline std::size_t process(generator& g)
- {
- if (g.token_list_.size() >= stride_)
- {
- for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
- {
- token t;
- switch (stride_)
- {
- case 1 :
- {
- const token& t0 = g.token_list_[i];
- if (!operator()(t0))
- {
- return i;
- }
- }
- break;
- case 2 :
- {
- const token& t0 = g.token_list_[i ];
- const token& t1 = g.token_list_[i + 1];
- if (!operator()(t0, t1))
- {
- return i;
- }
- }
- break;
- case 3 :
- {
- const token& t0 = g.token_list_[i ];
- const token& t1 = g.token_list_[i + 1];
- const token& t2 = g.token_list_[i + 2];
- if (!operator()(t0, t1, t2))
- {
- return i;
- }
- }
- break;
- case 4 :
- {
- const token& t0 = g.token_list_[i ];
- const token& t1 = g.token_list_[i + 1];
- const token& t2 = g.token_list_[i + 2];
- const token& t3 = g.token_list_[i + 3];
- if (!operator()(t0, t1, t2, t3))
- {
- return i;
- }
- }
- break;
- }
- }
- }
- return (g.token_list_.size() - stride_ + 1);
- }
- virtual bool operator() (const token&)
- {
- return false;
- }
- virtual bool operator() (const token&, const token&)
- {
- return false;
- }
- virtual bool operator() (const token&, const token&, const token&)
- {
- return false;
- }
- virtual bool operator() (const token&, const token&, const token&, const token&)
- {
- return false;
- }
- private:
- const std::size_t stride_;
- };
- class token_modifier : public helper_interface
- {
- public:
- inline std::size_t process(generator& g)
- {
- std::size_t changes = 0;
- for (std::size_t i = 0; i < g.token_list_.size(); ++i)
- {
- if (modify(g.token_list_[i])) changes++;
- }
- return changes;
- }
- virtual bool modify(token& t) = 0;
- };
- class token_inserter : public helper_interface
- {
- public:
- explicit token_inserter(const std::size_t& stride)
- : stride_(stride)
- {
- if (stride > 5)
- {
- throw std::invalid_argument("token_inserter() - Invalid stride value");
- }
- }
- inline std::size_t process(generator& g)
- {
- if (g.token_list_.empty())
- return 0;
- else if (g.token_list_.size() < stride_)
- return 0;
- std::size_t changes = 0;
- for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
- {
- int insert_index = -1;
- token t;
- switch (stride_)
- {
- case 1 : insert_index = insert(g.token_list_[i],t);
- break;
- case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
- break;
- case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
- break;
- case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t);
- break;
- case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t);
- break;
- }
- typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
- if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
- {
- g.token_list_.insert(
- g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
- changes++;
- }
- }
- return changes;
- }
- #define token_inserter_empty_body \
- { \
- return -1; \
- } \
- inline virtual int insert(const token&, token&)
- token_inserter_empty_body
- inline virtual int insert(const token&, const token&, token&)
- token_inserter_empty_body
- inline virtual int insert(const token&, const token&, const token&, token&)
- token_inserter_empty_body
- inline virtual int insert(const token&, const token&, const token&, const token&, token&)
- token_inserter_empty_body
- inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
- token_inserter_empty_body
- #undef token_inserter_empty_body
- private:
- const std::size_t stride_;
- };
- class token_joiner : public helper_interface
- {
- public:
- explicit token_joiner(const std::size_t& stride)
- : stride_(stride)
- {}
- inline std::size_t process(generator& g)
- {
- if (g.token_list_.empty())
- return 0;
- switch (stride_)
- {
- case 2 : return process_stride_2(g);
- case 3 : return process_stride_3(g);
- default : return 0;
- }
- }
- virtual bool join(const token&, const token&, token&) { return false; }
- virtual bool join(const token&, const token&, const token&, token&) { return false; }
- private:
- inline std::size_t process_stride_2(generator& g)
- {
- typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
- if (g.token_list_.size() < 2)
- return 0;
- std::size_t changes = 0;
- for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
- {
- token t;
- while (join(g[i], g[i + 1], t))
- {
- g.token_list_[i] = t;
- g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
- ++changes;
- if (static_cast<std::size_t>(i + 1) >= g.token_list_.size())
- break;
- }
- }
- return changes;
- }
- inline std::size_t process_stride_3(generator& g)
- {
- typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
- if (g.token_list_.size() < 3)
- return 0;
- std::size_t changes = 0;
- for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
- {
- token t;
- while (join(g[i], g[i + 1], g[i + 2], t))
- {
- g.token_list_[i] = t;
- g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),
- g.token_list_.begin() + static_cast<diff_t>(i + 3));
- ++changes;
- if (static_cast<std::size_t>(i + 2) >= g.token_list_.size())
- break;
- }
- }
- return changes;
- }
- const std::size_t stride_;
- };
- namespace helper
- {
- inline void dump(lexer::generator& generator)
- {
- for (std::size_t i = 0; i < generator.size(); ++i)
- {
- lexer::token t = generator[i];
- printf("Token[%02d] @ %03d %6s --> '%s'\n",
- static_cast<int>(i),
- static_cast<int>(t.position),
- t.to_str(t.type).c_str(),
- t.value.c_str());
- }
- }
- class commutative_inserter : public lexer::token_inserter
- {
- public:
- using lexer::token_inserter::insert;
- commutative_inserter()
- : lexer::token_inserter(2)
- {}
- inline void ignore_symbol(const std::string& symbol)
- {
- ignore_set_.insert(symbol);
- }
- inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
- {
- bool match = false;
- new_token.type = lexer::token::e_mul;
- new_token.value = "*";
- new_token.position = t1.position;
- if (t0.type == lexer::token::e_symbol)
- {
- if (ignore_set_.end() != ignore_set_.find(t0.value))
- {
- return -1;
- }
- else if (!t0.value.empty() && ('$' == t0.value[0]))
- {
- return -1;
- }
- }
- if (t1.type == lexer::token::e_symbol)
- {
- if (ignore_set_.end() != ignore_set_.find(t1.value))
- {
- return -1;
- }
- }
- if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
- else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
- else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
- else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
- else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
- else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
- else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
- else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
- else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
- else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
- else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
- else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true;
- return (match) ? 1 : -1;
- }
- private:
- std::set<std::string,details::ilesscompare> ignore_set_;
- };
- class operator_joiner : public token_joiner
- {
- public:
- explicit operator_joiner(const std::size_t& stride)
- : token_joiner(stride)
- {}
- inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
- {
- // ': =' --> ':='
- if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_assign;
- t.value = ":=";
- t.position = t0.position;
- return true;
- }
- // '+ =' --> '+='
- else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_addass;
- t.value = "+=";
- t.position = t0.position;
- return true;
- }
- // '- =' --> '-='
- else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_subass;
- t.value = "-=";
- t.position = t0.position;
- return true;
- }
- // '* =' --> '*='
- else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_mulass;
- t.value = "*=";
- t.position = t0.position;
- return true;
- }
- // '/ =' --> '/='
- else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_divass;
- t.value = "/=";
- t.position = t0.position;
- return true;
- }
- // '% =' --> '%='
- else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_modass;
- t.value = "%=";
- t.position = t0.position;
- return true;
- }
- // '> =' --> '>='
- else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_gte;
- t.value = ">=";
- t.position = t0.position;
- return true;
- }
- // '< =' --> '<='
- else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_lte;
- t.value = "<=";
- t.position = t0.position;
- return true;
- }
- // '= =' --> '=='
- else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_eq;
- t.value = "==";
- t.position = t0.position;
- return true;
- }
- // '! =' --> '!='
- else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
- {
- t.type = lexer::token::e_ne;
- t.value = "!=";
- t.position = t0.position;
- return true;
- }
- // '< >' --> '<>'
- else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
- {
- t.type = lexer::token::e_ne;
- t.value = "<>";
- t.position = t0.position;
- return true;
- }
- // '<= >' --> '<=>'
- else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
- {
- t.type = lexer::token::e_swap;
- t.value = "<=>";
- t.position = t0.position;
- return true;
- }
- // '+ -' --> '-'
- else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
- {
- t.type = lexer::token::e_sub;
- t.value = "-";
- t.position = t0.position;
- return true;
- }
- // '- +' --> '-'
- else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
- {
- t.type = lexer::token::e_sub;
- t.value = "-";
- t.position = t0.position;
- return true;
- }
- // '- -' --> '+'
- else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
- {
- /*
- Note: May need to reconsider this when wanting to implement
- pre/postfix decrement operator
- */
- t.type = lexer::token::e_add;
- t.value = "+";
- t.position = t0.position;
- return true;
- }
- else
- return false;
- }
- inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
- {
- // '[ * ]' --> '[*]'
- if (
- (t0.type == lexer::token::e_lsqrbracket) &&
- (t1.type == lexer::token::e_mul ) &&
- (t2.type == lexer::token::e_rsqrbracket)
- )
- {
- t.type = lexer::token::e_symbol;
- t.value = "[*]";
- t.position = t0.position;
- return true;
- }
- else
- return false;
- }
- };
- class bracket_checker : public lexer::token_scanner
- {
- public:
- using lexer::token_scanner::operator();
- bracket_checker()
- : token_scanner(1),
- state_(true)
- {}
- bool result()
- {
- if (!stack_.empty())
- {
- lexer::token t;
- t.value = stack_.top().first;
- t.position = stack_.top().second;
- error_token_ = t;
- state_ = false;
- return false;
- }
- else
- return state_;
- }
- lexer::token error_token()
- {
- return error_token_;
- }
- void reset()
- {
- // Why? because msvc doesn't support swap properly.
- stack_ = std::stack<std::pair<char,std::size_t> >();
- state_ = true;
- error_token_.clear();
- }
- bool operator() (const lexer::token& t)
- {
- if (
- !t.value.empty() &&
- (lexer::token::e_string != t.type) &&
- (lexer::token::e_symbol != t.type) &&
- exprtk::details::is_bracket(t.value[0])
- )
- {
- details::char_t c = t.value[0];
- if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position));
- else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
- else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
- else if (exprtk::details::is_right_bracket(c))
- {
- if (stack_.empty())
- {
- state_ = false;
- error_token_ = t;
- return false;
- }
- else if (c != stack_.top().first)
- {
- state_ = false;
- error_token_ = t;
- return false;
- }
- else
- stack_.pop();
- }
- }
- return true;
- }
- private:
- bool state_;
- std::stack<std::pair<char,std::size_t> > stack_;
- lexer::token error_token_;
- };
- class numeric_checker : public lexer::token_scanner
- {
- public:
- using lexer::token_scanner::operator();
- numeric_checker()
- : token_scanner (1),
- current_index_(0)
- {}
- bool result()
- {
- return error_list_.empty();
- }
- void reset()
- {
- error_list_.clear();
- current_index_ = 0;
- }
- bool operator() (const lexer::token& t)
- {
- if (token::e_number == t.type)
- {
- double v;
- if (!exprtk::details::string_to_real(t.value,v))
- {
- error_list_.push_back(current_index_);
- }
- }
- ++current_index_;
- return true;
- }
- std::size_t error_count() const
- {
- return error_list_.size();
- }
- std::size_t error_index(const std::size_t& i)
- {
- if (i < error_list_.size())
- return error_list_[i];
- else
- return std::numeric_limits<std::size_t>::max();
- }
- void clear_errors()
- {
- error_list_.clear();
- }
- private:
- std::size_t current_index_;
- std::vector<std::size_t> error_list_;
- };
- class symbol_replacer : public lexer::token_modifier
- {
- private:
- typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
- public:
- bool remove(const std::string& target_symbol)
- {
- const replace_map_t::iterator itr = replace_map_.find(target_symbol);
- if (replace_map_.end() == itr)
- return false;
- replace_map_.erase(itr);
- return true;
- }
- bool add_replace(const std::string& target_symbol,
- const std::string& replace_symbol,
- const lexer::token::token_type token_type = lexer::token::e_symbol)
- {
- const replace_map_t::iterator itr = replace_map_.find(target_symbol);
- if (replace_map_.end() != itr)
- {
- return false;
- }
- replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
- return true;
- }
- void clear()
- {
- replace_map_.clear();
- }
- private:
- bool modify(lexer::token& t)
- {
- if (lexer::token::e_symbol == t.type)
- {
- if (replace_map_.empty())
- return false;
- const replace_map_t::iterator itr = replace_map_.find(t.value);
- if (replace_map_.end() != itr)
- {
- t.value = itr->second.first;
- t.type = itr->second.second;
- return true;
- }
- }
- return false;
- }
- replace_map_t replace_map_;
- };
- class sequence_validator : public lexer::token_scanner
- {
- private:
- typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
- typedef std::set<token_pair_t> set_t;
- public:
- using lexer::token_scanner::operator();
- sequence_validator()
- : lexer::token_scanner(2)
- {
- add_invalid(lexer::token::e_number, lexer::token::e_number);
- add_invalid(lexer::token::e_string, lexer::token::e_string);
- add_invalid(lexer::token::e_number, lexer::token::e_string);
- add_invalid(lexer::token::e_string, lexer::token::e_number);
- add_invalid_set1(lexer::token::e_assign );
- add_invalid_set1(lexer::token::e_shr );
- add_invalid_set1(lexer::token::e_shl );
- add_invalid_set1(lexer::token::e_lte );
- add_invalid_set1(lexer::token::e_ne );
- add_invalid_set1(lexer::token::e_gte );
- add_invalid_set1(lexer::token::e_lt );
- add_invalid_set1(lexer::token::e_gt );
- add_invalid_set1(lexer::token::e_eq );
- add_invalid_set1(lexer::token::e_comma );
- add_invalid_set1(lexer::token::e_add );
- add_invalid_set1(lexer::token::e_sub );
- add_invalid_set1(lexer::token::e_div );
- add_invalid_set1(lexer::token::e_mul );
- add_invalid_set1(lexer::token::e_mod );
- add_invalid_set1(lexer::token::e_pow );
- add_invalid_set1(lexer::token::e_colon );
- add_invalid_set1(lexer::token::e_ternary);
- }
- bool result()
- {
- return error_list_.empty();
- }
- bool operator() (const lexer::token& t0, const lexer::token& t1)
- {
- const set_t::value_type p = std::make_pair(t0.type,t1.type);
- if (invalid_bracket_check(t0.type,t1.type))
- {
- error_list_.push_back(std::make_pair(t0,t1));
- }
- else if (invalid_comb_.find(p) != invalid_comb_.end())
- {
- error_list_.push_back(std::make_pair(t0,t1));
- }
- return true;
- }
- std::size_t error_count() const
- {
- return error_list_.size();
- }
- std::pair<lexer::token,lexer::token> error(const std::size_t index)
- {
- if (index < error_list_.size())
- {
- return error_list_[index];
- }
- else
- {
- static const lexer::token error_token;
- return std::make_pair(error_token,error_token);
- }
- }
- void clear_errors()
- {
- error_list_.clear();
- }
- private:
- void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
- {
- invalid_comb_.insert(std::make_pair(base,t));
- }
- void add_invalid_set1(lexer::token::token_type t)
- {
- add_invalid(t, lexer::token::e_assign);
- add_invalid(t, lexer::token::e_shr );
- add_invalid(t, lexer::token::e_shl );
- add_invalid(t, lexer::token::e_lte );
- add_invalid(t, lexer::token::e_ne );
- add_invalid(t, lexer::token::e_gte );
- add_invalid(t, lexer::token::e_lt );
- add_invalid(t, lexer::token::e_gt );
- add_invalid(t, lexer::token::e_eq );
- add_invalid(t, lexer::token::e_comma );
- add_invalid(t, lexer::token::e_div );
- add_invalid(t, lexer::token::e_mul );
- add_invalid(t, lexer::token::e_mod );
- add_invalid(t, lexer::token::e_pow );
- add_invalid(t, lexer::token::e_colon );
- }
- bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
- {
- if (details::is_right_bracket(static_cast<char>(base)))
- {
- switch (t)
- {
- case lexer::token::e_assign : return (']' != base);
- case lexer::token::e_string : return (')' != base);
- default : return false;
- }
- }
- else if (details::is_left_bracket(static_cast<char>(base)))
- {
- if (details::is_right_bracket(static_cast<char>(t)))
- return false;
- else if (details::is_left_bracket(static_cast<char>(t)))
- return false;
- else
- {
- switch (t)
- {
- case lexer::token::e_number : return false;
- case lexer::token::e_symbol : return false;
- case lexer::token::e_string : return false;
- case lexer::token::e_add : return false;
- case lexer::token::e_sub : return false;
- case lexer::token::e_colon : return false;
- case lexer::token::e_ternary : return false;
- default : return true ;
- }
- }
- }
- else if (details::is_right_bracket(static_cast<char>(t)))
- {
- switch (base)
- {
- case lexer::token::e_number : return false;
- case lexer::token::e_symbol : return false;
- case lexer::token::e_string : return false;
- case lexer::token::e_eof : return false;
- case lexer::token::e_colon : return false;
- case lexer::token::e_ternary : return false;
- default : return true ;
- }
- }
- else if (details::is_left_bracket(static_cast<char>(t)))
- {
- switch (base)
- {
- case lexer::token::e_rbracket : return true;
- case lexer::token::e_rsqrbracket : return true;
- case lexer::token::e_rcrlbracket : return true;
- default : return false;
- }
- }
- return false;
- }
- set_t invalid_comb_;
- std::vector<std::pair<lexer::token,lexer::token> > error_list_;
- };
- class sequence_validator_3tokens : public lexer::token_scanner
- {
- private:
- typedef lexer::token::token_type token_t;
- typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
- typedef std::set<token_triplet_t> set_t;
- public:
- using lexer::token_scanner::operator();
- sequence_validator_3tokens()
- : lexer::token_scanner(3)
- {
- add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
- add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
- add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
- add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add );
- add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub );
- add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div );
- add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul );
- add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod );
- add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow );
- add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add );
- add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub );
- add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div );
- add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul );
- add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod );
- add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow );
- }
- bool result()
- {
- return error_list_.empty();
- }
- bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
- {
- const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
- if (invalid_comb_.find(p) != invalid_comb_.end())
- {
- error_list_.push_back(std::make_pair(t0,t1));
- }
- return true;
- }
- std::size_t error_count() const
- {
- return error_list_.size();
- }
- std::pair<lexer::token,lexer::token> error(const std::size_t index)
- {
- if (index < error_list_.size())
- {
- return error_list_[index];
- }
- else
- {
- static const lexer::token error_token;
- return std::make_pair(error_token,error_token);
- }
- }
- void clear_errors()
- {
- error_list_.clear();
- }
- private:
- void add_invalid(token_t t0, token_t t1, token_t t2)
- {
- invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
- }
- set_t invalid_comb_;
- std::vector<std::pair<lexer::token,lexer::token> > error_list_;
- };
- struct helper_assembly
- {
- inline bool register_scanner(lexer::token_scanner* scanner)
- {
- if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
- token_scanner_list.end (),
- scanner))
- {
- return false;
- }
- token_scanner_list.push_back(scanner);
- return true;
- }
- inline bool register_modifier(lexer::token_modifier* modifier)
- {
- if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
- token_modifier_list.end (),
- modifier))
- {
- return false;
- }
- token_modifier_list.push_back(modifier);
- return true;
- }
- inline bool register_joiner(lexer::token_joiner* joiner)
- {
- if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
- token_joiner_list.end (),
- joiner))
- {
- return false;
- }
- token_joiner_list.push_back(joiner);
- return true;
- }
- inline bool register_inserter(lexer::token_inserter* inserter)
- {
- if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
- token_inserter_list.end (),
- inserter))
- {
- return false;
- }
- token_inserter_list.push_back(inserter);
- return true;
- }
- inline bool run_modifiers(lexer::generator& g)
- {
- error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
- for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
- {
- lexer::token_modifier& modifier = (*token_modifier_list[i]);
- modifier.reset();
- modifier.process(g);
- if (!modifier.result())
- {
- error_token_modifier = token_modifier_list[i];
- return false;
- }
- }
- return true;
- }
- inline bool run_joiners(lexer::generator& g)
- {
- error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
- for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
- {
- lexer::token_joiner& joiner = (*token_joiner_list[i]);
- joiner.reset();
- joiner.process(g);
- if (!joiner.result())
- {
- error_token_joiner = token_joiner_list[i];
- return false;
- }
- }
- return true;
- }
- inline bool run_inserters(lexer::generator& g)
- {
- error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
- for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
- {
- lexer::token_inserter& inserter = (*token_inserter_list[i]);
- inserter.reset();
- inserter.process(g);
- if (!inserter.result())
- {
- error_token_inserter = token_inserter_list[i];
- return false;
- }
- }
- return true;
- }
- inline bool run_scanners(lexer::generator& g)
- {
- error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
- for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
- {
- lexer::token_scanner& scanner = (*token_scanner_list[i]);
- scanner.reset();
- scanner.process(g);
- if (!scanner.result())
- {
- error_token_scanner = token_scanner_list[i];
- return false;
- }
- }
- return true;
- }
- std::vector<lexer::token_scanner*> token_scanner_list;
- std::vector<lexer::token_modifier*> token_modifier_list;
- std::vector<lexer::token_joiner*> token_joiner_list;
- std::vector<lexer::token_inserter*> token_inserter_list;
- lexer::token_scanner* error_token_scanner;
- lexer::token_modifier* error_token_modifier;
- lexer::token_joiner* error_token_joiner;
- lexer::token_inserter* error_token_inserter;
- };
- }
- class parser_helper
- {
- public:
- typedef token token_t;
- typedef generator generator_t;
- inline bool init(const std::string& str)
- {
- if (!lexer_.process(str))
- {
- return false;
- }
- lexer_.begin();
- next_token();
- return true;
- }
- inline generator_t& lexer()
- {
- return lexer_;
- }
- inline const generator_t& lexer() const
- {
- return lexer_;
- }
- inline void store_token()
- {
- lexer_.store();
- store_current_token_ = current_token_;
- }
- inline void restore_token()
- {
- lexer_.restore();
- current_token_ = store_current_token_;
- }
- inline void next_token()
- {
- current_token_ = lexer_.next_token();
- }
- inline const token_t& current_token() const
- {
- return current_token_;
- }
- enum token_advance_mode
- {
- e_hold = 0,
- e_advance = 1
- };
- inline void advance_token(const token_advance_mode mode)
- {
- if (e_advance == mode)
- {
- next_token();
- }
- }
- inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
- {
- if (current_token().type != ttype)
- {
- return false;
- }
- advance_token(mode);
- return true;
- }
- inline bool token_is(const token_t::token_type& ttype,
- const std::string& value,
- const token_advance_mode mode = e_advance)
- {
- if (
- (current_token().type != ttype) ||
- !exprtk::details::imatch(value,current_token().value)
- )
- {
- return false;
- }
- advance_token(mode);
- return true;
- }
- inline bool peek_token_is(const token_t::token_type& ttype)
- {
- return (lexer_.peek_next_token().type == ttype);
- }
- inline bool peek_token_is(const std::string& s)
- {
- return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
- }
- private:
- generator_t lexer_;
- token_t current_token_;
- token_t store_current_token_;
- };
- }
- template <typename T>
- class vector_view
- {
- public:
- typedef T* data_ptr_t;
- vector_view(data_ptr_t data, const std::size_t& size)
- : size_(size),
- data_(data),
- data_ref_(0)
- {}
- vector_view(const vector_view<T>& vv)
- : size_(vv.size_),
- data_(vv.data_),
- data_ref_(0)
- {}
- inline void rebase(data_ptr_t data)
- {
- data_ = data;
- if (!data_ref_.empty())
- {
- for (std::size_t i = 0; i < data_ref_.size(); ++i)
- {
- (*data_ref_[i]) = data;
- }
- }
- }
- inline data_ptr_t data() const
- {
- return data_;
- }
- inline std::size_t size() const
- {
- return size_;
- }
- inline const T& operator[](const std::size_t index) const
- {
- return data_[index];
- }
- inline T& operator[](const std::size_t index)
- {
- return data_[index];
- }
- void set_ref(data_ptr_t* data_ref)
- {
- data_ref_.push_back(data_ref);
- }
- private:
- const std::size_t size_;
- data_ptr_t data_;
- std::vector<data_ptr_t*> data_ref_;
- };
- template <typename T>
- inline vector_view<T> make_vector_view(T* data,
- const std::size_t size, const std::size_t offset = 0)
- {
- return vector_view<T>(data + offset, size);
- }
- template <typename T>
- inline vector_view<T> make_vector_view(std::vector<T>& v,
- const std::size_t size, const std::size_t offset = 0)
- {
- return vector_view<T>(v.data() + offset, size);
- }
- template <typename T> class results_context;
- template <typename T>
- struct type_store
- {
- enum store_type
- {
- e_unknown,
- e_scalar ,
- e_vector ,
- e_string
- };
- type_store()
- : data(0),
- size(0),
- type(e_unknown)
- {}
- union
- {
- void* data;
- T* vec_data;
- };
- std::size_t size;
- store_type type;
- class parameter_list
- {
- public:
- parameter_list(std::vector<type_store>& pl)
- : parameter_list_(pl)
- {}
- inline bool empty() const
- {
- return parameter_list_.empty();
- }
- inline std::size_t size() const
- {
- return parameter_list_.size();
- }
- inline type_store& operator[](const std::size_t& index)
- {
- return parameter_list_[index];
- }
- inline const type_store& operator[](const std::size_t& index) const
- {
- return parameter_list_[index];
- }
- inline type_store& front()
- {
- return parameter_list_[0];
- }
- inline const type_store& front() const
- {
- return parameter_list_[0];
- }
- inline type_store& back()
- {
- return parameter_list_.back();
- }
- inline const type_store& back() const
- {
- return parameter_list_.back();
- }
- private:
- std::vector<type_store>& parameter_list_;
- friend class results_context<T>;
- };
- template <typename ViewType>
- struct type_view
- {
- typedef type_store<T> type_store_t;
- typedef ViewType value_t;
- type_view(type_store_t& ts)
- : ts_(ts),
- data_(reinterpret_cast<value_t*>(ts_.data))
- {}
- type_view(const type_store_t& ts)
- : ts_(const_cast<type_store_t&>(ts)),
- data_(reinterpret_cast<value_t*>(ts_.data))
- {}
- inline std::size_t size() const
- {
- return ts_.size;
- }
- inline value_t& operator[](const std::size_t& i)
- {
- return data_[i];
- }
- inline const value_t& operator[](const std::size_t& i) const
- {
- return data_[i];
- }
- inline const value_t* begin() const { return data_; }
- inline value_t* begin() { return data_; }
- inline const value_t* end() const
- {
- return static_cast<value_t*>(data_ + ts_.size);
- }
- inline value_t* end()
- {
- return static_cast<value_t*>(data_ + ts_.size);
- }
- type_store_t& ts_;
- value_t* data_;
- };
- typedef type_view<T> vector_view;
- typedef type_view<char> string_view;
- struct scalar_view
- {
- typedef type_store<T> type_store_t;
- typedef T value_t;
- scalar_view(type_store_t& ts)
- : v_(*reinterpret_cast<value_t*>(ts.data))
- {}
- scalar_view(const type_store_t& ts)
- : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
- {}
- inline value_t& operator() ()
- {
- return v_;
- }
- inline const value_t& operator() () const
- {
- return v_;
- }
- template <typename IntType>
- inline bool to_int(IntType& i) const
- {
- if (!exprtk::details::numeric::is_integer(v_))
- return false;
- i = static_cast<IntType>(v_);
- return true;
- }
- template <typename UIntType>
- inline bool to_uint(UIntType& u) const
- {
- if (v_ < T(0))
- return false;
- else if (!exprtk::details::numeric::is_integer(v_))
- return false;
- u = static_cast<UIntType>(v_);
- return true;
- }
- T& v_;
- };
- };
- template <typename StringView>
- inline std::string to_str(const StringView& view)
- {
- return std::string(view.begin(),view.size());
- }
- #ifndef exprtk_disable_return_statement
- namespace details
- {
- template <typename T> class return_node;
- template <typename T> class return_envelope_node;
- }
- #endif
- template <typename T>
- class results_context
- {
- public:
- typedef type_store<T> type_store_t;
- results_context()
- : results_available_(false)
- {}
- inline std::size_t count() const
- {
- if (results_available_)
- return parameter_list_.size();
- else
- return 0;
- }
- inline type_store_t& operator[](const std::size_t& index)
- {
- return parameter_list_[index];
- }
- inline const type_store_t& operator[](const std::size_t& index) const
- {
- return parameter_list_[index];
- }
- private:
- inline void clear()
- {
- results_available_ = false;
- }
- typedef std::vector<type_store_t> ts_list_t;
- typedef typename type_store_t::parameter_list parameter_list_t;
- inline void assign(const parameter_list_t& pl)
- {
- parameter_list_ = pl.parameter_list_;
- results_available_ = true;
- }
- bool results_available_;
- ts_list_t parameter_list_;
- #ifndef exprtk_disable_return_statement
- friend class details::return_node<T>;
- friend class details::return_envelope_node<T>;
- #endif
- };
- namespace details
- {
- enum operator_type
- {
- e_default , e_null , e_add , e_sub ,
- e_mul , e_div , e_mod , e_pow ,
- e_atan2 , e_min , e_max , e_avg ,
- e_sum , e_prod , e_lt , e_lte ,
- e_eq , e_equal , e_ne , e_nequal ,
- e_gte , e_gt , e_and , e_nand ,
- e_or , e_nor , e_xor , e_xnor ,
- e_mand , e_mor , e_scand , e_scor ,
- e_shr , e_shl , e_abs , e_acos ,
- e_acosh , e_asin , e_asinh , e_atan ,
- e_atanh , e_ceil , e_cos , e_cosh ,
- e_exp , e_expm1 , e_floor , e_log ,
- e_log10 , e_log2 , e_log1p , e_logn ,
- e_neg , e_pos , e_round , e_roundn ,
- e_root , e_sqrt , e_sin , e_sinc ,
- e_sinh , e_sec , e_csc , e_tan ,
- e_tanh , e_cot , e_clamp , e_iclamp ,
- e_inrange , e_sgn , e_r2d , e_d2r ,
- e_d2g , e_g2d , e_hypot , e_notl ,
- e_erf , e_erfc , e_ncdf , e_frac ,
- e_trunc , e_assign , e_addass , e_subass ,
- e_mulass , e_divass , e_modass , e_in ,
- e_like , e_ilike , e_multi , e_smulti ,
- e_swap ,
- // Do not add new functions/operators after this point.
- e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
- e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
- e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
- e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
- e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
- e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
- e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
- e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
- e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
- e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
- e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
- e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
- e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
- e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
- e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
- e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
- e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
- e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
- e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
- e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
- e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
- e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
- e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
- e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
- e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
- e_sffinal = 1100,
- e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
- e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
- e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
- e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
- e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
- e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
- e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
- e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
- e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
- e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
- e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
- e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
- e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
- e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
- e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
- e_sf4ext60 = 2060, e_sf4ext61 = 2061
- };
- inline std::string to_str(const operator_type opr)
- {
- switch (opr)
- {
- case e_add : return "+" ;
- case e_sub : return "-" ;
- case e_mul : return "*" ;
- case e_div : return "/" ;
- case e_mod : return "%" ;
- case e_pow : return "^" ;
- case e_assign : return ":=" ;
- case e_addass : return "+=" ;
- case e_subass : return "-=" ;
- case e_mulass : return "*=" ;
- case e_divass : return "/=" ;
- case e_modass : return "%=" ;
- case e_lt : return "<" ;
- case e_lte : return "<=" ;
- case e_eq : return "==" ;
- case e_equal : return "=" ;
- case e_ne : return "!=" ;
- case e_nequal : return "<>" ;
- case e_gte : return ">=" ;
- case e_gt : return ">" ;
- case e_and : return "and" ;
- case e_or : return "or" ;
- case e_xor : return "xor" ;
- case e_nand : return "nand";
- case e_nor : return "nor" ;
- case e_xnor : return "xnor";
- default : return "N/A" ;
- }
- }
- struct base_operation_t
- {
- base_operation_t(const operator_type t, const unsigned int& np)
- : type(t),
- num_params(np)
- {}
- operator_type type;
- unsigned int num_params;
- };
- namespace loop_unroll
- {
- #ifndef exprtk_disable_superscalar_unroll
- const unsigned int global_loop_batch_size = 16;
- #else
- const unsigned int global_loop_batch_size = 4;
- #endif
- struct details
- {
- details(const std::size_t& vsize,
- const unsigned int loop_batch_size = global_loop_batch_size)
- : batch_size(loop_batch_size ),
- remainder (vsize % batch_size),
- upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
- {}
- unsigned int batch_size;
- int remainder;
- int upper_bound;
- };
- }
- #ifdef exprtk_enable_debugging
- inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
- {
- if (size)
- exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
- else
- exprtk_debug(("%s - addr: %p size: %d\n",
- s.c_str(),
- ptr,
- static_cast<unsigned int>(size)));
- }
- #else
- inline void dump_ptr(const std::string&, const void*) {}
- inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
- #endif
- template <typename T>
- class vec_data_store
- {
- public:
- typedef vec_data_store<T> type;
- typedef T* data_t;
- private:
- struct control_block
- {
- control_block()
- : ref_count(1),
- size (0),
- data (0),
- destruct (true)
- {}
- control_block(const std::size_t& dsize)
- : ref_count(1 ),
- size (dsize),
- data (0 ),
- destruct (true )
- { create_data(); }
- control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
- : ref_count(1 ),
- size (dsize ),
- data (dptr ),
- destruct (dstrct)
- {}
- ~control_block()
- {
- if (data && destruct && (0 == ref_count))
- {
- dump_ptr("~control_block() data",data);
- delete[] data;
- data = reinterpret_cast<data_t>(0);
- }
- }
- static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
- {
- if (dsize)
- {
- if (0 == data_ptr)
- return (new control_block(dsize));
- else
- return (new control_block(dsize, data_ptr, dstrct));
- }
- else
- return (new control_block);
- }
- static inline void destroy(control_block*& cntrl_blck)
- {
- if (cntrl_blck)
- {
- if (
- (0 != cntrl_blck->ref_count) &&
- (0 == --cntrl_blck->ref_count)
- )
- {
- delete cntrl_blck;
- }
- cntrl_blck = 0;
- }
- }
- std::size_t ref_count;
- std::size_t size;
- data_t data;
- bool destruct;
- private:
- control_block(const control_block&);
- control_block& operator=(const control_block&);
- inline void create_data()
- {
- destruct = true;
- data = new T[size];
- std::fill_n(data,size,T(0));
- dump_ptr("control_block::create_data() - data",data,size);
- }
- };
- public:
- vec_data_store()
- : control_block_(control_block::create(0))
- {}
- vec_data_store(const std::size_t& size)
- : control_block_(control_block::create(size,(data_t)(0),true))
- {}
- vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
- : control_block_(control_block::create(size, data, dstrct))
- {}
- vec_data_store(const type& vds)
- {
- control_block_ = vds.control_block_;
- control_block_->ref_count++;
- }
- ~vec_data_store()
- {
- control_block::destroy(control_block_);
- }
- type& operator=(const type& vds)
- {
- if (this != &vds)
- {
- std::size_t final_size = min_size(control_block_, vds.control_block_);
- vds.control_block_->size = final_size;
- control_block_->size = final_size;
- if (control_block_->destruct || (0 == control_block_->data))
- {
- control_block::destroy(control_block_);
- control_block_ = vds.control_block_;
- control_block_->ref_count++;
- }
- }
- return (*this);
- }
- inline data_t data()
- {
- return control_block_->data;
- }
- inline data_t data() const
- {
- return control_block_->data;
- }
- inline std::size_t size()
- {
- return control_block_->size;
- }
- inline std::size_t size() const
- {
- return control_block_->size;
- }
- inline data_t& ref()
- {
- return control_block_->data;
- }
- inline void dump() const
- {
- #ifdef exprtk_enable_debugging
- exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
- size(),
- data(),
- (control_block_->destruct ? 'T' : 'F')));
- for (std::size_t i = 0; i < size(); ++i)
- {
- if (5 == i)
- exprtk_debug(("\n"));
- exprtk_debug(("%15.10f ",data()[i]));
- }
- exprtk_debug(("\n"));
- #endif
- }
- static inline void match_sizes(type& vds0, type& vds1)
- {
- std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
- vds0.control_block_->size = size;
- vds1.control_block_->size = size;
- }
- private:
- static inline std::size_t min_size(control_block* cb0, control_block* cb1)
- {
- const std::size_t size0 = cb0->size;
- const std::size_t size1 = cb1->size;
- if (size0 && size1)
- return std::min(size0,size1);
- else
- return (size0) ? size0 : size1;
- }
- control_block* control_block_;
- };
- namespace numeric
- {
- namespace details
- {
- template <typename T>
- inline T process_impl(const operator_type operation, const T arg)
- {
- switch (operation)
- {
- case e_abs : return numeric::abs (arg);
- case e_acos : return numeric::acos (arg);
- case e_acosh : return numeric::acosh(arg);
- case e_asin : return numeric::asin (arg);
- case e_asinh : return numeric::asinh(arg);
- case e_atan : return numeric::atan (arg);
- case e_atanh : return numeric::atanh(arg);
- case e_ceil : return numeric::ceil (arg);
- case e_cos : return numeric::cos (arg);
- case e_cosh : return numeric::cosh (arg);
- case e_exp : return numeric::exp (arg);
- case e_expm1 : return numeric::expm1(arg);
- case e_floor : return numeric::floor(arg);
- case e_log : return numeric::log (arg);
- case e_log10 : return numeric::log10(arg);
- case e_log2 : return numeric::log2 (arg);
- case e_log1p : return numeric::log1p(arg);
- case e_neg : return numeric::neg (arg);
- case e_pos : return numeric::pos (arg);
- case e_round : return numeric::round(arg);
- case e_sin : return numeric::sin (arg);
- case e_sinc : return numeric::sinc (arg);
- case e_sinh : return numeric::sinh (arg);
- case e_sqrt : return numeric::sqrt (arg);
- case e_tan : return numeric::tan (arg);
- case e_tanh : return numeric::tanh (arg);
- case e_cot : return numeric::cot (arg);
- case e_sec : return numeric::sec (arg);
- case e_csc : return numeric::csc (arg);
- case e_r2d : return numeric::r2d (arg);
- case e_d2r : return numeric::d2r (arg);
- case e_d2g : return numeric::d2g (arg);
- case e_g2d : return numeric::g2d (arg);
- case e_notl : return numeric::notl (arg);
- case e_sgn : return numeric::sgn (arg);
- case e_erf : return numeric::erf (arg);
- case e_erfc : return numeric::erfc (arg);
- case e_ncdf : return numeric::ncdf (arg);
- case e_frac : return numeric::frac (arg);
- case e_trunc : return numeric::trunc(arg);
- default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
- return std::numeric_limits<T>::quiet_NaN();
- }
- }
- template <typename T>
- inline T process_impl(const operator_type operation, const T arg0, const T arg1)
- {
- switch (operation)
- {
- case e_add : return (arg0 + arg1);
- case e_sub : return (arg0 - arg1);
- case e_mul : return (arg0 * arg1);
- case e_div : return (arg0 / arg1);
- case e_mod : return modulus<T>(arg0,arg1);
- case e_pow : return pow<T>(arg0,arg1);
- case e_atan2 : return atan2<T>(arg0,arg1);
- case e_min : return std::min<T>(arg0,arg1);
- case e_max : return std::max<T>(arg0,arg1);
- case e_logn : return logn<T>(arg0,arg1);
- case e_lt : return (arg0 < arg1) ? T(1) : T(0);
- case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
- case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
- case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
- case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
- case e_gt : return (arg0 > arg1) ? T(1) : T(0);
- case e_and : return and_opr <T>(arg0,arg1);
- case e_nand : return nand_opr<T>(arg0,arg1);
- case e_or : return or_opr <T>(arg0,arg1);
- case e_nor : return nor_opr <T>(arg0,arg1);
- case e_xor : return xor_opr <T>(arg0,arg1);
- case e_xnor : return xnor_opr<T>(arg0,arg1);
- case e_root : return root <T>(arg0,arg1);
- case e_roundn : return roundn <T>(arg0,arg1);
- case e_equal : return equal (arg0,arg1);
- case e_nequal : return nequal (arg0,arg1);
- case e_hypot : return hypot <T>(arg0,arg1);
- case e_shr : return shr <T>(arg0,arg1);
- case e_shl : return shl <T>(arg0,arg1);
- default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
- return std::numeric_limits<T>::quiet_NaN();
- }
- }
- template <typename T>
- inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
- {
- switch (operation)
- {
- case e_add : return (arg0 + arg1);
- case e_sub : return (arg0 - arg1);
- case e_mul : return (arg0 * arg1);
- case e_div : return (arg0 / arg1);
- case e_mod : return arg0 % arg1;
- case e_pow : return pow<T>(arg0,arg1);
- case e_min : return std::min<T>(arg0,arg1);
- case e_max : return std::max<T>(arg0,arg1);
- case e_logn : return logn<T>(arg0,arg1);
- case e_lt : return (arg0 < arg1) ? T(1) : T(0);
- case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
- case e_eq : return (arg0 == arg1) ? T(1) : T(0);
- case e_ne : return (arg0 != arg1) ? T(1) : T(0);
- case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
- case e_gt : return (arg0 > arg1) ? T(1) : T(0);
- case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
- case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
- case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
- case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
- case e_xor : return arg0 ^ arg1;
- case e_xnor : return !(arg0 ^ arg1);
- case e_root : return root<T>(arg0,arg1);
- case e_equal : return arg0 == arg1;
- case e_nequal : return arg0 != arg1;
- case e_hypot : return hypot<T>(arg0,arg1);
- case e_shr : return arg0 >> arg1;
- case e_shl : return arg0 << arg1;
- default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
- return std::numeric_limits<T>::quiet_NaN();
- }
- }
- }
- template <typename T>
- inline T process(const operator_type operation, const T arg)
- {
- return exprtk::details::numeric::details::process_impl(operation,arg);
- }
- template <typename T>
- inline T process(const operator_type operation, const T arg0, const T arg1)
- {
- return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
- }
- }
- template <typename T>
- class expression_node
- {
- public:
- enum node_type
- {
- e_none , e_null , e_constant , e_unary ,
- e_binary , e_binary_ext , e_trinary , e_quaternary ,
- e_vararg , e_conditional , e_while , e_repeat ,
- e_for , e_switch , e_mswitch , e_return ,
- e_retenv , e_variable , e_stringvar , e_stringconst ,
- e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat ,
- e_stringvarsize , e_strswap , e_stringsize , e_stringvararg ,
- e_function , e_vafunction , e_genfunction , e_strfunction ,
- e_strcondition , e_strccondition , e_add , e_sub ,
- e_mul , e_div , e_mod , e_pow ,
- e_lt , e_lte , e_gt , e_gte ,
- e_eq , e_ne , e_and , e_nand ,
- e_or , e_nor , e_xor , e_xnor ,
- e_in , e_like , e_ilike , e_inranges ,
- e_ipow , e_ipowinv , e_abs , e_acos ,
- e_acosh , e_asin , e_asinh , e_atan ,
- e_atanh , e_ceil , e_cos , e_cosh ,
- e_exp , e_expm1 , e_floor , e_log ,
- e_log10 , e_log2 , e_log1p , e_neg ,
- e_pos , e_round , e_sin , e_sinc ,
- e_sinh , e_sqrt , e_tan , e_tanh ,
- e_cot , e_sec , e_csc , e_r2d ,
- e_d2r , e_d2g , e_g2d , e_notl ,
- e_sgn , e_erf , e_erfc , e_ncdf ,
- e_frac , e_trunc , e_uvouv , e_vov ,
- e_cov , e_voc , e_vob , e_bov ,
- e_cob , e_boc , e_vovov , e_vovoc ,
- e_vocov , e_covov , e_covoc , e_vovovov ,
- e_vovovoc , e_vovocov , e_vocovov , e_covovov ,
- e_covocov , e_vocovoc , e_covovoc , e_vococov ,
- e_sf3ext , e_sf4ext , e_nulleq , e_strass ,
- e_vector , e_vecelem , e_rbvecelem , e_rbveccelem ,
- e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass ,
- e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq ,
- e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith ,
- e_valvecarith , e_vecunaryop , e_break , e_continue ,
- e_swap
- };
- typedef T value_type;
- typedef expression_node<T>* expression_ptr;
- virtual ~expression_node()
- {}
- inline virtual T value() const
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
- {
- return reinterpret_cast<expression_ptr>(index * 0);
- }
- inline virtual node_type type() const
- {
- return e_none;
- }
- };
- template <typename T>
- inline bool is_generally_string_node(const expression_node<T>* node);
- inline bool is_true(const double v)
- {
- return std::not_equal_to<double>()(0.0,v);
- }
- inline bool is_true(const long double v)
- {
- return std::not_equal_to<long double>()(0.0L,v);
- }
- inline bool is_true(const float v)
- {
- return std::not_equal_to<float>()(0.0f,v);
- }
- template <typename T>
- inline bool is_true(const std::complex<T>& v)
- {
- return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
- }
- template <typename T>
- inline bool is_true(const expression_node<T>* node)
- {
- return std::not_equal_to<T>()(T(0),node->value());
- }
- template <typename T>
- inline bool is_false(const expression_node<T>* node)
- {
- return std::equal_to<T>()(T(0),node->value());
- }
- template <typename T>
- inline bool is_unary_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_unary == node->type());
- }
- template <typename T>
- inline bool is_neg_unary_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_neg == node->type());
- }
- template <typename T>
- inline bool is_binary_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_binary == node->type());
- }
- template <typename T>
- inline bool is_variable_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_variable == node->type());
- }
- template <typename T>
- inline bool is_ivariable_node(const expression_node<T>* node)
- {
- return node &&
- (
- details::expression_node<T>::e_variable == node->type() ||
- details::expression_node<T>::e_vecelem == node->type() ||
- details::expression_node<T>::e_rbvecelem == node->type() ||
- details::expression_node<T>::e_rbveccelem == node->type()
- );
- }
- template <typename T>
- inline bool is_vector_elem_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_vecelem == node->type());
- }
- template <typename T>
- inline bool is_rebasevector_elem_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_rbvecelem == node->type());
- }
- template <typename T>
- inline bool is_rebasevector_celem_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_rbveccelem == node->type());
- }
- template <typename T>
- inline bool is_vector_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_vector == node->type());
- }
- template <typename T>
- inline bool is_ivector_node(const expression_node<T>* node)
- {
- if (node)
- {
- switch (node->type())
- {
- case details::expression_node<T>::e_vector :
- case details::expression_node<T>::e_vecvalass :
- case details::expression_node<T>::e_vecvecass :
- case details::expression_node<T>::e_vecopvalass :
- case details::expression_node<T>::e_vecopvecass :
- case details::expression_node<T>::e_vecvecswap :
- case details::expression_node<T>::e_vecvecarith :
- case details::expression_node<T>::e_vecvalarith :
- case details::expression_node<T>::e_valvecarith :
- case details::expression_node<T>::e_vecunaryop : return true;
- default : return false;
- }
- }
- else
- return false;
- }
- template <typename T>
- inline bool is_constant_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_constant == node->type());
- }
- template <typename T>
- inline bool is_null_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_null == node->type());
- }
- template <typename T>
- inline bool is_break_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_break == node->type());
- }
- template <typename T>
- inline bool is_continue_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_continue == node->type());
- }
- template <typename T>
- inline bool is_swap_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_swap == node->type());
- }
- template <typename T>
- inline bool is_function(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_function == node->type());
- }
- template <typename T>
- inline bool is_return_node(const expression_node<T>* node)
- {
- return node && (details::expression_node<T>::e_return == node->type());
- }
- template <typename T> class unary_node;
- template <typename T>
- inline bool is_negate_node(const expression_node<T>* node)
- {
- if (node && is_unary_node(node))
- {
- return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
- }
- else
- return false;
- }
- template <typename T>
- inline bool branch_deletable(expression_node<T>* node)
- {
- return !is_variable_node(node) &&
- !is_string_node (node) ;
- }
- template <std::size_t N, typename T>
- inline bool all_nodes_valid(expression_node<T>* (&b)[N])
- {
- for (std::size_t i = 0; i < N; ++i)
- {
- if (0 == b[i]) return false;
- }
- return true;
- }
- template <typename T,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
- {
- for (std::size_t i = 0; i < b.size(); ++i)
- {
- if (0 == b[i]) return false;
- }
- return true;
- }
- template <std::size_t N, typename T>
- inline bool all_nodes_variables(expression_node<T>* (&b)[N])
- {
- for (std::size_t i = 0; i < N; ++i)
- {
- if (0 == b[i])
- return false;
- else if (!is_variable_node(b[i]))
- return false;
- }
- return true;
- }
- template <typename T,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
- {
- for (std::size_t i = 0; i < b.size(); ++i)
- {
- if (0 == b[i])
- return false;
- else if (!is_variable_node(b[i]))
- return false;
- }
- return true;
- }
- template <typename NodeAllocator, typename T, std::size_t N>
- inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
- {
- for (std::size_t i = 0; i < N; ++i)
- {
- free_node(node_allocator,b[i]);
- }
- }
- template <typename NodeAllocator,
- typename T,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
- {
- for (std::size_t i = 0; i < b.size(); ++i)
- {
- free_node(node_allocator,b[i]);
- }
- b.clear();
- }
- template <typename NodeAllocator, typename T>
- inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
- {
- if (0 != node)
- {
- if (
- (is_variable_node(node) || is_string_node(node)) ||
- force_delete
- )
- return;
- node_allocator.free(node);
- node = reinterpret_cast<expression_node<T>*>(0);
- }
- }
- template <typename T>
- inline void destroy_node(expression_node<T>*& node)
- {
- delete node;
- node = reinterpret_cast<expression_node<T>*>(0);
- }
- template <typename Type>
- class vector_holder
- {
- private:
- typedef Type value_type;
- typedef value_type* value_ptr;
- typedef const value_ptr const_value_ptr;
- class vector_holder_base
- {
- public:
- virtual ~vector_holder_base() {}
- inline value_ptr operator[](const std::size_t& index) const
- {
- return value_at(index);
- }
- inline std::size_t size() const
- {
- return vector_size();
- }
- inline value_ptr data() const
- {
- return value_at(0);
- }
- virtual inline bool rebaseable() const
- {
- return false;
- }
- virtual void set_ref(value_ptr*) {}
- protected:
- virtual value_ptr value_at(const std::size_t&) const = 0;
- virtual std::size_t vector_size() const = 0;
- };
- class array_vector_impl : public vector_holder_base
- {
- public:
- array_vector_impl(const Type* vec, const std::size_t& vec_size)
- : vec_(vec),
- size_(vec_size)
- {}
- protected:
- value_ptr value_at(const std::size_t& index) const
- {
- if (index < size_)
- return const_cast<const_value_ptr>(vec_ + index);
- else
- return const_value_ptr(0);
- }
- std::size_t vector_size() const
- {
- return size_;
- }
- private:
- array_vector_impl operator=(const array_vector_impl&);
- const Type* vec_;
- const std::size_t size_;
- };
- template <typename Allocator,
- template <typename, typename> class Sequence>
- class sequence_vector_impl : public vector_holder_base
- {
- public:
- typedef Sequence<Type,Allocator> sequence_t;
- sequence_vector_impl(sequence_t& seq)
- : sequence_(seq)
- {}
- protected:
- value_ptr value_at(const std::size_t& index) const
- {
- return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
- }
- std::size_t vector_size() const
- {
- return sequence_.size();
- }
- private:
- sequence_vector_impl operator=(const sequence_vector_impl&);
- sequence_t& sequence_;
- };
- class vector_view_impl : public vector_holder_base
- {
- public:
- typedef exprtk::vector_view<Type> vector_view_t;
- vector_view_impl(vector_view_t& vec_view)
- : vec_view_(vec_view)
- {}
- void set_ref(value_ptr* ref)
- {
- vec_view_.set_ref(ref);
- }
- virtual inline bool rebaseable() const
- {
- return true;
- }
- protected:
- value_ptr value_at(const std::size_t& index) const
- {
- return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
- }
- std::size_t vector_size() const
- {
- return vec_view_.size();
- }
- private:
- vector_view_impl operator=(const vector_view_impl&);
- vector_view_t& vec_view_;
- };
- public:
- typedef typename details::vec_data_store<Type> vds_t;
- vector_holder(Type* vec, const std::size_t& vec_size)
- : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
- {}
- vector_holder(const vds_t& vds)
- : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
- {}
- template <typename Allocator>
- vector_holder(std::vector<Type,Allocator>& vec)
- : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
- {}
- vector_holder(exprtk::vector_view<Type>& vec)
- : vector_holder_base_(new(buffer)vector_view_impl(vec))
- {}
- inline value_ptr operator[](const std::size_t& index) const
- {
- return (*vector_holder_base_)[index];
- }
- inline std::size_t size() const
- {
- return vector_holder_base_->size();
- }
- inline value_ptr data() const
- {
- return vector_holder_base_->data();
- }
- void set_ref(value_ptr* ref)
- {
- vector_holder_base_->set_ref(ref);
- }
- bool rebaseable() const
- {
- return vector_holder_base_->rebaseable();
- }
- private:
- mutable vector_holder_base* vector_holder_base_;
- uchar_t buffer[64];
- };
- template <typename T>
- class null_node : public expression_node<T>
- {
- public:
- inline T value() const
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_null;
- }
- };
- template <typename T>
- class null_eq_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- null_eq_node(expression_ptr brnch, const bool equality = true)
- : branch_(brnch),
- branch_deletable_(branch_deletable(branch_)),
- equality_(equality)
- {}
- ~null_eq_node()
- {
- if (branch_ && branch_deletable_)
- {
- destroy_node(branch_);
- }
- }
- inline T value() const
- {
- const T v = branch_->value();
- const bool result = details::numeric::is_nan(v);
- if (result)
- return (equality_) ? T(1) : T(0);
- else
- return (equality_) ? T(0) : T(1);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_nulleq;
- }
- inline operator_type operation() const
- {
- return details::e_eq;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_;
- }
- private:
- expression_ptr branch_;
- const bool branch_deletable_;
- bool equality_;
- };
- template <typename T>
- class literal_node : public expression_node<T>
- {
- public:
- explicit literal_node(const T& v)
- : value_(v)
- {}
- inline T value() const
- {
- return value_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_constant;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return reinterpret_cast<expression_node<T>*>(0);
- }
- private:
- literal_node(literal_node<T>&) {}
- literal_node<T>& operator=(literal_node<T>&) { return (*this); }
- const T value_;
- };
- template <typename T>
- struct range_pack;
- template <typename T>
- struct range_data_type;
- template <typename T>
- class range_interface
- {
- public:
- typedef range_pack<T> range_t;
- virtual ~range_interface()
- {}
- virtual range_t& range_ref() = 0;
- virtual const range_t& range_ref() const = 0;
- };
- #ifndef exprtk_disable_string_capabilities
- template <typename T>
- class string_base_node
- {
- public:
- typedef range_data_type<T> range_data_type_t;
- virtual ~string_base_node()
- {}
- virtual std::string str () const = 0;
- virtual char_cptr base() const = 0;
- virtual std::size_t size() const = 0;
- };
- template <typename T>
- class string_literal_node : public expression_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef range_pack<T> range_t;
- explicit string_literal_node(const std::string& v)
- : value_(v)
- {
- rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
- rp_.cache.first = rp_.n0_c.second;
- rp_.cache.second = rp_.n1_c.second;
- }
- inline T value() const
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_stringconst;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return reinterpret_cast<expression_node<T>*>(0);
- }
- std::string str() const
- {
- return value_;
- }
- char_cptr base() const
- {
- return value_.data();
- }
- std::size_t size() const
- {
- return value_.size();
- }
- range_t& range_ref()
- {
- return rp_;
- }
- const range_t& range_ref() const
- {
- return rp_;
- }
- private:
- string_literal_node(const string_literal_node<T>&);
- string_literal_node<T>& operator=(const string_literal_node<T>&);
- const std::string value_;
- range_t rp_;
- };
- #endif
- template <typename T>
- class unary_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- unary_node(const operator_type& opr,
- expression_ptr brnch)
- : operation_(opr),
- branch_(brnch),
- branch_deletable_(branch_deletable(branch_))
- {}
- ~unary_node()
- {
- if (branch_ && branch_deletable_)
- {
- destroy_node(branch_);
- }
- }
- inline T value() const
- {
- const T arg = branch_->value();
- return numeric::process<T>(operation_,arg);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_unary;
- }
- inline operator_type operation() const
- {
- return operation_;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_;
- }
- inline void release()
- {
- branch_deletable_ = false;
- }
- protected:
- operator_type operation_;
- expression_ptr branch_;
- bool branch_deletable_;
- };
- template <typename T, std::size_t D, bool B>
- struct construct_branch_pair
- {
- template <std::size_t N>
- static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
- {}
- };
- template <typename T, std::size_t D>
- struct construct_branch_pair<T,D,true>
- {
- template <std::size_t N>
- static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
- {
- if (b)
- {
- branch[D] = std::make_pair(b,branch_deletable(b));
- }
- }
- };
- template <std::size_t N, typename T>
- inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
- expression_node<T>* b0,
- expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
- expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
- {
- construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
- construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
- construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
- construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
- construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
- construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
- construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
- construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
- construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
- construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
- }
- struct cleanup_branches
- {
- template <typename T, std::size_t N>
- static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
- {
- for (std::size_t i = 0; i < N; ++i)
- {
- if (branch[i].first && branch[i].second)
- {
- destroy_node(branch[i].first);
- }
- }
- }
- template <typename T,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
- {
- for (std::size_t i = 0; i < branch.size(); ++i)
- {
- if (branch[i].first && branch[i].second)
- {
- destroy_node(branch[i].first);
- }
- }
- }
- };
- template <typename T>
- class binary_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- binary_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : operation_(opr)
- {
- init_branches<2>(branch_, branch0, branch1);
- }
- ~binary_node()
- {
- cleanup_branches::execute<T,2>(branch_);
- }
- inline T value() const
- {
- const T arg0 = branch_[0].first->value();
- const T arg1 = branch_[1].first->value();
- return numeric::process<T>(operation_,arg0,arg1);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_binary;
- }
- inline operator_type operation()
- {
- return operation_;
- }
- inline expression_node<T>* branch(const std::size_t& index = 0) const
- {
- if (0 == index)
- return branch_[0].first;
- else if (1 == index)
- return branch_[1].first;
- else
- return reinterpret_cast<expression_ptr>(0);
- }
- protected:
- operator_type operation_;
- branch_t branch_[2];
- };
- template <typename T, typename Operation>
- class binary_ext_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- binary_ext_node(expression_ptr branch0, expression_ptr branch1)
- {
- init_branches<2>(branch_, branch0, branch1);
- }
- ~binary_ext_node()
- {
- cleanup_branches::execute<T,2>(branch_);
- }
- inline T value() const
- {
- const T arg0 = branch_[0].first->value();
- const T arg1 = branch_[1].first->value();
- return Operation::process(arg0,arg1);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_binary_ext;
- }
- inline operator_type operation()
- {
- return Operation::operation();
- }
- inline expression_node<T>* branch(const std::size_t& index = 0) const
- {
- if (0 == index)
- return branch_[0].first;
- else if (1 == index)
- return branch_[1].first;
- else
- return reinterpret_cast<expression_ptr>(0);
- }
- protected:
- branch_t branch_[2];
- };
- template <typename T>
- class trinary_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- trinary_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1,
- expression_ptr branch2)
- : operation_(opr)
- {
- init_branches<3>(branch_, branch0, branch1, branch2);
- }
- ~trinary_node()
- {
- cleanup_branches::execute<T,3>(branch_);
- }
- inline T value() const
- {
- const T arg0 = branch_[0].first->value();
- const T arg1 = branch_[1].first->value();
- const T arg2 = branch_[2].first->value();
- switch (operation_)
- {
- case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
- case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
- case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
- return arg1;
- else
- return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
- default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
- return std::numeric_limits<T>::quiet_NaN();
- }
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_trinary;
- }
- protected:
- operator_type operation_;
- branch_t branch_[3];
- };
- template <typename T>
- class quaternary_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- quaternary_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1,
- expression_ptr branch2,
- expression_ptr branch3)
- : operation_(opr)
- {
- init_branches<4>(branch_, branch0, branch1, branch2, branch3);
- }
- ~quaternary_node()
- {
- cleanup_branches::execute<T,4>(branch_);
- }
- inline T value() const
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_quaternary;
- }
- protected:
- operator_type operation_;
- branch_t branch_[4];
- };
- template <typename T>
- class conditional_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- conditional_node(expression_ptr test,
- expression_ptr consequent,
- expression_ptr alternative)
- : test_(test),
- consequent_(consequent),
- alternative_(alternative),
- test_deletable_(branch_deletable(test_)),
- consequent_deletable_(branch_deletable(consequent_)),
- alternative_deletable_(branch_deletable(alternative_))
- {}
- ~conditional_node()
- {
- if (test_ && test_deletable_)
- {
- destroy_node(test_);
- }
- if (consequent_ && consequent_deletable_ )
- {
- destroy_node(consequent_);
- }
- if (alternative_ && alternative_deletable_)
- {
- destroy_node(alternative_);
- }
- }
- inline T value() const
- {
- if (is_true(test_))
- return consequent_->value();
- else
- return alternative_->value();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_conditional;
- }
- private:
- expression_ptr test_;
- expression_ptr consequent_;
- expression_ptr alternative_;
- const bool test_deletable_;
- const bool consequent_deletable_;
- const bool alternative_deletable_;
- };
- template <typename T>
- class cons_conditional_node : public expression_node<T>
- {
- public:
- // Consequent only conditional statement node
- typedef expression_node<T>* expression_ptr;
- cons_conditional_node(expression_ptr test,
- expression_ptr consequent)
- : test_(test),
- consequent_(consequent),
- test_deletable_(branch_deletable(test_)),
- consequent_deletable_(branch_deletable(consequent_))
- {}
- ~cons_conditional_node()
- {
- if (test_ && test_deletable_)
- {
- destroy_node(test_);
- }
- if (consequent_ && consequent_deletable_)
- {
- destroy_node(consequent_);
- }
- }
- inline T value() const
- {
- if (is_true(test_))
- return consequent_->value();
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_conditional;
- }
- private:
- expression_ptr test_;
- expression_ptr consequent_;
- const bool test_deletable_;
- const bool consequent_deletable_;
- };
- #ifndef exprtk_disable_break_continue
- template <typename T>
- class break_exception
- {
- public:
- break_exception(const T& v)
- : value(v)
- {}
- T value;
- };
- class continue_exception
- {};
- template <typename T>
- class break_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- break_node(expression_ptr ret = expression_ptr(0))
- : return_(ret),
- return_deletable_(branch_deletable(return_))
- {}
- ~break_node()
- {
- if (return_deletable_)
- {
- destroy_node(return_);
- }
- }
- inline T value() const
- {
- throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
- #ifndef _MSC_VER
- return std::numeric_limits<T>::quiet_NaN();
- #endif
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_break;
- }
- private:
- expression_ptr return_;
- const bool return_deletable_;
- };
- template <typename T>
- class continue_node : public expression_node<T>
- {
- public:
- inline T value() const
- {
- throw continue_exception();
- #ifndef _MSC_VER
- return std::numeric_limits<T>::quiet_NaN();
- #endif
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_break;
- }
- };
- #endif
- template <typename T>
- class while_loop_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- while_loop_node(expression_ptr condition, expression_ptr loop_body)
- : condition_(condition),
- loop_body_(loop_body),
- condition_deletable_(branch_deletable(condition_)),
- loop_body_deletable_(branch_deletable(loop_body_))
- {}
- ~while_loop_node()
- {
- if (condition_ && condition_deletable_)
- {
- destroy_node(condition_);
- }
- if (loop_body_ && loop_body_deletable_)
- {
- destroy_node(loop_body_);
- }
- }
- inline T value() const
- {
- T result = T(0);
- while (is_true(condition_))
- {
- result = loop_body_->value();
- }
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_while;
- }
- private:
- expression_ptr condition_;
- expression_ptr loop_body_;
- const bool condition_deletable_;
- const bool loop_body_deletable_;
- };
- template <typename T>
- class repeat_until_loop_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
- : condition_(condition),
- loop_body_(loop_body),
- condition_deletable_(branch_deletable(condition_)),
- loop_body_deletable_(branch_deletable(loop_body_))
- {}
- ~repeat_until_loop_node()
- {
- if (condition_ && condition_deletable_)
- {
- destroy_node(condition_);
- }
- if (loop_body_ && loop_body_deletable_)
- {
- destroy_node(loop_body_);
- }
- }
- inline T value() const
- {
- T result = T(0);
- do
- {
- result = loop_body_->value();
- }
- while (is_false(condition_));
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_repeat;
- }
- private:
- expression_ptr condition_;
- expression_ptr loop_body_;
- const bool condition_deletable_;
- const bool loop_body_deletable_;
- };
- template <typename T>
- class for_loop_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- for_loop_node(expression_ptr initialiser,
- expression_ptr condition,
- expression_ptr incrementor,
- expression_ptr loop_body)
- : initialiser_(initialiser),
- condition_ (condition ),
- incrementor_(incrementor),
- loop_body_ (loop_body ),
- initialiser_deletable_(branch_deletable(initialiser_)),
- condition_deletable_ (branch_deletable(condition_ )),
- incrementor_deletable_(branch_deletable(incrementor_)),
- loop_body_deletable_ (branch_deletable(loop_body_ ))
- {}
- ~for_loop_node()
- {
- if (initialiser_ && initialiser_deletable_)
- {
- destroy_node(initialiser_);
- }
- if (condition_ && condition_deletable_)
- {
- destroy_node(condition_);
- }
- if (incrementor_ && incrementor_deletable_)
- {
- destroy_node(incrementor_);
- }
- if (loop_body_ && loop_body_deletable_)
- {
- destroy_node(loop_body_);
- }
- }
- inline T value() const
- {
- T result = T(0);
- if (initialiser_)
- initialiser_->value();
- if (incrementor_)
- {
- while (is_true(condition_))
- {
- result = loop_body_->value();
- incrementor_->value();
- }
- }
- else
- {
- while (is_true(condition_))
- {
- result = loop_body_->value();
- }
- }
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_for;
- }
- private:
- expression_ptr initialiser_ ;
- expression_ptr condition_ ;
- expression_ptr incrementor_ ;
- expression_ptr loop_body_ ;
- const bool initialiser_deletable_;
- const bool condition_deletable_ ;
- const bool incrementor_deletable_;
- const bool loop_body_deletable_ ;
- };
- #ifndef exprtk_disable_break_continue
- template <typename T>
- class while_loop_bc_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
- : condition_(condition),
- loop_body_(loop_body),
- condition_deletable_(branch_deletable(condition_)),
- loop_body_deletable_(branch_deletable(loop_body_))
- {}
- ~while_loop_bc_node()
- {
- if (condition_ && condition_deletable_)
- {
- destroy_node(condition_);
- }
- if (loop_body_ && loop_body_deletable_)
- {
- destroy_node(loop_body_);
- }
- }
- inline T value() const
- {
- T result = T(0);
- while (is_true(condition_))
- {
- try
- {
- result = loop_body_->value();
- }
- catch(const break_exception<T>& e)
- {
- return e.value;
- }
- catch(const continue_exception&)
- {}
- }
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_while;
- }
- private:
- expression_ptr condition_;
- expression_ptr loop_body_;
- const bool condition_deletable_;
- const bool loop_body_deletable_;
- };
- template <typename T>
- class repeat_until_loop_bc_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
- : condition_(condition),
- loop_body_(loop_body),
- condition_deletable_(branch_deletable(condition_)),
- loop_body_deletable_(branch_deletable(loop_body_))
- {}
- ~repeat_until_loop_bc_node()
- {
- if (condition_ && condition_deletable_)
- {
- destroy_node(condition_);
- }
- if (loop_body_ && loop_body_deletable_)
- {
- destroy_node(loop_body_);
- }
- }
- inline T value() const
- {
- T result = T(0);
- do
- {
- try
- {
- result = loop_body_->value();
- }
- catch(const break_exception<T>& e)
- {
- return e.value;
- }
- catch(const continue_exception&)
- {}
- }
- while (is_false(condition_));
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_repeat;
- }
- private:
- expression_ptr condition_;
- expression_ptr loop_body_;
- const bool condition_deletable_;
- const bool loop_body_deletable_;
- };
- template <typename T>
- class for_loop_bc_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- for_loop_bc_node(expression_ptr initialiser,
- expression_ptr condition,
- expression_ptr incrementor,
- expression_ptr loop_body)
- : initialiser_(initialiser),
- condition_ (condition ),
- incrementor_(incrementor),
- loop_body_ (loop_body ),
- initialiser_deletable_(branch_deletable(initialiser_)),
- condition_deletable_ (branch_deletable(condition_ )),
- incrementor_deletable_(branch_deletable(incrementor_)),
- loop_body_deletable_ (branch_deletable(loop_body_ ))
- {}
- ~for_loop_bc_node()
- {
- if (initialiser_ && initialiser_deletable_)
- {
- destroy_node(initialiser_);
- }
- if (condition_ && condition_deletable_)
- {
- destroy_node(condition_);
- }
- if (incrementor_ && incrementor_deletable_)
- {
- destroy_node(incrementor_);
- }
- if (loop_body_ && loop_body_deletable_)
- {
- destroy_node(loop_body_);
- }
- }
- inline T value() const
- {
- T result = T(0);
- if (initialiser_)
- initialiser_->value();
- if (incrementor_)
- {
- while (is_true(condition_))
- {
- try
- {
- result = loop_body_->value();
- }
- catch(const break_exception<T>& e)
- {
- return e.value;
- }
- catch(const continue_exception&)
- {}
- incrementor_->value();
- }
- }
- else
- {
- while (is_true(condition_))
- {
- try
- {
- result = loop_body_->value();
- }
- catch(const break_exception<T>& e)
- {
- return e.value;
- }
- catch(const continue_exception&)
- {}
- }
- }
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_for;
- }
- private:
- expression_ptr initialiser_;
- expression_ptr condition_ ;
- expression_ptr incrementor_;
- expression_ptr loop_body_ ;
- const bool initialiser_deletable_;
- const bool condition_deletable_ ;
- const bool incrementor_deletable_;
- const bool loop_body_deletable_ ;
- };
- #endif
- template <typename T>
- class switch_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- template <typename Allocator,
- template <typename, typename> class Sequence>
- explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
- {
- if (1 != (arg_list.size() & 1))
- return;
- arg_list_.resize(arg_list.size());
- delete_branch_.resize(arg_list.size());
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (arg_list[i])
- {
- arg_list_[i] = arg_list[i];
- delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
- }
- else
- {
- arg_list_.clear();
- delete_branch_.clear();
- return;
- }
- }
- }
- ~switch_node()
- {
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- if (arg_list_[i] && delete_branch_[i])
- {
- destroy_node(arg_list_[i]);
- }
- }
- }
- inline T value() const
- {
- if (!arg_list_.empty())
- {
- const std::size_t upper_bound = (arg_list_.size() - 1);
- for (std::size_t i = 0; i < upper_bound; i += 2)
- {
- expression_ptr condition = arg_list_[i ];
- expression_ptr consequent = arg_list_[i + 1];
- if (is_true(condition))
- {
- return consequent->value();
- }
- }
- return arg_list_[upper_bound]->value();
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_switch;
- }
- protected:
- std::vector<expression_ptr> arg_list_;
- std::vector<unsigned char> delete_branch_;
- };
- template <typename T, typename Switch_N>
- class switch_n_node : public switch_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- template <typename Allocator,
- template <typename, typename> class Sequence>
- explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
- : switch_node<T>(arg_list)
- {}
- inline T value() const
- {
- return Switch_N::process(switch_node<T>::arg_list_);
- }
- };
- template <typename T>
- class multi_switch_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- template <typename Allocator,
- template <typename, typename> class Sequence>
- explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
- {
- if (0 != (arg_list.size() & 1))
- return;
- arg_list_.resize(arg_list.size());
- delete_branch_.resize(arg_list.size());
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (arg_list[i])
- {
- arg_list_[i] = arg_list[i];
- delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
- }
- else
- {
- arg_list_.clear();
- delete_branch_.clear();
- return;
- }
- }
- }
- ~multi_switch_node()
- {
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- if (arg_list_[i] && delete_branch_[i])
- {
- destroy_node(arg_list_[i]);
- }
- }
- }
- inline T value() const
- {
- T result = T(0);
- if (arg_list_.empty())
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- const std::size_t upper_bound = (arg_list_.size() - 1);
- for (std::size_t i = 0; i < upper_bound; i += 2)
- {
- expression_ptr condition = arg_list_[i ];
- expression_ptr consequent = arg_list_[i + 1];
- if (is_true(condition))
- {
- result = consequent->value();
- }
- }
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_mswitch;
- }
- private:
- std::vector<expression_ptr> arg_list_;
- std::vector<unsigned char> delete_branch_;
- };
- template <typename T>
- class ivariable
- {
- public:
- virtual ~ivariable()
- {}
- virtual T& ref() = 0;
- virtual const T& ref() const = 0;
- };
- template <typename T>
- class variable_node : public expression_node<T>,
- public ivariable <T>
- {
- public:
- static T null_value;
- explicit variable_node()
- : value_(&null_value)
- {}
- explicit variable_node(T& v)
- : value_(&v)
- {}
- inline bool operator <(const variable_node<T>& v) const
- {
- return this < (&v);
- }
- inline T value() const
- {
- return (*value_);
- }
- inline T& ref()
- {
- return (*value_);
- }
- inline const T& ref() const
- {
- return (*value_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_variable;
- }
- private:
- T* value_;
- };
- template <typename T>
- T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
- template <typename T>
- struct range_pack
- {
- typedef expression_node<T>* expression_node_ptr;
- typedef std::pair<std::size_t,std::size_t> cached_range_t;
- range_pack()
- : n0_e (std::make_pair(false,expression_node_ptr(0))),
- n1_e (std::make_pair(false,expression_node_ptr(0))),
- n0_c (std::make_pair(false,0)),
- n1_c (std::make_pair(false,0)),
- cache(std::make_pair(0,0))
- {}
- void clear()
- {
- n0_e = std::make_pair(false,expression_node_ptr(0));
- n1_e = std::make_pair(false,expression_node_ptr(0));
- n0_c = std::make_pair(false,0);
- n1_c = std::make_pair(false,0);
- cache = std::make_pair(0,0);
- }
- void free()
- {
- if (n0_e.first && n0_e.second)
- {
- n0_e.first = false;
- if (
- !is_variable_node(n0_e.second) &&
- !is_string_node (n0_e.second)
- )
- {
- destroy_node(n0_e.second);
- }
- }
- if (n1_e.first && n1_e.second)
- {
- n1_e.first = false;
- if (
- !is_variable_node(n1_e.second) &&
- !is_string_node (n1_e.second)
- )
- {
- destroy_node(n1_e.second);
- }
- }
- }
- bool const_range()
- {
- return ( n0_c.first && n1_c.first) &&
- (!n0_e.first && !n1_e.first);
- }
- bool var_range()
- {
- return ( n0_e.first && n1_e.first) &&
- (!n0_c.first && !n1_c.first);
- }
- bool operator() (std::size_t& r0, std::size_t& r1,
- const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
- {
- if (n0_c.first)
- r0 = n0_c.second;
- else if (n0_e.first)
- {
- const T r0_value = n0_e.second->value();
- if (r0_value < 0)
- return false;
- else
- r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
- }
- else
- return false;
- if (n1_c.first)
- r1 = n1_c.second;
- else if (n1_e.first)
- {
- const T r1_value = n1_e.second->value();
- if (r1_value < 0)
- return false;
- else
- r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
- }
- else
- return false;
- if (
- (std::numeric_limits<std::size_t>::max() != size) &&
- (std::numeric_limits<std::size_t>::max() == r1 )
- )
- {
- r1 = size - 1;
- }
- cache.first = r0;
- cache.second = r1;
- return (r0 <= r1);
- }
- inline std::size_t const_size() const
- {
- return (n1_c.second - n0_c.second + 1);
- }
- inline std::size_t cache_size() const
- {
- return (cache.second - cache.first + 1);
- }
- std::pair<bool,expression_node_ptr> n0_e;
- std::pair<bool,expression_node_ptr> n1_e;
- std::pair<bool,std::size_t > n0_c;
- std::pair<bool,std::size_t > n1_c;
- mutable cached_range_t cache;
- };
- template <typename T>
- class string_base_node;
- template <typename T>
- struct range_data_type
- {
- typedef range_pack<T> range_t;
- typedef string_base_node<T>* strbase_ptr_t;
- range_data_type()
- : range(0),
- data (0),
- size (0),
- type_size(0),
- str_node (0)
- {}
- range_t* range;
- void* data;
- std::size_t size;
- std::size_t type_size;
- strbase_ptr_t str_node;
- };
- template <typename T> class vector_node;
- template <typename T>
- class vector_interface
- {
- public:
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- virtual ~vector_interface()
- {}
- virtual std::size_t size () const = 0;
- virtual vector_node_ptr vec() const = 0;
- virtual vector_node_ptr vec() = 0;
- virtual vds_t& vds () = 0;
- virtual const vds_t& vds () const = 0;
- virtual bool side_effect () const { return false; }
- };
- template <typename T>
- class vector_node : public expression_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_holder<T> vector_holder_t;
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- explicit vector_node(vector_holder_t* vh)
- : vector_holder_(vh),
- vds_((*vector_holder_).size(),(*vector_holder_)[0])
- {
- vector_holder_->set_ref(&vds_.ref());
- }
- vector_node(const vds_t& vds, vector_holder_t* vh)
- : vector_holder_(vh),
- vds_(vds)
- {}
- inline T value() const
- {
- return vds().data()[0];
- }
- vector_node_ptr vec() const
- {
- return const_cast<vector_node_ptr>(this);
- }
- vector_node_ptr vec()
- {
- return this;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vector;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- inline vector_holder_t& vec_holder()
- {
- return (*vector_holder_);
- }
- private:
- vector_holder_t* vector_holder_;
- vds_t vds_;
- };
- template <typename T>
- class vector_elem_node : public expression_node<T>,
- public ivariable <T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_holder<T> vector_holder_t;
- typedef vector_holder_t* vector_holder_ptr;
- vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
- : index_(index),
- vec_holder_(vec_holder),
- vector_base_((*vec_holder)[0]),
- index_deletable_(branch_deletable(index_))
- {}
- ~vector_elem_node()
- {
- if (index_ && index_deletable_)
- {
- destroy_node(index_);
- }
- }
- inline T value() const
- {
- return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
- }
- inline T& ref()
- {
- return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
- }
- inline const T& ref() const
- {
- return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecelem;
- }
- inline vector_holder_t& vec_holder()
- {
- return (*vec_holder_);
- }
- private:
- expression_ptr index_;
- vector_holder_ptr vec_holder_;
- T* vector_base_;
- const bool index_deletable_;
- };
- template <typename T>
- class rebasevector_elem_node : public expression_node<T>,
- public ivariable <T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_holder<T> vector_holder_t;
- typedef vector_holder_t* vector_holder_ptr;
- typedef vec_data_store<T> vds_t;
- rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
- : index_(index),
- index_deletable_(branch_deletable(index_)),
- vector_holder_(vec_holder),
- vds_((*vector_holder_).size(),(*vector_holder_)[0])
- {
- vector_holder_->set_ref(&vds_.ref());
- }
- ~rebasevector_elem_node()
- {
- if (index_ && index_deletable_)
- {
- destroy_node(index_);
- }
- }
- inline T value() const
- {
- return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
- }
- inline T& ref()
- {
- return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
- }
- inline const T& ref() const
- {
- return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_rbvecelem;
- }
- inline vector_holder_t& vec_holder()
- {
- return (*vector_holder_);
- }
- private:
- expression_ptr index_;
- const bool index_deletable_;
- vector_holder_ptr vector_holder_;
- vds_t vds_;
- };
- template <typename T>
- class rebasevector_celem_node : public expression_node<T>,
- public ivariable <T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_holder<T> vector_holder_t;
- typedef vector_holder_t* vector_holder_ptr;
- typedef vec_data_store<T> vds_t;
- rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
- : index_(index),
- vector_holder_(vec_holder),
- vds_((*vector_holder_).size(),(*vector_holder_)[0])
- {
- vector_holder_->set_ref(&vds_.ref());
- }
- inline T value() const
- {
- return *(vds_.data() + index_);
- }
- inline T& ref()
- {
- return *(vds_.data() + index_);
- }
- inline const T& ref() const
- {
- return *(vds_.data() + index_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_rbveccelem;
- }
- inline vector_holder_t& vec_holder()
- {
- return (*vector_holder_);
- }
- private:
- const std::size_t index_;
- vector_holder_ptr vector_holder_;
- vds_t vds_;
- };
- template <typename T>
- class vector_assignment_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- vector_assignment_node(T* vector_base,
- const std::size_t& size,
- const std::vector<expression_ptr>& initialiser_list,
- const bool single_value_initialse)
- : vector_base_(vector_base),
- initialiser_list_(initialiser_list),
- size_(size),
- single_value_initialse_(single_value_initialse)
- {}
- ~vector_assignment_node()
- {
- for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
- {
- if (branch_deletable(initialiser_list_[i]))
- {
- destroy_node(initialiser_list_[i]);
- }
- }
- }
- inline T value() const
- {
- if (single_value_initialse_)
- {
- for (std::size_t i = 0; i < size_; ++i)
- {
- *(vector_base_ + i) = initialiser_list_[0]->value();
- }
- }
- else
- {
- std::size_t il_size = initialiser_list_.size();
- for (std::size_t i = 0; i < il_size; ++i)
- {
- *(vector_base_ + i) = initialiser_list_[i]->value();
- }
- if (il_size < size_)
- {
- for (std::size_t i = il_size; i < size_; ++i)
- {
- *(vector_base_ + i) = T(0);
- }
- }
- }
- return *(vector_base_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecdefass;
- }
- private:
- vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
- mutable T* vector_base_;
- std::vector<expression_ptr> initialiser_list_;
- const std::size_t size_;
- const bool single_value_initialse_;
- };
- template <typename T>
- class swap_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef variable_node<T>* variable_node_ptr;
- swap_node(variable_node_ptr var0, variable_node_ptr var1)
- : var0_(var0),
- var1_(var1)
- {}
- inline T value() const
- {
- std::swap(var0_->ref(),var1_->ref());
- return var1_->ref();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_swap;
- }
- private:
- variable_node_ptr var0_;
- variable_node_ptr var1_;
- };
- template <typename T>
- class swap_generic_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef ivariable<T>* ivariable_ptr;
- swap_generic_node(expression_ptr var0, expression_ptr var1)
- : binary_node<T>(details::e_swap, var0, var1),
- var0_(dynamic_cast<ivariable_ptr>(var0)),
- var1_(dynamic_cast<ivariable_ptr>(var1))
- {}
- inline T value() const
- {
- std::swap(var0_->ref(),var1_->ref());
- return var1_->ref();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_swap;
- }
- private:
- ivariable_ptr var0_;
- ivariable_ptr var1_;
- };
- template <typename T>
- class swap_vecvec_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- swap_vecvec_node(expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(details::e_swap, branch0, branch1),
- vec0_node_ptr_(0),
- vec1_node_ptr_(0),
- vec_size_ (0),
- initialised_ (false)
- {
- if (is_ivector_node(binary_node<T>::branch_[0].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
- {
- vec0_node_ptr_ = vi->vec();
- vds() = vi->vds();
- }
- }
- if (is_ivector_node(binary_node<T>::branch_[1].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
- {
- vec1_node_ptr_ = vi->vec();
- }
- }
- if (vec0_node_ptr_ && vec1_node_ptr_)
- {
- vec_size_ = std::min(vec0_node_ptr_->vds().size(),
- vec1_node_ptr_->vds().size());
- initialised_ = true;
- }
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- T* vec0 = vec0_node_ptr_->vds().data();
- T* vec1 = vec1_node_ptr_->vds().data();
- for (std::size_t i = 0; i < vec_size_; ++i)
- {
- std::swap(vec0[i],vec1[i]);
- }
- return vec1_node_ptr_->value();
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return vec0_node_ptr_;
- }
- vector_node_ptr vec()
- {
- return vec0_node_ptr_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecvecswap;
- }
- std::size_t size() const
- {
- return vec_size_;
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node<T>* vec0_node_ptr_;
- vector_node<T>* vec1_node_ptr_;
- std::size_t vec_size_;
- bool initialised_;
- vds_t vds_;
- };
- #ifndef exprtk_disable_string_capabilities
- template <typename T>
- class stringvar_node : public expression_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef range_pack<T> range_t;
- static std::string null_value;
- explicit stringvar_node()
- : value_(&null_value)
- {}
- explicit stringvar_node(std::string& v)
- : value_(&v)
- {
- rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
- rp_.cache.first = rp_.n0_c.second;
- rp_.cache.second = rp_.n1_c.second;
- }
- inline bool operator <(const stringvar_node<T>& v) const
- {
- return this < (&v);
- }
- inline T value() const
- {
- rp_.n1_c.second = (*value_).size() - 1;
- rp_.cache.second = rp_.n1_c.second;
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return ref();
- }
- char_cptr base() const
- {
- return &(*value_)[0];
- }
- std::size_t size() const
- {
- return ref().size();
- }
- std::string& ref()
- {
- return (*value_);
- }
- const std::string& ref() const
- {
- return (*value_);
- }
- range_t& range_ref()
- {
- return rp_;
- }
- const range_t& range_ref() const
- {
- return rp_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_stringvar;
- }
- private:
- std::string* value_;
- mutable range_t rp_;
- };
- template <typename T>
- std::string stringvar_node<T>::null_value = std::string("");
- template <typename T>
- class string_range_node : public expression_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef range_pack<T> range_t;
- static std::string null_value;
- explicit string_range_node(std::string& v, const range_t& rp)
- : value_(&v),
- rp_(rp)
- {}
- virtual ~string_range_node()
- {
- rp_.free();
- }
- inline bool operator <(const string_range_node<T>& v) const
- {
- return this < (&v);
- }
- inline T value() const
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline std::string str() const
- {
- return (*value_);
- }
- char_cptr base() const
- {
- return &(*value_)[0];
- }
- std::size_t size() const
- {
- return ref().size();
- }
- inline range_t range() const
- {
- return rp_;
- }
- inline virtual std::string& ref()
- {
- return (*value_);
- }
- inline virtual const std::string& ref() const
- {
- return (*value_);
- }
- inline range_t& range_ref()
- {
- return rp_;
- }
- inline const range_t& range_ref() const
- {
- return rp_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_stringvarrng;
- }
- private:
- std::string* value_;
- range_t rp_;
- };
- template <typename T>
- std::string string_range_node<T>::null_value = std::string("");
- template <typename T>
- class const_string_range_node : public expression_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef range_pack<T> range_t;
- explicit const_string_range_node(const std::string& v, const range_t& rp)
- : value_(v),
- rp_(rp)
- {}
- ~const_string_range_node()
- {
- rp_.free();
- }
- inline T value() const
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return value_;
- }
- char_cptr base() const
- {
- return value_.data();
- }
- std::size_t size() const
- {
- return value_.size();
- }
- range_t range() const
- {
- return rp_;
- }
- range_t& range_ref()
- {
- return rp_;
- }
- const range_t& range_ref() const
- {
- return rp_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_cstringvarrng;
- }
- private:
- const_string_range_node<T>& operator=(const const_string_range_node<T>&);
- const std::string value_;
- range_t rp_;
- };
- template <typename T>
- class generic_string_range_node : public expression_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef stringvar_node <T>* strvar_node_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- generic_string_range_node(expression_ptr str_branch, const range_t& brange)
- : initialised_(false),
- branch_(str_branch),
- branch_deletable_(branch_deletable(branch_)),
- str_base_ptr_ (0),
- str_range_ptr_(0),
- base_range_(brange)
- {
- range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
- range_.cache.first = range_.n0_c.second;
- range_.cache.second = range_.n1_c.second;
- if (is_generally_string_node(branch_))
- {
- str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
- if (0 == str_base_ptr_)
- return;
- str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
- if (0 == str_range_ptr_)
- return;
- }
- initialised_ = (str_base_ptr_ && str_range_ptr_);
- }
- ~generic_string_range_node()
- {
- base_range_.free();
- if (branch_ && branch_deletable_)
- {
- destroy_node(branch_);
- }
- }
- inline T value() const
- {
- if (initialised_)
- {
- branch_->value();
- std::size_t str_r0 = 0;
- std::size_t str_r1 = 0;
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- range_t& range = str_range_ptr_->range_ref();
- const std::size_t base_str_size = str_base_ptr_->size();
- if (
- range (str_r0, str_r1, base_str_size) &&
- base_range_( r0, r1, base_str_size)
- )
- {
- const std::size_t size = (r1 - r0) + 1;
- range_.n1_c.second = size - 1;
- range_.cache.second = range_.n1_c.second;
- value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return value_;
- }
- char_cptr base() const
- {
- return &value_[0];
- }
- std::size_t size() const
- {
- return value_.size();
- }
- range_t& range_ref()
- {
- return range_;
- }
- const range_t& range_ref() const
- {
- return range_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strgenrange;
- }
- private:
- bool initialised_;
- expression_ptr branch_;
- const bool branch_deletable_;
- str_base_ptr str_base_ptr_;
- irange_ptr str_range_ptr_;
- mutable range_t base_range_;
- mutable range_t range_;
- mutable std::string value_;
- };
- template <typename T>
- class string_concat_node : public binary_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- string_concat_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- initialised_(false),
- str0_base_ptr_ (0),
- str1_base_ptr_ (0),
- str0_range_ptr_(0),
- str1_range_ptr_(0)
- {
- range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
- range_.cache.first = range_.n0_c.second;
- range_.cache.second = range_.n1_c.second;
- if (is_generally_string_node(binary_node<T>::branch_[0].first))
- {
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
- if (0 == str0_base_ptr_)
- return;
- str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
- if (0 == str0_range_ptr_)
- return;
- }
- if (is_generally_string_node(binary_node<T>::branch_[1].first))
- {
- str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
- if (0 == str1_base_ptr_)
- return;
- str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
- if (0 == str1_range_ptr_)
- return;
- }
- initialised_ = str0_base_ptr_ &&
- str1_base_ptr_ &&
- str0_range_ptr_ &&
- str1_range_ptr_ ;
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- std::size_t str0_r0 = 0;
- std::size_t str0_r1 = 0;
- std::size_t str1_r0 = 0;
- std::size_t str1_r1 = 0;
- range_t& range0 = str0_range_ptr_->range_ref();
- range_t& range1 = str1_range_ptr_->range_ref();
- if (
- range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
- range1(str1_r0, str1_r1, str1_base_ptr_->size())
- )
- {
- const std::size_t size0 = (str0_r1 - str0_r0) + 1;
- const std::size_t size1 = (str1_r1 - str1_r0) + 1;
- value_.assign(str0_base_ptr_->base() + str0_r0, size0);
- value_.append(str1_base_ptr_->base() + str1_r0, size1);
- range_.n1_c.second = value_.size() - 1;
- range_.cache.second = range_.n1_c.second;
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return value_;
- }
- char_cptr base() const
- {
- return &value_[0];
- }
- std::size_t size() const
- {
- return value_.size();
- }
- range_t& range_ref()
- {
- return range_;
- }
- const range_t& range_ref() const
- {
- return range_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strconcat;
- }
- private:
- bool initialised_;
- str_base_ptr str0_base_ptr_;
- str_base_ptr str1_base_ptr_;
- irange_ptr str0_range_ptr_;
- irange_ptr str1_range_ptr_;
- mutable range_t range_;
- mutable std::string value_;
- };
- template <typename T>
- class swap_string_node : public binary_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef stringvar_node <T>* strvar_node_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- swap_string_node(expression_ptr branch0, expression_ptr branch1)
- : binary_node<T>(details::e_swap, branch0, branch1),
- initialised_(false),
- str0_node_ptr_(0),
- str1_node_ptr_(0)
- {
- if (is_string_node(binary_node<T>::branch_[0].first))
- {
- str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
- }
- if (is_string_node(binary_node<T>::branch_[1].first))
- {
- str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
- }
- initialised_ = (str0_node_ptr_ && str1_node_ptr_);
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return str0_node_ptr_->str();
- }
- char_cptr base() const
- {
- return str0_node_ptr_->base();
- }
- std::size_t size() const
- {
- return str0_node_ptr_->size();
- }
- range_t& range_ref()
- {
- return str0_node_ptr_->range_ref();
- }
- const range_t& range_ref() const
- {
- return str0_node_ptr_->range_ref();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strswap;
- }
- private:
- bool initialised_;
- strvar_node_ptr str0_node_ptr_;
- strvar_node_ptr str1_node_ptr_;
- };
- template <typename T>
- class swap_genstrings_node : public binary_node<T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- swap_genstrings_node(expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(details::e_default, branch0, branch1),
- str0_base_ptr_ (0),
- str1_base_ptr_ (0),
- str0_range_ptr_(0),
- str1_range_ptr_(0),
- initialised_(false)
- {
- if (is_generally_string_node(binary_node<T>::branch_[0].first))
- {
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
- if (0 == str0_base_ptr_)
- return;
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
- if (0 == range)
- return;
- str0_range_ptr_ = &(range->range_ref());
- }
- if (is_generally_string_node(binary_node<T>::branch_[1].first))
- {
- str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
- if (0 == str1_base_ptr_)
- return;
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
- if (0 == range)
- return;
- str1_range_ptr_ = &(range->range_ref());
- }
- initialised_ = str0_base_ptr_ &&
- str1_base_ptr_ &&
- str0_range_ptr_ &&
- str1_range_ptr_ ;
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- std::size_t str0_r0 = 0;
- std::size_t str0_r1 = 0;
- std::size_t str1_r0 = 0;
- std::size_t str1_r1 = 0;
- range_t& range0 = (*str0_range_ptr_);
- range_t& range1 = (*str1_range_ptr_);
- if (
- range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
- range1(str1_r0, str1_r1, str1_base_ptr_->size())
- )
- {
- const std::size_t size0 = range0.cache_size();
- const std::size_t size1 = range1.cache_size();
- const std::size_t max_size = std::min(size0,size1);
- char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
- char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
- loop_unroll::details lud(max_size);
- char_cptr upper_bound = s0 + lud.upper_bound;
- while (s0 < upper_bound)
- {
- #define exprtk_loop(N) \
- std::swap(s0[N], s1[N]); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- s0 += lud.batch_size;
- s1 += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : { std::swap(s0[i], s1[i]); ++i; } \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strswap;
- }
- private:
- swap_genstrings_node(swap_genstrings_node<T>&);
- swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
- str_base_ptr str0_base_ptr_;
- str_base_ptr str1_base_ptr_;
- range_ptr str0_range_ptr_;
- range_ptr str1_range_ptr_;
- bool initialised_;
- };
- template <typename T>
- class stringvar_size_node : public expression_node<T>
- {
- public:
- static std::string null_value;
- explicit stringvar_size_node()
- : value_(&null_value)
- {}
- explicit stringvar_size_node(std::string& v)
- : value_(&v)
- {}
- inline T value() const
- {
- return T((*value_).size());
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_stringvarsize;
- }
- private:
- std::string* value_;
- };
- template <typename T>
- std::string stringvar_size_node<T>::null_value = std::string("");
- template <typename T>
- class string_size_node : public expression_node<T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- explicit string_size_node(expression_ptr brnch)
- : branch_(brnch),
- branch_deletable_(branch_deletable(branch_)),
- str_base_ptr_(0)
- {
- if (is_generally_string_node(branch_))
- {
- str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
- if (0 == str_base_ptr_)
- return;
- }
- }
- ~string_size_node()
- {
- if (branch_ && branch_deletable_)
- {
- destroy_node(branch_);
- }
- }
- inline T value() const
- {
- T result = std::numeric_limits<T>::quiet_NaN();
- if (str_base_ptr_)
- {
- branch_->value();
- result = T(str_base_ptr_->size());
- }
- return result;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_stringsize;
- }
- private:
- expression_ptr branch_;
- const bool branch_deletable_;
- str_base_ptr str_base_ptr_;
- };
- struct asn_assignment
- {
- static inline void execute(std::string& s, char_cptr data, const std::size_t size)
- { s.assign(data,size); }
- };
- struct asn_addassignment
- {
- static inline void execute(std::string& s, char_cptr data, const std::size_t size)
- { s.append(data,size); }
- };
- template <typename T, typename AssignmentProcess = asn_assignment>
- class assignment_string_node : public binary_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef stringvar_node <T>* strvar_node_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- assignment_string_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- initialised_(false),
- str0_base_ptr_ (0),
- str1_base_ptr_ (0),
- str0_node_ptr_ (0),
- str1_range_ptr_(0)
- {
- if (is_string_node(binary_node<T>::branch_[0].first))
- {
- str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
- }
- if (is_generally_string_node(binary_node<T>::branch_[1].first))
- {
- str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
- if (0 == str1_base_ptr_)
- return;
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
- if (0 == range)
- return;
- str1_range_ptr_ = &(range->range_ref());
- }
- initialised_ = str0_base_ptr_ &&
- str1_base_ptr_ &&
- str0_node_ptr_ &&
- str1_range_ptr_ ;
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[1].first->value();
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- range_t& range = (*str1_range_ptr_);
- if (range(r0, r1, str1_base_ptr_->size()))
- {
- AssignmentProcess::execute(str0_node_ptr_->ref(),
- str1_base_ptr_->base() + r0,
- (r1 - r0) + 1);
- binary_node<T>::branch_[0].first->value();
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return str0_node_ptr_->str();
- }
- char_cptr base() const
- {
- return str0_node_ptr_->base();
- }
- std::size_t size() const
- {
- return str0_node_ptr_->size();
- }
- range_t& range_ref()
- {
- return str0_node_ptr_->range_ref();
- }
- const range_t& range_ref() const
- {
- return str0_node_ptr_->range_ref();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strass;
- }
- private:
- bool initialised_;
- str_base_ptr str0_base_ptr_;
- str_base_ptr str1_base_ptr_;
- strvar_node_ptr str0_node_ptr_;
- range_ptr str1_range_ptr_;
- };
- template <typename T, typename AssignmentProcess = asn_assignment>
- class assignment_string_range_node : public binary_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef stringvar_node <T>* strvar_node_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- assignment_string_range_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- initialised_(false),
- str0_base_ptr_ (0),
- str1_base_ptr_ (0),
- str0_node_ptr_ (0),
- str0_range_ptr_(0),
- str1_range_ptr_(0)
- {
- if (is_string_range_node(binary_node<T>::branch_[0].first))
- {
- str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
- if (0 == range)
- return;
- str0_range_ptr_ = &(range->range_ref());
- }
- if (is_generally_string_node(binary_node<T>::branch_[1].first))
- {
- str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
- if (0 == str1_base_ptr_)
- return;
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
- if (0 == range)
- return;
- str1_range_ptr_ = &(range->range_ref());
- }
- initialised_ = str0_base_ptr_ &&
- str1_base_ptr_ &&
- str0_node_ptr_ &&
- str0_range_ptr_ &&
- str1_range_ptr_ ;
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- std::size_t s0_r0 = 0;
- std::size_t s0_r1 = 0;
- std::size_t s1_r0 = 0;
- std::size_t s1_r1 = 0;
- range_t& range0 = (*str0_range_ptr_);
- range_t& range1 = (*str1_range_ptr_);
- if (
- range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
- range1(s1_r0, s1_r1, str1_base_ptr_->size())
- )
- {
- std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
- std::copy(str1_base_ptr_->base() + s1_r0,
- str1_base_ptr_->base() + s1_r0 + size,
- const_cast<char_ptr>(base() + s0_r0));
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return str0_node_ptr_->str();
- }
- char_cptr base() const
- {
- return str0_node_ptr_->base();
- }
- std::size_t size() const
- {
- return str0_node_ptr_->size();
- }
- range_t& range_ref()
- {
- return str0_node_ptr_->range_ref();
- }
- const range_t& range_ref() const
- {
- return str0_node_ptr_->range_ref();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strass;
- }
- private:
- bool initialised_;
- str_base_ptr str0_base_ptr_;
- str_base_ptr str1_base_ptr_;
- strvar_node_ptr str0_node_ptr_;
- range_ptr str0_range_ptr_;
- range_ptr str1_range_ptr_;
- };
- template <typename T>
- class conditional_string_node : public trinary_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- conditional_string_node(expression_ptr test,
- expression_ptr consequent,
- expression_ptr alternative)
- : trinary_node<T>(details::e_default,consequent,alternative,test),
- initialised_(false),
- str0_base_ptr_ (0),
- str1_base_ptr_ (0),
- str0_range_ptr_(0),
- str1_range_ptr_(0),
- test_ (test),
- consequent_ (consequent),
- alternative_(alternative)
- {
- range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
- range_.cache.first = range_.n0_c.second;
- range_.cache.second = range_.n1_c.second;
- if (is_generally_string_node(trinary_node<T>::branch_[0].first))
- {
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
- if (0 == str0_base_ptr_)
- return;
- str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
- if (0 == str0_range_ptr_)
- return;
- }
- if (is_generally_string_node(trinary_node<T>::branch_[1].first))
- {
- str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
- if (0 == str1_base_ptr_)
- return;
- str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
- if (0 == str1_range_ptr_)
- return;
- }
- initialised_ = str0_base_ptr_ &&
- str1_base_ptr_ &&
- str0_range_ptr_ &&
- str1_range_ptr_ ;
- }
- inline T value() const
- {
- if (initialised_)
- {
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- if (is_true(test_))
- {
- consequent_->value();
- range_t& range = str0_range_ptr_->range_ref();
- if (range(r0, r1, str0_base_ptr_->size()))
- {
- const std::size_t size = (r1 - r0) + 1;
- value_.assign(str0_base_ptr_->base() + r0, size);
- range_.n1_c.second = value_.size() - 1;
- range_.cache.second = range_.n1_c.second;
- return T(1);
- }
- }
- else
- {
- alternative_->value();
- range_t& range = str1_range_ptr_->range_ref();
- if (range(r0, r1, str1_base_ptr_->size()))
- {
- const std::size_t size = (r1 - r0) + 1;
- value_.assign(str1_base_ptr_->base() + r0, size);
- range_.n1_c.second = value_.size() - 1;
- range_.cache.second = range_.n1_c.second;
- return T(0);
- }
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return value_;
- }
- char_cptr base() const
- {
- return &value_[0];
- }
- std::size_t size() const
- {
- return value_.size();
- }
- range_t& range_ref()
- {
- return range_;
- }
- const range_t& range_ref() const
- {
- return range_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strcondition;
- }
- private:
- bool initialised_;
- str_base_ptr str0_base_ptr_;
- str_base_ptr str1_base_ptr_;
- irange_ptr str0_range_ptr_;
- irange_ptr str1_range_ptr_;
- mutable range_t range_;
- mutable std::string value_;
- expression_ptr test_;
- expression_ptr consequent_;
- expression_ptr alternative_;
- };
- template <typename T>
- class cons_conditional_str_node : public binary_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- cons_conditional_str_node(expression_ptr test,
- expression_ptr consequent)
- : binary_node<T>(details::e_default, consequent, test),
- initialised_(false),
- str0_base_ptr_ (0),
- str0_range_ptr_(0),
- test_ (test),
- consequent_(consequent)
- {
- range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
- range_.cache.first = range_.n0_c.second;
- range_.cache.second = range_.n1_c.second;
- if (is_generally_string_node(binary_node<T>::branch_[0].first))
- {
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
- if (0 == str0_base_ptr_)
- return;
- str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
- if (0 == str0_range_ptr_)
- return;
- }
- initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
- }
- inline T value() const
- {
- if (initialised_)
- {
- if (is_true(test_))
- {
- consequent_->value();
- range_t& range = str0_range_ptr_->range_ref();
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- if (range(r0, r1, str0_base_ptr_->size()))
- {
- const std::size_t size = (r1 - r0) + 1;
- value_.assign(str0_base_ptr_->base() + r0, size);
- range_.n1_c.second = value_.size() - 1;
- range_.cache.second = range_.n1_c.second;
- return T(1);
- }
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return value_;
- }
- char_cptr base() const
- {
- return &value_[0];
- }
- std::size_t size() const
- {
- return value_.size();
- }
- range_t& range_ref()
- {
- return range_;
- }
- const range_t& range_ref() const
- {
- return range_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strccondition;
- }
- private:
- bool initialised_;
- str_base_ptr str0_base_ptr_;
- irange_ptr str0_range_ptr_;
- mutable range_t range_;
- mutable std::string value_;
- expression_ptr test_;
- expression_ptr consequent_;
- };
- template <typename T, typename VarArgFunction>
- class str_vararg_node : public expression_node <T>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- template <typename Allocator,
- template <typename, typename> class Sequence>
- explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
- : final_node_(arg_list.back()),
- final_deletable_(branch_deletable(final_node_)),
- initialised_(false),
- str_base_ptr_ (0),
- str_range_ptr_(0)
- {
- if (0 == final_node_)
- return;
- else if (!is_generally_string_node(final_node_))
- return;
- str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);
- if (0 == str_base_ptr_)
- return;
- str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);
- if (0 == str_range_ptr_)
- return;
- initialised_ = str_base_ptr_ && str_range_ptr_;
- if (arg_list.size() > 1)
- {
- const std::size_t arg_list_size = arg_list.size() - 1;
- arg_list_.resize(arg_list_size);
- delete_branch_.resize(arg_list_size);
- for (std::size_t i = 0; i < arg_list_size; ++i)
- {
- if (arg_list[i])
- {
- arg_list_[i] = arg_list[i];
- delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
- }
- else
- {
- arg_list_ .clear();
- delete_branch_.clear();
- return;
- }
- }
- }
- }
- ~str_vararg_node()
- {
- if (final_node_ && final_deletable_)
- {
- destroy_node(final_node_);
- }
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- if (arg_list_[i] && delete_branch_[i])
- {
- destroy_node(arg_list_[i]);
- }
- }
- }
- inline T value() const
- {
- if (!arg_list_.empty())
- {
- VarArgFunction::process(arg_list_);
- }
- final_node_->value();
- return std::numeric_limits<T>::quiet_NaN();
- }
- std::string str() const
- {
- return str_base_ptr_->str();
- }
- char_cptr base() const
- {
- return str_base_ptr_->base();
- }
- std::size_t size() const
- {
- return str_base_ptr_->size();
- }
- range_t& range_ref()
- {
- return str_range_ptr_->range_ref();
- }
- const range_t& range_ref() const
- {
- return str_range_ptr_->range_ref();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_stringvararg;
- }
- private:
- expression_ptr final_node_;
- bool final_deletable_;
- bool initialised_;
- str_base_ptr str_base_ptr_;
- irange_ptr str_range_ptr_;
- std::vector<expression_ptr> arg_list_;
- std::vector<unsigned char> delete_branch_;
- };
- #endif
- template <typename T, std::size_t N>
- inline T axn(T a, T x)
- {
- // a*x^n
- return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
- }
- template <typename T, std::size_t N>
- inline T axnb(T a, T x, T b)
- {
- // a*x^n+b
- return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
- }
- template <typename T>
- struct sf_base
- {
- typedef typename details::functor_t<T>::Type Type;
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::qfunc_t quaternary_functor_t;
- typedef typename functor_t::tfunc_t trinary_functor_t;
- typedef typename functor_t::bfunc_t binary_functor_t;
- typedef typename functor_t::ufunc_t unary_functor_t;
- };
- #define define_sfop3(NN,OP0,OP1) \
- template <typename T> \
- struct sf##NN##_op : public sf_base<T> \
- { \
- typedef typename sf_base<T>::Type const Type; \
- static inline T process(Type x, Type y, Type z) \
- { \
- return (OP0); \
- } \
- static inline std::string id() \
- { \
- return OP1; \
- } \
- }; \
- define_sfop3(00,(x + y) / z ,"(t+t)/t")
- define_sfop3(01,(x + y) * z ,"(t+t)*t")
- define_sfop3(02,(x + y) - z ,"(t+t)-t")
- define_sfop3(03,(x + y) + z ,"(t+t)+t")
- define_sfop3(04,(x - y) + z ,"(t-t)+t")
- define_sfop3(05,(x - y) / z ,"(t-t)/t")
- define_sfop3(06,(x - y) * z ,"(t-t)*t")
- define_sfop3(07,(x * y) + z ,"(t*t)+t")
- define_sfop3(08,(x * y) - z ,"(t*t)-t")
- define_sfop3(09,(x * y) / z ,"(t*t)/t")
- define_sfop3(10,(x * y) * z ,"(t*t)*t")
- define_sfop3(11,(x / y) + z ,"(t/t)+t")
- define_sfop3(12,(x / y) - z ,"(t/t)-t")
- define_sfop3(13,(x / y) / z ,"(t/t)/t")
- define_sfop3(14,(x / y) * z ,"(t/t)*t")
- define_sfop3(15,x / (y + z) ,"t/(t+t)")
- define_sfop3(16,x / (y - z) ,"t/(t-t)")
- define_sfop3(17,x / (y * z) ,"t/(t*t)")
- define_sfop3(18,x / (y / z) ,"t/(t/t)")
- define_sfop3(19,x * (y + z) ,"t*(t+t)")
- define_sfop3(20,x * (y - z) ,"t*(t-t)")
- define_sfop3(21,x * (y * z) ,"t*(t*t)")
- define_sfop3(22,x * (y / z) ,"t*(t/t)")
- define_sfop3(23,x - (y + z) ,"t-(t+t)")
- define_sfop3(24,x - (y - z) ,"t-(t-t)")
- define_sfop3(25,x - (y / z) ,"t-(t/t)")
- define_sfop3(26,x - (y * z) ,"t-(t*t)")
- define_sfop3(27,x + (y * z) ,"t+(t*t)")
- define_sfop3(28,x + (y / z) ,"t+(t/t)")
- define_sfop3(29,x + (y + z) ,"t+(t+t)")
- define_sfop3(30,x + (y - z) ,"t+(t-t)")
- define_sfop3(31,(axnb<T,2>(x,y,z))," ")
- define_sfop3(32,(axnb<T,3>(x,y,z))," ")
- define_sfop3(33,(axnb<T,4>(x,y,z))," ")
- define_sfop3(34,(axnb<T,5>(x,y,z))," ")
- define_sfop3(35,(axnb<T,6>(x,y,z))," ")
- define_sfop3(36,(axnb<T,7>(x,y,z))," ")
- define_sfop3(37,(axnb<T,8>(x,y,z))," ")
- define_sfop3(38,(axnb<T,9>(x,y,z))," ")
- define_sfop3(39,x * numeric::log(y) + z,"")
- define_sfop3(40,x * numeric::log(y) - z,"")
- define_sfop3(41,x * numeric::log10(y) + z,"")
- define_sfop3(42,x * numeric::log10(y) - z,"")
- define_sfop3(43,x * numeric::sin(y) + z ,"")
- define_sfop3(44,x * numeric::sin(y) - z ,"")
- define_sfop3(45,x * numeric::cos(y) + z ,"")
- define_sfop3(46,x * numeric::cos(y) - z ,"")
- define_sfop3(47,details::is_true(x) ? y : z,"")
- #define define_sfop4(NN,OP0,OP1) \
- template <typename T> \
- struct sf##NN##_op : public sf_base<T> \
- { \
- typedef typename sf_base<T>::Type const Type; \
- static inline T process(Type x, Type y, Type z, Type w) \
- { \
- return (OP0); \
- } \
- static inline std::string id() { return OP1; } \
- }; \
- define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
- define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
- define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
- define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
- define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
- define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
- define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
- define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
- define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
- define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
- define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
- define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
- define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
- define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
- define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
- define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
- define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
- define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
- define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
- define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
- define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
- define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
- define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
- define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
- define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
- define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
- define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
- define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
- define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
- define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
- define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
- define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
- define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
- define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
- define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
- define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
- define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
- define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
- define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
- define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
- define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
- define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
- define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
- define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
- define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
- define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
- define_sfop4(94,((x < y) ? z : w),"")
- define_sfop4(95,((x <= y) ? z : w),"")
- define_sfop4(96,((x > y) ? z : w),"")
- define_sfop4(97,((x >= y) ? z : w),"")
- define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
- define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
- define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
- define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
- define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
- define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
- define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
- define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
- define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
- define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
- define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
- define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
- define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
- define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
- define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
- define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
- define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
- define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
- define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
- define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
- define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
- define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
- define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
- define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
- define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
- define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
- define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
- define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
- define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
- define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
- define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
- define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
- define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
- define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
- define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
- define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
- define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
- define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
- define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
- define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
- define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
- define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
- define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
- define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
- define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
- define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
- define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
- define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
- define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
- define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
- define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
- define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
- define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
- define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
- define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
- define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
- define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
- define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
- define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
- define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
- define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
- define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
- define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
- define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
- #undef define_sfop3
- #undef define_sfop4
- template <typename T, typename SpecialFunction>
- class sf3_node : public trinary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- sf3_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1,
- expression_ptr branch2)
- : trinary_node<T>(opr, branch0, branch1, branch2)
- {}
- inline T value() const
- {
- const T x = trinary_node<T>::branch_[0].first->value();
- const T y = trinary_node<T>::branch_[1].first->value();
- const T z = trinary_node<T>::branch_[2].first->value();
- return SpecialFunction::process(x, y, z);
- }
- };
- template <typename T, typename SpecialFunction>
- class sf4_node : public quaternary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- sf4_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1,
- expression_ptr branch2,
- expression_ptr branch3)
- : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
- {}
- inline T value() const
- {
- const T x = quaternary_node<T>::branch_[0].first->value();
- const T y = quaternary_node<T>::branch_[1].first->value();
- const T z = quaternary_node<T>::branch_[2].first->value();
- const T w = quaternary_node<T>::branch_[3].first->value();
- return SpecialFunction::process(x, y, z, w);
- }
- };
- template <typename T, typename SpecialFunction>
- class sf3_var_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- sf3_var_node(const T& v0, const T& v1, const T& v2)
- : v0_(v0),
- v1_(v1),
- v2_(v2)
- {}
- inline T value() const
- {
- return SpecialFunction::process(v0_, v1_, v2_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_trinary;
- }
- private:
- sf3_var_node(sf3_var_node<T,SpecialFunction>&);
- sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
- const T& v0_;
- const T& v1_;
- const T& v2_;
- };
- template <typename T, typename SpecialFunction>
- class sf4_var_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
- : v0_(v0),
- v1_(v1),
- v2_(v2),
- v3_(v3)
- {}
- inline T value() const
- {
- return SpecialFunction::process(v0_, v1_, v2_, v3_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_trinary;
- }
- private:
- sf4_var_node(sf4_var_node<T,SpecialFunction>&);
- sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
- const T& v0_;
- const T& v1_;
- const T& v2_;
- const T& v3_;
- };
- template <typename T, typename VarArgFunction>
- class vararg_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- template <typename Allocator,
- template <typename, typename> class Sequence>
- explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
- {
- arg_list_ .resize(arg_list.size());
- delete_branch_.resize(arg_list.size());
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (arg_list[i])
- {
- arg_list_[i] = arg_list[i];
- delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
- }
- else
- {
- arg_list_.clear();
- delete_branch_.clear();
- return;
- }
- }
- }
- ~vararg_node()
- {
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- if (arg_list_[i] && delete_branch_[i])
- {
- destroy_node(arg_list_[i]);
- }
- }
- }
- inline T value() const
- {
- return VarArgFunction::process(arg_list_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vararg;
- }
- private:
- std::vector<expression_ptr> arg_list_;
- std::vector<unsigned char> delete_branch_;
- };
- template <typename T, typename VarArgFunction>
- class vararg_varnode : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- template <typename Allocator,
- template <typename, typename> class Sequence>
- explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
- {
- arg_list_.resize(arg_list.size());
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (arg_list[i] && is_variable_node(arg_list[i]))
- {
- variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
- arg_list_[i] = (&var_node_ptr->ref());
- }
- else
- {
- arg_list_.clear();
- return;
- }
- }
- }
- inline T value() const
- {
- if (!arg_list_.empty())
- return VarArgFunction::process(arg_list_);
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vararg;
- }
- private:
- std::vector<const T*> arg_list_;
- };
- template <typename T, typename VecFunction>
- class vectorize_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- explicit vectorize_node(const expression_ptr v)
- : ivec_ptr_(0),
- v_(v),
- v_deletable_(branch_deletable(v_))
- {
- if (is_ivector_node(v))
- {
- ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
- }
- else
- ivec_ptr_ = 0;
- }
- ~vectorize_node()
- {
- if (v_ && v_deletable_)
- {
- destroy_node(v_);
- }
- }
- inline T value() const
- {
- if (ivec_ptr_)
- {
- v_->value();
- return VecFunction::process(ivec_ptr_);
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecfunc;
- }
- private:
- vector_interface<T>* ivec_ptr_;
- expression_ptr v_;
- const bool v_deletable_;
- };
- template <typename T>
- class assignment_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- var_node_ptr_(0)
- {
- if (is_variable_node(binary_node<T>::branch_[0].first))
- {
- var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (var_node_ptr_)
- {
- T& result = var_node_ptr_->ref();
- result = binary_node<T>::branch_[1].first->value();
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- variable_node<T>* var_node_ptr_;
- };
- template <typename T>
- class assignment_vec_elem_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_vec_elem_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec_node_ptr_(0)
- {
- if (is_vector_elem_node(binary_node<T>::branch_[0].first))
- {
- vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (vec_node_ptr_)
- {
- T& result = vec_node_ptr_->ref();
- result = binary_node<T>::branch_[1].first->value();
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- vector_elem_node<T>* vec_node_ptr_;
- };
- template <typename T>
- class assignment_rebasevec_elem_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_rebasevec_elem_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- rbvec_node_ptr_(0)
- {
- if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
- {
- rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (rbvec_node_ptr_)
- {
- T& result = rbvec_node_ptr_->ref();
- result = binary_node<T>::branch_[1].first->value();
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- rebasevector_elem_node<T>* rbvec_node_ptr_;
- };
- template <typename T>
- class assignment_rebasevec_celem_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_rebasevec_celem_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- rbvec_node_ptr_(0)
- {
- if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
- {
- rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (rbvec_node_ptr_)
- {
- T& result = rbvec_node_ptr_->ref();
- result = binary_node<T>::branch_[1].first->value();
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- rebasevector_celem_node<T>* rbvec_node_ptr_;
- };
- template <typename T>
- class assignment_vec_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- assignment_vec_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec_node_ptr_(0)
- {
- if (is_vector_node(binary_node<T>::branch_[0].first))
- {
- vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
- vds() = vec_node_ptr_->vds();
- }
- }
- inline T value() const
- {
- if (vec_node_ptr_)
- {
- const T v = binary_node<T>::branch_[1].first->value();
- T* vec = vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec + lud.upper_bound;
- while (vec < upper_bound)
- {
- #define exprtk_loop(N) \
- vec[N] = v; \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec += lud.batch_size;
- }
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : *vec++ = v; \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return vec_node_ptr_->value();
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return vec_node_ptr_;
- }
- vector_node_ptr vec()
- {
- return vec_node_ptr_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecvalass;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node<T>* vec_node_ptr_;
- vds_t vds_;
- };
- template <typename T>
- class assignment_vecvec_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- assignment_vecvec_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec0_node_ptr_(0),
- vec1_node_ptr_(0),
- initialised_(false),
- src_is_ivec_(false)
- {
- if (is_vector_node(binary_node<T>::branch_[0].first))
- {
- vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
- vds() = vec0_node_ptr_->vds();
- }
- if (is_vector_node(binary_node<T>::branch_[1].first))
- {
- vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
- vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
- }
- else if (is_ivector_node(binary_node<T>::branch_[1].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
- {
- vec1_node_ptr_ = vi->vec();
- if (!vi->side_effect())
- {
- vi->vds() = vds();
- src_is_ivec_ = true;
- }
- else
- vds_t::match_sizes(vds(),vi->vds());
- }
- }
- initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[1].first->value();
- if (src_is_ivec_)
- return vec0_node_ptr_->value();
- T* vec0 = vec0_node_ptr_->vds().data();
- T* vec1 = vec1_node_ptr_->vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec0 + lud.upper_bound;
- while (vec0 < upper_bound)
- {
- #define exprtk_loop(N) \
- vec0[N] = vec1[N]; \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec0 += lud.batch_size;
- vec1 += lud.batch_size;
- }
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : *vec0++ = *vec1++; \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return vec0_node_ptr_->value();
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return vec0_node_ptr_;
- }
- vector_node_ptr vec()
- {
- return vec0_node_ptr_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecvecass;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node<T>* vec0_node_ptr_;
- vector_node<T>* vec1_node_ptr_;
- bool initialised_;
- bool src_is_ivec_;
- vds_t vds_;
- };
- template <typename T, typename Operation>
- class assignment_op_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_op_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- var_node_ptr_(0)
- {
- if (is_variable_node(binary_node<T>::branch_[0].first))
- {
- var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (var_node_ptr_)
- {
- T& v = var_node_ptr_->ref();
- v = Operation::process(v,binary_node<T>::branch_[1].first->value());
- return v;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- variable_node<T>* var_node_ptr_;
- };
- template <typename T, typename Operation>
- class assignment_vec_elem_op_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_vec_elem_op_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec_node_ptr_(0)
- {
- if (is_vector_elem_node(binary_node<T>::branch_[0].first))
- {
- vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (vec_node_ptr_)
- {
- T& v = vec_node_ptr_->ref();
- v = Operation::process(v,binary_node<T>::branch_[1].first->value());
- return v;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- vector_elem_node<T>* vec_node_ptr_;
- };
- template <typename T, typename Operation>
- class assignment_rebasevec_elem_op_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_rebasevec_elem_op_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- rbvec_node_ptr_(0)
- {
- if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
- {
- rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (rbvec_node_ptr_)
- {
- T& v = rbvec_node_ptr_->ref();
- v = Operation::process(v,binary_node<T>::branch_[1].first->value());
- return v;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- rebasevector_elem_node<T>* rbvec_node_ptr_;
- };
- template <typename T, typename Operation>
- class assignment_rebasevec_celem_op_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- assignment_rebasevec_celem_op_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- rbvec_node_ptr_(0)
- {
- if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
- {
- rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
- }
- }
- inline T value() const
- {
- if (rbvec_node_ptr_)
- {
- T& v = rbvec_node_ptr_->ref();
- v = Operation::process(v,binary_node<T>::branch_[1].first->value());
- return v;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- private:
- rebasevector_celem_node<T>* rbvec_node_ptr_;
- };
- template <typename T, typename Operation>
- class assignment_vec_op_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- assignment_vec_op_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec_node_ptr_(0)
- {
- if (is_vector_node(binary_node<T>::branch_[0].first))
- {
- vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
- vds() = vec_node_ptr_->vds();
- }
- }
- inline T value() const
- {
- if (vec_node_ptr_)
- {
- const T v = binary_node<T>::branch_[1].first->value();
- T* vec = vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec + lud.upper_bound;
- while (vec < upper_bound)
- {
- #define exprtk_loop(N) \
- Operation::assign(vec[N],v); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec += lud.batch_size;
- }
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : Operation::assign(*vec++,v); \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return vec_node_ptr_->value();
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return vec_node_ptr_;
- }
- vector_node_ptr vec()
- {
- return vec_node_ptr_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecopvalass;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- bool side_effect() const
- {
- return true;
- }
- private:
- vector_node<T>* vec_node_ptr_;
- vds_t vds_;
- };
- template <typename T, typename Operation>
- class assignment_vecvec_op_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vec_data_store<T> vds_t;
- assignment_vecvec_op_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec0_node_ptr_(0),
- vec1_node_ptr_(0),
- initialised_(false)
- {
- if (is_vector_node(binary_node<T>::branch_[0].first))
- {
- vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
- vds() = vec0_node_ptr_->vds();
- }
- if (is_vector_node(binary_node<T>::branch_[1].first))
- {
- vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
- vec1_node_ptr_->vds() = vds();
- }
- else if (is_ivector_node(binary_node<T>::branch_[1].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
- {
- vec1_node_ptr_ = vi->vec();
- vec1_node_ptr_->vds() = vds();
- }
- else
- vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
- }
- initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- T* vec0 = vec0_node_ptr_->vds().data();
- const T* vec1 = vec1_node_ptr_->vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec0 + lud.upper_bound;
- while (vec0 < upper_bound)
- {
- #define exprtk_loop(N) \
- vec0[N] = Operation::process(vec0[N], vec1[N]); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec0 += lud.batch_size;
- vec1 += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return vec0_node_ptr_->value();
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return vec0_node_ptr_;
- }
- vector_node_ptr vec()
- {
- return vec0_node_ptr_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecopvecass;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- bool side_effect() const
- {
- return true;
- }
- private:
- vector_node<T>* vec0_node_ptr_;
- vector_node<T>* vec1_node_ptr_;
- bool initialised_;
- vds_t vds_;
- };
- template <typename T, typename Operation>
- class vec_binop_vecvec_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vector_holder<T>* vector_holder_ptr;
- typedef vec_data_store<T> vds_t;
- vec_binop_vecvec_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec0_node_ptr_(0),
- vec1_node_ptr_(0),
- temp_ (0),
- temp_vec_node_(0),
- initialised_(false)
- {
- bool v0_is_ivec = false;
- bool v1_is_ivec = false;
- if (is_vector_node(binary_node<T>::branch_[0].first))
- {
- vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
- }
- else if (is_ivector_node(binary_node<T>::branch_[0].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
- {
- vec0_node_ptr_ = vi->vec();
- v0_is_ivec = true;
- }
- }
- if (is_vector_node(binary_node<T>::branch_[1].first))
- {
- vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
- }
- else if (is_ivector_node(binary_node<T>::branch_[1].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
- {
- vec1_node_ptr_ = vi->vec();
- v1_is_ivec = true;
- }
- }
- if (vec0_node_ptr_ && vec1_node_ptr_)
- {
- vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
- vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
- if (v0_is_ivec && (vec0.size() <= vec1.size()))
- vds_ = vds_t(vec0_node_ptr_->vds());
- else if (v1_is_ivec && (vec1.size() <= vec0.size()))
- vds_ = vds_t(vec1_node_ptr_->vds());
- else
- vds_ = vds_t(std::min(vec0.size(),vec1.size()));
- temp_ = new vector_holder<T>(vds().data(),vds().size());
- temp_vec_node_ = new vector_node<T> (vds(),temp_);
- initialised_ = true;
- }
- }
- ~vec_binop_vecvec_node()
- {
- delete temp_;
- delete temp_vec_node_;
- }
- inline T value() const
- {
- if (initialised_)
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- const T* vec0 = vec0_node_ptr_->vds().data();
- const T* vec1 = vec1_node_ptr_->vds().data();
- T* vec2 = vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec2 + lud.upper_bound;
- while (vec2 < upper_bound)
- {
- #define exprtk_loop(N) \
- vec2[N] = Operation::process(vec0[N], vec1[N]); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec0 += lud.batch_size;
- vec1 += lud.batch_size;
- vec2 += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return (vds().data())[0];
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return temp_vec_node_;
- }
- vector_node_ptr vec()
- {
- return temp_vec_node_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecvecarith;
- }
- std::size_t size() const
- {
- return vds_.size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node_ptr vec0_node_ptr_;
- vector_node_ptr vec1_node_ptr_;
- vector_holder_ptr temp_;
- vector_node_ptr temp_vec_node_;
- bool initialised_;
- vds_t vds_;
- };
- template <typename T, typename Operation>
- class vec_binop_vecval_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vector_holder<T>* vector_holder_ptr;
- typedef vec_data_store<T> vds_t;
- vec_binop_vecval_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec0_node_ptr_(0),
- temp_ (0),
- temp_vec_node_(0)
- {
- bool v0_is_ivec = false;
- if (is_vector_node(binary_node<T>::branch_[0].first))
- {
- vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
- }
- else if (is_ivector_node(binary_node<T>::branch_[0].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
- {
- vec0_node_ptr_ = vi->vec();
- v0_is_ivec = true;
- }
- }
- if (vec0_node_ptr_)
- {
- if (v0_is_ivec)
- vds() = vec0_node_ptr_->vds();
- else
- vds() = vds_t(vec0_node_ptr_->size());
- temp_ = new vector_holder<T>(vds());
- temp_vec_node_ = new vector_node<T> (vds(),temp_);
- }
- }
- ~vec_binop_vecval_node()
- {
- delete temp_;
- delete temp_vec_node_;
- }
- inline T value() const
- {
- if (vec0_node_ptr_)
- {
- binary_node<T>::branch_[0].first->value();
- const T v = binary_node<T>::branch_[1].first->value();
- const T* vec0 = vec0_node_ptr_->vds().data();
- T* vec1 = vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec0 + lud.upper_bound;
- while (vec0 < upper_bound)
- {
- #define exprtk_loop(N) \
- vec1[N] = Operation::process(vec0[N], v); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec0 += lud.batch_size;
- vec1 += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return (vds().data())[0];
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return temp_vec_node_;
- }
- vector_node_ptr vec()
- {
- return temp_vec_node_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecvalarith;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node_ptr vec0_node_ptr_;
- vector_holder_ptr temp_;
- vector_node_ptr temp_vec_node_;
- vds_t vds_;
- };
- template <typename T, typename Operation>
- class vec_binop_valvec_node : public binary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vector_holder<T>* vector_holder_ptr;
- typedef vec_data_store<T> vds_t;
- vec_binop_valvec_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- vec1_node_ptr_(0),
- temp_ (0),
- temp_vec_node_(0)
- {
- bool v1_is_ivec = false;
- if (is_vector_node(binary_node<T>::branch_[1].first))
- {
- vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
- }
- else if (is_ivector_node(binary_node<T>::branch_[1].first))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
- {
- vec1_node_ptr_ = vi->vec();
- v1_is_ivec = true;
- }
- }
- if (vec1_node_ptr_)
- {
- if (v1_is_ivec)
- vds() = vec1_node_ptr_->vds();
- else
- vds() = vds_t(vec1_node_ptr_->size());
- temp_ = new vector_holder<T>(vds());
- temp_vec_node_ = new vector_node<T> (vds(),temp_);
- }
- }
- ~vec_binop_valvec_node()
- {
- delete temp_;
- delete temp_vec_node_;
- }
- inline T value() const
- {
- if (vec1_node_ptr_)
- {
- const T v = binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- T* vec0 = vds().data();
- const T* vec1 = vec1_node_ptr_->vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec0 + lud.upper_bound;
- while (vec0 < upper_bound)
- {
- #define exprtk_loop(N) \
- vec0[N] = Operation::process(v, vec1[N]); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec0 += lud.batch_size;
- vec1 += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return (vds().data())[0];
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return temp_vec_node_;
- }
- vector_node_ptr vec()
- {
- return temp_vec_node_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecvalarith;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node_ptr vec1_node_ptr_;
- vector_holder_ptr temp_;
- vector_node_ptr temp_vec_node_;
- vds_t vds_;
- };
- template <typename T, typename Operation>
- class unary_vector_node : public unary_node <T>,
- public vector_interface<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef vector_node<T>* vector_node_ptr;
- typedef vector_holder<T>* vector_holder_ptr;
- typedef vec_data_store<T> vds_t;
- unary_vector_node(const operator_type& opr, expression_ptr branch0)
- : unary_node<T>(opr, branch0),
- vec0_node_ptr_(0),
- temp_ (0),
- temp_vec_node_(0)
- {
- bool vec0_is_ivec = false;
- if (is_vector_node(unary_node<T>::branch_))
- {
- vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
- }
- else if (is_ivector_node(unary_node<T>::branch_))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
- {
- vec0_node_ptr_ = vi->vec();
- vec0_is_ivec = true;
- }
- }
- if (vec0_node_ptr_)
- {
- if (vec0_is_ivec)
- vds_ = vec0_node_ptr_->vds();
- else
- vds_ = vds_t(vec0_node_ptr_->size());
- temp_ = new vector_holder<T>(vds());
- temp_vec_node_ = new vector_node<T> (vds(),temp_);
- }
- }
- ~unary_vector_node()
- {
- delete temp_;
- delete temp_vec_node_;
- }
- inline T value() const
- {
- unary_node<T>::branch_->value();
- if (vec0_node_ptr_)
- {
- const T* vec0 = vec0_node_ptr_->vds().data();
- T* vec1 = vds().data();
- loop_unroll::details lud(size());
- const T* upper_bound = vec0 + lud.upper_bound;
- while (vec0 < upper_bound)
- {
- #define exprtk_loop(N) \
- vec1[N] = Operation::process(vec0[N]); \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec0 += lud.batch_size;
- vec1 += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return (vds().data())[0];
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- vector_node_ptr vec() const
- {
- return temp_vec_node_;
- }
- vector_node_ptr vec()
- {
- return temp_vec_node_;
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vecunaryop;
- }
- std::size_t size() const
- {
- return vds().size();
- }
- vds_t& vds()
- {
- return vds_;
- }
- const vds_t& vds() const
- {
- return vds_;
- }
- private:
- vector_node_ptr vec0_node_ptr_;
- vector_holder_ptr temp_;
- vector_node_ptr temp_vec_node_;
- vds_t vds_;
- };
- template <typename T>
- class scand_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- scand_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1)
- {}
- inline T value() const
- {
- return (
- std::not_equal_to<T>()
- (T(0),binary_node<T>::branch_[0].first->value()) &&
- std::not_equal_to<T>()
- (T(0),binary_node<T>::branch_[1].first->value())
- ) ? T(1) : T(0);
- }
- };
- template <typename T>
- class scor_node : public binary_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- scor_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1)
- {}
- inline T value() const
- {
- return (
- std::not_equal_to<T>()
- (T(0),binary_node<T>::branch_[0].first->value()) ||
- std::not_equal_to<T>()
- (T(0),binary_node<T>::branch_[1].first->value())
- ) ? T(1) : T(0);
- }
- };
- template <typename T, typename IFunction, std::size_t N>
- class function_N_node : public expression_node<T>
- {
- public:
- // Function of N paramters.
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- typedef IFunction ifunction;
- explicit function_N_node(ifunction* func)
- : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
- parameter_count_(func->param_count)
- {}
- ~function_N_node()
- {
- cleanup_branches::execute<T,N>(branch_);
- }
- template <std::size_t NumBranches>
- bool init_branches(expression_ptr (&b)[NumBranches])
- {
- // Needed for incompetent and broken msvc compiler versions
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable: 4127)
- #endif
- if (N != NumBranches)
- return false;
- else
- {
- for (std::size_t i = 0; i < NumBranches; ++i)
- {
- if (b[i])
- branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
- else
- return false;
- }
- return true;
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- }
- inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
- {
- return this < (&fn);
- }
- inline T value() const
- {
- // Needed for incompetent and broken msvc compiler versions
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable: 4127)
- #endif
- if ((0 == function_) || (0 == N))
- return std::numeric_limits<T>::quiet_NaN();
- else
- {
- T v[N];
- evaluate_branches<T,N>::execute(v,branch_);
- return invoke<T,N>::execute(*function_,v);
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- }
- template <typename T_, std::size_t BranchCount>
- struct evaluate_branches
- {
- static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
- {
- for (std::size_t i = 0; i < BranchCount; ++i)
- {
- v[i] = b[i].first->value();
- }
- }
- };
- template <typename T_>
- struct evaluate_branches <T_,5>
- {
- static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
- {
- v[0] = b[0].first->value();
- v[1] = b[1].first->value();
- v[2] = b[2].first->value();
- v[3] = b[3].first->value();
- v[4] = b[4].first->value();
- }
- };
- template <typename T_>
- struct evaluate_branches <T_,4>
- {
- static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
- {
- v[0] = b[0].first->value();
- v[1] = b[1].first->value();
- v[2] = b[2].first->value();
- v[3] = b[3].first->value();
- }
- };
- template <typename T_>
- struct evaluate_branches <T_,3>
- {
- static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
- {
- v[0] = b[0].first->value();
- v[1] = b[1].first->value();
- v[2] = b[2].first->value();
- }
- };
- template <typename T_>
- struct evaluate_branches <T_,2>
- {
- static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
- {
- v[0] = b[0].first->value();
- v[1] = b[1].first->value();
- }
- };
- template <typename T_>
- struct evaluate_branches <T_,1>
- {
- static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
- {
- v[0] = b[0].first->value();
- }
- };
- template <typename T_, std::size_t ParamCount>
- struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
- template <typename T_>
- struct invoke<T_,20>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[20])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
- };
- template <typename T_>
- struct invoke<T_,19>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[19])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
- };
- template <typename T_>
- struct invoke<T_,18>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[18])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
- };
- template <typename T_>
- struct invoke<T_,17>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[17])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
- };
- template <typename T_>
- struct invoke<T_,16>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[16])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
- };
- template <typename T_>
- struct invoke<T_,15>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[15])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
- };
- template <typename T_>
- struct invoke<T_,14>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[14])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
- };
- template <typename T_>
- struct invoke<T_,13>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[13])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
- };
- template <typename T_>
- struct invoke<T_,12>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[12])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
- };
- template <typename T_>
- struct invoke<T_,11>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[11])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
- };
- template <typename T_>
- struct invoke<T_,10>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[10])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
- };
- template <typename T_>
- struct invoke<T_,9>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[9])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
- };
- template <typename T_>
- struct invoke<T_,8>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[8])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
- };
- template <typename T_>
- struct invoke<T_,7>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[7])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
- };
- template <typename T_>
- struct invoke<T_,6>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[6])
- { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
- };
- template <typename T_>
- struct invoke<T_,5>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[5])
- { return f(v[0],v[1],v[2],v[3],v[4]); }
- };
- template <typename T_>
- struct invoke<T_,4>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[4])
- { return f(v[0],v[1],v[2],v[3]); }
- };
- template <typename T_>
- struct invoke<T_,3>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[3])
- { return f(v[0],v[1],v[2]); }
- };
- template <typename T_>
- struct invoke<T_,2>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[2])
- { return f(v[0],v[1]); }
- };
- template <typename T_>
- struct invoke<T_,1>
- {
- static inline T_ execute(ifunction& f, T_ (&v)[1])
- { return f(v[0]); }
- };
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_function;
- }
- private:
- ifunction* function_;
- std::size_t parameter_count_;
- branch_t branch_[N];
- };
- template <typename T, typename IFunction>
- class function_N_node<T,IFunction,0> : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef IFunction ifunction;
- explicit function_N_node(ifunction* func)
- : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
- {}
- inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
- {
- return this < (&fn);
- }
- inline T value() const
- {
- if (function_)
- return (*function_)();
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_function;
- }
- private:
- ifunction* function_;
- };
- template <typename T, typename VarArgFunction>
- class vararg_function_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- vararg_function_node(VarArgFunction* func,
- const std::vector<expression_ptr>& arg_list)
- : function_(func),
- arg_list_(arg_list)
- {
- value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
- }
- ~vararg_function_node()
- {
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
- {
- destroy_node(arg_list_[i]);
- }
- }
- }
- inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
- {
- return this < (&fn);
- }
- inline T value() const
- {
- if (function_)
- {
- populate_value_list();
- return (*function_)(value_list_);
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_vafunction;
- }
- private:
- inline void populate_value_list() const
- {
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- value_list_[i] = arg_list_[i]->value();
- }
- }
- VarArgFunction* function_;
- std::vector<expression_ptr> arg_list_;
- mutable std::vector<T> value_list_;
- };
- template <typename T, typename GenericFunction>
- class generic_function_node : public expression_node<T>
- {
- public:
- typedef type_store<T> type_store_t;
- typedef expression_node<T>* expression_ptr;
- typedef variable_node<T> variable_node_t;
- typedef vector_node<T> vector_node_t;
- typedef variable_node_t* variable_node_ptr_t;
- typedef vector_node_t* vector_node_ptr_t;
- typedef range_interface<T> range_interface_t;
- typedef range_data_type<T> range_data_type_t;
- typedef range_pack<T> range_t;
- typedef std::pair<expression_ptr,bool> branch_t;
- typedef std::pair<void*,std::size_t> void_t;
- typedef std::vector<T> tmp_vs_t;
- typedef std::vector<type_store_t> typestore_list_t;
- typedef std::vector<range_data_type_t> range_list_t;
- generic_function_node(const std::vector<expression_ptr>& arg_list,
- GenericFunction* func = (GenericFunction*)(0))
- : function_(func),
- arg_list_(arg_list)
- {}
- virtual ~generic_function_node()
- {
- cleanup_branches::execute(branch_);
- }
- virtual bool init_branches()
- {
- expr_as_vec1_store_.resize(arg_list_.size(),T(0) );
- typestore_list_ .resize(arg_list_.size(),type_store_t() );
- range_list_ .resize(arg_list_.size(),range_data_type_t());
- branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
- for (std::size_t i = 0; i < arg_list_.size(); ++i)
- {
- type_store_t& ts = typestore_list_[i];
- if (0 == arg_list_[i])
- return false;
- else if (is_ivector_node(arg_list_[i]))
- {
- vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
- if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
- return false;
- ts.size = vi->size();
- ts.data = vi->vds().data();
- ts.type = type_store_t::e_vector;
- vi->vec()->vec_holder().set_ref(&ts.vec_data);
- }
- #ifndef exprtk_disable_string_capabilities
- else if (is_generally_string_node(arg_list_[i]))
- {
- string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
- if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
- return false;
- ts.size = sbn->size();
- ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
- ts.type = type_store_t::e_string;
- range_list_[i].data = ts.data;
- range_list_[i].size = ts.size;
- range_list_[i].type_size = sizeof(char);
- range_list_[i].str_node = sbn;
- range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
- if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
- return false;
- range_t& rp = ri->range_ref();
- if (
- rp.const_range() &&
- is_const_string_range_node(arg_list_[i])
- )
- {
- ts.size = rp.const_size();
- ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
- range_list_[i].range = reinterpret_cast<range_t*>(0);
- }
- else
- range_list_[i].range = &(ri->range_ref());
- }
- #endif
- else if (is_variable_node(arg_list_[i]))
- {
- variable_node_ptr_t var = variable_node_ptr_t(0);
- if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
- return false;
- ts.size = 1;
- ts.data = &var->ref();
- ts.type = type_store_t::e_scalar;
- }
- else
- {
- ts.size = 1;
- ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
- ts.type = type_store_t::e_scalar;
- }
- branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
- }
- return true;
- }
- inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
- {
- return this < (&fn);
- }
- inline T value() const
- {
- if (function_)
- {
- if (populate_value_list())
- {
- typedef typename GenericFunction::parameter_list_t parameter_list_t;
- return (*function_)(parameter_list_t(typestore_list_));
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_genfunction;
- }
- protected:
- inline virtual bool populate_value_list() const
- {
- for (std::size_t i = 0; i < branch_.size(); ++i)
- {
- expr_as_vec1_store_[i] = branch_[i].first->value();
- }
- for (std::size_t i = 0; i < branch_.size(); ++i)
- {
- range_data_type_t& rdt = range_list_[i];
- if (rdt.range)
- {
- range_t& rp = (*rdt.range);
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- if (rp(r0,r1,rdt.size))
- {
- type_store_t& ts = typestore_list_[i];
- ts.size = rp.cache_size();
- #ifndef exprtk_disable_string_capabilities
- if (ts.type == type_store_t::e_string)
- ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
- else
- #endif
- ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
- }
- else
- return false;
- }
- }
- return true;
- }
- GenericFunction* function_;
- mutable typestore_list_t typestore_list_;
- private:
- std::vector<expression_ptr> arg_list_;
- std::vector<branch_t> branch_;
- mutable tmp_vs_t expr_as_vec1_store_;
- mutable range_list_t range_list_;
- };
- #ifndef exprtk_disable_string_capabilities
- template <typename T, typename StringFunction>
- class string_function_node : public generic_function_node<T,StringFunction>,
- public string_base_node<T>,
- public range_interface <T>
- {
- public:
- typedef generic_function_node<T,StringFunction> gen_function_t;
- typedef range_pack<T> range_t;
- string_function_node(StringFunction* func,
- const std::vector<typename gen_function_t::expression_ptr>& arg_list)
- : gen_function_t(arg_list,func)
- {
- range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
- range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
- range_.cache.first = range_.n0_c.second;
- range_.cache.second = range_.n1_c.second;
- }
- inline bool operator <(const string_function_node<T,StringFunction>& fn) const
- {
- return this < (&fn);
- }
- inline T value() const
- {
- if (gen_function_t::function_)
- {
- if (gen_function_t::populate_value_list())
- {
- typedef typename StringFunction::parameter_list_t parameter_list_t;
- const T result = (*gen_function_t::function_)
- (
- ret_string_,
- parameter_list_t(gen_function_t::typestore_list_)
- );
- range_.n1_c.second = ret_string_.size() - 1;
- range_.cache.second = range_.n1_c.second;
- return result;
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strfunction;
- }
- std::string str() const
- {
- return ret_string_;
- }
- char_cptr base() const
- {
- return &ret_string_[0];
- }
- std::size_t size() const
- {
- return ret_string_.size();
- }
- range_t& range_ref()
- {
- return range_;
- }
- const range_t& range_ref() const
- {
- return range_;
- }
- protected:
- mutable range_t range_;
- mutable std::string ret_string_;
- };
- #endif
- template <typename T, typename GenericFunction>
- class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
- {
- public:
- typedef generic_function_node<T,GenericFunction> gen_function_t;
- typedef range_pack<T> range_t;
- multimode_genfunction_node(GenericFunction* func,
- const std::size_t& param_seq_index,
- const std::vector<typename gen_function_t::expression_ptr>& arg_list)
- : gen_function_t(arg_list,func),
- param_seq_index_(param_seq_index)
- {}
- inline T value() const
- {
- if (gen_function_t::function_)
- {
- if (gen_function_t::populate_value_list())
- {
- typedef typename GenericFunction::parameter_list_t parameter_list_t;
- return (*gen_function_t::function_)
- (
- param_seq_index_,
- parameter_list_t(gen_function_t::typestore_list_)
- );
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_genfunction;
- }
- private:
- std::size_t param_seq_index_;
- };
- #ifndef exprtk_disable_string_capabilities
- template <typename T, typename StringFunction>
- class multimode_strfunction_node : public string_function_node<T,StringFunction>
- {
- public:
- typedef string_function_node<T,StringFunction> str_function_t;
- typedef range_pack<T> range_t;
- multimode_strfunction_node(StringFunction* func,
- const std::size_t& param_seq_index,
- const std::vector<typename str_function_t::expression_ptr>& arg_list)
- : str_function_t(func,arg_list),
- param_seq_index_(param_seq_index)
- {}
- inline T value() const
- {
- if (str_function_t::function_)
- {
- if (str_function_t::populate_value_list())
- {
- typedef typename StringFunction::parameter_list_t parameter_list_t;
- const T result = (*str_function_t::function_)
- (
- param_seq_index_,
- str_function_t::ret_string_,
- parameter_list_t(str_function_t::typestore_list_)
- );
- str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1;
- str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
- return result;
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_strfunction;
- }
- private:
- const std::size_t param_seq_index_;
- };
- #endif
- class return_exception
- {};
- template <typename T>
- class null_igenfunc
- {
- public:
- virtual ~null_igenfunc()
- {}
- typedef type_store<T> generic_type;
- typedef typename generic_type::parameter_list parameter_list_t;
- inline virtual T operator() (parameter_list_t)
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- };
- #ifndef exprtk_disable_return_statement
- template <typename T>
- class return_node : public generic_function_node<T,null_igenfunc<T> >
- {
- public:
- typedef null_igenfunc<T> igeneric_function_t;
- typedef igeneric_function_t* igeneric_function_ptr;
- typedef generic_function_node<T,igeneric_function_t> gen_function_t;
- typedef results_context<T> results_context_t;
- return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
- results_context_t& rc)
- : gen_function_t (arg_list),
- results_context_(&rc)
- {}
- inline T value() const
- {
- if (
- (0 != results_context_) &&
- gen_function_t::populate_value_list()
- )
- {
- typedef typename type_store<T>::parameter_list parameter_list_t;
- results_context_->
- assign(parameter_list_t(gen_function_t::typestore_list_));
- throw return_exception();
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_return;
- }
- private:
- results_context_t* results_context_;
- };
- template <typename T>
- class return_envelope_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef results_context<T> results_context_t;
- return_envelope_node(expression_ptr body, results_context_t& rc)
- : results_context_(&rc ),
- return_invoked_ (false),
- body_ (body ),
- body_deletable_ (branch_deletable(body_))
- {}
- ~return_envelope_node()
- {
- if (body_ && body_deletable_)
- {
- destroy_node(body_);
- }
- }
- inline T value() const
- {
- try
- {
- return_invoked_ = false;
- results_context_->clear();
- return body_->value();
- }
- catch(const return_exception&)
- {
- return_invoked_ = true;
- return std::numeric_limits<T>::quiet_NaN();
- }
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_retenv;
- }
- inline bool* retinvk_ptr()
- {
- return &return_invoked_;
- }
- private:
- results_context_t* results_context_;
- mutable bool return_invoked_;
- expression_ptr body_;
- const bool body_deletable_;
- };
- #endif
- #define exprtk_define_unary_op(OpName) \
- template <typename T> \
- struct OpName##_op \
- { \
- typedef typename functor_t<T>::Type Type; \
- typedef typename expression_node<T>::node_type node_t; \
- \
- static inline T process(Type v) \
- { \
- return numeric:: OpName (v); \
- } \
- \
- static inline node_t type() \
- { \
- return expression_node<T>::e_##OpName; \
- } \
- \
- static inline details::operator_type operation() \
- { \
- return details::e_##OpName; \
- } \
- }; \
- exprtk_define_unary_op(abs )
- exprtk_define_unary_op(acos )
- exprtk_define_unary_op(acosh)
- exprtk_define_unary_op(asin )
- exprtk_define_unary_op(asinh)
- exprtk_define_unary_op(atan )
- exprtk_define_unary_op(atanh)
- exprtk_define_unary_op(ceil )
- exprtk_define_unary_op(cos )
- exprtk_define_unary_op(cosh )
- exprtk_define_unary_op(cot )
- exprtk_define_unary_op(csc )
- exprtk_define_unary_op(d2g )
- exprtk_define_unary_op(d2r )
- exprtk_define_unary_op(erf )
- exprtk_define_unary_op(erfc )
- exprtk_define_unary_op(exp )
- exprtk_define_unary_op(expm1)
- exprtk_define_unary_op(floor)
- exprtk_define_unary_op(frac )
- exprtk_define_unary_op(g2d )
- exprtk_define_unary_op(log )
- exprtk_define_unary_op(log10)
- exprtk_define_unary_op(log2 )
- exprtk_define_unary_op(log1p)
- exprtk_define_unary_op(ncdf )
- exprtk_define_unary_op(neg )
- exprtk_define_unary_op(notl )
- exprtk_define_unary_op(pos )
- exprtk_define_unary_op(r2d )
- exprtk_define_unary_op(round)
- exprtk_define_unary_op(sec )
- exprtk_define_unary_op(sgn )
- exprtk_define_unary_op(sin )
- exprtk_define_unary_op(sinc )
- exprtk_define_unary_op(sinh )
- exprtk_define_unary_op(sqrt )
- exprtk_define_unary_op(tan )
- exprtk_define_unary_op(tanh )
- exprtk_define_unary_op(trunc)
- #undef exprtk_define_unary_op
- template <typename T>
- struct opr_base
- {
- typedef typename details::functor_t<T>::Type Type;
- typedef typename details::functor_t<T>::RefType RefType;
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::qfunc_t quaternary_functor_t;
- typedef typename functor_t::tfunc_t trinary_functor_t;
- typedef typename functor_t::bfunc_t binary_functor_t;
- typedef typename functor_t::ufunc_t unary_functor_t;
- };
- template <typename T>
- struct add_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- typedef typename opr_base<T>::RefType RefType;
- static inline T process(Type t1, Type t2) { return t1 + t2; }
- static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
- static inline void assign(RefType t1, Type t2) { t1 += t2; }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
- static inline details::operator_type operation() { return details::e_add; }
- };
- template <typename T>
- struct mul_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- typedef typename opr_base<T>::RefType RefType;
- static inline T process(Type t1, Type t2) { return t1 * t2; }
- static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
- static inline void assign(RefType t1, Type t2) { t1 *= t2; }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
- static inline details::operator_type operation() { return details::e_mul; }
- };
- template <typename T>
- struct sub_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- typedef typename opr_base<T>::RefType RefType;
- static inline T process(Type t1, Type t2) { return t1 - t2; }
- static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
- static inline void assign(RefType t1, Type t2) { t1 -= t2; }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
- static inline details::operator_type operation() { return details::e_sub; }
- };
- template <typename T>
- struct div_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- typedef typename opr_base<T>::RefType RefType;
- static inline T process(Type t1, Type t2) { return t1 / t2; }
- static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
- static inline void assign(RefType t1, Type t2) { t1 /= t2; }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
- static inline details::operator_type operation() { return details::e_div; }
- };
- template <typename T>
- struct mod_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- typedef typename opr_base<T>::RefType RefType;
- static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
- static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
- static inline details::operator_type operation() { return details::e_mod; }
- };
- template <typename T>
- struct pow_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- typedef typename opr_base<T>::RefType RefType;
- static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
- static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
- static inline details::operator_type operation() { return details::e_pow; }
- };
- template <typename T>
- struct lt_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
- static inline details::operator_type operation() { return details::e_lt; }
- };
- template <typename T>
- struct lte_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
- static inline details::operator_type operation() { return details::e_lte; }
- };
- template <typename T>
- struct gt_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
- static inline details::operator_type operation() { return details::e_gt; }
- };
- template <typename T>
- struct gte_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
- static inline details::operator_type operation() { return details::e_gte; }
- };
- template <typename T>
- struct eq_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
- static inline details::operator_type operation() { return details::e_eq; }
- };
- template <typename T>
- struct equal_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
- static inline details::operator_type operation() { return details::e_equal; }
- };
- template <typename T>
- struct ne_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
- static inline details::operator_type operation() { return details::e_ne; }
- };
- template <typename T>
- struct and_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
- static inline details::operator_type operation() { return details::e_and; }
- };
- template <typename T>
- struct nand_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
- static inline details::operator_type operation() { return details::e_nand; }
- };
- template <typename T>
- struct or_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
- static inline details::operator_type operation() { return details::e_or; }
- };
- template <typename T>
- struct nor_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
- static inline details::operator_type operation() { return details::e_nor; }
- };
- template <typename T>
- struct xor_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
- static inline details::operator_type operation() { return details::e_xor; }
- };
- template <typename T>
- struct xnor_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
- static inline details::operator_type operation() { return details::e_xnor; }
- };
- template <typename T>
- struct in_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
- static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
- static inline details::operator_type operation() { return details::e_in; }
- };
- template <typename T>
- struct like_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
- static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
- static inline details::operator_type operation() { return details::e_like; }
- };
- template <typename T>
- struct ilike_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
- static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
- static inline details::operator_type operation() { return details::e_ilike; }
- };
- template <typename T>
- struct inrange_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
- static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
- {
- return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
- }
- static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
- static inline details::operator_type operation() { return details::e_inrange; }
- };
- template <typename T>
- inline T value(details::expression_node<T>* n)
- {
- return n->value();
- }
- template <typename T>
- inline T value(T* t)
- {
- return (*t);
- }
- template <typename T>
- struct vararg_add_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 0 : return T(0);
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default :
- {
- T result = T(0);
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- result += value(arg_list[i]);
- }
- return result;
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return value(arg_list[0]);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return value(arg_list[0]) + value(arg_list[1]);
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return value(arg_list[0]) + value(arg_list[1]) +
- value(arg_list[2]) ;
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return value(arg_list[0]) + value(arg_list[1]) +
- value(arg_list[2]) + value(arg_list[3]) ;
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return value(arg_list[0]) + value(arg_list[1]) +
- value(arg_list[2]) + value(arg_list[3]) +
- value(arg_list[4]) ;
- }
- };
- template <typename T>
- struct vararg_mul_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 0 : return T(0);
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default :
- {
- T result = T(value(arg_list[0]));
- for (std::size_t i = 1; i < arg_list.size(); ++i)
- {
- result *= value(arg_list[i]);
- }
- return result;
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return value(arg_list[0]);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return value(arg_list[0]) * value(arg_list[1]);
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return value(arg_list[0]) * value(arg_list[1]) *
- value(arg_list[2]) ;
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return value(arg_list[0]) * value(arg_list[1]) *
- value(arg_list[2]) * value(arg_list[3]) ;
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return value(arg_list[0]) * value(arg_list[1]) *
- value(arg_list[2]) * value(arg_list[3]) *
- value(arg_list[4]) ;
- }
- };
- template <typename T>
- struct vararg_avg_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 0 : return T(0);
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return value(arg_list[0]);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return (value(arg_list[0]) + value(arg_list[1])) / T(2);
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return (value(arg_list[0]) + value(arg_list[1]) +
- value(arg_list[2]) + value(arg_list[3])) / T(4);
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return (value(arg_list[0]) + value(arg_list[1]) +
- value(arg_list[2]) + value(arg_list[3]) +
- value(arg_list[4])) / T(5);
- }
- };
- template <typename T>
- struct vararg_min_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 0 : return T(0);
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default :
- {
- T result = T(value(arg_list[0]));
- for (std::size_t i = 1; i < arg_list.size(); ++i)
- {
- const T v = value(arg_list[i]);
- if (v < result)
- result = v;
- }
- return result;
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return value(arg_list[0]);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return std::min<T>(value(arg_list[0]),value(arg_list[1]));
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return std::min<T>(
- std::min<T>(value(arg_list[0]), value(arg_list[1])),
- std::min<T>(value(arg_list[2]), value(arg_list[3])));
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return std::min<T>(
- std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
- std::min<T>(value(arg_list[2]), value(arg_list[3]))),
- value(arg_list[4]));
- }
- };
- template <typename T>
- struct vararg_max_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 0 : return T(0);
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default :
- {
- T result = T(value(arg_list[0]));
- for (std::size_t i = 1; i < arg_list.size(); ++i)
- {
- const T v = value(arg_list[i]);
- if (v > result)
- result = v;
- }
- return result;
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return value(arg_list[0]);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return std::max<T>(value(arg_list[0]),value(arg_list[1]));
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return std::max<T>(
- std::max<T>(value(arg_list[0]), value(arg_list[1])),
- std::max<T>(value(arg_list[2]), value(arg_list[3])));
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return std::max<T>(
- std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
- std::max<T>(value(arg_list[2]), value(arg_list[3]))),
- value(arg_list[4]));
- }
- };
- template <typename T>
- struct vararg_mand_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default :
- {
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (std::equal_to<T>()(T(0), value(arg_list[i])))
- return T(0);
- }
- return T(1);
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return std::not_equal_to<T>()
- (T(0), value(arg_list[0])) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[1]))
- ) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[2]))
- ) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[3]))
- ) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
- std::not_equal_to<T>()(T(0), value(arg_list[4]))
- ) ? T(1) : T(0);
- }
- };
- template <typename T>
- struct vararg_mor_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- default :
- {
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
- return T(1);
- }
- return T(0);
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return std::not_equal_to<T>()
- (T(0), value(arg_list[0])) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[1]))
- ) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[2]))
- ) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[3]))
- ) ? T(1) : T(0);
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- return (
- std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
- std::not_equal_to<T>()(T(0), value(arg_list[4]))
- ) ? T(1) : T(0);
- }
- };
- template <typename T>
- struct vararg_multi_op : public opr_base<T>
- {
- typedef typename opr_base<T>::Type Type;
- template <typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- static inline T process(const Sequence<Type,Allocator>& arg_list)
- {
- switch (arg_list.size())
- {
- case 0 : return std::numeric_limits<T>::quiet_NaN();
- case 1 : return process_1(arg_list);
- case 2 : return process_2(arg_list);
- case 3 : return process_3(arg_list);
- case 4 : return process_4(arg_list);
- case 5 : return process_5(arg_list);
- case 6 : return process_6(arg_list);
- case 7 : return process_7(arg_list);
- case 8 : return process_8(arg_list);
- default :
- {
- for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
- {
- value(arg_list[i]);
- }
- return value(arg_list.back());
- }
- }
- }
- template <typename Sequence>
- static inline T process_1(const Sequence& arg_list)
- {
- return value(arg_list[0]);
- }
- template <typename Sequence>
- static inline T process_2(const Sequence& arg_list)
- {
- value(arg_list[0]);
- return value(arg_list[1]);
- }
- template <typename Sequence>
- static inline T process_3(const Sequence& arg_list)
- {
- value(arg_list[0]);
- value(arg_list[1]);
- return value(arg_list[2]);
- }
- template <typename Sequence>
- static inline T process_4(const Sequence& arg_list)
- {
- value(arg_list[0]);
- value(arg_list[1]);
- value(arg_list[2]);
- return value(arg_list[3]);
- }
- template <typename Sequence>
- static inline T process_5(const Sequence& arg_list)
- {
- value(arg_list[0]);
- value(arg_list[1]);
- value(arg_list[2]);
- value(arg_list[3]);
- return value(arg_list[4]);
- }
- template <typename Sequence>
- static inline T process_6(const Sequence& arg_list)
- {
- value(arg_list[0]);
- value(arg_list[1]);
- value(arg_list[2]);
- value(arg_list[3]);
- value(arg_list[4]);
- return value(arg_list[5]);
- }
- template <typename Sequence>
- static inline T process_7(const Sequence& arg_list)
- {
- value(arg_list[0]);
- value(arg_list[1]);
- value(arg_list[2]);
- value(arg_list[3]);
- value(arg_list[4]);
- value(arg_list[5]);
- return value(arg_list[6]);
- }
- template <typename Sequence>
- static inline T process_8(const Sequence& arg_list)
- {
- value(arg_list[0]);
- value(arg_list[1]);
- value(arg_list[2]);
- value(arg_list[3]);
- value(arg_list[4]);
- value(arg_list[5]);
- value(arg_list[6]);
- return value(arg_list[7]);
- }
- };
- template <typename T>
- struct vec_add_op
- {
- typedef vector_interface<T>* ivector_ptr;
- static inline T process(const ivector_ptr v)
- {
- const T* vec = v->vec()->vds().data();
- const std::size_t vec_size = v->vec()->vds().size();
- loop_unroll::details lud(vec_size);
- if (vec_size <= static_cast<std::size_t>(lud.batch_size))
- {
- T result = T(0);
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (vec_size)
- {
- #define case_stmt(N) \
- case N : result += vec[i++]; \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(16) case_stmt(15)
- case_stmt(14) case_stmt(13)
- case_stmt(12) case_stmt(11)
- case_stmt(10) case_stmt( 9)
- case_stmt( 8) case_stmt( 7)
- case_stmt( 6) case_stmt( 5)
- #endif
- case_stmt( 4) case_stmt( 3)
- case_stmt( 2) case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef case_stmt
- return result;
- }
- T r[] = {
- T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
- T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
- };
- const T* upper_bound = vec + lud.upper_bound;
- while (vec < upper_bound)
- {
- #define exprtk_loop(N) \
- r[N] += vec[N]; \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : r[0] += vec[i++]; \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
- #ifndef exprtk_disable_superscalar_unroll
- + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
- + (r[ 8] + r[ 9] + r[10] + r[11])
- + (r[12] + r[13] + r[14] + r[15])
- #endif
- ;
- }
- };
- template <typename T>
- struct vec_mul_op
- {
- typedef vector_interface<T>* ivector_ptr;
- static inline T process(const ivector_ptr v)
- {
- const T* vec = v->vec()->vds().data();
- const std::size_t vec_size = v->vec()->vds().size();
- loop_unroll::details lud(vec_size);
- if (vec_size <= static_cast<std::size_t>(lud.batch_size))
- {
- T result = T(1);
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (vec_size)
- {
- #define case_stmt(N) \
- case N : result *= vec[i++]; \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(16) case_stmt(15)
- case_stmt(14) case_stmt(13)
- case_stmt(12) case_stmt(11)
- case_stmt(10) case_stmt( 9)
- case_stmt( 8) case_stmt( 7)
- case_stmt( 6) case_stmt( 5)
- #endif
- case_stmt( 4) case_stmt( 3)
- case_stmt( 2) case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef case_stmt
- return result;
- }
- T r[] = {
- T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
- T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
- };
- const T* upper_bound = vec + lud.upper_bound;
- while (vec < upper_bound)
- {
- #define exprtk_loop(N) \
- r[N] *= vec[N]; \
- exprtk_loop( 0) exprtk_loop( 1)
- exprtk_loop( 2) exprtk_loop( 3)
- #ifndef exprtk_disable_superscalar_unroll
- exprtk_loop( 4) exprtk_loop( 5)
- exprtk_loop( 6) exprtk_loop( 7)
- exprtk_loop( 8) exprtk_loop( 9)
- exprtk_loop(10) exprtk_loop(11)
- exprtk_loop(12) exprtk_loop(13)
- exprtk_loop(14) exprtk_loop(15)
- #endif
- vec += lud.batch_size;
- }
- int i = 0;
- exprtk_disable_fallthrough_begin
- switch (lud.remainder)
- {
- #define case_stmt(N) \
- case N : r[0] *= vec[i++]; \
- #ifndef exprtk_disable_superscalar_unroll
- case_stmt(15) case_stmt(14)
- case_stmt(13) case_stmt(12)
- case_stmt(11) case_stmt(10)
- case_stmt( 9) case_stmt( 8)
- case_stmt( 7) case_stmt( 6)
- case_stmt( 5) case_stmt( 4)
- #endif
- case_stmt( 3) case_stmt( 2)
- case_stmt( 1)
- }
- exprtk_disable_fallthrough_end
- #undef exprtk_loop
- #undef case_stmt
- return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
- #ifndef exprtk_disable_superscalar_unroll
- + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
- + (r[ 8] * r[ 9] * r[10] * r[11])
- + (r[12] * r[13] * r[14] * r[15])
- #endif
- ;
- }
- };
- template <typename T>
- struct vec_avg_op
- {
- typedef vector_interface<T>* ivector_ptr;
- static inline T process(const ivector_ptr v)
- {
- const std::size_t vec_size = v->vec()->vds().size();
- return vec_add_op<T>::process(v) / vec_size;
- }
- };
- template <typename T>
- struct vec_min_op
- {
- typedef vector_interface<T>* ivector_ptr;
- static inline T process(const ivector_ptr v)
- {
- const T* vec = v->vec()->vds().data();
- const std::size_t vec_size = v->vec()->vds().size();
- T result = vec[0];
- for (std::size_t i = 1; i < vec_size; ++i)
- {
- T v_i = vec[i];
- if (v_i < result)
- result = v_i;
- }
- return result;
- }
- };
- template <typename T>
- struct vec_max_op
- {
- typedef vector_interface<T>* ivector_ptr;
- static inline T process(const ivector_ptr v)
- {
- const T* vec = v->vec()->vds().data();
- const std::size_t vec_size = v->vec()->vds().size();
- T result = vec[0];
- for (std::size_t i = 1; i < vec_size; ++i)
- {
- T v_i = vec[i];
- if (v_i > result)
- result = v_i;
- }
- return result;
- }
- };
- template <typename T>
- class vov_base_node : public expression_node<T>
- {
- public:
- virtual ~vov_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- virtual const T& v0() const = 0;
- virtual const T& v1() const = 0;
- };
- template <typename T>
- class cov_base_node : public expression_node<T>
- {
- public:
- virtual ~cov_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- virtual const T c() const = 0;
- virtual const T& v() const = 0;
- };
- template <typename T>
- class voc_base_node : public expression_node<T>
- {
- public:
- virtual ~voc_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- virtual const T c() const = 0;
- virtual const T& v() const = 0;
- };
- template <typename T>
- class vob_base_node : public expression_node<T>
- {
- public:
- virtual ~vob_base_node()
- {}
- virtual const T& v() const = 0;
- };
- template <typename T>
- class bov_base_node : public expression_node<T>
- {
- public:
- virtual ~bov_base_node()
- {}
- virtual const T& v() const = 0;
- };
- template <typename T>
- class cob_base_node : public expression_node<T>
- {
- public:
- virtual ~cob_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- virtual const T c() const = 0;
- virtual void set_c(const T) = 0;
- virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
- };
- template <typename T>
- class boc_base_node : public expression_node<T>
- {
- public:
- virtual ~boc_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- virtual const T c() const = 0;
- virtual void set_c(const T) = 0;
- virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
- };
- template <typename T>
- class uv_base_node : public expression_node<T>
- {
- public:
- virtual ~uv_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- virtual const T& v() const = 0;
- };
- template <typename T>
- class sos_base_node : public expression_node<T>
- {
- public:
- virtual ~sos_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- };
- template <typename T>
- class sosos_base_node : public expression_node<T>
- {
- public:
- virtual ~sosos_base_node()
- {}
- inline virtual operator_type operation() const
- {
- return details::e_default;
- }
- };
- template <typename T>
- class T0oT1oT2_base_node : public expression_node<T>
- {
- public:
- virtual ~T0oT1oT2_base_node()
- {}
- virtual std::string type_id() const = 0;
- };
- template <typename T>
- class T0oT1oT2oT3_base_node : public expression_node<T>
- {
- public:
- virtual ~T0oT1oT2oT3_base_node()
- {}
- virtual std::string type_id() const = 0;
- };
- template <typename T, typename Operation>
- class unary_variable_node : public uv_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- explicit unary_variable_node(const T& var)
- : v_(var)
- {}
- inline T value() const
- {
- return Operation::process(v_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T& v() const
- {
- return v_;
- }
- private:
- unary_variable_node(unary_variable_node<T,Operation>&);
- unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
- const T& v_;
- };
- template <typename T>
- class uvouv_node : public expression_node<T>
- {
- public:
- // UOpr1(v0) Op UOpr2(v1)
- typedef expression_node<T>* expression_ptr;
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::bfunc_t bfunc_t;
- typedef typename functor_t::ufunc_t ufunc_t;
- explicit uvouv_node(const T& var0,const T& var1,
- ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
- : v0_(var0),
- v1_(var1),
- u0_(uf0 ),
- u1_(uf1 ),
- f_ (bf )
- {}
- inline T value() const
- {
- return f_(u0_(v0_),u1_(v1_));
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_uvouv;
- }
- inline operator_type operation() const
- {
- return details::e_default;
- }
- inline const T& v0()
- {
- return v0_;
- }
- inline const T& v1()
- {
- return v1_;
- }
- inline ufunc_t u0()
- {
- return u0_;
- }
- inline ufunc_t u1()
- {
- return u1_;
- }
- inline ufunc_t f()
- {
- return f_;
- }
- private:
- uvouv_node(uvouv_node<T>&);
- uvouv_node<T>& operator=(uvouv_node<T>&);
- const T& v0_;
- const T& v1_;
- const ufunc_t u0_;
- const ufunc_t u1_;
- const bfunc_t f_;
- };
- template <typename T, typename Operation>
- class unary_branch_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- explicit unary_branch_node(expression_ptr brnch)
- : branch_(brnch),
- branch_deletable_(branch_deletable(branch_))
- {}
- ~unary_branch_node()
- {
- if (branch_ && branch_deletable_)
- {
- destroy_node(branch_);
- }
- }
- inline T value() const
- {
- return Operation::process(branch_->value());
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_;
- }
- inline void release()
- {
- branch_deletable_ = false;
- }
- private:
- unary_branch_node(unary_branch_node<T,Operation>&);
- unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
- expression_ptr branch_;
- bool branch_deletable_;
- };
- template <typename T> struct is_const { enum {result = 0}; };
- template <typename T> struct is_const <const T> { enum {result = 1}; };
- template <typename T> struct is_const_ref { enum {result = 0}; };
- template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
- template <typename T> struct is_ref { enum {result = 0}; };
- template <typename T> struct is_ref<T&> { enum {result = 1}; };
- template <typename T> struct is_ref<const T&> { enum {result = 0}; };
- template <std::size_t State>
- struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
- template <>
- struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
- #define exprtk_crtype(Type) \
- param_to_str<is_const_ref< Type >::result>::result() \
- template <typename T>
- struct T0oT1oT2process
- {
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::bfunc_t bfunc_t;
- struct mode0
- {
- static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
- {
- // (T0 o0 T1) o1 T2
- return bf1(bf0(t0,t1),t2);
- }
- template <typename T0, typename T1, typename T2>
- static inline std::string id()
- {
- static const std::string result = "(" + exprtk_crtype(T0) + "o" +
- exprtk_crtype(T1) + ")o(" +
- exprtk_crtype(T2) + ")" ;
- return result;
- }
- };
- struct mode1
- {
- static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
- {
- // T0 o0 (T1 o1 T2)
- return bf0(t0,bf1(t1,t2));
- }
- template <typename T0, typename T1, typename T2>
- static inline std::string id()
- {
- static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
- exprtk_crtype(T1) + "o" +
- exprtk_crtype(T2) + ")" ;
- return result;
- }
- };
- };
- template <typename T>
- struct T0oT1oT20T3process
- {
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::bfunc_t bfunc_t;
- struct mode0
- {
- static inline T process(const T& t0, const T& t1,
- const T& t2, const T& t3,
- const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
- {
- // (T0 o0 T1) o1 (T2 o2 T3)
- return bf1(bf0(t0,t1),bf2(t2,t3));
- }
- template <typename T0, typename T1, typename T2, typename T3>
- static inline std::string id()
- {
- static const std::string result = "(" + exprtk_crtype(T0) + "o" +
- exprtk_crtype(T1) + ")o" +
- "(" + exprtk_crtype(T2) + "o" +
- exprtk_crtype(T3) + ")" ;
- return result;
- }
- };
- struct mode1
- {
- static inline T process(const T& t0, const T& t1,
- const T& t2, const T& t3,
- const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
- {
- // (T0 o0 (T1 o1 (T2 o2 T3))
- return bf0(t0,bf1(t1,bf2(t2,t3)));
- }
- template <typename T0, typename T1, typename T2, typename T3>
- static inline std::string id()
- {
- static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
- exprtk_crtype(T1) + ")o(" +
- exprtk_crtype(T2) + "o" +
- exprtk_crtype(T3) + "))" ;
- return result;
- }
- };
- struct mode2
- {
- static inline T process(const T& t0, const T& t1,
- const T& t2, const T& t3,
- const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
- {
- // (T0 o0 ((T1 o1 T2) o2 T3)
- return bf0(t0,bf2(bf1(t1,t2),t3));
- }
- template <typename T0, typename T1, typename T2, typename T3>
- static inline std::string id()
- {
- static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
- exprtk_crtype(T1) + "o" +
- exprtk_crtype(T2) + ")o(" +
- exprtk_crtype(T3) + "))" ;
- return result;
- }
- };
- struct mode3
- {
- static inline T process(const T& t0, const T& t1,
- const T& t2, const T& t3,
- const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
- {
- // (((T0 o0 T1) o1 T2) o2 T3)
- return bf2(bf1(bf0(t0,t1),t2),t3);
- }
- template <typename T0, typename T1, typename T2, typename T3>
- static inline std::string id()
- {
- static const std::string result = "((" + exprtk_crtype(T0) + "o" +
- exprtk_crtype(T1) + ")o(" +
- exprtk_crtype(T2) + "))o(" +
- exprtk_crtype(T3) + ")";
- return result;
- }
- };
- struct mode4
- {
- static inline T process(const T& t0, const T& t1,
- const T& t2, const T& t3,
- const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
- {
- // ((T0 o0 (T1 o1 T2)) o2 T3
- return bf2(bf0(t0,bf1(t1,t2)),t3);
- }
- template <typename T0, typename T1, typename T2, typename T3>
- static inline std::string id()
- {
- static const std::string result = "((" + exprtk_crtype(T0) + ")o(" +
- exprtk_crtype(T1) + "o" +
- exprtk_crtype(T2) + "))o(" +
- exprtk_crtype(T3) + ")" ;
- return result;
- }
- };
- };
- #undef exprtk_crtype
- template <typename T, typename T0, typename T1>
- struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
- template <typename T, typename T0, typename T1>
- const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
- #define synthesis_node_type_define(T0_,T1_,v_) \
- template <typename T, typename T0, typename T1> \
- struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
- template <typename T, typename T0, typename T1> \
- const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
- synthesis_node_type_define(const T0&, const T1&, e_vov)
- synthesis_node_type_define(const T0&, const T1 , e_voc)
- synthesis_node_type_define(const T0 , const T1&, e_cov)
- synthesis_node_type_define( T0&, T1&, e_none)
- synthesis_node_type_define(const T0 , const T1 , e_none)
- synthesis_node_type_define( T0&, const T1 , e_none)
- synthesis_node_type_define(const T0 , T1&, e_none)
- synthesis_node_type_define(const T0&, T1&, e_none)
- synthesis_node_type_define( T0&, const T1&, e_none)
- #undef synthesis_node_type_define
- template <typename T, typename T0, typename T1, typename T2>
- struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
- template <typename T, typename T0, typename T1, typename T2>
- const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
- #define synthesis_node_type_define(T0_,T1_,T2_,v_) \
- template <typename T, typename T0, typename T1, typename T2> \
- struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
- template <typename T, typename T0, typename T1, typename T2> \
- const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
- synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
- synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
- synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
- synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
- synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
- synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
- synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
- synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
- synthesis_node_type_define( T0&, T1&, T2&, e_none )
- #undef synthesis_node_type_define
- template <typename T, typename T0, typename T1, typename T2, typename T3>
- struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
- template <typename T, typename T0, typename T1, typename T2, typename T3>
- const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
- #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \
- template <typename T, typename T0, typename T1, typename T2, typename T3> \
- struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
- template <typename T, typename T0, typename T1, typename T2, typename T3> \
- const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
- synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
- synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
- synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
- synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
- synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
- synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
- synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
- synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
- synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
- synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none )
- synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none )
- synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none )
- synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none )
- synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none )
- synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none )
- synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none )
- #undef synthesis_node_type_define
- template <typename T, typename T0, typename T1>
- class T0oT1 : public expression_node<T>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::bfunc_t bfunc_t;
- typedef T value_type;
- typedef T0oT1<T,T0,T1> node_type;
- T0oT1(T0 p0, T1 p1, const bfunc_t p2)
- : t0_(p0),
- t1_(p1),
- f_ (p2)
- {}
- inline typename expression_node<T>::node_type type() const
- {
- static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
- return result;
- }
- inline operator_type operation() const
- {
- return e_default;
- }
- inline T value() const
- {
- return f_(t0_,t1_);
- }
- inline T0 t0() const
- {
- return t0_;
- }
- inline T1 t1() const
- {
- return t1_;
- }
- inline bfunc_t f() const
- {
- return f_;
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator,
- T0 p0, T1 p1,
- bfunc_t p2)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, bfunc_t&>
- (p0, p1, p2);
- }
- private:
- T0oT1(T0oT1<T,T0,T1>&) {}
- T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
- T0 t0_;
- T1 t1_;
- const bfunc_t f_;
- };
- template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
- class T0oT1oT2 : public T0oT1oT2_base_node<T>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::bfunc_t bfunc_t;
- typedef T value_type;
- typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
- typedef ProcessMode process_mode_t;
- T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
- : t0_(p0),
- t1_(p1),
- t2_(p2),
- f0_(p3),
- f1_(p4)
- {}
- inline typename expression_node<T>::node_type type() const
- {
- static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
- return result;
- }
- inline operator_type operation() const
- {
- return e_default;
- }
- inline T value() const
- {
- return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
- }
- inline T0 t0() const
- {
- return t0_;
- }
- inline T1 t1() const
- {
- return t1_;
- }
- inline T2 t2() const
- {
- return t2_;
- }
- bfunc_t f0() const
- {
- return f0_;
- }
- bfunc_t f1() const
- {
- return f1_;
- }
- std::string type_id() const
- {
- return id();
- }
- static inline std::string id()
- {
- return process_mode_t::template id<T0,T1,T2>();
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
- (p0, p1, p2, p3, p4);
- }
- private:
- T0oT1oT2(node_type&) {}
- node_type& operator=(node_type&) { return (*this); }
- T0 t0_;
- T1 t1_;
- T2 t2_;
- const bfunc_t f0_;
- const bfunc_t f1_;
- };
- template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
- class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::bfunc_t bfunc_t;
- typedef T value_type;
- typedef T0_ T0;
- typedef T1_ T1;
- typedef T2_ T2;
- typedef T3_ T3;
- typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
- typedef ProcessMode process_mode_t;
- T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
- : t0_(p0),
- t1_(p1),
- t2_(p2),
- t3_(p3),
- f0_(p4),
- f1_(p5),
- f2_(p6)
- {}
- inline T value() const
- {
- return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
- }
- inline T0 t0() const
- {
- return t0_;
- }
- inline T1 t1() const
- {
- return t1_;
- }
- inline T2 t2() const
- {
- return t2_;
- }
- inline T3 t3() const
- {
- return t3_;
- }
- inline bfunc_t f0() const
- {
- return f0_;
- }
- inline bfunc_t f1() const
- {
- return f1_;
- }
- inline bfunc_t f2() const
- {
- return f2_;
- }
- inline std::string type_id() const
- {
- return id();
- }
- static inline std::string id()
- {
- return process_mode_t::template id<T0, T1, T2, T3>();
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator,
- T0 p0, T1 p1, T2 p2, T3 p3,
- bfunc_t p4, bfunc_t p5, bfunc_t p6)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
- (p0, p1, p2, p3, p4, p5, p6);
- }
- private:
- T0oT1oT2oT3(node_type&) {}
- node_type& operator=(node_type&) { return (*this); }
- T0 t0_;
- T1 t1_;
- T2 t2_;
- T3 t3_;
- const bfunc_t f0_;
- const bfunc_t f1_;
- const bfunc_t f2_;
- };
- template <typename T, typename T0, typename T1, typename T2>
- class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::tfunc_t tfunc_t;
- typedef T value_type;
- typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
- T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
- : t0_(p0),
- t1_(p1),
- t2_(p2),
- f_ (p3)
- {}
- inline typename expression_node<T>::node_type type() const
- {
- static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
- return result;
- }
- inline operator_type operation() const
- {
- return e_default;
- }
- inline T value() const
- {
- return f_(t0_, t1_, t2_);
- }
- inline T0 t0() const
- {
- return t0_;
- }
- inline T1 t1() const
- {
- return t1_;
- }
- inline T2 t2() const
- {
- return t2_;
- }
- tfunc_t f() const
- {
- return f_;
- }
- std::string type_id() const
- {
- return id();
- }
- static inline std::string id()
- {
- return "sf3";
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, T2, tfunc_t>
- (p0, p1, p2, p3);
- }
- private:
- T0oT1oT2_sf3(node_type&) {}
- node_type& operator=(node_type&) { return (*this); }
- T0 t0_;
- T1 t1_;
- T2 t2_;
- const tfunc_t f_;
- };
- template <typename T, typename T0, typename T1, typename T2>
- class sf3ext_type_node : public T0oT1oT2_base_node<T>
- {
- public:
- virtual ~sf3ext_type_node()
- {}
- virtual T0 t0() const = 0;
- virtual T1 t1() const = 0;
- virtual T2 t2() const = 0;
- };
- template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
- class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::tfunc_t tfunc_t;
- typedef T value_type;
- typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
- T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
- : t0_(p0),
- t1_(p1),
- t2_(p2)
- {}
- inline typename expression_node<T>::node_type type() const
- {
- static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
- return result;
- }
- inline operator_type operation() const
- {
- return e_default;
- }
- inline T value() const
- {
- return SF3Operation::process(t0_, t1_, t2_);
- }
- T0 t0() const
- {
- return t0_;
- }
- T1 t1() const
- {
- return t1_;
- }
- T2 t2() const
- {
- return t2_;
- }
- std::string type_id() const
- {
- return id();
- }
- static inline std::string id()
- {
- return SF3Operation::id();
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, T2>
- (p0, p1, p2);
- }
- private:
- T0oT1oT2_sf3ext(node_type&) {}
- node_type& operator=(node_type&) { return (*this); }
- T0 t0_;
- T1 t1_;
- T2 t2_;
- };
- template <typename T>
- inline bool is_sf3ext_node(const expression_node<T>* n)
- {
- switch (n->type())
- {
- case expression_node<T>::e_vovov : return true;
- case expression_node<T>::e_vovoc : return true;
- case expression_node<T>::e_vocov : return true;
- case expression_node<T>::e_covov : return true;
- case expression_node<T>::e_covoc : return true;
- default : return false;
- }
- }
- template <typename T, typename T0, typename T1, typename T2, typename T3>
- class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::qfunc_t qfunc_t;
- typedef T value_type;
- typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
- T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
- : t0_(p0),
- t1_(p1),
- t2_(p2),
- t3_(p3),
- f_ (p4)
- {}
- inline typename expression_node<T>::node_type type() const
- {
- static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
- return result;
- }
- inline operator_type operation() const
- {
- return e_default;
- }
- inline T value() const
- {
- return f_(t0_, t1_, t2_, t3_);
- }
- inline T0 t0() const
- {
- return t0_;
- }
- inline T1 t1() const
- {
- return t1_;
- }
- inline T2 t2() const
- {
- return t2_;
- }
- inline T3 t3() const
- {
- return t3_;
- }
- qfunc_t f() const
- {
- return f_;
- }
- std::string type_id() const
- {
- return id();
- }
- static inline std::string id()
- {
- return "sf4";
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
- (p0, p1, p2, p3, p4);
- }
- private:
- T0oT1oT2oT3_sf4(node_type&) {}
- node_type& operator=(node_type&) { return (*this); }
- T0 t0_;
- T1 t1_;
- T2 t2_;
- T3 t3_;
- const qfunc_t f_;
- };
- template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
- class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
- {
- public:
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::tfunc_t tfunc_t;
- typedef T value_type;
- typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
- T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
- : t0_(p0),
- t1_(p1),
- t2_(p2),
- t3_(p3)
- {}
- inline typename expression_node<T>::node_type type() const
- {
- static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
- return result;
- }
- inline operator_type operation() const
- {
- return e_default;
- }
- inline T value() const
- {
- return SF4Operation::process(t0_, t1_, t2_, t3_);
- }
- inline T0 t0() const
- {
- return t0_;
- }
- inline T1 t1() const
- {
- return t1_;
- }
- inline T2 t2() const
- {
- return t2_;
- }
- inline T3 t3() const
- {
- return t3_;
- }
- std::string type_id() const
- {
- return id();
- }
- static inline std::string id()
- {
- return SF4Operation::id();
- }
- template <typename Allocator>
- static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
- {
- return allocator
- .template allocate_type<node_type, T0, T1, T2, T3>
- (p0, p1, p2, p3);
- }
- private:
- T0oT1oT2oT3_sf4ext(node_type&) {}
- node_type& operator=(node_type&) { return (*this); }
- T0 t0_;
- T1 t1_;
- T2 t2_;
- T3 t3_;
- };
- template <typename T>
- inline bool is_sf4ext_node(const expression_node<T>* n)
- {
- switch (n->type())
- {
- case expression_node<T>::e_vovovov : return true;
- case expression_node<T>::e_vovovoc : return true;
- case expression_node<T>::e_vovocov : return true;
- case expression_node<T>::e_vocovov : return true;
- case expression_node<T>::e_covovov : return true;
- case expression_node<T>::e_covocov : return true;
- case expression_node<T>::e_vocovoc : return true;
- case expression_node<T>::e_covovoc : return true;
- case expression_node<T>::e_vococov : return true;
- default : return false;
- }
- }
- template <typename T, typename T0, typename T1>
- struct T0oT1_define
- {
- typedef details::T0oT1<T, T0, T1> type0;
- };
- template <typename T, typename T0, typename T1, typename T2>
- struct T0oT1oT2_define
- {
- typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
- typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
- typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
- typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
- };
- template <typename T, typename T0, typename T1, typename T2, typename T3>
- struct T0oT1oT2oT3_define
- {
- typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
- typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
- typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
- typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
- typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
- typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
- };
- template <typename T, typename Operation>
- class vov_node : public vov_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // variable op variable node
- explicit vov_node(const T& var0, const T& var1)
- : v0_(var0),
- v1_(var1)
- {}
- inline T value() const
- {
- return Operation::process(v0_,v1_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T& v0() const
- {
- return v0_;
- }
- inline const T& v1() const
- {
- return v1_;
- }
- protected:
- const T& v0_;
- const T& v1_;
- private:
- vov_node(vov_node<T,Operation>&);
- vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
- };
- template <typename T, typename Operation>
- class cov_node : public cov_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // constant op variable node
- explicit cov_node(const T& const_var, const T& var)
- : c_(const_var),
- v_(var)
- {}
- inline T value() const
- {
- return Operation::process(c_,v_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T c() const
- {
- return c_;
- }
- inline const T& v() const
- {
- return v_;
- }
- protected:
- const T c_;
- const T& v_;
- private:
- cov_node(const cov_node<T,Operation>&);
- cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
- };
- template <typename T, typename Operation>
- class voc_node : public voc_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // variable op constant node
- explicit voc_node(const T& var, const T& const_var)
- : v_(var),
- c_(const_var)
- {}
- inline T value() const
- {
- return Operation::process(v_,c_);
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T c() const
- {
- return c_;
- }
- inline const T& v() const
- {
- return v_;
- }
- protected:
- const T& v_;
- const T c_;
- private:
- voc_node(const voc_node<T,Operation>&);
- voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
- };
- template <typename T, typename Operation>
- class vob_node : public vob_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- typedef Operation operation_t;
- // variable op constant node
- explicit vob_node(const T& var, const expression_ptr brnch)
- : v_(var)
- {
- init_branches<1>(branch_,brnch);
- }
- ~vob_node()
- {
- cleanup_branches::execute<T,1>(branch_);
- }
- inline T value() const
- {
- return Operation::process(v_,branch_[0].first->value());
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T& v() const
- {
- return v_;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_[0].first;
- }
- private:
- vob_node(const vob_node<T,Operation>&);
- vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
- const T& v_;
- branch_t branch_[1];
- };
- template <typename T, typename Operation>
- class bov_node : public bov_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- typedef Operation operation_t;
- // variable op constant node
- explicit bov_node(const expression_ptr brnch, const T& var)
- : v_(var)
- {
- init_branches<1>(branch_,brnch);
- }
- ~bov_node()
- {
- cleanup_branches::execute<T,1>(branch_);
- }
- inline T value() const
- {
- return Operation::process(branch_[0].first->value(),v_);
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T& v() const
- {
- return v_;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_[0].first;
- }
- private:
- bov_node(const bov_node<T,Operation>&);
- bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
- const T& v_;
- branch_t branch_[1];
- };
- template <typename T, typename Operation>
- class cob_node : public cob_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- typedef Operation operation_t;
- // variable op constant node
- explicit cob_node(const T const_var, const expression_ptr brnch)
- : c_(const_var)
- {
- init_branches<1>(branch_,brnch);
- }
- ~cob_node()
- {
- cleanup_branches::execute<T,1>(branch_);
- }
- inline T value() const
- {
- return Operation::process(c_,branch_[0].first->value());
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T c() const
- {
- return c_;
- }
- inline void set_c(const T new_c)
- {
- (*const_cast<T*>(&c_)) = new_c;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_[0].first;
- }
- inline expression_node<T>* move_branch(const std::size_t&)
- {
- branch_[0].second = false;
- return branch_[0].first;
- }
- private:
- cob_node(const cob_node<T,Operation>&);
- cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
- const T c_;
- branch_t branch_[1];
- };
- template <typename T, typename Operation>
- class boc_node : public boc_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr,bool> branch_t;
- typedef Operation operation_t;
- // variable op constant node
- explicit boc_node(const expression_ptr brnch, const T const_var)
- : c_(const_var)
- {
- init_branches<1>(branch_,brnch);
- }
- ~boc_node()
- {
- cleanup_branches::execute<T,1>(branch_);
- }
- inline T value() const
- {
- return Operation::process(branch_[0].first->value(),c_);
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline const T c() const
- {
- return c_;
- }
- inline void set_c(const T new_c)
- {
- (*const_cast<T*>(&c_)) = new_c;
- }
- inline expression_node<T>* branch(const std::size_t&) const
- {
- return branch_[0].first;
- }
- inline expression_node<T>* move_branch(const std::size_t&)
- {
- branch_[0].second = false;
- return branch_[0].first;
- }
- private:
- boc_node(const boc_node<T,Operation>&);
- boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
- const T c_;
- branch_t branch_[1];
- };
- #ifndef exprtk_disable_string_capabilities
- template <typename T, typename SType0, typename SType1, typename Operation>
- class sos_node : public sos_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // string op string node
- explicit sos_node(SType0 p0, SType1 p1)
- : s0_(p0),
- s1_(p1)
- {}
- inline T value() const
- {
- return Operation::process(s0_,s1_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline std::string& s0()
- {
- return s0_;
- }
- inline std::string& s1()
- {
- return s1_;
- }
- protected:
- SType0 s0_;
- SType1 s1_;
- private:
- sos_node(sos_node<T,SType0,SType1,Operation>&);
- sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
- };
- template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
- class str_xrox_node : public sos_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // string-range op string node
- explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
- : s0_ (p0 ),
- s1_ (p1 ),
- rp0_(rp0)
- {}
- ~str_xrox_node()
- {
- rp0_.free();
- }
- inline T value() const
- {
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- if (rp0_(r0, r1, s0_.size()))
- return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
- else
- return T(0);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline std::string& s0()
- {
- return s0_;
- }
- inline std::string& s1()
- {
- return s1_;
- }
- protected:
- SType0 s0_;
- SType1 s1_;
- RangePack rp0_;
- private:
- str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
- str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
- };
- template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
- class str_xoxr_node : public sos_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // string op string range node
- explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
- : s0_ (p0 ),
- s1_ (p1 ),
- rp1_(rp1)
- {}
- ~str_xoxr_node()
- {
- rp1_.free();
- }
- inline T value() const
- {
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- if (rp1_(r0, r1, s1_.size()))
- return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
- else
- return T(0);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline std::string& s0()
- {
- return s0_;
- }
- inline std::string& s1()
- {
- return s1_;
- }
- protected:
- SType0 s0_;
- SType1 s1_;
- RangePack rp1_;
- private:
- str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
- str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
- };
- template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
- class str_xroxr_node : public sos_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // string-range op string-range node
- explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
- : s0_ (p0 ),
- s1_ (p1 ),
- rp0_(rp0),
- rp1_(rp1)
- {}
- ~str_xroxr_node()
- {
- rp0_.free();
- rp1_.free();
- }
- inline T value() const
- {
- std::size_t r0_0 = 0;
- std::size_t r0_1 = 0;
- std::size_t r1_0 = 0;
- std::size_t r1_1 = 0;
- if (
- rp0_(r0_0, r1_0, s0_.size()) &&
- rp1_(r0_1, r1_1, s1_.size())
- )
- {
- return Operation::process(
- s0_.substr(r0_0, (r1_0 - r0_0) + 1),
- s1_.substr(r0_1, (r1_1 - r0_1) + 1)
- );
- }
- else
- return T(0);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline std::string& s0()
- {
- return s0_;
- }
- inline std::string& s1()
- {
- return s1_;
- }
- protected:
- SType0 s0_;
- SType1 s1_;
- RangePack rp0_;
- RangePack rp1_;
- private:
- str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
- str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
- };
- template <typename T, typename Operation>
- class str_sogens_node : public binary_node<T>
- {
- public:
- typedef expression_node <T>* expression_ptr;
- typedef string_base_node<T>* str_base_ptr;
- typedef range_pack <T> range_t;
- typedef range_t* range_ptr;
- typedef range_interface<T> irange_t;
- typedef irange_t* irange_ptr;
- str_sogens_node(const operator_type& opr,
- expression_ptr branch0,
- expression_ptr branch1)
- : binary_node<T>(opr, branch0, branch1),
- str0_base_ptr_ (0),
- str1_base_ptr_ (0),
- str0_range_ptr_(0),
- str1_range_ptr_(0)
- {
- if (is_generally_string_node(binary_node<T>::branch_[0].first))
- {
- str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
- if (0 == str0_base_ptr_)
- return;
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
- if (0 == range)
- return;
- str0_range_ptr_ = &(range->range_ref());
- }
- if (is_generally_string_node(binary_node<T>::branch_[1].first))
- {
- str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
- if (0 == str1_base_ptr_)
- return;
- irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
- if (0 == range)
- return;
- str1_range_ptr_ = &(range->range_ref());
- }
- }
- inline T value() const
- {
- if (
- str0_base_ptr_ &&
- str1_base_ptr_ &&
- str0_range_ptr_ &&
- str1_range_ptr_
- )
- {
- binary_node<T>::branch_[0].first->value();
- binary_node<T>::branch_[1].first->value();
- std::size_t str0_r0 = 0;
- std::size_t str0_r1 = 0;
- std::size_t str1_r0 = 0;
- std::size_t str1_r1 = 0;
- range_t& range0 = (*str0_range_ptr_);
- range_t& range1 = (*str1_range_ptr_);
- if (
- range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
- range1(str1_r0, str1_r1, str1_base_ptr_->size())
- )
- {
- return Operation::process(
- str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
- str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
- );
- }
- }
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- private:
- str_sogens_node(str_sogens_node<T,Operation>&);
- str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
- str_base_ptr str0_base_ptr_;
- str_base_ptr str1_base_ptr_;
- range_ptr str0_range_ptr_;
- range_ptr str1_range_ptr_;
- };
- template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
- class sosos_node : public sosos_base_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef Operation operation_t;
- // variable op variable node
- explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
- : s0_(p0),
- s1_(p1),
- s2_(p2)
- {}
- inline T value() const
- {
- return Operation::process(s0_,s1_,s2_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return Operation::type();
- }
- inline operator_type operation() const
- {
- return Operation::operation();
- }
- inline std::string& s0()
- {
- return s0_;
- }
- inline std::string& s1()
- {
- return s1_;
- }
- inline std::string& s2()
- {
- return s2_;
- }
- protected:
- SType0 s0_;
- SType1 s1_;
- SType2 s2_;
- private:
- sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
- sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
- };
- #endif
- template <typename T, typename PowOp>
- class ipow_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef PowOp operation_t;
- explicit ipow_node(const T& v)
- : v_(v)
- {}
- inline T value() const
- {
- return PowOp::result(v_);
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_ipow;
- }
- private:
- ipow_node(const ipow_node<T,PowOp>&);
- ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
- const T& v_;
- };
- template <typename T, typename PowOp>
- class bipow_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr, bool> branch_t;
- typedef PowOp operation_t;
- explicit bipow_node(expression_ptr brnch)
- {
- init_branches<1>(branch_, brnch);
- }
- ~bipow_node()
- {
- cleanup_branches::execute<T,1>(branch_);
- }
- inline T value() const
- {
- return PowOp::result(branch_[0].first->value());
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_ipow;
- }
- private:
- bipow_node(const bipow_node<T,PowOp>&);
- bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
- branch_t branch_[1];
- };
- template <typename T, typename PowOp>
- class ipowinv_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef PowOp operation_t;
- explicit ipowinv_node(const T& v)
- : v_(v)
- {}
- inline T value() const
- {
- return (T(1) / PowOp::result(v_));
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_ipowinv;
- }
- private:
- ipowinv_node(const ipowinv_node<T,PowOp>&);
- ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
- const T& v_;
- };
- template <typename T, typename PowOp>
- class bipowninv_node : public expression_node<T>
- {
- public:
- typedef expression_node<T>* expression_ptr;
- typedef std::pair<expression_ptr, bool> branch_t;
- typedef PowOp operation_t;
- explicit bipowninv_node(expression_ptr brnch)
- {
- init_branches<1>(branch_, brnch);
- }
- ~bipowninv_node()
- {
- cleanup_branches::execute<T,1>(branch_);
- }
- inline T value() const
- {
- return (T(1) / PowOp::result(branch_[0].first->value()));
- }
- inline typename expression_node<T>::node_type type() const
- {
- return expression_node<T>::e_ipowinv;
- }
- private:
- bipowninv_node(const bipowninv_node<T,PowOp>&);
- bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
- branch_t branch_[1];
- };
- template <typename T>
- inline bool is_vov_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const vov_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_cov_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const cov_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_voc_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const voc_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_cob_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const cob_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_boc_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const boc_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_t0ot1ot2_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_uv_node(const expression_node<T>* node)
- {
- return (0 != dynamic_cast<const uv_base_node<T>*>(node));
- }
- template <typename T>
- inline bool is_string_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_stringvar == node->type());
- }
- template <typename T>
- inline bool is_string_range_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_stringvarrng == node->type());
- }
- template <typename T>
- inline bool is_const_string_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_stringconst == node->type());
- }
- template <typename T>
- inline bool is_const_string_range_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_cstringvarrng == node->type());
- }
- template <typename T>
- inline bool is_string_assignment_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_strass == node->type());
- }
- template <typename T>
- inline bool is_string_concat_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_strconcat == node->type());
- }
- template <typename T>
- inline bool is_string_function_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_strfunction == node->type());
- }
- template <typename T>
- inline bool is_string_condition_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_strcondition == node->type());
- }
- template <typename T>
- inline bool is_string_ccondition_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_strccondition == node->type());
- }
- template <typename T>
- inline bool is_string_vararg_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_stringvararg == node->type());
- }
- template <typename T>
- inline bool is_genricstring_range_node(const expression_node<T>* node)
- {
- return node && (expression_node<T>::e_strgenrange == node->type());
- }
- template <typename T>
- inline bool is_generally_string_node(const expression_node<T>* node)
- {
- if (node)
- {
- switch (node->type())
- {
- case expression_node<T>::e_stringvar :
- case expression_node<T>::e_stringconst :
- case expression_node<T>::e_stringvarrng :
- case expression_node<T>::e_cstringvarrng :
- case expression_node<T>::e_strgenrange :
- case expression_node<T>::e_strass :
- case expression_node<T>::e_strconcat :
- case expression_node<T>::e_strfunction :
- case expression_node<T>::e_strcondition :
- case expression_node<T>::e_strccondition :
- case expression_node<T>::e_stringvararg : return true;
- default : return false;
- }
- }
- return false;
- }
- class node_allocator
- {
- public:
- template <typename ResultNode, typename OpType, typename ExprNode>
- inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
- {
- return allocate<ResultNode>(operation, branch[0]);
- }
- template <typename ResultNode, typename OpType, typename ExprNode>
- inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
- {
- return allocate<ResultNode>(operation, branch[0], branch[1]);
- }
- template <typename ResultNode, typename OpType, typename ExprNode>
- inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
- {
- return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
- }
- template <typename ResultNode, typename OpType, typename ExprNode>
- inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
- {
- return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
- }
- template <typename ResultNode, typename OpType, typename ExprNode>
- inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
- {
- return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
- }
- template <typename ResultNode, typename OpType, typename ExprNode>
- inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
- {
- return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
- }
- template <typename node_type>
- inline expression_node<typename node_type::value_type>* allocate() const
- {
- return (new node_type());
- }
- template <typename node_type,
- typename Type,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
- {
- return (new node_type(seq));
- }
- template <typename node_type, typename T1>
- inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
- {
- return (new node_type(t1));
- }
- template <typename node_type, typename T1>
- inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
- {
- return (new node_type(t1));
- }
- template <typename node_type,
- typename T1, typename T2>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
- {
- return (new node_type(t1, t2));
- }
- template <typename node_type,
- typename T1, typename T2>
- inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
- {
- return (new node_type(t1, t2));
- }
- template <typename node_type,
- typename T1, typename T2>
- inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
- {
- return (new node_type(t1, t2));
- }
- template <typename node_type,
- typename T1, typename T2>
- inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
- {
- return (new node_type(t1, t2));
- }
- template <typename node_type,
- typename T1, typename T2>
- inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
- {
- return (new node_type(t1, t2));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3>
- inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
- {
- return (new node_type(t1, t2, t3));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3, typename T4>
- inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
- {
- return (new node_type(t1, t2, t3, t4));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3>
- inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
- {
- return (new node_type(t1, t2, t3));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3, typename T4>
- inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
- {
- return (new node_type(t1, t2, t3, t4));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3, typename T4, typename T5>
- inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
- {
- return (new node_type(t1, t2, t3, t4, t5));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3) const
- {
- return (new node_type(t1, t2, t3));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4) const
- {
- return (new node_type(t1, t2, t3, t4));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4, typename T5>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4,
- const T5& t5) const
- {
- return (new node_type(t1, t2, t3, t4, t5));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4, typename T5, typename T6>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4,
- const T5& t5, const T6& t6) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5, typename T6, typename T7>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4,
- const T5& t5, const T6& t6,
- const T7& t7) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6, t7));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5, typename T6,
- typename T7, typename T8>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4,
- const T5& t5, const T6& t6,
- const T7& t7, const T8& t8) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5, typename T6,
- typename T7, typename T8, typename T9>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4,
- const T5& t5, const T6& t6,
- const T7& t7, const T8& t8,
- const T9& t9) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5, typename T6,
- typename T7, typename T8,
- typename T9, typename T10>
- inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
- const T3& t3, const T4& t4,
- const T5& t5, const T6& t6,
- const T7& t7, const T8& t8,
- const T9& t9, const T10& t10) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
- }
- template <typename node_type,
- typename T1, typename T2, typename T3>
- inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
- {
- return (new node_type(t1, t2, t3));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4>
- inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
- T3 t3, T4 t4) const
- {
- return (new node_type(t1, t2, t3, t4));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5>
- inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
- T3 t3, T4 t4,
- T5 t5) const
- {
- return (new node_type(t1, t2, t3, t4, t5));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5, typename T6>
- inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
- T3 t3, T4 t4,
- T5 t5, T6 t6) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6));
- }
- template <typename node_type,
- typename T1, typename T2,
- typename T3, typename T4,
- typename T5, typename T6, typename T7>
- inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
- T3 t3, T4 t4,
- T5 t5, T6 t6,
- T7 t7) const
- {
- return (new node_type(t1, t2, t3, t4, t5, t6, t7));
- }
- template <typename T>
- void inline free(expression_node<T>*& e) const
- {
- delete e;
- e = 0;
- }
- };
- inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
- {
- #define register_op(Symbol,Type,Args) \
- m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
- register_op( "abs", e_abs , 1)
- register_op( "acos", e_acos , 1)
- register_op( "acosh", e_acosh , 1)
- register_op( "asin", e_asin , 1)
- register_op( "asinh", e_asinh , 1)
- register_op( "atan", e_atan , 1)
- register_op( "atanh", e_atanh , 1)
- register_op( "ceil", e_ceil , 1)
- register_op( "cos", e_cos , 1)
- register_op( "cosh", e_cosh , 1)
- register_op( "exp", e_exp , 1)
- register_op( "expm1", e_expm1 , 1)
- register_op( "floor", e_floor , 1)
- register_op( "log", e_log , 1)
- register_op( "log10", e_log10 , 1)
- register_op( "log2", e_log2 , 1)
- register_op( "log1p", e_log1p , 1)
- register_op( "round", e_round , 1)
- register_op( "sin", e_sin , 1)
- register_op( "sinc", e_sinc , 1)
- register_op( "sinh", e_sinh , 1)
- register_op( "sec", e_sec , 1)
- register_op( "csc", e_csc , 1)
- register_op( "sqrt", e_sqrt , 1)
- register_op( "tan", e_tan , 1)
- register_op( "tanh", e_tanh , 1)
- register_op( "cot", e_cot , 1)
- register_op( "rad2deg", e_r2d , 1)
- register_op( "deg2rad", e_d2r , 1)
- register_op( "deg2grad", e_d2g , 1)
- register_op( "grad2deg", e_g2d , 1)
- register_op( "sgn", e_sgn , 1)
- register_op( "not", e_notl , 1)
- register_op( "erf", e_erf , 1)
- register_op( "erfc", e_erfc , 1)
- register_op( "ncdf", e_ncdf , 1)
- register_op( "frac", e_frac , 1)
- register_op( "trunc", e_trunc , 1)
- register_op( "atan2", e_atan2 , 2)
- register_op( "mod", e_mod , 2)
- register_op( "logn", e_logn , 2)
- register_op( "pow", e_pow , 2)
- register_op( "root", e_root , 2)
- register_op( "roundn", e_roundn , 2)
- register_op( "equal", e_equal , 2)
- register_op("not_equal", e_nequal , 2)
- register_op( "hypot", e_hypot , 2)
- register_op( "shr", e_shr , 2)
- register_op( "shl", e_shl , 2)
- register_op( "clamp", e_clamp , 3)
- register_op( "iclamp", e_iclamp , 3)
- register_op( "inrange", e_inrange , 3)
- #undef register_op
- }
- } // namespace details
- class function_traits
- {
- public:
- function_traits()
- : allow_zero_parameters_(false),
- has_side_effects_(true),
- min_num_args_(0),
- max_num_args_(std::numeric_limits<std::size_t>::max())
- {}
- inline bool& allow_zero_parameters()
- {
- return allow_zero_parameters_;
- }
- inline bool& has_side_effects()
- {
- return has_side_effects_;
- }
- std::size_t& min_num_args()
- {
- return min_num_args_;
- }
- std::size_t& max_num_args()
- {
- return max_num_args_;
- }
- private:
- bool allow_zero_parameters_;
- bool has_side_effects_;
- std::size_t min_num_args_;
- std::size_t max_num_args_;
- };
- template <typename FunctionType>
- void enable_zero_parameters(FunctionType& func)
- {
- func.allow_zero_parameters() = true;
- if (0 != func.min_num_args())
- {
- func.min_num_args() = 0;
- }
- }
- template <typename FunctionType>
- void disable_zero_parameters(FunctionType& func)
- {
- func.allow_zero_parameters() = false;
- }
- template <typename FunctionType>
- void enable_has_side_effects(FunctionType& func)
- {
- func.has_side_effects() = true;
- }
- template <typename FunctionType>
- void disable_has_side_effects(FunctionType& func)
- {
- func.has_side_effects() = false;
- }
- template <typename FunctionType>
- void set_min_num_args(FunctionType& func, const std::size_t& num_args)
- {
- func.min_num_args() = num_args;
- if ((0 != func.min_num_args()) && func.allow_zero_parameters())
- func.allow_zero_parameters() = false;
- }
- template <typename FunctionType>
- void set_max_num_args(FunctionType& func, const std::size_t& num_args)
- {
- func.max_num_args() = num_args;
- }
- template <typename T>
- class ifunction : public function_traits
- {
- public:
- explicit ifunction(const std::size_t& pc)
- : param_count(pc)
- {}
- virtual ~ifunction()
- {}
- #define empty_method_body \
- { \
- return std::numeric_limits<T>::quiet_NaN(); \
- } \
- inline virtual T operator() ()
- empty_method_body
- inline virtual T operator() (const T&)
- empty_method_body
- inline virtual T operator() (const T&,const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
- const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
- empty_method_body
- #undef empty_method_body
- std::size_t param_count;
- };
- template <typename T>
- class ivararg_function : public function_traits
- {
- public:
- virtual ~ivararg_function()
- {}
- inline virtual T operator() (const std::vector<T>&)
- {
- exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
- return std::numeric_limits<T>::quiet_NaN();
- }
- };
- template <typename T>
- class igeneric_function : public function_traits
- {
- public:
- enum return_type
- {
- e_rtrn_scalar = 0,
- e_rtrn_string = 1,
- e_rtrn_overload = 2
- };
- typedef T type;
- typedef type_store<T> generic_type;
- typedef typename generic_type::parameter_list parameter_list_t;
- igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
- : parameter_sequence(param_seq),
- rtrn_type(rtr_type)
- {}
- virtual ~igeneric_function()
- {}
- #define igeneric_function_empty_body(N) \
- { \
- exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
- return std::numeric_limits<T>::quiet_NaN(); \
- } \
- // f(i_0,i_1,....,i_N) --> Scalar
- inline virtual T operator() (parameter_list_t)
- igeneric_function_empty_body(1)
- // f(i_0,i_1,....,i_N) --> String
- inline virtual T operator() (std::string&, parameter_list_t)
- igeneric_function_empty_body(2)
- // f(psi,i_0,i_1,....,i_N) --> Scalar
- inline virtual T operator() (const std::size_t&, parameter_list_t)
- igeneric_function_empty_body(3)
- // f(psi,i_0,i_1,....,i_N) --> String
- inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
- igeneric_function_empty_body(4)
- std::string parameter_sequence;
- return_type rtrn_type;
- };
- template <typename T> class parser;
- template <typename T> class expression_helper;
- template <typename T>
- class symbol_table
- {
- public:
- typedef T (*ff00_functor)();
- typedef T (*ff01_functor)(T);
- typedef T (*ff02_functor)(T, T);
- typedef T (*ff03_functor)(T, T, T);
- typedef T (*ff04_functor)(T, T, T, T);
- typedef T (*ff05_functor)(T, T, T, T, T);
- typedef T (*ff06_functor)(T, T, T, T, T, T);
- typedef T (*ff07_functor)(T, T, T, T, T, T, T);
- typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
- typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
- typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
- typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
- typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
- typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
- typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
- typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
- protected:
- struct freefunc00 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
- inline T operator() ()
- { return f(); }
- ff00_functor f;
- };
- struct freefunc01 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
- inline T operator() (const T& v0)
- { return f(v0); }
- ff01_functor f;
- };
- struct freefunc02 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
- inline T operator() (const T& v0, const T& v1)
- { return f(v0, v1); }
- ff02_functor f;
- };
- struct freefunc03 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2)
- { return f(v0, v1, v2); }
- ff03_functor f;
- };
- struct freefunc04 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
- { return f(v0, v1, v2, v3); }
- ff04_functor f;
- };
- struct freefunc05 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
- { return f(v0, v1, v2, v3, v4); }
- ff05_functor f;
- };
- struct freefunc06 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
- { return f(v0, v1, v2, v3, v4, v5); }
- ff06_functor f;
- };
- struct freefunc07 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
- const T& v5, const T& v6)
- { return f(v0, v1, v2, v3, v4, v5, v6); }
- ff07_functor f;
- };
- struct freefunc08 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
- const T& v5, const T& v6, const T& v7)
- { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
- ff08_functor f;
- };
- struct freefunc09 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
- const T& v5, const T& v6, const T& v7, const T& v8)
- { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
- ff09_functor f;
- };
- struct freefunc10 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
- const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
- { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
- ff10_functor f;
- };
- struct freefunc11 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
- inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
- const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
- { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
- ff11_functor f;
- };
- struct freefunc12 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
- inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
- const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
- const T& v10, const T& v11)
- { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
- ff12_functor f;
- };
- struct freefunc13 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
- inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
- const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
- const T& v10, const T& v11, const T& v12)
- { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
- ff13_functor f;
- };
- struct freefunc14 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
- inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
- const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
- const T& v10, const T& v11, const T& v12, const T& v13)
- { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
- ff14_functor f;
- };
- struct freefunc15 : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
- inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
- const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
- const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
- { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
- ff15_functor f;
- };
- template <typename Type, typename RawType>
- struct type_store
- {
- typedef details::expression_node<T>* expression_ptr;
- typedef typename details::variable_node<T> variable_node_t;
- typedef ifunction<T> ifunction_t;
- typedef ivararg_function<T> ivararg_function_t;
- typedef igeneric_function<T> igeneric_function_t;
- typedef details::vector_holder<T> vector_t;
- #ifndef exprtk_disable_string_capabilities
- typedef typename details::stringvar_node<T> stringvar_node_t;
- #endif
- typedef Type type_t;
- typedef type_t* type_ptr;
- typedef std::pair<bool,type_ptr> type_pair_t;
- typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
- typedef typename type_map_t::iterator tm_itr_t;
- typedef typename type_map_t::const_iterator tm_const_itr_t;
- enum { lut_size = 256 };
- type_map_t map;
- std::size_t size;
- type_store()
- : size(0)
- {}
- inline bool symbol_exists(const std::string& symbol_name) const
- {
- if (symbol_name.empty())
- return false;
- else if (map.end() != map.find(symbol_name))
- return true;
- else
- return false;
- }
- template <typename PtrType>
- inline std::string entity_name(const PtrType& ptr) const
- {
- if (map.empty())
- return std::string();
- tm_const_itr_t itr = map.begin();
- while (map.end() != itr)
- {
- if (itr->second.second == ptr)
- {
- return itr->first;
- }
- else
- ++itr;
- }
- return std::string();
- }
- inline bool is_constant(const std::string& symbol_name) const
- {
- if (symbol_name.empty())
- return false;
- else
- {
- const tm_const_itr_t itr = map.find(symbol_name);
- if (map.end() == itr)
- return false;
- else
- return (*itr).second.first;
- }
- }
- template <typename Tie, typename RType>
- inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
- {
- if (symbol_name.size() > 1)
- {
- for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
- {
- if (details::imatch(symbol_name, details::reserved_symbols[i]))
- {
- return false;
- }
- }
- }
- const tm_itr_t itr = map.find(symbol_name);
- if (map.end() == itr)
- {
- map[symbol_name] = Tie::make(t,is_const);
- ++size;
- }
- return true;
- }
- struct tie_array
- {
- static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
- {
- return std::make_pair(is_const, new vector_t(v.first, v.second));
- }
- };
- struct tie_stdvec
- {
- template <typename Allocator>
- static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
- {
- return std::make_pair(is_const, new vector_t(v));
- }
- };
- struct tie_vecview
- {
- static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
- {
- return std::make_pair(is_const, new vector_t(v));
- }
- };
- struct tie_stddeq
- {
- template <typename Allocator>
- static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
- {
- return std::make_pair(is_const, new vector_t(v));
- }
- };
- template <std::size_t v_size>
- inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
- {
- return add_impl<tie_array,std::pair<T*,std::size_t> >
- (symbol_name, std::make_pair(v,v_size), is_const);
- }
- inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
- {
- return add_impl<tie_array,std::pair<T*,std::size_t> >
- (symbol_name, std::make_pair(v,v_size), is_const);
- }
- template <typename Allocator>
- inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
- {
- return add_impl<tie_stdvec,std::vector<T,Allocator>&>
- (symbol_name, v, is_const);
- }
- inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
- {
- return add_impl<tie_vecview,exprtk::vector_view<T>&>
- (symbol_name, v, is_const);
- }
- template <typename Allocator>
- inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
- {
- return add_impl<tie_stddeq,std::deque<T,Allocator>&>
- (symbol_name, v, is_const);
- }
- inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
- {
- struct tie
- {
- static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
- {
- return std::make_pair(is_const, new variable_node_t(t));
- }
- #ifndef exprtk_disable_string_capabilities
- static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
- {
- return std::make_pair(is_const, new stringvar_node_t(t));
- }
- #endif
- static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
- {
- return std::make_pair(is_constant,&t);
- }
- static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
- {
- return std::make_pair(is_const,&t);
- }
- static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
- {
- return std::make_pair(is_constant,&t);
- }
- };
- const tm_itr_t itr = map.find(symbol_name);
- if (map.end() == itr)
- {
- map[symbol_name] = tie::make(t,is_const);
- ++size;
- }
- return true;
- }
- inline type_ptr get(const std::string& symbol_name) const
- {
- const tm_const_itr_t itr = map.find(symbol_name);
- if (map.end() == itr)
- return reinterpret_cast<type_ptr>(0);
- else
- return itr->second.second;
- }
- template <typename TType, typename TRawType, typename PtrType>
- struct ptr_match
- {
- static inline bool test(const PtrType, const void*)
- {
- return false;
- }
- };
- template <typename TType, typename TRawType>
- struct ptr_match<TType,TRawType,variable_node_t*>
- {
- static inline bool test(const variable_node_t* p, const void* ptr)
- {
- exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
- return (&(p->ref()) == ptr);
- }
- };
- inline type_ptr get_from_varptr(const void* ptr) const
- {
- tm_const_itr_t itr = map.begin();
- while (map.end() != itr)
- {
- type_ptr ret_ptr = itr->second.second;
- if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
- {
- return ret_ptr;
- }
- ++itr;
- }
- return type_ptr(0);
- }
- inline bool remove(const std::string& symbol_name, const bool delete_node = true)
- {
- const tm_itr_t itr = map.find(symbol_name);
- if (map.end() != itr)
- {
- struct deleter
- {
- static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
- static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
- #ifndef exprtk_disable_string_capabilities
- static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
- #endif
- static inline void process(std::pair<bool,function_t*>&) { }
- };
- if (delete_node)
- {
- deleter::process((*itr).second);
- }
- map.erase(itr);
- --size;
- return true;
- }
- else
- return false;
- }
- inline RawType& type_ref(const std::string& symbol_name)
- {
- struct init_type
- {
- static inline double set(double) { return (0.0); }
- static inline double set(long double) { return (0.0); }
- static inline float set(float) { return (0.0f); }
- static inline std::string set(std::string) { return std::string(""); }
- };
- static RawType null_type = init_type::set(RawType());
- const tm_const_itr_t itr = map.find(symbol_name);
- if (map.end() == itr)
- return null_type;
- else
- return itr->second.second->ref();
- }
- inline void clear(const bool delete_node = true)
- {
- struct deleter
- {
- static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
- static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
- static inline void process(std::pair<bool,function_t*>&) { }
- #ifndef exprtk_disable_string_capabilities
- static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
- #endif
- };
- if (!map.empty())
- {
- if (delete_node)
- {
- tm_itr_t itr = map.begin();
- tm_itr_t end = map.end ();
- while (end != itr)
- {
- deleter::process((*itr).second);
- ++itr;
- }
- }
- map.clear();
- }
- size = 0;
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
- {
- std::size_t count = 0;
- if (!map.empty())
- {
- tm_const_itr_t itr = map.begin();
- tm_const_itr_t end = map.end ();
- while (end != itr)
- {
- list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
- ++itr;
- ++count;
- }
- }
- return count;
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
- {
- std::size_t count = 0;
- if (!map.empty())
- {
- tm_const_itr_t itr = map.begin();
- tm_const_itr_t end = map.end ();
- while (end != itr)
- {
- vlist.push_back((*itr).first);
- ++itr;
- ++count;
- }
- }
- return count;
- }
- };
- typedef details::expression_node<T>* expression_ptr;
- typedef typename details::variable_node<T> variable_t;
- typedef typename details::vector_holder<T> vector_holder_t;
- typedef variable_t* variable_ptr;
- #ifndef exprtk_disable_string_capabilities
- typedef typename details::stringvar_node<T> stringvar_t;
- typedef stringvar_t* stringvar_ptr;
- #endif
- typedef ifunction <T> function_t;
- typedef ivararg_function <T> vararg_function_t;
- typedef igeneric_function<T> generic_function_t;
- typedef function_t* function_ptr;
- typedef vararg_function_t* vararg_function_ptr;
- typedef generic_function_t* generic_function_ptr;
- static const std::size_t lut_size = 256;
- // Symbol Table Holder
- struct control_block
- {
- struct st_data
- {
- type_store<typename details::variable_node<T>,T> variable_store;
- #ifndef exprtk_disable_string_capabilities
- type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
- #endif
- type_store<ifunction<T>,ifunction<T> > function_store;
- type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;
- type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;
- type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;
- type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store;
- type_store<vector_holder_t,vector_holder_t> vector_store;
- st_data()
- {
- for (std::size_t i = 0; i < details::reserved_words_size; ++i)
- {
- reserved_symbol_table_.insert(details::reserved_words[i]);
- }
- for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
- {
- reserved_symbol_table_.insert(details::reserved_symbols[i]);
- }
- }
- ~st_data()
- {
- for (std::size_t i = 0; i < free_function_list_.size(); ++i)
- {
- delete free_function_list_[i];
- }
- }
- inline bool is_reserved_symbol(const std::string& symbol) const
- {
- return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
- }
- static inline st_data* create()
- {
- return (new st_data);
- }
- static inline void destroy(st_data*& sd)
- {
- delete sd;
- sd = reinterpret_cast<st_data*>(0);
- }
- std::list<T> local_symbol_list_;
- std::list<std::string> local_stringvar_list_;
- std::set<std::string> reserved_symbol_table_;
- std::vector<ifunction<T>*> free_function_list_;
- };
- control_block()
- : ref_count(1),
- data_(st_data::create())
- {}
- explicit control_block(st_data* data)
- : ref_count(1),
- data_(data)
- {}
- ~control_block()
- {
- if (data_ && (0 == ref_count))
- {
- st_data::destroy(data_);
- }
- }
- static inline control_block* create()
- {
- return (new control_block);
- }
- template <typename SymTab>
- static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
- {
- if (cntrl_blck)
- {
- if (
- (0 != cntrl_blck->ref_count) &&
- (0 == --cntrl_blck->ref_count)
- )
- {
- if (sym_tab)
- sym_tab->clear();
- delete cntrl_blck;
- }
- cntrl_blck = 0;
- }
- }
- std::size_t ref_count;
- st_data* data_;
- };
- public:
- symbol_table()
- : control_block_(control_block::create())
- {
- clear();
- }
- ~symbol_table()
- {
- control_block::destroy(control_block_,this);
- }
- symbol_table(const symbol_table<T>& st)
- {
- control_block_ = st.control_block_;
- control_block_->ref_count++;
- }
- inline symbol_table<T>& operator=(const symbol_table<T>& st)
- {
- if (this != &st)
- {
- control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
- control_block_ = st.control_block_;
- control_block_->ref_count++;
- }
- return (*this);
- }
- inline bool operator==(const symbol_table<T>& st) const
- {
- return (this == &st) || (control_block_ == st.control_block_);
- }
- inline void clear_variables(const bool delete_node = true)
- {
- local_data().variable_store.clear(delete_node);
- }
- inline void clear_functions()
- {
- local_data().function_store.clear();
- }
- inline void clear_strings()
- {
- #ifndef exprtk_disable_string_capabilities
- local_data().stringvar_store.clear();
- #endif
- }
- inline void clear_vectors()
- {
- local_data().vector_store.clear();
- }
- inline void clear_local_constants()
- {
- local_data().local_symbol_list_.clear();
- }
- inline void clear()
- {
- if (!valid()) return;
- clear_variables ();
- clear_functions ();
- clear_strings ();
- clear_vectors ();
- clear_local_constants();
- }
- inline std::size_t variable_count() const
- {
- if (valid())
- return local_data().variable_store.size;
- else
- return 0;
- }
- #ifndef exprtk_disable_string_capabilities
- inline std::size_t stringvar_count() const
- {
- if (valid())
- return local_data().stringvar_store.size;
- else
- return 0;
- }
- #endif
- inline std::size_t function_count() const
- {
- if (valid())
- return local_data().function_store.size;
- else
- return 0;
- }
- inline std::size_t vector_count() const
- {
- if (valid())
- return local_data().vector_store.size;
- else
- return 0;
- }
- inline variable_ptr get_variable(const std::string& variable_name) const
- {
- if (!valid())
- return reinterpret_cast<variable_ptr>(0);
- else if (!valid_symbol(variable_name))
- return reinterpret_cast<variable_ptr>(0);
- else
- return local_data().variable_store.get(variable_name);
- }
- inline variable_ptr get_variable(const T& var_ref) const
- {
- if (!valid())
- return reinterpret_cast<variable_ptr>(0);
- else
- return local_data().variable_store.get_from_varptr(
- reinterpret_cast<const void*>(&var_ref));
- }
- #ifndef exprtk_disable_string_capabilities
- inline stringvar_ptr get_stringvar(const std::string& string_name) const
- {
- if (!valid())
- return reinterpret_cast<stringvar_ptr>(0);
- else if (!valid_symbol(string_name))
- return reinterpret_cast<stringvar_ptr>(0);
- else
- return local_data().stringvar_store.get(string_name);
- }
- #endif
- inline function_ptr get_function(const std::string& function_name) const
- {
- if (!valid())
- return reinterpret_cast<function_ptr>(0);
- else if (!valid_symbol(function_name))
- return reinterpret_cast<function_ptr>(0);
- else
- return local_data().function_store.get(function_name);
- }
- inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
- {
- if (!valid())
- return reinterpret_cast<vararg_function_ptr>(0);
- else if (!valid_symbol(vararg_function_name))
- return reinterpret_cast<vararg_function_ptr>(0);
- else
- return local_data().vararg_function_store.get(vararg_function_name);
- }
- inline generic_function_ptr get_generic_function(const std::string& function_name) const
- {
- if (!valid())
- return reinterpret_cast<generic_function_ptr>(0);
- else if (!valid_symbol(function_name))
- return reinterpret_cast<generic_function_ptr>(0);
- else
- return local_data().generic_function_store.get(function_name);
- }
- inline generic_function_ptr get_string_function(const std::string& function_name) const
- {
- if (!valid())
- return reinterpret_cast<generic_function_ptr>(0);
- else if (!valid_symbol(function_name))
- return reinterpret_cast<generic_function_ptr>(0);
- else
- return local_data().string_function_store.get(function_name);
- }
- inline generic_function_ptr get_overload_function(const std::string& function_name) const
- {
- if (!valid())
- return reinterpret_cast<generic_function_ptr>(0);
- else if (!valid_symbol(function_name))
- return reinterpret_cast<generic_function_ptr>(0);
- else
- return local_data().overload_function_store.get(function_name);
- }
- typedef vector_holder_t* vector_holder_ptr;
- inline vector_holder_ptr get_vector(const std::string& vector_name) const
- {
- if (!valid())
- return reinterpret_cast<vector_holder_ptr>(0);
- else if (!valid_symbol(vector_name))
- return reinterpret_cast<vector_holder_ptr>(0);
- else
- return local_data().vector_store.get(vector_name);
- }
- inline T& variable_ref(const std::string& symbol_name)
- {
- static T null_var = T(0);
- if (!valid())
- return null_var;
- else if (!valid_symbol(symbol_name))
- return null_var;
- else
- return local_data().variable_store.type_ref(symbol_name);
- }
- #ifndef exprtk_disable_string_capabilities
- inline std::string& stringvar_ref(const std::string& symbol_name)
- {
- static std::string null_stringvar;
- if (!valid())
- return null_stringvar;
- else if (!valid_symbol(symbol_name))
- return null_stringvar;
- else
- return local_data().stringvar_store.type_ref(symbol_name);
- }
- #endif
- inline bool is_constant_node(const std::string& symbol_name) const
- {
- if (!valid())
- return false;
- else if (!valid_symbol(symbol_name))
- return false;
- else
- return local_data().variable_store.is_constant(symbol_name);
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool is_constant_string(const std::string& symbol_name) const
- {
- if (!valid())
- return false;
- else if (!valid_symbol(symbol_name))
- return false;
- else if (!local_data().stringvar_store.symbol_exists(symbol_name))
- return false;
- else
- return local_data().stringvar_store.is_constant(symbol_name);
- }
- #endif
- inline bool create_variable(const std::string& variable_name, const T& value = T(0))
- {
- if (!valid())
- return false;
- else if (!valid_symbol(variable_name))
- return false;
- else if (symbol_exists(variable_name))
- return false;
- local_data().local_symbol_list_.push_back(value);
- T& t = local_data().local_symbol_list_.back();
- return add_variable(variable_name,t);
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
- {
- if (!valid())
- return false;
- else if (!valid_symbol(stringvar_name))
- return false;
- else if (symbol_exists(stringvar_name))
- return false;
- local_data().local_stringvar_list_.push_back(value);
- std::string& s = local_data().local_stringvar_list_.back();
- return add_stringvar(stringvar_name,s);
- }
- #endif
- inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(variable_name))
- return false;
- else if (symbol_exists(variable_name))
- return false;
- else
- return local_data().variable_store.add(variable_name, t, is_constant);
- }
- inline bool add_constant(const std::string& constant_name, const T& value)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(constant_name))
- return false;
- else if (symbol_exists(constant_name))
- return false;
- local_data().local_symbol_list_.push_back(value);
- T& t = local_data().local_symbol_list_.back();
- return add_variable(constant_name, t, true);
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(stringvar_name))
- return false;
- else if (symbol_exists(stringvar_name))
- return false;
- else
- return local_data().stringvar_store.add(stringvar_name, s, is_constant);
- }
- #endif
- inline bool add_function(const std::string& function_name, function_t& function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
- else
- return local_data().function_store.add(function_name,function);
- }
- inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(vararg_function_name))
- return false;
- else if (symbol_exists(vararg_function_name))
- return false;
- else
- return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
- }
- inline bool add_function(const std::string& function_name, generic_function_t& function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
- else if (
- (
- (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
- (generic_function_t::e_rtrn_string == function.rtrn_type)
- ) &&
- std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|")
- )
- return false;
- else if (
- (generic_function_t::e_rtrn_overload == function.rtrn_type) &&
- std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:")
- )
- return false;
- switch (function.rtrn_type)
- {
- case generic_function_t::e_rtrn_scalar :
- return local_data().generic_function_store.add(function_name,function);
- case generic_function_t::e_rtrn_string :
- return local_data().string_function_store.add(function_name,function);
- case generic_function_t::e_rtrn_overload :
- return local_data().overload_function_store.add(function_name,function);
- }
- return false;
- }
- #define exprtk_define_freefunction(NN) \
- inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
- { \
- if (!valid()) \
- { return false; } \
- if (!valid_symbol(function_name)) \
- { return false; } \
- if (symbol_exists(function_name)) \
- { return false; } \
- \
- exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
- \
- local_data().free_function_list_.push_back(ifunc); \
- \
- return add_function(function_name,(*local_data().free_function_list_.back())); \
- } \
- exprtk_define_freefunction(00) exprtk_define_freefunction(01)
- exprtk_define_freefunction(02) exprtk_define_freefunction(03)
- exprtk_define_freefunction(04) exprtk_define_freefunction(05)
- exprtk_define_freefunction(06) exprtk_define_freefunction(07)
- exprtk_define_freefunction(08) exprtk_define_freefunction(09)
- exprtk_define_freefunction(10) exprtk_define_freefunction(11)
- exprtk_define_freefunction(12) exprtk_define_freefunction(13)
- exprtk_define_freefunction(14) exprtk_define_freefunction(15)
- #undef exprtk_define_freefunction
- inline bool add_reserved_function(const std::string& function_name, function_t& function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name,false))
- return false;
- else if (symbol_exists(function_name,false))
- return false;
- else
- return local_data().function_store.add(function_name,function);
- }
- inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(vararg_function_name,false))
- return false;
- else if (symbol_exists(vararg_function_name,false))
- return false;
- else
- return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
- }
- inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name,false))
- return false;
- else if (symbol_exists(function_name,false))
- return false;
- else if (
- (
- (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
- (generic_function_t::e_rtrn_string == function.rtrn_type)
- ) &&
- std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|")
- )
- return false;
- else if (
- generic_function_t::e_rtrn_overload &&
- std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:")
- )
- return false;
- switch (function.rtrn_type)
- {
- case generic_function_t::e_rtrn_scalar :
- return local_data().generic_function_store.add(function_name,function);
- case generic_function_t::e_rtrn_string :
- return local_data().string_function_store.add(function_name,function);
- case generic_function_t::e_rtrn_overload :
- return local_data().overload_function_store.add(function_name,function);
- }
- return false;
- }
- template <std::size_t N>
- inline bool add_vector(const std::string& vector_name, T (&v)[N])
- {
- if (!valid())
- return false;
- else if (!valid_symbol(vector_name))
- return false;
- else if (symbol_exists(vector_name))
- return false;
- else
- return local_data().vector_store.add(vector_name,v);
- }
- inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(vector_name))
- return false;
- else if (symbol_exists(vector_name))
- return false;
- else if (0 == v_size)
- return false;
- else
- return local_data().vector_store.add(vector_name, v, v_size);
- }
- template <typename Allocator>
- inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(vector_name))
- return false;
- else if (symbol_exists(vector_name))
- return false;
- else if (0 == v.size())
- return false;
- else
- return local_data().vector_store.add(vector_name,v);
- }
- inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(vector_name))
- return false;
- else if (symbol_exists(vector_name))
- return false;
- else if (0 == v.size())
- return false;
- else
- return local_data().vector_store.add(vector_name,v);
- }
- inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
- {
- if (!valid())
- return false;
- else
- return local_data().variable_store.remove(variable_name, delete_node);
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool remove_stringvar(const std::string& string_name)
- {
- if (!valid())
- return false;
- else
- return local_data().stringvar_store.remove(string_name);
- }
- #endif
- inline bool remove_function(const std::string& function_name)
- {
- if (!valid())
- return false;
- else
- return local_data().function_store.remove(function_name);
- }
- inline bool remove_vararg_function(const std::string& vararg_function_name)
- {
- if (!valid())
- return false;
- else
- return local_data().vararg_function_store.remove(vararg_function_name);
- }
- inline bool remove_vector(const std::string& vector_name)
- {
- if (!valid())
- return false;
- else
- return local_data().vector_store.remove(vector_name);
- }
- inline bool add_constants()
- {
- return add_pi () &&
- add_epsilon () &&
- add_infinity() ;
- }
- inline bool add_pi()
- {
- const typename details::numeric::details::number_type<T>::type num_type;
- static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
- return add_constant("pi",local_pi);
- }
- inline bool add_epsilon()
- {
- static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
- return add_constant("epsilon",local_epsilon);
- }
- inline bool add_infinity()
- {
- static const T local_infinity = std::numeric_limits<T>::infinity();
- return add_constant("inf",local_infinity);
- }
- template <typename Package>
- inline bool add_package(Package& package)
- {
- return package.register_package(*this);
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
- {
- if (!valid())
- return 0;
- else
- return local_data().variable_store.get_list(vlist);
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
- {
- if (!valid())
- return 0;
- else
- return local_data().variable_store.get_list(vlist);
- }
- #ifndef exprtk_disable_string_capabilities
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
- {
- if (!valid())
- return 0;
- else
- return local_data().stringvar_store.get_list(svlist);
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
- {
- if (!valid())
- return 0;
- else
- return local_data().stringvar_store.get_list(svlist);
- }
- #endif
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
- {
- if (!valid())
- return 0;
- else
- return local_data().vector_store.get_list(vlist);
- }
- inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
- {
- /*
- Function will return true if symbol_name exists as either a
- reserved symbol, variable, stringvar, vector or function name
- in any of the type stores.
- */
- if (!valid())
- return false;
- else if (local_data().variable_store.symbol_exists(symbol_name))
- return true;
- #ifndef exprtk_disable_string_capabilities
- else if (local_data().stringvar_store.symbol_exists(symbol_name))
- return true;
- #endif
- else if (local_data().vector_store.symbol_exists(symbol_name))
- return true;
- else if (local_data().function_store.symbol_exists(symbol_name))
- return true;
- else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
- return true;
- else
- return false;
- }
- inline bool is_variable(const std::string& variable_name) const
- {
- if (!valid())
- return false;
- else
- return local_data().variable_store.symbol_exists(variable_name);
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool is_stringvar(const std::string& stringvar_name) const
- {
- if (!valid())
- return false;
- else
- return local_data().stringvar_store.symbol_exists(stringvar_name);
- }
- inline bool is_conststr_stringvar(const std::string& symbol_name) const
- {
- if (!valid())
- return false;
- else if (!valid_symbol(symbol_name))
- return false;
- else if (!local_data().stringvar_store.symbol_exists(symbol_name))
- return false;
- return (
- local_data().stringvar_store.symbol_exists(symbol_name) ||
- local_data().stringvar_store.is_constant (symbol_name)
- );
- }
- #endif
- inline bool is_function(const std::string& function_name) const
- {
- if (!valid())
- return false;
- else
- return local_data().function_store.symbol_exists(function_name);
- }
- inline bool is_vararg_function(const std::string& vararg_function_name) const
- {
- if (!valid())
- return false;
- else
- return local_data().vararg_function_store.symbol_exists(vararg_function_name);
- }
- inline bool is_vector(const std::string& vector_name) const
- {
- if (!valid())
- return false;
- else
- return local_data().vector_store.symbol_exists(vector_name);
- }
- inline std::string get_variable_name(const expression_ptr& ptr) const
- {
- return local_data().variable_store.entity_name(ptr);
- }
- inline std::string get_vector_name(const vector_holder_ptr& ptr) const
- {
- return local_data().vector_store.entity_name(ptr);
- }
- #ifndef exprtk_disable_string_capabilities
- inline std::string get_stringvar_name(const expression_ptr& ptr) const
- {
- return local_data().stringvar_store.entity_name(ptr);
- }
- inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
- {
- return local_data().stringvar_store.entity_name(ptr);
- }
- #endif
- inline bool valid() const
- {
- // Symbol table sanity check.
- return control_block_ && control_block_->data_;
- }
- inline void load_from(const symbol_table<T>& st)
- {
- {
- std::vector<std::string> name_list;
- st.local_data().function_store.get_list(name_list);
- if (!name_list.empty())
- {
- for (std::size_t i = 0; i < name_list.size(); ++i)
- {
- exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
- add_function(name_list[i],ifunc);
- }
- }
- }
- {
- std::vector<std::string> name_list;
- st.local_data().vararg_function_store.get_list(name_list);
- if (!name_list.empty())
- {
- for (std::size_t i = 0; i < name_list.size(); ++i)
- {
- exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
- add_function(name_list[i],ivafunc);
- }
- }
- }
- {
- std::vector<std::string> name_list;
- st.local_data().generic_function_store.get_list(name_list);
- if (!name_list.empty())
- {
- for (std::size_t i = 0; i < name_list.size(); ++i)
- {
- exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
- add_function(name_list[i],ifunc);
- }
- }
- }
- {
- std::vector<std::string> name_list;
- st.local_data().string_function_store.get_list(name_list);
- if (!name_list.empty())
- {
- for (std::size_t i = 0; i < name_list.size(); ++i)
- {
- exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
- add_function(name_list[i],ifunc);
- }
- }
- }
- {
- std::vector<std::string> name_list;
- st.local_data().overload_function_store.get_list(name_list);
- if (!name_list.empty())
- {
- for (std::size_t i = 0; i < name_list.size(); ++i)
- {
- exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
- add_function(name_list[i],ifunc);
- }
- }
- }
- }
- private:
- inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
- {
- if (symbol.empty())
- return false;
- else if (!details::is_letter(symbol[0]))
- return false;
- else if (symbol.size() > 1)
- {
- for (std::size_t i = 1; i < symbol.size(); ++i)
- {
- if (
- !details::is_letter_or_digit(symbol[i]) &&
- ('_' != symbol[i])
- )
- {
- if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
- continue;
- else
- return false;
- }
- }
- }
- return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
- }
- inline bool valid_function(const std::string& symbol) const
- {
- if (symbol.empty())
- return false;
- else if (!details::is_letter(symbol[0]))
- return false;
- else if (symbol.size() > 1)
- {
- for (std::size_t i = 1; i < symbol.size(); ++i)
- {
- if (
- !details::is_letter_or_digit(symbol[i]) &&
- ('_' != symbol[i])
- )
- {
- if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
- continue;
- else
- return false;
- }
- }
- }
- return true;
- }
- typedef typename control_block::st_data local_data_t;
- inline local_data_t& local_data()
- {
- return *(control_block_->data_);
- }
- inline const local_data_t& local_data() const
- {
- return *(control_block_->data_);
- }
- control_block* control_block_;
- friend class parser<T>;
- };
- template <typename T>
- class function_compositor;
- template <typename T>
- class expression
- {
- private:
- typedef details::expression_node<T>* expression_ptr;
- typedef details::vector_holder<T>* vector_holder_ptr;
- typedef std::vector<symbol_table<T> > symtab_list_t;
- struct control_block
- {
- enum data_type
- {
- e_unknown ,
- e_expr ,
- e_vecholder,
- e_data ,
- e_vecdata ,
- e_string
- };
- struct data_pack
- {
- data_pack()
- : pointer(0),
- type(e_unknown),
- size(0)
- {}
- data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
- : pointer(ptr),
- type(dt),
- size(sz)
- {}
- void* pointer;
- data_type type;
- std::size_t size;
- };
- typedef std::vector<data_pack> local_data_list_t;
- typedef results_context<T> results_context_t;
- control_block()
- : ref_count(0),
- expr (0),
- results (0),
- retinv_null(false),
- return_invoked(&retinv_null)
- {}
- explicit control_block(expression_ptr e)
- : ref_count(1),
- expr (e),
- results (0),
- retinv_null(false),
- return_invoked(&retinv_null)
- {}
- ~control_block()
- {
- if (expr && details::branch_deletable(expr))
- {
- destroy_node(expr);
- }
- if (!local_data_list.empty())
- {
- for (std::size_t i = 0; i < local_data_list.size(); ++i)
- {
- switch (local_data_list[i].type)
- {
- case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
- break;
- case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
- break;
- case e_data : delete (T*)(local_data_list[i].pointer);
- break;
- case e_vecdata : delete [] (T*)(local_data_list[i].pointer);
- break;
- case e_string : delete (std::string*)(local_data_list[i].pointer);
- break;
- default : break;
- }
- }
- }
- if (results)
- {
- delete results;
- }
- }
- static inline control_block* create(expression_ptr e)
- {
- return new control_block(e);
- }
- static inline void destroy(control_block*& cntrl_blck)
- {
- if (cntrl_blck)
- {
- if (
- (0 != cntrl_blck->ref_count) &&
- (0 == --cntrl_blck->ref_count)
- )
- {
- delete cntrl_blck;
- }
- cntrl_blck = 0;
- }
- }
- std::size_t ref_count;
- expression_ptr expr;
- local_data_list_t local_data_list;
- results_context_t* results;
- bool retinv_null;
- bool* return_invoked;
- friend class function_compositor<T>;
- };
- public:
- expression()
- : control_block_(0)
- {
- set_expression(new details::null_node<T>());
- }
- expression(const expression<T>& e)
- : control_block_ (e.control_block_ ),
- symbol_table_list_(e.symbol_table_list_)
- {
- control_block_->ref_count++;
- }
- explicit expression(const symbol_table<T>& symbol_table)
- : control_block_(0)
- {
- set_expression(new details::null_node<T>());
- symbol_table_list_.push_back(symbol_table);
- }
- inline expression<T>& operator=(const expression<T>& e)
- {
- if (this != &e)
- {
- if (control_block_)
- {
- if (
- (0 != control_block_->ref_count) &&
- (0 == --control_block_->ref_count)
- )
- {
- delete control_block_;
- }
- control_block_ = 0;
- }
- control_block_ = e.control_block_;
- control_block_->ref_count++;
- symbol_table_list_ = e.symbol_table_list_;
- }
- return *this;
- }
- inline bool operator==(const expression<T>& e) const
- {
- return (this == &e);
- }
- inline bool operator!() const
- {
- return (
- (0 == control_block_ ) ||
- (0 == control_block_->expr)
- );
- }
- inline expression<T>& release()
- {
- control_block::destroy(control_block_);
- return (*this);
- }
- ~expression()
- {
- control_block::destroy(control_block_);
- }
- inline T value() const
- {
- return control_block_->expr->value();
- }
- inline T operator() () const
- {
- return value();
- }
- inline operator T() const
- {
- return value();
- }
- inline operator bool() const
- {
- return details::is_true(value());
- }
- inline void register_symbol_table(symbol_table<T>& st)
- {
- symbol_table_list_.push_back(st);
- }
- inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
- {
- return symbol_table_list_[index];
- }
- inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
- {
- return symbol_table_list_[index];
- }
- typedef results_context<T> results_context_t;
- inline const results_context_t& results() const
- {
- if (control_block_->results)
- return (*control_block_->results);
- else
- {
- static const results_context_t null_results;
- return null_results;
- }
- }
- inline bool return_invoked() const
- {
- return (*control_block_->return_invoked);
- }
- private:
- inline symtab_list_t get_symbol_table_list() const
- {
- return symbol_table_list_;
- }
- inline void set_expression(const expression_ptr expr)
- {
- if (expr)
- {
- if (control_block_)
- {
- if (0 == --control_block_->ref_count)
- {
- delete control_block_;
- }
- }
- control_block_ = control_block::create(expr);
- }
- }
- inline void register_local_var(expression_ptr expr)
- {
- if (expr)
- {
- if (control_block_)
- {
- control_block_->
- local_data_list.push_back(
- typename expression<T>::control_block::
- data_pack(reinterpret_cast<void*>(expr),
- control_block::e_expr));
- }
- }
- }
- inline void register_local_var(vector_holder_ptr vec_holder)
- {
- if (vec_holder)
- {
- if (control_block_)
- {
- control_block_->
- local_data_list.push_back(
- typename expression<T>::control_block::
- data_pack(reinterpret_cast<void*>(vec_holder),
- control_block::e_vecholder));
- }
- }
- }
- inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
- {
- if (data)
- {
- if (control_block_)
- {
- typename control_block::data_type dt = control_block::e_data;
- switch (data_mode)
- {
- case 0 : dt = control_block::e_data; break;
- case 1 : dt = control_block::e_vecdata; break;
- case 2 : dt = control_block::e_string; break;
- }
- control_block_->
- local_data_list.push_back(
- typename expression<T>::control_block::
- data_pack(reinterpret_cast<void*>(data), dt, size));
- }
- }
- }
- inline const typename control_block::local_data_list_t& local_data_list()
- {
- if (control_block_)
- {
- return control_block_->local_data_list;
- }
- else
- {
- static typename control_block::local_data_list_t null_local_data_list;
- return null_local_data_list;
- }
- }
- inline void register_return_results(results_context_t* rc)
- {
- if (control_block_ && rc)
- {
- control_block_->results = rc;
- }
- }
- inline void set_retinvk(bool* retinvk_ptr)
- {
- if (control_block_)
- {
- control_block_->return_invoked = retinvk_ptr;
- }
- }
- control_block* control_block_;
- symtab_list_t symbol_table_list_;
- friend class parser<T>;
- friend class expression_helper<T>;
- friend class function_compositor<T>;
- };
- template <typename T>
- class expression_helper
- {
- public:
- static inline bool is_constant(const expression<T>& expr)
- {
- return details::is_constant_node(expr.control_block_->expr);
- }
- static inline bool is_variable(const expression<T>& expr)
- {
- return details::is_variable_node(expr.control_block_->expr);
- }
- static inline bool is_unary(const expression<T>& expr)
- {
- return details::is_unary_node(expr.control_block_->expr);
- }
- static inline bool is_binary(const expression<T>& expr)
- {
- return details::is_binary_node(expr.control_block_->expr);
- }
- static inline bool is_function(const expression<T>& expr)
- {
- return details::is_function(expr.control_block_->expr);
- }
- static inline bool is_null(const expression<T>& expr)
- {
- return details::is_null_node(expr.control_block_->expr);
- }
- };
- template <typename T>
- inline bool is_valid(const expression<T>& expr)
- {
- return !expression_helper<T>::is_null(expr);
- }
- namespace parser_error
- {
- enum error_mode
- {
- e_unknown = 0,
- e_syntax = 1,
- e_token = 2,
- e_numeric = 4,
- e_symtab = 5,
- e_lexer = 6,
- e_helper = 7
- };
- struct type
- {
- type()
- : mode(parser_error::e_unknown),
- line_no (0),
- column_no(0)
- {}
- lexer::token token;
- error_mode mode;
- std::string diagnostic;
- std::string src_location;
- std::string error_line;
- std::size_t line_no;
- std::size_t column_no;
- };
- inline type make_error(const error_mode mode,
- const std::string& diagnostic = "",
- const std::string& src_location = "")
- {
- type t;
- t.mode = mode;
- t.token.type = lexer::token::e_error;
- t.diagnostic = diagnostic;
- t.src_location = src_location;
- exprtk_debug(("%s\n",diagnostic .c_str()));
- return t;
- }
- inline type make_error(const error_mode mode,
- const lexer::token& tk,
- const std::string& diagnostic = "",
- const std::string& src_location = "")
- {
- type t;
- t.mode = mode;
- t.token = tk;
- t.diagnostic = diagnostic;
- t.src_location = src_location;
- exprtk_debug(("%s\n",diagnostic .c_str()));
- return t;
- }
- inline std::string to_str(error_mode mode)
- {
- switch (mode)
- {
- case e_unknown : return std::string("Unknown Error");
- case e_syntax : return std::string("Syntax Error" );
- case e_token : return std::string("Token Error" );
- case e_numeric : return std::string("Numeric Error");
- case e_symtab : return std::string("Symbol Error" );
- case e_lexer : return std::string("Lexer Error" );
- case e_helper : return std::string("Helper Error" );
- default : return std::string("Unknown Error");
- }
- }
- inline bool update_error(type& error, const std::string& expression)
- {
- if (
- expression.empty() ||
- (error.token.position > expression.size()) ||
- (std::numeric_limits<std::size_t>::max() == error.token.position)
- )
- {
- return false;
- }
- std::size_t error_line_start = 0;
- for (std::size_t i = error.token.position; i > 0; --i)
- {
- const details::char_t c = expression[i];
- if (('\n' == c) || ('\r' == c))
- {
- error_line_start = i + 1;
- break;
- }
- }
- std::size_t next_nl_position = std::min(expression.size(),
- expression.find_first_of('\n',error.token.position + 1));
- error.column_no = error.token.position - error_line_start;
- error.error_line = expression.substr(error_line_start,
- next_nl_position - error_line_start);
- error.line_no = 0;
- for (std::size_t i = 0; i < next_nl_position; ++i)
- {
- if ('\n' == expression[i])
- ++error.line_no;
- }
- return true;
- }
- inline void dump_error(const type& error)
- {
- printf("Position: %02d Type: [%s] Msg: %s\n",
- static_cast<int>(error.token.position),
- exprtk::parser_error::to_str(error.mode).c_str(),
- error.diagnostic.c_str());
- }
- }
- namespace details
- {
- template <typename Parser>
- inline void disable_type_checking(Parser& p)
- {
- p.state_.type_check_enabled = false;
- }
- }
- template <typename T>
- class parser : public lexer::parser_helper
- {
- private:
- enum precedence_level
- {
- e_level00,
- e_level01,
- e_level02,
- e_level03,
- e_level04,
- e_level05,
- e_level06,
- e_level07,
- e_level08,
- e_level09,
- e_level10,
- e_level11,
- e_level12,
- e_level13,
- e_level14
- };
- typedef const T& cref_t;
- typedef const T const_t;
- typedef ifunction <T> F;
- typedef ivararg_function <T> VAF;
- typedef igeneric_function <T> GF;
- typedef ifunction <T> ifunction_t;
- typedef ivararg_function <T> ivararg_function_t;
- typedef igeneric_function <T> igeneric_function_t;
- typedef details::expression_node <T> expression_node_t;
- typedef details::literal_node <T> literal_node_t;
- typedef details::unary_node <T> unary_node_t;
- typedef details::binary_node <T> binary_node_t;
- typedef details::trinary_node <T> trinary_node_t;
- typedef details::quaternary_node <T> quaternary_node_t;
- typedef details::conditional_node<T> conditional_node_t;
- typedef details::cons_conditional_node<T> cons_conditional_node_t;
- typedef details::while_loop_node <T> while_loop_node_t;
- typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t;
- typedef details::for_loop_node <T> for_loop_node_t;
- #ifndef exprtk_disable_break_continue
- typedef details::while_loop_bc_node <T> while_loop_bc_node_t;
- typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
- typedef details::for_loop_bc_node<T> for_loop_bc_node_t;
- #endif
- typedef details::switch_node <T> switch_node_t;
- typedef details::variable_node <T> variable_node_t;
- typedef details::vector_elem_node<T> vector_elem_node_t;
- typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t;
- typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
- typedef details::vector_node <T> vector_node_t;
- typedef details::range_pack <T> range_t;
- #ifndef exprtk_disable_string_capabilities
- typedef details::stringvar_node <T> stringvar_node_t;
- typedef details::string_literal_node<T> string_literal_node_t;
- typedef details::string_range_node <T> string_range_node_t;
- typedef details::const_string_range_node<T> const_string_range_node_t;
- typedef details::generic_string_range_node<T> generic_string_range_node_t;
- typedef details::string_concat_node <T> string_concat_node_t;
- typedef details::assignment_string_node<T> assignment_string_node_t;
- typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
- typedef details::conditional_string_node<T> conditional_string_node_t;
- typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
- #endif
- typedef details::assignment_node<T> assignment_node_t;
- typedef details::assignment_vec_elem_node <T> assignment_vec_elem_node_t;
- typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
- typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
- typedef details::assignment_vec_node <T> assignment_vec_node_t;
- typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t;
- typedef details::scand_node<T> scand_node_t;
- typedef details::scor_node<T> scor_node_t;
- typedef lexer::token token_t;
- typedef expression_node_t* expression_node_ptr;
- typedef expression<T> expression_t;
- typedef symbol_table<T> symbol_table_t;
- typedef typename expression<T>::symtab_list_t symbol_table_list_t;
- typedef details::vector_holder<T>* vector_holder_ptr;
- typedef typename details::functor_t<T> functor_t;
- typedef typename functor_t::qfunc_t quaternary_functor_t;
- typedef typename functor_t::tfunc_t trinary_functor_t;
- typedef typename functor_t::bfunc_t binary_functor_t;
- typedef typename functor_t::ufunc_t unary_functor_t;
- typedef details::operator_type operator_t;
- typedef std::map<operator_t, unary_functor_t> unary_op_map_t;
- typedef std::map<operator_t, binary_functor_t> binary_op_map_t;
- typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
- typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t;
- typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
- typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
- typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
- typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
- typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
- typedef details::T0oT1_define<T, const_t, cref_t> cov_t;
- typedef details::T0oT1_define<T, cref_t, const_t> voc_t;
- typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
- typedef details::T0oT1oT2_define<T, cref_t, cref_t, const_t> vovoc_t;
- typedef details::T0oT1oT2_define<T, cref_t, const_t, cref_t> vocov_t;
- typedef details::T0oT1oT2_define<T, const_t, cref_t, cref_t> covov_t;
- typedef details::T0oT1oT2_define<T, const_t, cref_t, const_t> covoc_t;
- typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t> cocov_t;
- typedef details::T0oT1oT2_define<T, cref_t, const_t, const_t> vococ_t;
- typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
- typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, const_t> vovovoc_t;
- typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, const_t, cref_t> vovocov_t;
- typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, cref_t> vocovov_t;
- typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, cref_t> covovov_t;
- typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, const_t, cref_t> covocov_t;
- typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, const_t> vocovoc_t;
- typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, const_t> covovoc_t;
- typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, const_t, cref_t> vococov_t;
- typedef results_context<T> results_context_t;
- typedef parser_helper prsrhlpr_t;
- struct scope_element
- {
- enum element_type
- {
- e_none ,
- e_variable,
- e_vector ,
- e_vecelem ,
- e_string
- };
- typedef details::vector_holder<T> vector_holder_t;
- typedef variable_node_t* variable_node_ptr;
- typedef vector_holder_t* vector_holder_ptr;
- typedef expression_node_t* expression_node_ptr;
- #ifndef exprtk_disable_string_capabilities
- typedef stringvar_node_t* stringvar_node_ptr;
- #endif
- scope_element()
- : name("???"),
- size (std::numeric_limits<std::size_t>::max()),
- index(std::numeric_limits<std::size_t>::max()),
- depth(std::numeric_limits<std::size_t>::max()),
- ref_count(0),
- ip_index (0),
- type (e_none),
- active(false),
- data (0),
- var_node(0),
- vec_node(0)
- #ifndef exprtk_disable_string_capabilities
- ,str_node(0)
- #endif
- {}
- bool operator < (const scope_element& se) const
- {
- if (ip_index < se.ip_index)
- return true;
- else if (ip_index > se.ip_index)
- return false;
- else if (depth < se.depth)
- return true;
- else if (depth > se.depth)
- return false;
- else if (index < se.index)
- return true;
- else if (index > se.index)
- return false;
- else
- return (name < se.name);
- }
- void clear()
- {
- name = "???";
- size = std::numeric_limits<std::size_t>::max();
- index = std::numeric_limits<std::size_t>::max();
- depth = std::numeric_limits<std::size_t>::max();
- type = e_none;
- active = false;
- ref_count = 0;
- ip_index = 0;
- data = 0;
- var_node = 0;
- vec_node = 0;
- #ifndef exprtk_disable_string_capabilities
- str_node = 0;
- #endif
- }
- std::string name;
- std::size_t size;
- std::size_t index;
- std::size_t depth;
- std::size_t ref_count;
- std::size_t ip_index;
- element_type type;
- bool active;
- void* data;
- expression_node_ptr var_node;
- vector_holder_ptr vec_node;
- #ifndef exprtk_disable_string_capabilities
- stringvar_node_ptr str_node;
- #endif
- };
- class scope_element_manager
- {
- public:
- typedef expression_node_t* expression_node_ptr;
- typedef variable_node_t* variable_node_ptr;
- typedef parser<T> parser_t;
- explicit scope_element_manager(parser<T>& p)
- : parser_(p),
- input_param_cnt_(0)
- {}
- inline std::size_t size() const
- {
- return element_.size();
- }
- inline bool empty() const
- {
- return element_.empty();
- }
- inline scope_element& get_element(const std::size_t& index)
- {
- if (index < element_.size())
- return element_[index];
- else
- return null_element_;
- }
- inline scope_element& get_element(const std::string& var_name,
- const std::size_t index = std::numeric_limits<std::size_t>::max())
- {
- const std::size_t current_depth = parser_.state_.scope_depth;
- for (std::size_t i = 0; i < element_.size(); ++i)
- {
- scope_element& se = element_[i];
- if (se.depth > current_depth)
- continue;
- else if (
- details::imatch(se.name, var_name) &&
- (se.index == index)
- )
- return se;
- }
- return null_element_;
- }
- inline scope_element& get_active_element(const std::string& var_name,
- const std::size_t index = std::numeric_limits<std::size_t>::max())
- {
- const std::size_t current_depth = parser_.state_.scope_depth;
- for (std::size_t i = 0; i < element_.size(); ++i)
- {
- scope_element& se = element_[i];
- if (se.depth > current_depth)
- continue;
- else if (
- details::imatch(se.name, var_name) &&
- (se.index == index) &&
- (se.active)
- )
- return se;
- }
- return null_element_;
- }
- inline bool add_element(const scope_element& se)
- {
- for (std::size_t i = 0; i < element_.size(); ++i)
- {
- scope_element& cse = element_[i];
- if (
- details::imatch(cse.name, se.name) &&
- (cse.depth <= se.depth) &&
- (cse.index == se.index) &&
- (cse.size == se.size ) &&
- (cse.type == se.type ) &&
- (cse.active)
- )
- return false;
- }
- element_.push_back(se);
- std::sort(element_.begin(),element_.end());
- return true;
- }
- inline void deactivate(const std::size_t& scope_depth)
- {
- exprtk_debug(("deactivate() - Scope depth: %d\n",
- static_cast<int>(parser_.state_.scope_depth)));
- for (std::size_t i = 0; i < element_.size(); ++i)
- {
- scope_element& se = element_[i];
- if (se.active && (se.depth >= scope_depth))
- {
- exprtk_debug(("deactivate() - element[%02d] '%s'\n",
- static_cast<int>(i),
- se.name.c_str()));
- se.active = false;
- }
- }
- }
- inline void free_element(scope_element& se)
- {
- #ifdef exprtk_enable_debugging
- exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
- #endif
- switch (se.type)
- {
- case scope_element::e_variable : if (se.data ) delete (T*) se.data;
- if (se.var_node) delete se.var_node;
- break;
- case scope_element::e_vector : if (se.data ) delete[] (T*) se.data;
- if (se.vec_node) delete se.vec_node;
- break;
- case scope_element::e_vecelem : if (se.var_node) delete se.var_node;
- break;
- #ifndef exprtk_disable_string_capabilities
- case scope_element::e_string : if (se.data ) delete (std::string*) se.data;
- if (se.str_node) delete se.str_node;
- break;
- #endif
- default : return;
- }
- se.clear();
- }
- inline void cleanup()
- {
- for (std::size_t i = 0; i < element_.size(); ++i)
- {
- free_element(element_[i]);
- }
- element_.clear();
- input_param_cnt_ = 0;
- }
- inline std::size_t next_ip_index()
- {
- return ++input_param_cnt_;
- }
- inline expression_node_ptr get_variable(const T& v)
- {
- for (std::size_t i = 0; i < element_.size(); ++i)
- {
- scope_element& se = element_[i];
- if (
- se.active &&
- se.var_node &&
- details::is_variable_node(se.var_node)
- )
- {
- variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
- if (&(vn->ref()) == (&v))
- {
- return se.var_node;
- }
- }
- }
- return expression_node_ptr(0);
- }
- private:
- scope_element_manager& operator=(const scope_element_manager&);
- parser_t& parser_;
- std::vector<scope_element> element_;
- scope_element null_element_;
- std::size_t input_param_cnt_;
- };
- class scope_handler
- {
- public:
- typedef parser<T> parser_t;
- explicit scope_handler(parser<T>& p)
- : parser_(p)
- {
- parser_.state_.scope_depth++;
- #ifdef exprtk_enable_debugging
- const std::string depth(2 * parser_.state_.scope_depth,'-');
- exprtk_debug(("%s> Scope Depth: %02d\n",
- depth.c_str(),
- static_cast<int>(parser_.state_.scope_depth)));
- #endif
- }
- ~scope_handler()
- {
- parser_.sem_.deactivate(parser_.state_.scope_depth);
- parser_.state_.scope_depth--;
- #ifdef exprtk_enable_debugging
- const std::string depth(2 * parser_.state_.scope_depth,'-');
- exprtk_debug(("<%s Scope Depth: %02d\n",
- depth.c_str(),
- static_cast<int>(parser_.state_.scope_depth)));
- #endif
- }
- private:
- scope_handler& operator=(const scope_handler&);
- parser_t& parser_;
- };
- struct symtab_store
- {
- symbol_table_list_t symtab_list_;
- typedef typename symbol_table_t::local_data_t local_data_t;
- typedef typename symbol_table_t::variable_ptr variable_ptr;
- typedef typename symbol_table_t::function_ptr function_ptr;
- #ifndef exprtk_disable_string_capabilities
- typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
- #endif
- typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr;
- typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr;
- typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
- inline bool empty() const
- {
- return symtab_list_.empty();
- }
- inline void clear()
- {
- symtab_list_.clear();
- }
- inline bool valid() const
- {
- if (!empty())
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (symtab_list_[i].valid())
- return true;
- }
- }
- return false;
- }
- inline bool valid_symbol(const std::string& symbol) const
- {
- if (!symtab_list_.empty())
- return symtab_list_[0].valid_symbol(symbol);
- else
- return false;
- }
- inline bool valid_function_name(const std::string& symbol) const
- {
- if (!symtab_list_.empty())
- return symtab_list_[0].valid_function(symbol);
- else
- return false;
- }
- inline variable_ptr get_variable(const std::string& variable_name) const
- {
- if (!valid_symbol(variable_name))
- return reinterpret_cast<variable_ptr>(0);
- variable_ptr result = reinterpret_cast<variable_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result = local_data(i)
- .variable_store.get(variable_name);
- if (result) break;
- }
- return result;
- }
- inline variable_ptr get_variable(const T& var_ref) const
- {
- variable_ptr result = reinterpret_cast<variable_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result = local_data(i).variable_store
- .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
- if (result) break;
- }
- return result;
- }
- #ifndef exprtk_disable_string_capabilities
- inline stringvar_ptr get_stringvar(const std::string& string_name) const
- {
- if (!valid_symbol(string_name))
- return reinterpret_cast<stringvar_ptr>(0);
- stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result = local_data(i)
- .stringvar_store.get(string_name);
- if (result) break;
- }
- return result;
- }
- #endif
- inline function_ptr get_function(const std::string& function_name) const
- {
- if (!valid_function_name(function_name))
- return reinterpret_cast<function_ptr>(0);
- function_ptr result = reinterpret_cast<function_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result = local_data(i)
- .function_store.get(function_name);
- if (result) break;
- }
- return result;
- }
- inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
- {
- if (!valid_function_name(vararg_function_name))
- return reinterpret_cast<vararg_function_ptr>(0);
- vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result = local_data(i)
- .vararg_function_store.get(vararg_function_name);
- if (result) break;
- }
- return result;
- }
- inline generic_function_ptr get_generic_function(const std::string& function_name) const
- {
- if (!valid_function_name(function_name))
- return reinterpret_cast<generic_function_ptr>(0);
- generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result = local_data(i)
- .generic_function_store.get(function_name);
- if (result) break;
- }
- return result;
- }
- inline generic_function_ptr get_string_function(const std::string& function_name) const
- {
- if (!valid_function_name(function_name))
- return reinterpret_cast<generic_function_ptr>(0);
- generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result =
- local_data(i).string_function_store.get(function_name);
- if (result) break;
- }
- return result;
- }
- inline generic_function_ptr get_overload_function(const std::string& function_name) const
- {
- if (!valid_function_name(function_name))
- return reinterpret_cast<generic_function_ptr>(0);
- generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result =
- local_data(i).overload_function_store.get(function_name);
- if (result) break;
- }
- return result;
- }
- inline vector_holder_ptr get_vector(const std::string& vector_name) const
- {
- if (!valid_symbol(vector_name))
- return reinterpret_cast<vector_holder_ptr>(0);
- vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else
- result =
- local_data(i).vector_store.get(vector_name);
- if (result) break;
- }
- return result;
- }
- inline bool is_constant_node(const std::string& symbol_name) const
- {
- if (!valid_symbol(symbol_name))
- return false;
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (local_data(i).variable_store.is_constant(symbol_name))
- return true;
- }
- return false;
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool is_constant_string(const std::string& symbol_name) const
- {
- if (!valid_symbol(symbol_name))
- return false;
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
- continue;
- else if ( local_data(i).stringvar_store.is_constant(symbol_name))
- return true;
- }
- return false;
- }
- #endif
- inline bool symbol_exists(const std::string& symbol) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (symtab_list_[i].symbol_exists(symbol))
- return true;
- }
- return false;
- }
- inline bool is_variable(const std::string& variable_name) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (
- symtab_list_[i].local_data().variable_store
- .symbol_exists(variable_name)
- )
- return true;
- }
- return false;
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool is_stringvar(const std::string& stringvar_name) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (
- symtab_list_[i].local_data().stringvar_store
- .symbol_exists(stringvar_name)
- )
- return true;
- }
- return false;
- }
- inline bool is_conststr_stringvar(const std::string& symbol_name) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (
- symtab_list_[i].local_data().stringvar_store
- .symbol_exists(symbol_name)
- )
- {
- return (
- local_data(i).stringvar_store.symbol_exists(symbol_name) ||
- local_data(i).stringvar_store.is_constant (symbol_name)
- );
- }
- }
- return false;
- }
- #endif
- inline bool is_function(const std::string& function_name) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (
- local_data(i).vararg_function_store
- .symbol_exists(function_name)
- )
- return true;
- }
- return false;
- }
- inline bool is_vararg_function(const std::string& vararg_function_name) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (
- local_data(i).vararg_function_store
- .symbol_exists(vararg_function_name)
- )
- return true;
- }
- return false;
- }
- inline bool is_vector(const std::string& vector_name) const
- {
- for (std::size_t i = 0; i < symtab_list_.size(); ++i)
- {
- if (!symtab_list_[i].valid())
- continue;
- else if (
- local_data(i).vector_store
- .symbol_exists(vector_name)
- )
- return true;
- }
- return false;
- }
- inline std::string get_variable_name(const expression_node_ptr& ptr) const
- {
- return local_data().variable_store.entity_name(ptr);
- }
- inline std::string get_vector_name(const vector_holder_ptr& ptr) const
- {
- return local_data().vector_store.entity_name(ptr);
- }
- #ifndef exprtk_disable_string_capabilities
- inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
- {
- return local_data().stringvar_store.entity_name(ptr);
- }
- inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
- {
- return local_data().stringvar_store.entity_name(ptr);
- }
- #endif
- inline local_data_t& local_data(const std::size_t& index = 0)
- {
- return symtab_list_[index].local_data();
- }
- inline const local_data_t& local_data(const std::size_t& index = 0) const
- {
- return symtab_list_[index].local_data();
- }
- inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
- {
- return symtab_list_[index];
- }
- };
- struct parser_state
- {
- parser_state()
- : type_check_enabled(true)
- {
- reset();
- }
- void reset()
- {
- parsing_return_stmt = false;
- parsing_break_stmt = false;
- return_stmt_present = false;
- side_effect_present = false;
- scope_depth = 0;
- }
- #ifndef exprtk_enable_debugging
- void activate_side_effect(const std::string&)
- #else
- void activate_side_effect(const std::string& source)
- #endif
- {
- if (!side_effect_present)
- {
- side_effect_present = true;
- exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
- }
- }
- bool parsing_return_stmt;
- bool parsing_break_stmt;
- bool return_stmt_present;
- bool side_effect_present;
- bool type_check_enabled;
- std::size_t scope_depth;
- };
- public:
- struct unknown_symbol_resolver
- {
- enum usr_symbol_type
- {
- e_usr_unknown_type = 0,
- e_usr_variable_type = 1,
- e_usr_constant_type = 2
- };
- enum usr_mode
- {
- e_usrmode_default = 0,
- e_usrmode_extended = 1
- };
- usr_mode mode;
- unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
- : mode(m)
- {}
- virtual ~unknown_symbol_resolver()
- {}
- virtual bool process(const std::string& /*unknown_symbol*/,
- usr_symbol_type& st,
- T& default_value,
- std::string& error_message)
- {
- if (e_usrmode_default != mode)
- return false;
- st = e_usr_variable_type;
- default_value = T(0);
- error_message.clear();
- return true;
- }
- virtual bool process(const std::string& /* unknown_symbol */,
- symbol_table_t& /* symbol_table */,
- std::string& /* error_message */)
- {
- return false;
- }
- };
- enum collect_type
- {
- e_ct_none = 0,
- e_ct_variables = 1,
- e_ct_functions = 2,
- e_ct_assignments = 4
- };
- enum symbol_type
- {
- e_st_unknown = 0,
- e_st_variable = 1,
- e_st_vector = 2,
- e_st_vecelem = 3,
- e_st_string = 4,
- e_st_function = 5,
- e_st_local_variable = 6,
- e_st_local_vector = 7,
- e_st_local_string = 8
- };
- class dependent_entity_collector
- {
- public:
- typedef std::pair<std::string,symbol_type> symbol_t;
- typedef std::vector<symbol_t> symbol_list_t;
- dependent_entity_collector(const std::size_t options = e_ct_none)
- : options_(options),
- collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ),
- collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ),
- collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
- return_present_ (false),
- final_stmt_return_(false)
- {}
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
- {
- if (!collect_variables_ && !collect_functions_)
- return 0;
- else if (symbol_name_list_.empty())
- return 0;
- for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
- {
- details::case_normalise(symbol_name_list_[i].first);
- }
- std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
- std::unique_copy(symbol_name_list_.begin(),
- symbol_name_list_.end (),
- std::back_inserter(symbols_list));
- return symbols_list.size();
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
- {
- if (!collect_assignments_)
- return 0;
- else if (assignment_name_list_.empty())
- return 0;
- for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
- {
- details::case_normalise(assignment_name_list_[i].first);
- }
- std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
- std::unique_copy(assignment_name_list_.begin(),
- assignment_name_list_.end (),
- std::back_inserter(assignment_list));
- return assignment_list.size();
- }
- void clear()
- {
- symbol_name_list_ .clear();
- assignment_name_list_.clear();
- retparam_list_ .clear();
- return_present_ = false;
- final_stmt_return_ = false;
- }
- bool& collect_variables()
- {
- return collect_variables_;
- }
- bool& collect_functions()
- {
- return collect_functions_;
- }
- bool& collect_assignments()
- {
- return collect_assignments_;
- }
- bool return_present() const
- {
- return return_present_;
- }
- bool final_stmt_return() const
- {
- return final_stmt_return_;
- }
- typedef std::vector<std::string> retparam_list_t;
- retparam_list_t return_param_type_list() const
- {
- return retparam_list_;
- }
- private:
- inline void add_symbol(const std::string& symbol, const symbol_type st)
- {
- switch (st)
- {
- case e_st_variable :
- case e_st_vector :
- case e_st_string :
- case e_st_local_variable :
- case e_st_local_vector :
- case e_st_local_string : if (collect_variables_)
- symbol_name_list_
- .push_back(std::make_pair(symbol, st));
- break;
- case e_st_function : if (collect_functions_)
- symbol_name_list_
- .push_back(std::make_pair(symbol, st));
- break;
- default : return;
- }
- }
- inline void add_assignment(const std::string& symbol, const symbol_type st)
- {
- switch (st)
- {
- case e_st_variable :
- case e_st_vector :
- case e_st_string : if (collect_assignments_)
- assignment_name_list_
- .push_back(std::make_pair(symbol, st));
- break;
- default : return;
- }
- }
- std::size_t options_;
- bool collect_variables_;
- bool collect_functions_;
- bool collect_assignments_;
- bool return_present_;
- bool final_stmt_return_;
- symbol_list_t symbol_name_list_;
- symbol_list_t assignment_name_list_;
- retparam_list_t retparam_list_;
- friend class parser<T>;
- };
- class settings_store
- {
- private:
- typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
- typedef disabled_entity_set_t::iterator des_itr_t;
- public:
- enum settings_compilation_options
- {
- e_unknown = 0,
- e_replacer = 1,
- e_joiner = 2,
- e_numeric_check = 4,
- e_bracket_check = 8,
- e_sequence_check = 16,
- e_commutative_check = 32,
- e_strength_reduction = 64,
- e_disable_vardef = 128,
- e_collect_vars = 256,
- e_collect_funcs = 512,
- e_collect_assings = 1024,
- e_disable_usr_on_rsrvd = 2048,
- e_disable_zero_return = 4096
- };
- enum settings_base_funcs
- {
- e_bf_unknown = 0,
- e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin ,
- e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh ,
- e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos ,
- e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal ,
- e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 ,
- e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp ,
- e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p ,
- e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max ,
- e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul ,
- e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round ,
- e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin ,
- e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum ,
- e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc ,
- e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad,
- e_bf_rad2deg , e_bf_grad2deg
- };
- enum settings_control_structs
- {
- e_ctrl_unknown = 0,
- e_ctrl_ifelse,
- e_ctrl_switch,
- e_ctrl_for_loop,
- e_ctrl_while_loop,
- e_ctrl_repeat_loop,
- e_ctrl_return
- };
- enum settings_logic_opr
- {
- e_logic_unknown = 0,
- e_logic_and, e_logic_nand, e_logic_nor,
- e_logic_not, e_logic_or, e_logic_xnor,
- e_logic_xor, e_logic_scand, e_logic_scor
- };
- enum settings_arithmetic_opr
- {
- e_arith_unknown = 0,
- e_arith_add, e_arith_sub, e_arith_mul,
- e_arith_div, e_arith_mod, e_arith_pow
- };
- enum settings_assignment_opr
- {
- e_assign_unknown = 0,
- e_assign_assign, e_assign_addass, e_assign_subass,
- e_assign_mulass, e_assign_divass, e_assign_modass
- };
- enum settings_inequality_opr
- {
- e_ineq_unknown = 0,
- e_ineq_lt, e_ineq_lte, e_ineq_eq,
- e_ineq_equal, e_ineq_ne, e_ineq_nequal,
- e_ineq_gte, e_ineq_gt
- };
- static const std::size_t compile_all_opts = e_replacer +
- e_joiner +
- e_numeric_check +
- e_bracket_check +
- e_sequence_check +
- e_commutative_check +
- e_strength_reduction;
- settings_store(const std::size_t compile_options = compile_all_opts)
- {
- load_compile_options(compile_options);
- }
- settings_store& enable_all_base_functions()
- {
- disabled_func_set_.clear();
- return (*this);
- }
- settings_store& enable_all_control_structures()
- {
- disabled_ctrl_set_.clear();
- return (*this);
- }
- settings_store& enable_all_logic_ops()
- {
- disabled_logic_set_.clear();
- return (*this);
- }
- settings_store& enable_all_arithmetic_ops()
- {
- disabled_arithmetic_set_.clear();
- return (*this);
- }
- settings_store& enable_all_assignment_ops()
- {
- disabled_assignment_set_.clear();
- return (*this);
- }
- settings_store& enable_all_inequality_ops()
- {
- disabled_inequality_set_.clear();
- return (*this);
- }
- settings_store& enable_local_vardef()
- {
- disable_vardef_ = false;
- return (*this);
- }
- settings_store& disable_all_base_functions()
- {
- std::copy(details::base_function_list,
- details::base_function_list + details::base_function_list_size,
- std::insert_iterator<disabled_entity_set_t>
- (disabled_func_set_, disabled_func_set_.begin()));
- return (*this);
- }
- settings_store& disable_all_control_structures()
- {
- std::copy(details::cntrl_struct_list,
- details::cntrl_struct_list + details::cntrl_struct_list_size,
- std::insert_iterator<disabled_entity_set_t>
- (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
- return (*this);
- }
- settings_store& disable_all_logic_ops()
- {
- std::copy(details::logic_ops_list,
- details::logic_ops_list + details::logic_ops_list_size,
- std::insert_iterator<disabled_entity_set_t>
- (disabled_logic_set_, disabled_logic_set_.begin()));
- return (*this);
- }
- settings_store& disable_all_arithmetic_ops()
- {
- std::copy(details::arithmetic_ops_list,
- details::arithmetic_ops_list + details::arithmetic_ops_list_size,
- std::insert_iterator<disabled_entity_set_t>
- (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
- return (*this);
- }
- settings_store& disable_all_assignment_ops()
- {
- std::copy(details::assignment_ops_list,
- details::assignment_ops_list + details::assignment_ops_list_size,
- std::insert_iterator<disabled_entity_set_t>
- (disabled_assignment_set_, disabled_assignment_set_.begin()));
- return (*this);
- }
- settings_store& disable_all_inequality_ops()
- {
- std::copy(details::inequality_ops_list,
- details::inequality_ops_list + details::inequality_ops_list_size,
- std::insert_iterator<disabled_entity_set_t>
- (disabled_inequality_set_, disabled_inequality_set_.begin()));
- return (*this);
- }
- settings_store& disable_local_vardef()
- {
- disable_vardef_ = true;
- return (*this);
- }
- bool replacer_enabled () const { return enable_replacer_; }
- bool commutative_check_enabled () const { return enable_commutative_check_; }
- bool joiner_enabled () const { return enable_joiner_; }
- bool numeric_check_enabled () const { return enable_numeric_check_; }
- bool bracket_check_enabled () const { return enable_bracket_check_; }
- bool sequence_check_enabled () const { return enable_sequence_check_; }
- bool strength_reduction_enabled () const { return enable_strength_reduction_; }
- bool collect_variables_enabled () const { return enable_collect_vars_; }
- bool collect_functions_enabled () const { return enable_collect_funcs_; }
- bool collect_assignments_enabled() const { return enable_collect_assings_; }
- bool vardef_disabled () const { return disable_vardef_; }
- bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; }
- bool zero_return_disabled () const { return disable_zero_return_; }
- bool function_enabled(const std::string& function_name) const
- {
- if (disabled_func_set_.empty())
- return true;
- else
- return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
- }
- bool control_struct_enabled(const std::string& control_struct) const
- {
- if (disabled_ctrl_set_.empty())
- return true;
- else
- return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
- }
- bool logic_enabled(const std::string& logic_operation) const
- {
- if (disabled_logic_set_.empty())
- return true;
- else
- return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
- }
- bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
- {
- if (disabled_logic_set_.empty())
- return true;
- else
- return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
- .find(arith_opr_to_string(arithmetic_operation));
- }
- bool assignment_enabled(const details::operator_type& assignment) const
- {
- if (disabled_assignment_set_.empty())
- return true;
- else
- return disabled_assignment_set_.end() == disabled_assignment_set_
- .find(assign_opr_to_string(assignment));
- }
- bool inequality_enabled(const details::operator_type& inequality) const
- {
- if (disabled_inequality_set_.empty())
- return true;
- else
- return disabled_inequality_set_.end() == disabled_inequality_set_
- .find(inequality_opr_to_string(inequality));
- }
- bool function_disabled(const std::string& function_name) const
- {
- if (disabled_func_set_.empty())
- return false;
- else
- return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
- }
- bool control_struct_disabled(const std::string& control_struct) const
- {
- if (disabled_ctrl_set_.empty())
- return false;
- else
- return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
- }
- bool logic_disabled(const std::string& logic_operation) const
- {
- if (disabled_logic_set_.empty())
- return false;
- else
- return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
- }
- bool assignment_disabled(const details::operator_type assignment_operation) const
- {
- if (disabled_assignment_set_.empty())
- return false;
- else
- return disabled_assignment_set_.end() != disabled_assignment_set_
- .find(assign_opr_to_string(assignment_operation));
- }
- bool logic_disabled(const details::operator_type logic_operation) const
- {
- if (disabled_logic_set_.empty())
- return false;
- else
- return disabled_logic_set_.end() != disabled_logic_set_
- .find(logic_opr_to_string(logic_operation));
- }
- bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
- {
- if (disabled_arithmetic_set_.empty())
- return false;
- else
- return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
- .find(arith_opr_to_string(arithmetic_operation));
- }
- bool inequality_disabled(const details::operator_type& inequality) const
- {
- if (disabled_inequality_set_.empty())
- return false;
- else
- return disabled_inequality_set_.end() != disabled_inequality_set_
- .find(inequality_opr_to_string(inequality));
- }
- settings_store& disable_base_function(settings_base_funcs bf)
- {
- if (
- (e_bf_unknown != bf) &&
- (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
- )
- {
- disabled_func_set_.insert(details::base_function_list[bf - 1]);
- }
- return (*this);
- }
- settings_store& disable_control_structure(settings_control_structs ctrl_struct)
- {
- if (
- (e_ctrl_unknown != ctrl_struct) &&
- (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
- )
- {
- disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
- }
- return (*this);
- }
- settings_store& disable_logic_operation(settings_logic_opr logic)
- {
- if (
- (e_logic_unknown != logic) &&
- (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
- )
- {
- disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
- }
- return (*this);
- }
- settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
- {
- if (
- (e_arith_unknown != arithmetic) &&
- (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
- )
- {
- disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
- }
- return (*this);
- }
- settings_store& disable_assignment_operation(settings_assignment_opr assignment)
- {
- if (
- (e_assign_unknown != assignment) &&
- (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
- )
- {
- disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
- }
- return (*this);
- }
- settings_store& disable_inequality_operation(settings_inequality_opr inequality)
- {
- if (
- (e_ineq_unknown != inequality) &&
- (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
- )
- {
- disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
- }
- return (*this);
- }
- settings_store& enable_base_function(settings_base_funcs bf)
- {
- if (
- (e_bf_unknown != bf) &&
- (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
- )
- {
- const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
- if (disabled_func_set_.end() != itr)
- {
- disabled_func_set_.erase(itr);
- }
- }
- return (*this);
- }
- settings_store& enable_control_structure(settings_control_structs ctrl_struct)
- {
- if (
- (e_ctrl_unknown != ctrl_struct) &&
- (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
- )
- {
- const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
- if (disabled_ctrl_set_.end() != itr)
- {
- disabled_ctrl_set_.erase(itr);
- }
- }
- return (*this);
- }
- settings_store& enable_logic_operation(settings_logic_opr logic)
- {
- if (
- (e_logic_unknown != logic) &&
- (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
- )
- {
- const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
- if (disabled_logic_set_.end() != itr)
- {
- disabled_logic_set_.erase(itr);
- }
- }
- return (*this);
- }
- settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
- {
- if (
- (e_arith_unknown != arithmetic) &&
- (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
- )
- {
- const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
- if (disabled_arithmetic_set_.end() != itr)
- {
- disabled_arithmetic_set_.erase(itr);
- }
- }
- return (*this);
- }
- settings_store& enable_assignment_operation(settings_assignment_opr assignment)
- {
- if (
- (e_assign_unknown != assignment) &&
- (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
- )
- {
- const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
- if (disabled_assignment_set_.end() != itr)
- {
- disabled_assignment_set_.erase(itr);
- }
- }
- return (*this);
- }
- settings_store& enable_inequality_operation(settings_inequality_opr inequality)
- {
- if (
- (e_ineq_unknown != inequality) &&
- (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
- )
- {
- const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
- if (disabled_inequality_set_.end() != itr)
- {
- disabled_inequality_set_.erase(itr);
- }
- }
- return (*this);
- }
- private:
- void load_compile_options(const std::size_t compile_options)
- {
- enable_replacer_ = (compile_options & e_replacer ) == e_replacer;
- enable_joiner_ = (compile_options & e_joiner ) == e_joiner;
- enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check;
- enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check;
- enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check;
- enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check;
- enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction;
- enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars;
- enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs;
- enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings;
- disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef;
- disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
- disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
- }
- std::string assign_opr_to_string(details::operator_type opr) const
- {
- switch (opr)
- {
- case details::e_assign : return ":=";
- case details::e_addass : return "+=";
- case details::e_subass : return "-=";
- case details::e_mulass : return "*=";
- case details::e_divass : return "/=";
- case details::e_modass : return "%=";
- default : return "";
- }
- }
- std::string arith_opr_to_string(details::operator_type opr) const
- {
- switch (opr)
- {
- case details::e_add : return "+";
- case details::e_sub : return "-";
- case details::e_mul : return "*";
- case details::e_div : return "/";
- case details::e_mod : return "%";
- default : return "";
- }
- }
- std::string inequality_opr_to_string(details::operator_type opr) const
- {
- switch (opr)
- {
- case details::e_lt : return "<";
- case details::e_lte : return "<=";
- case details::e_eq : return "==";
- case details::e_equal : return "=";
- case details::e_ne : return "!=";
- case details::e_nequal: return "<>";
- case details::e_gte : return ">=";
- case details::e_gt : return ">";
- default : return "";
- }
- }
- std::string logic_opr_to_string(details::operator_type opr) const
- {
- switch (opr)
- {
- case details::e_and : return "and" ;
- case details::e_or : return "or" ;
- case details::e_xor : return "xor" ;
- case details::e_nand : return "nand";
- case details::e_nor : return "nor" ;
- case details::e_xnor : return "xnor";
- case details::e_notl : return "not" ;
- default : return "" ;
- }
- }
- bool enable_replacer_;
- bool enable_joiner_;
- bool enable_numeric_check_;
- bool enable_bracket_check_;
- bool enable_sequence_check_;
- bool enable_commutative_check_;
- bool enable_strength_reduction_;
- bool enable_collect_vars_;
- bool enable_collect_funcs_;
- bool enable_collect_assings_;
- bool disable_vardef_;
- bool disable_rsrvd_sym_usr_;
- bool disable_zero_return_;
- disabled_entity_set_t disabled_func_set_ ;
- disabled_entity_set_t disabled_ctrl_set_ ;
- disabled_entity_set_t disabled_logic_set_;
- disabled_entity_set_t disabled_arithmetic_set_;
- disabled_entity_set_t disabled_assignment_set_;
- disabled_entity_set_t disabled_inequality_set_;
- friend class parser<T>;
- };
- typedef settings_store settings_t;
- parser(const settings_t& settings = settings_t())
- : settings_(settings),
- resolve_unknown_symbol_(false),
- results_context_(0),
- unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning (disable:4355)
- #endif
- sem_(*this),
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- operator_joiner_2_(2),
- operator_joiner_3_(3)
- {
- init_precompilation();
- load_operations_map (base_ops_map_ );
- load_unary_operations_map (unary_op_map_ );
- load_binary_operations_map (binary_op_map_ );
- load_inv_binary_operations_map(inv_binary_op_map_);
- load_sf3_map (sf3_map_ );
- load_sf4_map (sf4_map_ );
- expression_generator_.init_synthesize_map();
- expression_generator_.set_parser(*this);
- expression_generator_.set_uom(unary_op_map_);
- expression_generator_.set_bom(binary_op_map_);
- expression_generator_.set_ibom(inv_binary_op_map_);
- expression_generator_.set_sf3m(sf3_map_);
- expression_generator_.set_sf4m(sf4_map_);
- expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
- }
- ~parser()
- {}
- inline void init_precompilation()
- {
- if (settings_.collect_variables_enabled())
- dec_.collect_variables() = true;
- if (settings_.collect_functions_enabled())
- dec_.collect_functions() = true;
- if (settings_.collect_assignments_enabled())
- dec_.collect_assignments() = true;
- if (settings_.replacer_enabled())
- {
- symbol_replacer_.clear();
- symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
- symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
- helper_assembly_.token_modifier_list.clear();
- helper_assembly_.register_modifier(&symbol_replacer_);
- }
- if (settings_.commutative_check_enabled())
- {
- for (std::size_t i = 0; i < details::reserved_words_size; ++i)
- {
- commutative_inserter_.ignore_symbol(details::reserved_words[i]);
- }
- helper_assembly_.token_inserter_list.clear();
- helper_assembly_.register_inserter(&commutative_inserter_);
- }
- if (settings_.joiner_enabled())
- {
- helper_assembly_.token_joiner_list.clear();
- helper_assembly_.register_joiner(&operator_joiner_2_);
- helper_assembly_.register_joiner(&operator_joiner_3_);
- }
- if (
- settings_.numeric_check_enabled () ||
- settings_.bracket_check_enabled () ||
- settings_.sequence_check_enabled()
- )
- {
- helper_assembly_.token_scanner_list.clear();
- if (settings_.numeric_check_enabled())
- {
- helper_assembly_.register_scanner(&numeric_checker_);
- }
- if (settings_.bracket_check_enabled())
- {
- helper_assembly_.register_scanner(&bracket_checker_);
- }
- if (settings_.sequence_check_enabled())
- {
- helper_assembly_.register_scanner(&sequence_validator_ );
- helper_assembly_.register_scanner(&sequence_validator_3tkns_);
- }
- }
- }
- inline bool compile(const std::string& expression_string, expression<T>& expr)
- {
- state_ .reset();
- error_list_ .clear();
- brkcnt_list_ .clear();
- synthesis_error_.clear();
- sem_ .cleanup();
- return_cleanup();
- expression_generator_.set_allocator(node_allocator_);
- if (expression_string.empty())
- {
- set_error(
- make_error(parser_error::e_syntax,
- "ERR000 - Empty expression!",
- exprtk_error_location));
- return false;
- }
- if (!init(expression_string))
- {
- process_lexer_errors();
- return false;
- }
- if (lexer().empty())
- {
- set_error(
- make_error(parser_error::e_syntax,
- "ERR001 - Empty expression!",
- exprtk_error_location));
- return false;
- }
- if (!run_assemblies())
- {
- return false;
- }
- symtab_store_.symtab_list_ = expr.get_symbol_table_list();
- dec_.clear();
- lexer().begin();
- next_token();
- expression_node_ptr e = parse_corpus();
- if ((0 != e) && (token_t::e_eof == current_token().type))
- {
- bool* retinvk_ptr = 0;
- if (state_.return_stmt_present)
- {
- dec_.return_present_ = true;
- e = expression_generator_
- .return_envelope(e, results_context_, retinvk_ptr);
- }
- expr.set_expression(e);
- expr.set_retinvk(retinvk_ptr);
- register_local_vars(expr);
- register_return_results(expr);
- return !(!expr);
- }
- else
- {
- if (error_list_.empty())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR002 - Invalid expression encountered",
- exprtk_error_location));
- }
- if ((0 != e) && branch_deletable(e))
- {
- destroy_node(e);
- }
- dec_.clear ();
- sem_.cleanup ();
- return_cleanup();
- return false;
- }
- }
- inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
- {
- expression_t expr;
- expr.register_symbol_table(symtab);
- compile(expression_string,expr);
- return expr;
- }
- void process_lexer_errors()
- {
- for (std::size_t i = 0; i < lexer().size(); ++i)
- {
- if (lexer()[i].is_error())
- {
- std::string diagnostic = "ERR003 - ";
- switch (lexer()[i].type)
- {
- case lexer::token::e_error : diagnostic += "General token error";
- break;
- case lexer::token::e_err_symbol : diagnostic += "Symbol error";
- break;
- case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
- break;
- case lexer::token::e_err_string : diagnostic += "Invalid string token";
- break;
- case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
- break;
- default : diagnostic += "Unknown compiler error";
- }
- set_error(
- make_error(parser_error::e_lexer,
- lexer()[i],
- diagnostic + ": " + lexer()[i].value,
- exprtk_error_location));
- }
- }
- }
- inline bool run_assemblies()
- {
- if (settings_.commutative_check_enabled())
- {
- helper_assembly_.run_inserters(lexer());
- }
- if (settings_.joiner_enabled())
- {
- helper_assembly_.run_joiners(lexer());
- }
- if (settings_.replacer_enabled())
- {
- helper_assembly_.run_modifiers(lexer());
- }
- if (
- settings_.numeric_check_enabled () ||
- settings_.bracket_check_enabled () ||
- settings_.sequence_check_enabled()
- )
- {
- if (!helper_assembly_.run_scanners(lexer()))
- {
- if (helper_assembly_.error_token_scanner)
- {
- lexer::helper::bracket_checker* bracket_checker_ptr = 0;
- lexer::helper::numeric_checker* numeric_checker_ptr = 0;
- lexer::helper::sequence_validator* sequence_validator_ptr = 0;
- lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
- if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
- {
- set_error(
- make_error(parser_error::e_token,
- bracket_checker_ptr->error_token(),
- "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
- exprtk_error_location));
- }
- else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
- {
- for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
- {
- lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
- set_error(
- make_error(parser_error::e_token,
- error_token,
- "ERR005 - Invalid numeric token: '" + error_token.value + "'",
- exprtk_error_location));
- }
- if (numeric_checker_ptr->error_count())
- {
- numeric_checker_ptr->clear_errors();
- }
- }
- else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
- {
- for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
- {
- std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
- set_error(
- make_error(parser_error::e_token,
- error_token.first,
- "ERR006 - Invalid token sequence: '" +
- error_token.first.value + "' and '" +
- error_token.second.value + "'",
- exprtk_error_location));
- }
- if (sequence_validator_ptr->error_count())
- {
- sequence_validator_ptr->clear_errors();
- }
- }
- else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
- {
- for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
- {
- std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
- set_error(
- make_error(parser_error::e_token,
- error_token.first,
- "ERR007 - Invalid token sequence: '" +
- error_token.first.value + "' and '" +
- error_token.second.value + "'",
- exprtk_error_location));
- }
- if (sequence_validator3_ptr->error_count())
- {
- sequence_validator3_ptr->clear_errors();
- }
- }
- }
- return false;
- }
- }
- return true;
- }
- inline settings_store& settings()
- {
- return settings_;
- }
- inline parser_error::type get_error(const std::size_t& index) const
- {
- if (index < error_list_.size())
- return error_list_[index];
- else
- throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
- }
- inline std::string error() const
- {
- if (!error_list_.empty())
- {
- return error_list_[0].diagnostic;
- }
- else
- return std::string("No Error");
- }
- inline std::size_t error_count() const
- {
- return error_list_.size();
- }
- inline dependent_entity_collector& dec()
- {
- return dec_;
- }
- inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
- {
- if (!settings_.replacer_enabled())
- return false;
- else if (details::is_reserved_word(old_symbol))
- return false;
- else
- return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
- }
- inline bool remove_replace_symbol(const std::string& symbol)
- {
- if (!settings_.replacer_enabled())
- return false;
- else if (details::is_reserved_word(symbol))
- return false;
- else
- return symbol_replacer_.remove(symbol);
- }
- inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
- {
- resolve_unknown_symbol_ = true;
- if (usr)
- unknown_symbol_resolver_ = usr;
- else
- unknown_symbol_resolver_ = &default_usr_;
- }
- inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
- {
- enable_unknown_symbol_resolver(&usr);
- }
- inline void disable_unknown_symbol_resolver()
- {
- resolve_unknown_symbol_ = false;
- unknown_symbol_resolver_ = &default_usr_;
- }
- private:
- inline bool valid_base_operation(const std::string& symbol) const
- {
- const std::size_t length = symbol.size();
- if (
- (length < 3) || // Shortest base op symbol length
- (length > 9) // Longest base op symbol length
- )
- return false;
- else
- return settings_.function_enabled(symbol) &&
- (base_ops_map_.end() != base_ops_map_.find(symbol));
- }
- inline bool valid_vararg_operation(const std::string& symbol) const
- {
- static const std::string s_sum = "sum" ;
- static const std::string s_mul = "mul" ;
- static const std::string s_avg = "avg" ;
- static const std::string s_min = "min" ;
- static const std::string s_max = "max" ;
- static const std::string s_mand = "mand";
- static const std::string s_mor = "mor" ;
- static const std::string s_multi = "~" ;
- static const std::string s_mswitch = "[*]" ;
- return
- (
- details::imatch(symbol,s_sum ) ||
- details::imatch(symbol,s_mul ) ||
- details::imatch(symbol,s_avg ) ||
- details::imatch(symbol,s_min ) ||
- details::imatch(symbol,s_max ) ||
- details::imatch(symbol,s_mand ) ||
- details::imatch(symbol,s_mor ) ||
- details::imatch(symbol,s_multi ) ||
- details::imatch(symbol,s_mswitch)
- ) &&
- settings_.function_enabled(symbol);
- }
- bool is_invalid_logic_operation(const details::operator_type operation) const
- {
- return settings_.logic_disabled(operation);
- }
- bool is_invalid_arithmetic_operation(const details::operator_type operation) const
- {
- return settings_.arithmetic_disabled(operation);
- }
- bool is_invalid_assignment_operation(const details::operator_type operation) const
- {
- return settings_.assignment_disabled(operation);
- }
- bool is_invalid_inequality_operation(const details::operator_type operation) const
- {
- return settings_.inequality_disabled(operation);
- }
- #ifdef exprtk_enable_debugging
- inline void next_token()
- {
- const std::string ct_str = current_token().value;
- parser_helper::next_token();
- const std::string depth(2 * state_.scope_depth,' ');
- exprtk_debug(("%s"
- "prev[%s] --> curr[%s]\n",
- depth.c_str(),
- ct_str.c_str(),
- current_token().value.c_str()));
- }
- #endif
- inline expression_node_ptr parse_corpus()
- {
- std::vector<expression_node_ptr> arg_list;
- std::vector<bool> side_effect_list;
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- lexer::token begin_token;
- lexer::token end_token;
- for ( ; ; )
- {
- state_.side_effect_present = false;
- begin_token = current_token();
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- {
- if (error_list_.empty())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR008 - Invalid expression encountered",
- exprtk_error_location));
- }
- return error_node();
- }
- else
- {
- arg_list.push_back(arg);
- side_effect_list.push_back(state_.side_effect_present);
- end_token = current_token();
- const std::string sub_expr = construct_subexpr(begin_token, end_token);
- exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
- static_cast<int>(arg_list.size() - 1),
- sub_expr.c_str()));
- exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
- static_cast<int>(arg_list.size() - 1),
- state_.side_effect_present ? "true" : "false"));
- exprtk_debug(("-------------------------------------------------\n"));
- }
- if (lexer().finished())
- break;
- else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
- {
- if (lexer().finished())
- break;
- else
- next_token();
- }
- }
- if (
- !arg_list.empty() &&
- is_return_node(arg_list.back())
- )
- {
- dec_.final_stmt_return_ = true;
- }
- const expression_node_ptr result = simplify(arg_list,side_effect_list);
- sdd.delete_ptr = (0 == result);
- return result;
- }
- std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
- {
- std::string result = lexer().substr(begin_token.position,end_token.position);
- for (std::size_t i = 0; i < result.size(); ++i)
- {
- if (details::is_whitespace(result[i])) result[i] = ' ';
- }
- return result;
- }
- static const precedence_level default_precedence = e_level00;
- struct state_t
- {
- inline void set(const precedence_level& l,
- const precedence_level& r,
- const details::operator_type& o)
- {
- left = l;
- right = r;
- operation = o;
- }
- inline void reset()
- {
- left = e_level00;
- right = e_level00;
- operation = details::e_default;
- }
- precedence_level left;
- precedence_level right;
- details::operator_type operation;
- };
- inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
- {
- expression_node_ptr expression = parse_branch(precedence);
- if (0 == expression)
- {
- return error_node();
- }
- bool break_loop = false;
- state_t current_state;
- for ( ; ; )
- {
- current_state.reset();
- switch (current_token().type)
- {
- case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
- case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
- case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
- case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
- case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
- case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
- case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break;
- case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break;
- case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break;
- case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break;
- case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break;
- case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break;
- case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break;
- case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break;
- case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break;
- case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break;
- case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break;
- case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break;
- case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break;
- default : if (token_t::e_symbol == current_token().type)
- {
- static const std::string s_and = "and";
- static const std::string s_nand = "nand";
- static const std::string s_or = "or";
- static const std::string s_nor = "nor";
- static const std::string s_xor = "xor";
- static const std::string s_xnor = "xnor";
- static const std::string s_in = "in";
- static const std::string s_like = "like";
- static const std::string s_ilike = "ilike";
- static const std::string s_and1 = "&";
- static const std::string s_or1 = "|";
- static const std::string s_not = "not";
- if (details::imatch(current_token().value,s_and))
- {
- current_state.set(e_level03, e_level04, details::e_and);
- break;
- }
- else if (details::imatch(current_token().value,s_and1))
- {
- #ifndef exprtk_disable_sc_andor
- current_state.set(e_level03, e_level04, details::e_scand);
- #else
- current_state.set(e_level03, e_level04, details::e_and);
- #endif
- break;
- }
- else if (details::imatch(current_token().value,s_nand))
- {
- current_state.set(e_level03, e_level04, details::e_nand);
- break;
- }
- else if (details::imatch(current_token().value,s_or))
- {
- current_state.set(e_level01, e_level02, details::e_or);
- break;
- }
- else if (details::imatch(current_token().value,s_or1))
- {
- #ifndef exprtk_disable_sc_andor
- current_state.set(e_level01, e_level02, details::e_scor);
- #else
- current_state.set(e_level01, e_level02, details::e_or);
- #endif
- break;
- }
- else if (details::imatch(current_token().value,s_nor))
- {
- current_state.set(e_level01, e_level02, details::e_nor);
- break;
- }
- else if (details::imatch(current_token().value,s_xor))
- {
- current_state.set(e_level01, e_level02, details::e_xor);
- break;
- }
- else if (details::imatch(current_token().value,s_xnor))
- {
- current_state.set(e_level01, e_level02, details::e_xnor);
- break;
- }
- else if (details::imatch(current_token().value,s_in))
- {
- current_state.set(e_level04, e_level04, details::e_in);
- break;
- }
- else if (details::imatch(current_token().value,s_like))
- {
- current_state.set(e_level04, e_level04, details::e_like);
- break;
- }
- else if (details::imatch(current_token().value,s_ilike))
- {
- current_state.set(e_level04, e_level04, details::e_ilike);
- break;
- }
- else if (details::imatch(current_token().value,s_not))
- {
- break;
- }
- }
- break_loop = true;
- }
- if (break_loop)
- {
- parse_pending_string_rangesize(expression);
- break;
- }
- else if (current_state.left < precedence)
- break;
- const lexer::token prev_token = current_token();
- next_token();
- expression_node_ptr right_branch = error_node();
- expression_node_ptr new_expression = error_node();
- if (is_invalid_logic_operation(current_state.operation))
- {
- free_node(node_allocator_,expression);
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- "ERR009 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (is_invalid_arithmetic_operation(current_state.operation))
- {
- free_node(node_allocator_,expression);
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- "ERR010 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (is_invalid_inequality_operation(current_state.operation))
- {
- free_node(node_allocator_,expression);
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- "ERR011 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (is_invalid_assignment_operation(current_state.operation))
- {
- free_node(node_allocator_,expression);
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- "ERR012 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
- exprtk_error_location));
- return error_node();
- }
- if (0 != (right_branch = parse_expression(current_state.right)))
- {
- if (
- details::is_return_node( expression) ||
- details::is_return_node(right_branch)
- )
- {
- free_node(node_allocator_, expression);
- free_node(node_allocator_, right_branch);
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- "ERR013 - Return statements cannot be part of sub-expressions",
- exprtk_error_location));
- return error_node();
- }
- new_expression = expression_generator_
- (
- current_state.operation,
- expression,
- right_branch
- );
- }
- if (0 == new_expression)
- {
- if (error_list_.empty())
- {
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- !synthesis_error_.empty() ?
- synthesis_error_ :
- "ERR014 - General parsing error at token: '" + prev_token.value + "'",
- exprtk_error_location));
- }
- free_node(node_allocator_, expression);
- free_node(node_allocator_, right_branch);
- return error_node();
- }
- else
- {
- if (
- token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
- (precedence == e_level00)
- )
- {
- expression = parse_ternary_conditional_statement(new_expression);
- }
- else
- expression = new_expression;
- parse_pending_string_rangesize(expression);
- }
- }
- return expression;
- }
- bool simplify_unary_negation_branch(expression_node_ptr& node)
- {
- {
- typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
- ubn_t* n = dynamic_cast<ubn_t*>(node);
- if (n)
- {
- expression_node_ptr un_r = n->branch(0);
- n->release();
- free_node(node_allocator_,node);
- node = un_r;
- return true;
- }
- }
- {
- typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
- uvn_t* n = dynamic_cast<uvn_t*>(node);
- if (n)
- {
- const T& v = n->v();
- expression_node_ptr return_node = error_node();
- if (
- (0 != (return_node = symtab_store_.get_variable(v))) ||
- (0 != (return_node = sem_ .get_variable(v)))
- )
- {
- free_node(node_allocator_,node);
- node = return_node;
- return true;
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR015 - Failed to find variable node in symbol table",
- exprtk_error_location));
- free_node(node_allocator_,node);
- return false;
- }
- }
- }
- return false;
- }
- static inline expression_node_ptr error_node()
- {
- return reinterpret_cast<expression_node_ptr>(0);
- }
- template <typename Type, std::size_t N>
- struct scoped_delete
- {
- typedef Type* ptr_t;
- scoped_delete(parser<T>& pr, ptr_t& p)
- : delete_ptr(true),
- parser_(pr),
- p_(&p)
- {}
- scoped_delete(parser<T>& pr, ptr_t (&p)[N])
- : delete_ptr(true),
- parser_(pr),
- p_(&p[0])
- {}
- ~scoped_delete()
- {
- if (delete_ptr)
- {
- for (std::size_t i = 0; i < N; ++i)
- {
- free_node(parser_.node_allocator_,p_[i]);
- }
- }
- }
- bool delete_ptr;
- parser<T>& parser_;
- ptr_t* p_;
- private:
- scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
- };
- template <typename Type>
- struct scoped_deq_delete
- {
- typedef Type* ptr_t;
- scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
- : delete_ptr(true),
- parser_(pr),
- deq_(deq)
- {}
- ~scoped_deq_delete()
- {
- if (delete_ptr && !deq_.empty())
- {
- for (std::size_t i = 0; i < deq_.size(); ++i)
- {
- free_node(parser_.node_allocator_,deq_[i]);
- }
- deq_.clear();
- }
- }
- bool delete_ptr;
- parser<T>& parser_;
- std::deque<ptr_t>& deq_;
- private:
- scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
- };
- template <typename Type>
- struct scoped_vec_delete
- {
- typedef Type* ptr_t;
- scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
- : delete_ptr(true),
- parser_(pr),
- vec_(vec)
- {}
- ~scoped_vec_delete()
- {
- if (delete_ptr && !vec_.empty())
- {
- for (std::size_t i = 0; i < vec_.size(); ++i)
- {
- free_node(parser_.node_allocator_,vec_[i]);
- }
- vec_.clear();
- }
- }
- bool delete_ptr;
- parser<T>& parser_;
- std::vector<ptr_t>& vec_;
- private:
- scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
- };
- struct scoped_bool_negator
- {
- explicit scoped_bool_negator(bool& bb)
- : b(bb)
- { b = !b; }
- ~scoped_bool_negator()
- { b = !b; }
- bool& b;
- };
- struct scoped_bool_or_restorer
- {
- explicit scoped_bool_or_restorer(bool& bb)
- : b(bb),
- original_value_(bb)
- {}
- ~scoped_bool_or_restorer()
- {
- b = b || original_value_;
- }
- bool& b;
- bool original_value_;
- };
- inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
- {
- expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
- switch (function->param_count)
- {
- case 0 : func_node = parse_function_call_0 (function,function_name); break;
- case 1 : func_node = parse_function_call< 1>(function,function_name); break;
- case 2 : func_node = parse_function_call< 2>(function,function_name); break;
- case 3 : func_node = parse_function_call< 3>(function,function_name); break;
- case 4 : func_node = parse_function_call< 4>(function,function_name); break;
- case 5 : func_node = parse_function_call< 5>(function,function_name); break;
- case 6 : func_node = parse_function_call< 6>(function,function_name); break;
- case 7 : func_node = parse_function_call< 7>(function,function_name); break;
- case 8 : func_node = parse_function_call< 8>(function,function_name); break;
- case 9 : func_node = parse_function_call< 9>(function,function_name); break;
- case 10 : func_node = parse_function_call<10>(function,function_name); break;
- case 11 : func_node = parse_function_call<11>(function,function_name); break;
- case 12 : func_node = parse_function_call<12>(function,function_name); break;
- case 13 : func_node = parse_function_call<13>(function,function_name); break;
- case 14 : func_node = parse_function_call<14>(function,function_name); break;
- case 15 : func_node = parse_function_call<15>(function,function_name); break;
- case 16 : func_node = parse_function_call<16>(function,function_name); break;
- case 17 : func_node = parse_function_call<17>(function,function_name); break;
- case 18 : func_node = parse_function_call<18>(function,function_name); break;
- case 19 : func_node = parse_function_call<19>(function,function_name); break;
- case 20 : func_node = parse_function_call<20>(function,function_name); break;
- default : {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR016 - Invalid number of parameters for function: '" + function_name + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- if (func_node)
- return func_node;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR017 - Failed to generate call to function: '" + function_name + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- template <std::size_t NumberofParameters>
- inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
- {
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable: 4127)
- #endif
- if (0 == NumberofParameters)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR018 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
- exprtk_error_location));
- return error_node();
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- expression_node_ptr branch[NumberofParameters];
- expression_node_ptr result = error_node();
- std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
- scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
- next_token();
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR019 - Expecting argument list for function: '" + function_name + "'",
- exprtk_error_location));
- return error_node();
- }
- for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
- {
- branch[i] = parse_expression();
- if (0 == branch[i])
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR020 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (i < static_cast<int>(NumberofParameters - 1))
- {
- if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR021 - Invalid number of arguments for function: '" + function_name + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR022 - Invalid number of arguments for function: '" + function_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else
- result = expression_generator_.function(function,branch);
- sd.delete_ptr = false;
- return result;
- }
- inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
- {
- expression_node_ptr result = expression_generator_.function(function);
- state_.side_effect_present = function->has_side_effects();
- next_token();
- if (
- token_is(token_t::e_lbracket) &&
- !token_is(token_t::e_rbracket)
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR023 - Expecting '()' to proceed call to function: '" + function_name + "'",
- exprtk_error_location));
- free_node(node_allocator_,result);
- return error_node();
- }
- else
- return result;
- }
- template <std::size_t MaxNumberofParameters>
- inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "")
- {
- std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
- scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
- next_token();
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR024 - Expected a '(' at start of function call to '" + function_name +
- "', instead got: '" + current_token().value + "'",
- exprtk_error_location));
- return 0;
- }
- if (token_is(token_t::e_rbracket, e_hold))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR025 - Expected at least one input parameter for function call '" + function_name + "'",
- exprtk_error_location));
- return 0;
- }
- std::size_t param_index = 0;
- for (; param_index < MaxNumberofParameters; ++param_index)
- {
- param_list[param_index] = parse_expression();
- if (0 == param_list[param_index])
- return 0;
- else if (token_is(token_t::e_rbracket))
- {
- sd.delete_ptr = false;
- break;
- }
- else if (token_is(token_t::e_comma))
- continue;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR026 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
- exprtk_error_location));
- return 0;
- }
- }
- if (sd.delete_ptr)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR027 - Invalid number of input parameters passed to function '" + function_name + "'",
- exprtk_error_location));
- return 0;
- }
- return (param_index + 1);
- }
- inline expression_node_ptr parse_base_operation()
- {
- typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
- const std::string operation_name = current_token().value;
- const token_t diagnostic_token = current_token();
- map_range_t itr_range = base_ops_map_.equal_range(operation_name);
- if (0 == std::distance(itr_range.first,itr_range.second))
- {
- set_error(
- make_error(parser_error::e_syntax,
- diagnostic_token,
- "ERR028 - No entry found for base operation: " + operation_name,
- exprtk_error_location));
- return error_node();
- }
- static const std::size_t MaxNumberofParameters = 4;
- expression_node_ptr param_list[MaxNumberofParameters] = {0};
- const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
- if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
- {
- for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
- {
- const details::base_operation_t& operation = itr->second;
- if (operation.num_params == parameter_count)
- {
- switch (parameter_count)
- {
- #define base_opr_case(N) \
- case N : { \
- expression_node_ptr pl##N[N] = {0}; \
- std::copy(param_list, param_list + N, pl##N); \
- lodge_symbol(operation_name, e_st_function); \
- return expression_generator_(operation.type, pl##N); \
- } \
- base_opr_case(1)
- base_opr_case(2)
- base_opr_case(3)
- base_opr_case(4)
- #undef base_opr_case
- }
- }
- }
- }
- for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
- {
- free_node(node_allocator_, param_list[i]);
- }
- set_error(
- make_error(parser_error::e_syntax,
- diagnostic_token,
- "ERR029 - Invalid number of input parameters for call to function: '" + operation_name + "'",
- exprtk_error_location));
- return error_node();
- }
- inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
- {
- // Parse: [if][(][condition][,][consequent][,][alternative][)]
- expression_node_ptr consequent = error_node();
- expression_node_ptr alternative = error_node();
- bool result = true;
- if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR030 - Expected ',' between if-statement condition and consequent",
- exprtk_error_location));
- result = false;
- }
- else if (0 == (consequent = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR031 - Failed to parse consequent for if-statement",
- exprtk_error_location));
- result = false;
- }
- else if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR032 - Expected ',' between if-statement consequent and alternative",
- exprtk_error_location));
- result = false;
- }
- else if (0 == (alternative = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR033 - Failed to parse alternative for if-statement",
- exprtk_error_location));
- result = false;
- }
- else if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR034 - Expected ')' at the end of if-statement",
- exprtk_error_location));
- result = false;
- }
- #ifndef exprtk_disable_string_capabilities
- if (result)
- {
- const bool consq_is_str = is_generally_string_node( consequent);
- const bool alter_is_str = is_generally_string_node(alternative);
- if (consq_is_str || alter_is_str)
- {
- if (consq_is_str && alter_is_str)
- {
- return expression_generator_
- .conditional_string(condition, consequent, alternative);
- }
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR035 - Return types of ternary if-statement differ",
- exprtk_error_location));
- result = false;
- }
- }
- #endif
- if (!result)
- {
- free_node(node_allocator_, condition);
- free_node(node_allocator_, consequent);
- free_node(node_allocator_,alternative);
- return error_node();
- }
- else
- return expression_generator_
- .conditional(condition, consequent, alternative);
- }
- inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
- {
- expression_node_ptr consequent = error_node();
- expression_node_ptr alternative = error_node();
- bool result = true;
- if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
- {
- if (0 == (consequent = parse_multi_sequence("if-statement-01")))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR036 - Failed to parse body of consequent for if-statement",
- exprtk_error_location));
- result = false;
- }
- }
- else
- {
- if (
- settings_.commutative_check_enabled() &&
- token_is(token_t::e_mul,prsrhlpr_t::e_hold)
- )
- {
- next_token();
- }
- if (0 != (consequent = parse_expression()))
- {
- if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR037 - Expected ';' at the end of the consequent for if-statement",
- exprtk_error_location));
- result = false;
- }
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR038 - Failed to parse body of consequent for if-statement",
- exprtk_error_location));
- result = false;
- }
- }
- if (result)
- {
- if (details::imatch(current_token().value,"else"))
- {
- next_token();
- if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
- {
- if (0 == (alternative = parse_multi_sequence("else-statement-01")))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR039 - Failed to parse body of the 'else' for if-statement",
- exprtk_error_location));
- result = false;
- }
- }
- else if (details::imatch(current_token().value,"if"))
- {
- if (0 == (alternative = parse_conditional_statement()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR040 - Failed to parse body of if-else statement",
- exprtk_error_location));
- result = false;
- }
- }
- else if (0 != (alternative = parse_expression()))
- {
- if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR041 - Expected ';' at the end of the 'else-if' for the if-statement",
- exprtk_error_location));
- result = false;
- }
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR042 - Failed to parse body of the 'else' for if-statement",
- exprtk_error_location));
- result = false;
- }
- }
- }
- #ifndef exprtk_disable_string_capabilities
- if (result)
- {
- const bool consq_is_str = is_generally_string_node( consequent);
- const bool alter_is_str = is_generally_string_node(alternative);
- if (consq_is_str || alter_is_str)
- {
- if (consq_is_str && alter_is_str)
- {
- return expression_generator_
- .conditional_string(condition, consequent, alternative);
- }
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR043 - Return types of ternary if-statement differ",
- exprtk_error_location));
- result = false;
- }
- }
- #endif
- if (!result)
- {
- free_node(node_allocator_, condition);
- free_node(node_allocator_, consequent);
- free_node(node_allocator_, alternative);
- return error_node();
- }
- else
- return expression_generator_
- .conditional(condition, consequent, alternative);
- }
- inline expression_node_ptr parse_conditional_statement()
- {
- expression_node_ptr condition = error_node();
- next_token();
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR044 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (0 == (condition = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR045 - Failed to parse condition for if-statement",
- exprtk_error_location));
- return error_node();
- }
- else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
- {
- // if (x,y,z)
- return parse_conditional_statement_01(condition);
- }
- else if (token_is(token_t::e_rbracket))
- {
- // 00. if (x) y;
- // 01. if (x) y; else z;
- // 02. if (x) y; else {z0; ... zn;}
- // 03. if (x) y; else if (z) w;
- // 04. if (x) y; else if (z) w; else u;
- // 05. if (x) y; else if (z) w; else {u0; ... un;}
- // 06. if (x) y; else if (z) {w0; ... wn;}
- // 07. if (x) {y0; ... yn;}
- // 08. if (x) {y0; ... yn;} else z;
- // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
- // 10. if (x) {y0; ... yn;} else if (z) w;
- // 11. if (x) {y0; ... yn;} else if (z) w; else u;
- // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
- // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
- return parse_conditional_statement_02(condition);
- }
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR046 - Invalid if-statement",
- exprtk_error_location));
- free_node(node_allocator_,condition);
- return error_node();
- }
- inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
- {
- // Parse: [condition][?][consequent][:][alternative]
- expression_node_ptr consequent = error_node();
- expression_node_ptr alternative = error_node();
- bool result = true;
- if (0 == condition)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR047 - Encountered invalid condition branch for ternary if-statement",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_ternary))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR048 - Expected '?' after condition of ternary if-statement",
- exprtk_error_location));
- result = false;
- }
- else if (0 == (consequent = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR049 - Failed to parse consequent for ternary if-statement",
- exprtk_error_location));
- result = false;
- }
- else if (!token_is(token_t::e_colon))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR050 - Expected ':' between ternary if-statement consequent and alternative",
- exprtk_error_location));
- result = false;
- }
- else if (0 == (alternative = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR051 - Failed to parse alternative for ternary if-statement",
- exprtk_error_location));
- result = false;
- }
- #ifndef exprtk_disable_string_capabilities
- if (result)
- {
- const bool consq_is_str = is_generally_string_node( consequent);
- const bool alter_is_str = is_generally_string_node(alternative);
- if (consq_is_str || alter_is_str)
- {
- if (consq_is_str && alter_is_str)
- {
- return expression_generator_
- .conditional_string(condition, consequent, alternative);
- }
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR052 - Return types of ternary if-statement differ",
- exprtk_error_location));
- result = false;
- }
- }
- #endif
- if (!result)
- {
- free_node(node_allocator_, condition);
- free_node(node_allocator_, consequent);
- free_node(node_allocator_, alternative);
- return error_node();
- }
- else
- return expression_generator_
- .conditional(condition, consequent, alternative);
- }
- inline expression_node_ptr parse_not_statement()
- {
- if (settings_.logic_disabled("not"))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR053 - Invalid or disabled logic operation 'not'",
- exprtk_error_location));
- return error_node();
- }
- return parse_base_operation();
- }
- inline expression_node_ptr parse_while_loop()
- {
- // Parse: [while][(][test expr][)][{][expression][}]
- expression_node_ptr condition = error_node();
- expression_node_ptr branch = error_node();
- expression_node_ptr result_node = error_node();
- bool result = true;
- next_token();
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR054 - Expected '(' at start of while-loop condition statement",
- exprtk_error_location));
- return error_node();
- }
- else if (0 == (condition = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR055 - Failed to parse condition for while-loop",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR056 - Expected ')' at end of while-loop condition statement",
- exprtk_error_location));
- result = false;
- }
- brkcnt_list_.push_front(false);
- if (result)
- {
- if (0 == (branch = parse_multi_sequence("while-loop")))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR057 - Failed to parse body of while-loop"));
- result = false;
- }
- else if (0 == (result_node = expression_generator_.while_loop(condition,
- branch,
- brkcnt_list_.front())))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR058 - Failed to synthesize while-loop",
- exprtk_error_location));
- result = false;
- }
- }
- if (!result)
- {
- free_node(node_allocator_, branch);
- free_node(node_allocator_, condition);
- free_node(node_allocator_, result_node);
- brkcnt_list_.pop_front();
- return error_node();
- }
- else
- return result_node;
- }
- inline expression_node_ptr parse_repeat_until_loop()
- {
- // Parse: [repeat][{][expression][}][until][(][test expr][)]
- expression_node_ptr condition = error_node();
- expression_node_ptr branch = error_node();
- next_token();
- std::vector<expression_node_ptr> arg_list;
- std::vector<bool> side_effect_list;
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- brkcnt_list_.push_front(false);
- if (details::imatch(current_token().value,"until"))
- {
- next_token();
- branch = node_allocator_.allocate<details::null_node<T> >();
- }
- else
- {
- const token_t::token_type seperator = token_t::e_eof;
- scope_handler sh(*this);
- scoped_bool_or_restorer sbr(state_.side_effect_present);
- for ( ; ; )
- {
- state_.side_effect_present = false;
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return error_node();
- else
- {
- arg_list.push_back(arg);
- side_effect_list.push_back(state_.side_effect_present);
- }
- if (details::imatch(current_token().value,"until"))
- {
- next_token();
- break;
- }
- const bool is_next_until = peek_token_is(token_t::e_symbol) &&
- peek_token_is("until");
- if (!token_is(seperator) && is_next_until)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR059 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
- exprtk_error_location));
- return error_node();
- }
- if (details::imatch(current_token().value,"until"))
- {
- next_token();
- break;
- }
- }
- branch = simplify(arg_list,side_effect_list);
- sdd.delete_ptr = (0 == branch);
- if (sdd.delete_ptr)
- {
- brkcnt_list_.pop_front();
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR060 - Failed to parse body of repeat until loop",
- exprtk_error_location));
- return error_node();
- }
- }
- if (!token_is(token_t::e_lbracket))
- {
- brkcnt_list_.pop_front();
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR061 - Expected '(' before condition statement of repeat until loop",
- exprtk_error_location));
- free_node(node_allocator_,branch);
- return error_node();
- }
- else if (0 == (condition = parse_expression()))
- {
- brkcnt_list_.pop_front();
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR062 - Failed to parse condition for repeat until loop",
- exprtk_error_location));
- free_node(node_allocator_,branch);
- return error_node();
- }
- else if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR063 - Expected ')' after condition of repeat until loop",
- exprtk_error_location));
- free_node(node_allocator_, branch);
- free_node(node_allocator_, condition);
- brkcnt_list_.pop_front();
- return error_node();
- }
- expression_node_ptr result;
- result = expression_generator_
- .repeat_until_loop(condition, branch, brkcnt_list_.front());
- if (0 == result)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR064 - Failed to synthesize repeat until loop",
- exprtk_error_location));
- free_node(node_allocator_,condition);
- brkcnt_list_.pop_front();
- return error_node();
- }
- else
- {
- brkcnt_list_.pop_front();
- return result;
- }
- }
- inline expression_node_ptr parse_for_loop()
- {
- expression_node_ptr initialiser = error_node();
- expression_node_ptr condition = error_node();
- expression_node_ptr incrementor = error_node();
- expression_node_ptr loop_body = error_node();
- scope_element* se = 0;
- bool result = true;
- next_token();
- scope_handler sh(*this);
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR065 - Expected '(' at start of for-loop",
- exprtk_error_location));
- return error_node();
- }
- if (!token_is(token_t::e_eof))
- {
- if (
- !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
- details::imatch(current_token().value,"var")
- )
- {
- next_token();
- if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR066 - Expected a variable at the start of initialiser section of for-loop",
- exprtk_error_location));
- return error_node();
- }
- else if (!peek_token_is(token_t::e_assign))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR067 - Expected variable assignment of initialiser section of for-loop",
- exprtk_error_location));
- return error_node();
- }
- const std::string loop_counter_symbol = current_token().value;
- se = &sem_.get_element(loop_counter_symbol);
- if ((se->name == loop_counter_symbol) && se->active)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR068 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
- exprtk_error_location));
- return error_node();
- }
- else if (!symtab_store_.is_variable(loop_counter_symbol))
- {
- if (
- !se->active &&
- (se->name == loop_counter_symbol) &&
- (se->type == scope_element::e_variable)
- )
- {
- se->active = true;
- se->ref_count++;
- }
- else
- {
- scope_element nse;
- nse.name = loop_counter_symbol;
- nse.active = true;
- nse.ref_count = 1;
- nse.type = scope_element::e_variable;
- nse.depth = state_.scope_depth;
- nse.data = new T(T(0));
- nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
- if (!sem_.add_element(nse))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR069 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
- exprtk_error_location));
- sem_.free_element(nse);
- result = false;
- }
- else
- {
- exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
- state_.activate_side_effect("parse_for_loop()");
- }
- }
- }
- }
- if (0 == (initialiser = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR070 - Failed to parse initialiser of for-loop",
- exprtk_error_location));
- result = false;
- }
- else if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR071 - Expected ';' after initialiser of for-loop",
- exprtk_error_location));
- result = false;
- }
- }
- if (!token_is(token_t::e_eof))
- {
- if (0 == (condition = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR072 - Failed to parse condition of for-loop",
- exprtk_error_location));
- result = false;
- }
- else if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR073 - Expected ';' after condition section of for-loop",
- exprtk_error_location));
- result = false;
- }
- }
- if (!token_is(token_t::e_rbracket))
- {
- if (0 == (incrementor = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR074 - Failed to parse incrementor of for-loop",
- exprtk_error_location));
- result = false;
- }
- else if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR075 - Expected ')' after incrementor section of for-loop",
- exprtk_error_location));
- result = false;
- }
- }
- if (result)
- {
- brkcnt_list_.push_front(false);
- if (0 == (loop_body = parse_multi_sequence("for-loop")))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR076 - Failed to parse body of for-loop",
- exprtk_error_location));
- result = false;
- }
- }
- if (!result)
- {
- if (se)
- {
- se->ref_count--;
- }
- free_node(node_allocator_, initialiser);
- free_node(node_allocator_, condition);
- free_node(node_allocator_, incrementor);
- free_node(node_allocator_, loop_body);
- if (!brkcnt_list_.empty())
- {
- brkcnt_list_.pop_front();
- }
- return error_node();
- }
- else
- {
- expression_node_ptr result_node =
- expression_generator_.for_loop(initialiser,
- condition,
- incrementor,
- loop_body,
- brkcnt_list_.front());
- brkcnt_list_.pop_front();
- return result_node;
- }
- }
- inline expression_node_ptr parse_switch_statement()
- {
- std::vector<expression_node_ptr> arg_list;
- expression_node_ptr result = error_node();
- if (!details::imatch(current_token().value,"switch"))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR077 - Expected keyword 'switch'",
- exprtk_error_location));
- return error_node();
- }
- scoped_vec_delete<expression_node_t> svd((*this),arg_list);
- next_token();
- if (!token_is(token_t::e_lcrlbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR078 - Expected '{' for call to switch statement",
- exprtk_error_location));
- return error_node();
- }
- for ( ; ; )
- {
- if (!details::imatch("case",current_token().value))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR079 - Expected either a 'case' or 'default' statement",
- exprtk_error_location));
- return error_node();
- }
- next_token();
- expression_node_ptr condition = parse_expression();
- if (0 == condition)
- return error_node();
- else if (!token_is(token_t::e_colon))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR080 - Expected ':' for case of switch statement",
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr consequent = parse_expression();
- if (0 == consequent)
- return error_node();
- else if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR081 - Expected ';' at end of case for switch statement",
- exprtk_error_location));
- return error_node();
- }
- // Can we optimise away the case statement?
- if (is_constant_node(condition) && is_false(condition))
- {
- free_node(node_allocator_, condition);
- free_node(node_allocator_, consequent);
- }
- else
- {
- arg_list.push_back( condition);
- arg_list.push_back(consequent);
- }
- if (details::imatch("default",current_token().value))
- {
- next_token();
- if (!token_is(token_t::e_colon))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR082 - Expected ':' for default of switch statement",
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr default_statement = error_node();
- if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
- default_statement = parse_multi_sequence("switch-default");
- else
- default_statement = parse_expression();
- if (0 == default_statement)
- return error_node();
- else if (!token_is(token_t::e_eof))
- {
- free_node(node_allocator_,default_statement);
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR083 - Expected ';' at end of default for switch statement",
- exprtk_error_location));
- return error_node();
- }
- arg_list.push_back(default_statement);
- break;
- }
- }
- if (!token_is(token_t::e_rcrlbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR084 - Expected '}' at end of switch statement",
- exprtk_error_location));
- return error_node();
- }
- result = expression_generator_.switch_statement(arg_list);
- svd.delete_ptr = (0 == result);
- return result;
- }
- inline expression_node_ptr parse_multi_switch_statement()
- {
- std::vector<expression_node_ptr> arg_list;
- if (!details::imatch(current_token().value,"[*]"))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR085 - Expected token '[*]'",
- exprtk_error_location));
- return error_node();
- }
- scoped_vec_delete<expression_node_t> svd((*this),arg_list);
- next_token();
- if (!token_is(token_t::e_lcrlbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR086 - Expected '{' for call to [*] statement",
- exprtk_error_location));
- return error_node();
- }
- for ( ; ; )
- {
- if (!details::imatch("case",current_token().value))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR087 - Expected a 'case' statement for multi-switch",
- exprtk_error_location));
- return error_node();
- }
- next_token();
- expression_node_ptr condition = parse_expression();
- if (0 == condition)
- return error_node();
- if (!token_is(token_t::e_colon))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR088 - Expected ':' for case of [*] statement",
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr consequent = parse_expression();
- if (0 == consequent)
- return error_node();
- if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR089 - Expected ';' at end of case for [*] statement",
- exprtk_error_location));
- return error_node();
- }
- // Can we optimise away the case statement?
- if (is_constant_node(condition) && is_false(condition))
- {
- free_node(node_allocator_, condition);
- free_node(node_allocator_, consequent);
- }
- else
- {
- arg_list.push_back( condition);
- arg_list.push_back(consequent);
- }
- if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
- {
- break;
- }
- }
- if (!token_is(token_t::e_rcrlbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR090 - Expected '}' at end of [*] statement",
- exprtk_error_location));
- return error_node();
- }
- const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
- svd.delete_ptr = (0 == result);
- return result;
- }
- inline expression_node_ptr parse_vararg_function()
- {
- std::vector<expression_node_ptr> arg_list;
- details::operator_type opt_type = details::e_default;
- const std::string symbol = current_token().value;
- if (details::imatch(symbol,"~"))
- {
- next_token();
- return parse_multi_sequence();
- }
- else if (details::imatch(symbol,"[*]"))
- {
- return parse_multi_switch_statement();
- }
- else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
- else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
- else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
- else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
- else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
- else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
- else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR091 - Unsupported vararg function: " + symbol,
- exprtk_error_location));
- return error_node();
- }
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- lodge_symbol(symbol, e_st_function);
- next_token();
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR092 - Expected '(' for call to vararg function: " + symbol,
- exprtk_error_location));
- return error_node();
- }
- for ( ; ; )
- {
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return error_node();
- else
- arg_list.push_back(arg);
- if (token_is(token_t::e_rbracket))
- break;
- else if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR093 - Expected ',' for call to vararg function: " + symbol,
- exprtk_error_location));
- return error_node();
- }
- }
- const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
- sdd.delete_ptr = (0 == result);
- return result;
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
- {
- if (!token_is(token_t::e_lsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR094 - Expected '[' as start of string range definition",
- exprtk_error_location));
- free_node(node_allocator_,expression);
- return error_node();
- }
- else if (token_is(token_t::e_rsqrbracket))
- {
- return node_allocator_.allocate<details::string_size_node<T> >(expression);
- }
- range_t rp;
- if (!parse_range(rp,true))
- {
- free_node(node_allocator_,expression);
- return error_node();
- }
- expression_node_ptr result = expression_generator_(expression,rp);
- if (0 == result)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR095 - Failed to generate string range node",
- exprtk_error_location));
- free_node(node_allocator_,expression);
- }
- rp.clear();
- return result;
- }
- #else
- inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
- {
- return error_node();
- }
- #endif
- inline void parse_pending_string_rangesize(expression_node_ptr& expression)
- {
- // Allow no more than 100 range calls, eg: s[][][]...[][]
- const std::size_t max_rangesize_parses = 100;
- std::size_t i = 0;
- while
- (
- (0 != expression) &&
- (i++ < max_rangesize_parses) &&
- error_list_.empty() &&
- is_generally_string_node(expression) &&
- token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
- )
- {
- expression = parse_string_range_statement(expression);
- }
- }
- template <typename Allocator1,
- typename Allocator2,
- template <typename, typename> class Sequence>
- inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
- Sequence<bool,Allocator2>& side_effect_list,
- const bool specialise_on_final_type = false)
- {
- if (expression_list.empty())
- return error_node();
- else if (1 == expression_list.size())
- return expression_list[0];
- Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
- bool return_node_present = false;
- for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
- {
- if (is_variable_node(expression_list[i]))
- continue;
- else if (
- is_return_node (expression_list[i]) ||
- is_break_node (expression_list[i]) ||
- is_continue_node(expression_list[i])
- )
- {
- tmp_expression_list.push_back(expression_list[i]);
- // Remove all subexpressions after first short-circuit
- // node has been encountered.
- for (std::size_t j = i + 1; j < expression_list.size(); ++j)
- {
- free_node(node_allocator_,expression_list[j]);
- }
- return_node_present = true;
- break;
- }
- else if (
- is_constant_node(expression_list[i]) ||
- is_null_node (expression_list[i]) ||
- !side_effect_list[i]
- )
- {
- free_node(node_allocator_,expression_list[i]);
- continue;
- }
- else
- tmp_expression_list.push_back(expression_list[i]);
- }
- if (!return_node_present)
- {
- tmp_expression_list.push_back(expression_list.back());
- }
- expression_list.swap(tmp_expression_list);
- if (tmp_expression_list.size() > expression_list.size())
- {
- exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
- static_cast<int>(tmp_expression_list.size()),
- static_cast<int>(expression_list .size())));
- }
- if (
- return_node_present ||
- side_effect_list.back() ||
- (expression_list.size() > 1)
- )
- state_.activate_side_effect("simplify()");
- if (1 == expression_list.size())
- return expression_list[0];
- else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
- return expression_generator_.vararg_function(details::e_smulti,expression_list);
- else
- return expression_generator_.vararg_function(details::e_multi,expression_list);
- }
- inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
- {
- token_t::token_type close_bracket = token_t::e_rcrlbracket;
- token_t::token_type seperator = token_t::e_eof;
- if (!token_is(token_t::e_lcrlbracket))
- {
- if (token_is(token_t::e_lbracket))
- {
- close_bracket = token_t::e_rbracket;
- seperator = token_t::e_comma;
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR096 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
- ((!source.empty()) ? std::string(" section of " + source): ""),
- exprtk_error_location));
- return error_node();
- }
- }
- else if (token_is(token_t::e_rcrlbracket))
- {
- return node_allocator_.allocate<details::null_node<T> >();
- }
- std::vector<expression_node_ptr> arg_list;
- std::vector<bool> side_effect_list;
- expression_node_ptr result = error_node();
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- scope_handler sh(*this);
- scoped_bool_or_restorer sbr(state_.side_effect_present);
- for ( ; ; )
- {
- state_.side_effect_present = false;
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return error_node();
- else
- {
- arg_list.push_back(arg);
- side_effect_list.push_back(state_.side_effect_present);
- }
- if (token_is(close_bracket))
- break;
- const bool is_next_close = peek_token_is(close_bracket);
- if (!token_is(seperator) && is_next_close)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR097 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
- exprtk_error_location));
- return error_node();
- }
- if (token_is(close_bracket))
- break;
- }
- result = simplify(arg_list,side_effect_list,source.empty());
- sdd.delete_ptr = (0 == result);
- return result;
- }
- inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
- {
- // Examples of valid ranges:
- // 1. [1:5] -> 1..5
- // 2. [ :5] -> 0..5
- // 3. [1: ] -> 1..end
- // 4. [x:y] -> x..y where x <= y
- // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
- // 6. [ :y] -> 0..y where 0 <= y
- // 7. [x: ] -> x..end where x <= end
- rp.clear();
- if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR098 - Expected '[' for start of range",
- exprtk_error_location));
- return false;
- }
- if (token_is(token_t::e_colon))
- {
- rp.n0_c.first = true;
- rp.n0_c.second = 0;
- rp.cache.first = 0;
- }
- else
- {
- expression_node_ptr r0 = parse_expression();
- if (0 == r0)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR099 - Failed parse begin section of range",
- exprtk_error_location));
- return false;
- }
- else if (is_constant_node(r0))
- {
- const T r0_value = r0->value();
- if (r0_value >= T(0))
- {
- rp.n0_c.first = true;
- rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
- rp.cache.first = rp.n0_c.second;
- }
- free_node(node_allocator_,r0);
- if (r0_value < T(0))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR100 - Range lower bound less than zero! Constraint: r0 >= 0",
- exprtk_error_location));
- return false;
- }
- }
- else
- {
- rp.n0_e.first = true;
- rp.n0_e.second = r0;
- }
- if (!token_is(token_t::e_colon))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR101 - Expected ':' for break in range",
- exprtk_error_location));
- rp.free();
- return false;
- }
- }
- if (token_is(token_t::e_rsqrbracket))
- {
- rp.n1_c.first = true;
- rp.n1_c.second = std::numeric_limits<std::size_t>::max();
- }
- else
- {
- expression_node_ptr r1 = parse_expression();
- if (0 == r1)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR102 - Failed parse end section of range",
- exprtk_error_location));
- rp.free();
- return false;
- }
- else if (is_constant_node(r1))
- {
- const T r1_value = r1->value();
- if (r1_value >= T(0))
- {
- rp.n1_c.first = true;
- rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
- rp.cache.second = rp.n1_c.second;
- }
- free_node(node_allocator_,r1);
- if (r1_value < T(0))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR103 - Range upper bound less than zero! Constraint: r1 >= 0",
- exprtk_error_location));
- return false;
- }
- }
- else
- {
- rp.n1_e.first = true;
- rp.n1_e.second = r1;
- }
- if (!token_is(token_t::e_rsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR104 - Expected ']' for start of range",
- exprtk_error_location));
- rp.free();
- return false;
- }
- }
- if (rp.const_range())
- {
- std::size_t r0 = 0;
- std::size_t r1 = 0;
- const bool rp_result = rp(r0,r1);
- if (!rp_result || (r0 > r1))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR105 - Invalid range, Constraint: r0 <= r1",
- exprtk_error_location));
- return false;
- }
- }
- return true;
- }
- inline void lodge_symbol(const std::string& symbol,
- const symbol_type st)
- {
- dec_.add_symbol(symbol,st);
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr parse_string()
- {
- const std::string symbol = current_token().value;
- typedef details::stringvar_node<T>* strvar_node_t;
- expression_node_ptr result = error_node();
- strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
- scope_element& se = sem_.get_active_element(symbol);
- if (scope_element::e_string == se.type)
- {
- se.active = true;
- result = se.str_node;
- lodge_symbol(symbol, e_st_local_string);
- }
- else
- {
- if (!symtab_store_.is_conststr_stringvar(symbol))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR106 - Unknown string symbol",
- exprtk_error_location));
- return error_node();
- }
- result = symtab_store_.get_stringvar(symbol);
- if (symtab_store_.is_constant_string(symbol))
- {
- const_str_node = static_cast<strvar_node_t>(result);
- result = expression_generator_(const_str_node->str());
- }
- lodge_symbol(symbol, e_st_string);
- }
- if (peek_token_is(token_t::e_lsqrbracket))
- {
- next_token();
- if (peek_token_is(token_t::e_rsqrbracket))
- {
- next_token();
- next_token();
- if (const_str_node)
- {
- free_node(node_allocator_,result);
- return expression_generator_(T(const_str_node->size()));
- }
- else
- return node_allocator_.allocate<details::stringvar_size_node<T> >
- (static_cast<details::stringvar_node<T>*>(result)->ref());
- }
- range_t rp;
- if (!parse_range(rp))
- {
- free_node(node_allocator_,result);
- return error_node();
- }
- else if (const_str_node)
- {
- free_node(node_allocator_,result);
- result = expression_generator_(const_str_node->ref(),rp);
- }
- else
- result = expression_generator_(static_cast<details::stringvar_node<T>*>
- (result)->ref(), rp);
- if (result)
- rp.clear();
- }
- else
- next_token();
- return result;
- }
- #else
- inline expression_node_ptr parse_string()
- {
- return error_node();
- }
- #endif
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr parse_const_string()
- {
- const std::string const_str = current_token().value;
- expression_node_ptr result = expression_generator_(const_str);
- if (peek_token_is(token_t::e_lsqrbracket))
- {
- next_token();
- if (peek_token_is(token_t::e_rsqrbracket))
- {
- next_token();
- next_token();
- free_node(node_allocator_,result);
- return expression_generator_(T(const_str.size()));
- }
- range_t rp;
- if (!parse_range(rp))
- {
- free_node(node_allocator_,result);
- return error_node();
- }
- free_node(node_allocator_,result);
- if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
- {
- rp.n1_c.second = const_str.size() - 1;
- rp.cache.second = rp.n1_c.second;
- }
- if (
- (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
- (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR107 - Overflow in range for string: '" + const_str + "'[" +
- (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
- (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
- exprtk_error_location));
- return error_node();
- }
- result = expression_generator_(const_str,rp);
- if (result)
- rp.clear();
- }
- else
- next_token();
- return result;
- }
- #else
- inline expression_node_ptr parse_const_string()
- {
- return error_node();
- }
- #endif
- inline expression_node_ptr parse_vector()
- {
- const std::string symbol = current_token().value;
- vector_holder_ptr vec = vector_holder_ptr(0);
- const scope_element& se = sem_.get_active_element(symbol);
- if (
- !details::imatch(se.name, symbol) ||
- (se.depth > state_.scope_depth) ||
- (scope_element::e_vector != se.type)
- )
- {
- if (0 == (vec = symtab_store_.get_vector(symbol)))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR108 - Symbol '" + symbol+ " not a vector",
- exprtk_error_location));
- return error_node();
- }
- }
- else
- vec = se.vec_node;
- expression_node_ptr index_expr = error_node();
- next_token();
- if (!token_is(token_t::e_lsqrbracket))
- {
- return node_allocator_.allocate<vector_node_t>(vec);
- }
- else if (token_is(token_t::e_rsqrbracket))
- {
- return expression_generator_(T(vec->size()));
- }
- else if (0 == (index_expr = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR109 - Failed to parse index for vector: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_rsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR110 - Expected ']' for index of vector: '" + symbol + "'",
- exprtk_error_location));
- free_node(node_allocator_,index_expr);
- return error_node();
- }
- // Perform compile-time range check
- if (details::is_constant_node(index_expr))
- {
- const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
- const std::size_t vec_size = vec->size();
- if (index >= vec_size)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR111 - Index of " + details::to_str(index) + " out of range for "
- "vector '" + symbol + "' of size " + details::to_str(vec_size),
- exprtk_error_location));
- free_node(node_allocator_,index_expr);
- return error_node();
- }
- }
- return expression_generator_.vector_element(symbol, vec, index_expr);
- }
- inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
- {
- std::vector<expression_node_ptr> arg_list;
- expression_node_ptr result = error_node();
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- next_token();
- if (token_is(token_t::e_lbracket))
- {
- if (token_is(token_t::e_rbracket))
- {
- if (!vararg_function->allow_zero_parameters())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR112 - Zero parameter call to vararg function: "
- + vararg_function_name + " not allowed",
- exprtk_error_location));
- return error_node();
- }
- }
- else
- {
- for ( ; ; )
- {
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return error_node();
- else
- arg_list.push_back(arg);
- if (token_is(token_t::e_rbracket))
- break;
- else if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR113 - Expected ',' for call to vararg function: "
- + vararg_function_name,
- exprtk_error_location));
- return error_node();
- }
- }
- }
- }
- else if (!vararg_function->allow_zero_parameters())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR114 - Zero parameter call to vararg function: "
- + vararg_function_name + " not allowed",
- exprtk_error_location));
- return error_node();
- }
- if (arg_list.size() < vararg_function->min_num_args())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR115 - Invalid number of parameters to call to vararg function: "
- + vararg_function_name + ", require at least "
- + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
- exprtk_error_location));
- return error_node();
- }
- else if (arg_list.size() > vararg_function->max_num_args())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR116 - Invalid number of parameters to call to vararg function: "
- + vararg_function_name + ", require no more than "
- + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
- exprtk_error_location));
- return error_node();
- }
- result = expression_generator_.vararg_function_call(vararg_function,arg_list);
- sdd.delete_ptr = (0 == result);
- return result;
- }
- class type_checker
- {
- public:
- enum return_type_t
- {
- e_overload = ' ',
- e_numeric = 'T',
- e_string = 'S'
- };
- struct function_prototype_t
- {
- return_type_t return_type;
- std::string param_seq;
- };
- typedef parser<T> parser_t;
- typedef std::vector<function_prototype_t> function_definition_list_t;
- type_checker(parser_t& p,
- const std::string& func_name,
- const std::string& func_prototypes,
- const return_type_t default_return_type)
- : invalid_state_(true),
- parser_(p),
- function_name_(func_name),
- default_return_type_(default_return_type)
- {
- parse_function_prototypes(func_prototypes);
- }
- void set_default_return_type(const std::string& return_type)
- {
- default_return_type_ = return_type;
- }
- bool verify(const std::string& param_seq, std::size_t& pseq_index)
- {
- if (function_definition_list_.empty())
- return true;
- std::vector<std::pair<std::size_t,char> > error_list;
- for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
- {
- details::char_t diff_value = 0;
- std::size_t diff_index = 0;
- const bool result = details::sequence_match(function_definition_list_[i].param_seq,
- param_seq,
- diff_index, diff_value);
- if (result)
- {
- pseq_index = i;
- return true;
- }
- else
- error_list.push_back(std::make_pair(diff_index, diff_value));
- }
- if (1 == error_list.size())
- {
- parser_.
- set_error(
- make_error(parser_error::e_syntax,
- parser_.current_token(),
- "ERR117 - Failed parameter type check for function '" + function_name_ + "', "
- "Expected '" + function_definition_list_[0].param_seq +
- "' call set: '" + param_seq + "'",
- exprtk_error_location));
- }
- else
- {
- // find first with largest diff_index;
- std::size_t max_diff_index = 0;
- for (std::size_t i = 1; i < error_list.size(); ++i)
- {
- if (error_list[i].first > error_list[max_diff_index].first)
- {
- max_diff_index = i;
- }
- }
- parser_.
- set_error(
- make_error(parser_error::e_syntax,
- parser_.current_token(),
- "ERR118 - Failed parameter type check for function '" + function_name_ + "', "
- "Best match: '" + function_definition_list_[max_diff_index].param_seq +
- "' call set: '" + param_seq + "'",
- exprtk_error_location));
- }
- return false;
- }
- std::size_t paramseq_count() const
- {
- return function_definition_list_.size();
- }
- std::string paramseq(const std::size_t& index) const
- {
- return function_definition_list_[index].param_seq;
- }
- return_type_t return_type(const std::size_t& index) const
- {
- return function_definition_list_[index].return_type;
- }
- bool invalid() const
- {
- return !invalid_state_;
- }
- bool allow_zero_parameters() const
- {
- for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
- {
- if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
- {
- return true;
- }
- }
- return false;
- }
- private:
- std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
- {
- std::string::const_iterator current_begin = param_seq.begin();
- std::string::const_iterator iter = param_seq.begin();
- std::vector<std::string> result;
- while (iter != param_seq.end())
- {
- if (*iter == delimiter)
- {
- result.push_back(std::string(current_begin, iter));
- current_begin = ++iter;
- }
- else
- ++iter;
- }
- if (current_begin != iter)
- {
- result.push_back(std::string(current_begin, iter));
- }
- return result;
- }
- inline bool is_valid_token(std::string param_seq,
- function_prototype_t& funcproto) const
- {
- // Determine return type
- funcproto.return_type = default_return_type_;
- if (param_seq.size() > 2)
- {
- if (':' == param_seq[1])
- {
- // Note: Only overloaded igeneric functions can have return
- // type definitions.
- if (type_checker::e_overload != default_return_type_)
- return false;
- switch (param_seq[0])
- {
- case 'T' : funcproto.return_type = type_checker::e_numeric;
- break;
- case 'S' : funcproto.return_type = type_checker::e_string;
- break;
- default : return false;
- }
- param_seq.erase(0,2);
- }
- }
- if (
- (std::string::npos != param_seq.find("?*")) ||
- (std::string::npos != param_seq.find("**"))
- )
- {
- return false;
- }
- else if (
- (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
- ("Z" == param_seq)
- )
- {
- funcproto.param_seq = param_seq;
- return true;
- }
- return false;
- }
- void parse_function_prototypes(const std::string& func_prototypes)
- {
- if (func_prototypes.empty())
- return;
- std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
- typedef std::map<std::string,std::size_t> param_seq_map_t;
- param_seq_map_t param_seq_map;
- for (std::size_t i = 0; i < param_seq_list.size(); ++i)
- {
- function_prototype_t func_proto;
- if (!is_valid_token(param_seq_list[i], func_proto))
- {
- invalid_state_ = false;
- parser_.
- set_error(
- make_error(parser_error::e_syntax,
- parser_.current_token(),
- "ERR119 - Invalid parameter sequence of '" + param_seq_list[i] +
- "' for function: " + function_name_,
- exprtk_error_location));
- return;
- }
- param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
- if (param_seq_map.end() != seq_itr)
- {
- invalid_state_ = false;
- parser_.
- set_error(
- make_error(parser_error::e_syntax,
- parser_.current_token(),
- "ERR120 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
- "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
- "pseq_idx[" + details::to_str(i) + "] " +
- "param seq: " + param_seq_list[i],
- exprtk_error_location));
- return;
- }
- function_definition_list_.push_back(func_proto);
- }
- }
- type_checker(const type_checker&);
- type_checker& operator=(const type_checker&);
- bool invalid_state_;
- parser_t& parser_;
- std::string function_name_;
- const return_type_t default_return_type_;
- function_definition_list_t function_definition_list_;
- };
- inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
- {
- std::vector<expression_node_ptr> arg_list;
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- next_token();
- std::string param_type_list;
- type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
- if (tc.invalid())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR121 - Type checker instantiation failure for generic function: " + function_name,
- exprtk_error_location));
- return error_node();
- }
- if (token_is(token_t::e_lbracket))
- {
- if (token_is(token_t::e_rbracket))
- {
- if (
- !function->allow_zero_parameters() &&
- !tc .allow_zero_parameters()
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR122 - Zero parameter call to generic function: "
- + function_name + " not allowed",
- exprtk_error_location));
- return error_node();
- }
- }
- else
- {
- for ( ; ; )
- {
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return error_node();
- if (is_ivector_node(arg))
- param_type_list += 'V';
- else if (is_generally_string_node(arg))
- param_type_list += 'S';
- else // Everything else is assumed to be a scalar returning expression
- param_type_list += 'T';
- arg_list.push_back(arg);
- if (token_is(token_t::e_rbracket))
- break;
- else if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR123 - Expected ',' for call to generic function: " + function_name,
- exprtk_error_location));
- return error_node();
- }
- }
- }
- }
- else if (
- !function->parameter_sequence.empty() &&
- function->allow_zero_parameters () &&
- !tc .allow_zero_parameters ()
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR124 - Zero parameter call to generic function: "
- + function_name + " not allowed",
- exprtk_error_location));
- return error_node();
- }
- std::size_t param_seq_index = 0;
- if (
- state_.type_check_enabled &&
- !tc.verify(param_type_list, param_seq_index)
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR125 - Invalid input parameter sequence for call to generic function: " + function_name,
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr result = error_node();
- if (tc.paramseq_count() <= 1)
- result = expression_generator_
- .generic_function_call(function, arg_list);
- else
- result = expression_generator_
- .generic_function_call(function, arg_list, param_seq_index);
- sdd.delete_ptr = (0 == result);
- return result;
- }
- inline bool parse_igeneric_function_params(std::string& param_type_list,
- std::vector<expression_node_ptr>& arg_list,
- const std::string function_name,
- igeneric_function<T>* function,
- const type_checker& tc)
- {
- if (token_is(token_t::e_lbracket))
- {
- if (token_is(token_t::e_rbracket))
- {
- if (
- !function->allow_zero_parameters() &&
- !tc .allow_zero_parameters()
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR126 - Zero parameter call to generic function: "
- + function_name + " not allowed",
- exprtk_error_location));
- return false;
- }
- }
- else
- {
- for ( ; ; )
- {
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return false;
- if (is_ivector_node(arg))
- param_type_list += 'V';
- else if (is_generally_string_node(arg))
- param_type_list += 'S';
- else // Everything else is a scalar returning expression
- param_type_list += 'T';
- arg_list.push_back(arg);
- if (token_is(token_t::e_rbracket))
- break;
- else if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR127 - Expected ',' for call to string function: " + function_name,
- exprtk_error_location));
- return false;
- }
- }
- }
- return true;
- }
- else
- return false;
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
- {
- // Move pass the function name
- next_token();
- std::string param_type_list;
- type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
- if (
- (!function->parameter_sequence.empty()) &&
- (0 == tc.paramseq_count())
- )
- {
- return error_node();
- }
- std::vector<expression_node_ptr> arg_list;
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
- {
- return error_node();
- }
- std::size_t param_seq_index = 0;
- if (!tc.verify(param_type_list, param_seq_index))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR128 - Invalid input parameter sequence for call to string function: " + function_name,
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr result = error_node();
- if (tc.paramseq_count() <= 1)
- result = expression_generator_
- .string_function_call(function, arg_list);
- else
- result = expression_generator_
- .string_function_call(function, arg_list, param_seq_index);
- sdd.delete_ptr = (0 == result);
- return result;
- }
- inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
- {
- // Move pass the function name
- next_token();
- std::string param_type_list;
- type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
- if (
- (!function->parameter_sequence.empty()) &&
- (0 == tc.paramseq_count())
- )
- {
- return error_node();
- }
- std::vector<expression_node_ptr> arg_list;
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
- {
- return error_node();
- }
- std::size_t param_seq_index = 0;
- if (!tc.verify(param_type_list, param_seq_index))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR129 - Invalid input parameter sequence for call to overloaded function: " + function_name,
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr result = error_node();
- if (type_checker::e_numeric == tc.return_type(param_seq_index))
- {
- if (tc.paramseq_count() <= 1)
- result = expression_generator_
- .generic_function_call(function, arg_list);
- else
- result = expression_generator_
- .generic_function_call(function, arg_list, param_seq_index);
- }
- else if (type_checker::e_string == tc.return_type(param_seq_index))
- {
- if (tc.paramseq_count() <= 1)
- result = expression_generator_
- .string_function_call(function, arg_list);
- else
- result = expression_generator_
- .string_function_call(function, arg_list, param_seq_index);
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR130 - Invalid return type for call to overloaded function: " + function_name,
- exprtk_error_location));
- }
- sdd.delete_ptr = (0 == result);
- return result;
- }
- #endif
- template <typename Type, std::size_t NumberOfParameters>
- struct parse_special_function_impl
- {
- static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
- {
- expression_node_ptr branch[NumberOfParameters];
- expression_node_ptr result = error_node();
- std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
- scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
- p.next_token();
- if (!p.token_is(token_t::e_lbracket))
- {
- p.set_error(
- make_error(parser_error::e_syntax,
- p.current_token(),
- "ERR131 - Expected '(' for special function '" + sf_name + "'",
- exprtk_error_location));
- return error_node();
- }
- for (std::size_t i = 0; i < NumberOfParameters; ++i)
- {
- branch[i] = p.parse_expression();
- if (0 == branch[i])
- {
- return p.error_node();
- }
- else if (i < (NumberOfParameters - 1))
- {
- if (!p.token_is(token_t::e_comma))
- {
- p.set_error(
- make_error(parser_error::e_syntax,
- p.current_token(),
- "ERR132 - Expected ',' before next parameter of special function '" + sf_name + "'",
- exprtk_error_location));
- return p.error_node();
- }
- }
- }
- if (!p.token_is(token_t::e_rbracket))
- {
- p.set_error(
- make_error(parser_error::e_syntax,
- p.current_token(),
- "ERR133 - Invalid number of parameters for special function '" + sf_name + "'",
- exprtk_error_location));
- return p.error_node();
- }
- else
- result = p.expression_generator_.special_function(opt_type,branch);
- sd.delete_ptr = (0 == result);
- return result;
- }
- };
- inline expression_node_ptr parse_special_function()
- {
- const std::string sf_name = current_token().value;
- // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
- if (
- !details::is_digit(sf_name[2]) ||
- !details::is_digit(sf_name[3])
- )
- {
- set_error(
- make_error(parser_error::e_token,
- current_token(),
- "ERR134 - Invalid special function[1]: " + sf_name,
- exprtk_error_location));
- return error_node();
- }
- const int id = (sf_name[2] - '0') * 10 +
- (sf_name[3] - '0');
- if (id >= details::e_sffinal)
- {
- set_error(
- make_error(parser_error::e_token,
- current_token(),
- "ERR135 - Invalid special function[2]: " + sf_name,
- exprtk_error_location));
- return error_node();
- }
- const int sf_3_to_4 = details::e_sf48;
- const details::operator_type opt_type = details::operator_type(id + 1000);
- const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
- switch (NumberOfParameters)
- {
- case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
- case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
- default : return error_node();
- }
- }
- inline expression_node_ptr parse_null_statement()
- {
- next_token();
- return node_allocator_.allocate<details::null_node<T> >();
- }
- #ifndef exprtk_disable_break_continue
- inline expression_node_ptr parse_break_statement()
- {
- if (state_.parsing_break_stmt)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR136 - Break call within a break call is not allowed",
- exprtk_error_location));
- return error_node();
- }
- scoped_bool_negator sbn(state_.parsing_break_stmt);
- if (!brkcnt_list_.empty())
- {
- next_token();
- brkcnt_list_.front() = true;
- expression_node_ptr return_expr = error_node();
- if (token_is(token_t::e_lsqrbracket))
- {
- if (0 == (return_expr = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR137 - Failed to parse return expression for 'break' statement",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_rsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR138 - Expected ']' at the completion of break's return expression",
- exprtk_error_location));
- free_node(node_allocator_,return_expr);
- return error_node();
- }
- }
- state_.activate_side_effect("parse_break_statement()");
- return node_allocator_.allocate<details::break_node<T> >(return_expr);
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
- exprtk_error_location));
- }
- return error_node();
- }
- inline expression_node_ptr parse_continue_statement()
- {
- if (!brkcnt_list_.empty())
- {
- next_token();
- brkcnt_list_.front() = true;
- state_.activate_side_effect("parse_continue_statement()");
- return node_allocator_.allocate<details::continue_node<T> >();
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR140 - Invalid use of 'continue', allowed only in the scope of a loop",
- exprtk_error_location));
- return error_node();
- }
- }
- #endif
- inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
- {
- expression_node_ptr size_expr = error_node();
- if (!token_is(token_t::e_lsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR141 - Expected '[' as part of vector size definition",
- exprtk_error_location));
- return error_node();
- }
- else if (0 == (size_expr = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR142 - Failed to determine size of vector '" + vec_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (!is_constant_node(size_expr))
- {
- free_node(node_allocator_,size_expr);
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR143 - Expected a literal number as size of vector '" + vec_name + "'",
- exprtk_error_location));
- return error_node();
- }
- const T vector_size = size_expr->value();
- free_node(node_allocator_,size_expr);
- const T max_vector_size = T(2000000000.0);
- if (
- (vector_size <= T(0)) ||
- std::not_equal_to<T>()
- (T(0),vector_size - details::numeric::trunc(vector_size)) ||
- (vector_size > max_vector_size)
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR144 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
- details::to_str(details::numeric::to_int32(vector_size)),
- exprtk_error_location));
- return error_node();
- }
- std::vector<expression_node_ptr> vec_initilizer_list;
- scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
- bool single_value_initialiser = false;
- bool vec_to_vec_initialiser = false;
- bool null_initialisation = false;
- if (!token_is(token_t::e_rsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR145 - Expected ']' as part of vector size definition",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_eof))
- {
- if (!token_is(token_t::e_assign))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR146 - Expected ':=' as part of vector definition",
- exprtk_error_location));
- return error_node();
- }
- else if (token_is(token_t::e_lsqrbracket))
- {
- expression_node_ptr initialiser = parse_expression();
- if (0 == initialiser)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR147 - Failed to parse single vector initialiser",
- exprtk_error_location));
- return error_node();
- }
- vec_initilizer_list.push_back(initialiser);
- if (!token_is(token_t::e_rsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR148 - Expected ']' to close single value vector initialiser",
- exprtk_error_location));
- return error_node();
- }
- single_value_initialiser = true;
- }
- else if (!token_is(token_t::e_lcrlbracket))
- {
- expression_node_ptr initialiser = error_node();
- // Is this a vector to vector assignment and initialisation?
- if (token_t::e_symbol == current_token().type)
- {
- // Is it a locally defined vector?
- scope_element& se = sem_.get_active_element(current_token().value);
- if (scope_element::e_vector == se.type)
- {
- if (0 != (initialiser = parse_expression()))
- vec_initilizer_list.push_back(initialiser);
- else
- return error_node();
- }
- // Are we dealing with a user defined vector?
- else if (symtab_store_.is_vector(current_token().value))
- {
- lodge_symbol(current_token().value, e_st_vector);
- if (0 != (initialiser = parse_expression()))
- vec_initilizer_list.push_back(initialiser);
- else
- return error_node();
- }
- // Are we dealing with a null initialisation vector definition?
- else if (token_is(token_t::e_symbol,"null"))
- null_initialisation = true;
- }
- if (!null_initialisation)
- {
- if (0 == initialiser)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR149 - Expected '{' as part of vector initialiser list",
- exprtk_error_location));
- return error_node();
- }
- else
- vec_to_vec_initialiser = true;
- }
- }
- else if (!token_is(token_t::e_rcrlbracket))
- {
- for ( ; ; )
- {
- expression_node_ptr initialiser = parse_expression();
- if (0 == initialiser)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR150 - Expected '{' as part of vector initialiser list",
- exprtk_error_location));
- return error_node();
- }
- else
- vec_initilizer_list.push_back(initialiser);
- if (token_is(token_t::e_rcrlbracket))
- break;
- const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
- if (!token_is(token_t::e_comma) && is_next_close)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR151 - Expected ',' between vector initialisers",
- exprtk_error_location));
- return error_node();
- }
- if (token_is(token_t::e_rcrlbracket))
- break;
- }
- }
- if (
- !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
- !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
- !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
- )
- {
- if (!token_is(token_t::e_eof))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR152 - Expected ';' at end of vector definition",
- exprtk_error_location));
- return error_node();
- }
- }
- if (vec_initilizer_list.size() > vector_size)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR153 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
- const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
- scope_element& se = sem_.get_element(vec_name);
- if (se.name == vec_name)
- {
- if (se.active)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR154 - Illegal redefinition of local vector: '" + vec_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (
- (se.size == vec_size) &&
- (scope_element::e_vector == se.type)
- )
- {
- vec_holder = se.vec_node;
- se.active = true;
- se.depth = state_.scope_depth;
- se.ref_count++;
- }
- }
- if (0 == vec_holder)
- {
- scope_element nse;
- nse.name = vec_name;
- nse.active = true;
- nse.ref_count = 1;
- nse.type = scope_element::e_vector;
- nse.depth = state_.scope_depth;
- nse.size = vec_size;
- nse.data = new T[vec_size];
- nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
- if (!sem_.add_element(nse))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR155 - Failed to add new local vector '" + vec_name + "' to SEM",
- exprtk_error_location));
- sem_.free_element(nse);
- return error_node();
- }
- vec_holder = nse.vec_node;
- exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
- nse.name.c_str(),
- static_cast<int>(nse.size)));
- }
- state_.activate_side_effect("parse_define_vector_statement()");
- lodge_symbol(vec_name, e_st_local_vector);
- expression_node_ptr result = error_node();
- if (null_initialisation)
- result = expression_generator_(T(0.0));
- else if (vec_to_vec_initialiser)
- {
- expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
- result = expression_generator_(
- details::e_assign,
- vec_node,
- vec_initilizer_list[0]);
- }
- else
- result = node_allocator_
- .allocate<details::vector_assignment_node<T> >(
- (*vec_holder)[0],
- vec_size,
- vec_initilizer_list,
- single_value_initialiser);
- svd.delete_ptr = (0 == result);
- return result;
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
- {
- stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
- scope_element& se = sem_.get_element(str_name);
- if (se.name == str_name)
- {
- if (se.active)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR156 - Illegal redefinition of local variable: '" + str_name + "'",
- exprtk_error_location));
- free_node(node_allocator_,initialisation_expression);
- return error_node();
- }
- else if (scope_element::e_string == se.type)
- {
- str_node = se.str_node;
- se.active = true;
- se.depth = state_.scope_depth;
- se.ref_count++;
- }
- }
- if (0 == str_node)
- {
- scope_element nse;
- nse.name = str_name;
- nse.active = true;
- nse.ref_count = 1;
- nse.type = scope_element::e_string;
- nse.depth = state_.scope_depth;
- nse.data = new std::string;
- nse.str_node = new stringvar_node_t(*(std::string*)(nse.data));
- if (!sem_.add_element(nse))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR157 - Failed to add new local string variable '" + str_name + "' to SEM",
- exprtk_error_location));
- free_node(node_allocator_,initialisation_expression);
- sem_.free_element(nse);
- return error_node();
- }
- str_node = nse.str_node;
- exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
- }
- lodge_symbol(str_name, e_st_local_string);
- state_.activate_side_effect("parse_define_string_statement()");
- expression_node_ptr branch[2] = {0};
- branch[0] = str_node;
- branch[1] = initialisation_expression;
- return expression_generator_(details::e_assign,branch);
- }
- #else
- inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
- {
- return error_node();
- }
- #endif
- inline bool local_variable_is_shadowed(const std::string& symbol)
- {
- const scope_element& se = sem_.get_element(symbol);
- return (se.name == symbol) && se.active;
- }
- inline expression_node_ptr parse_define_var_statement()
- {
- if (settings_.vardef_disabled())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR158 - Illegal variable definition",
- exprtk_error_location));
- return error_node();
- }
- else if (!details::imatch(current_token().value,"var"))
- {
- return error_node();
- }
- else
- next_token();
- const std::string var_name = current_token().value;
- expression_node_ptr initialisation_expression = error_node();
- if (!token_is(token_t::e_symbol))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR159 - Expected a symbol for variable definition",
- exprtk_error_location));
- return error_node();
- }
- else if (details::is_reserved_symbol(var_name))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR160 - Illegal redefinition of reserved keyword: '" + var_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (symtab_store_.symbol_exists(var_name))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR161 - Illegal redefinition of variable '" + var_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (local_variable_is_shadowed(var_name))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR162 - Illegal redefinition of local variable: '" + var_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
- {
- return parse_define_vector_statement(var_name);
- }
- else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
- {
- return parse_uninitialised_var_statement(var_name);
- }
- else if (token_is(token_t::e_assign))
- {
- if (0 == (initialisation_expression = parse_expression()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR163 - Failed to parse initialisation expression",
- exprtk_error_location));
- return error_node();
- }
- }
- if (
- !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
- !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
- !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
- )
- {
- if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR164 - Expected ';' after variable definition",
- exprtk_error_location));
- free_node(node_allocator_,initialisation_expression);
- return error_node();
- }
- }
- if (
- (0 != initialisation_expression) &&
- details::is_generally_string_node(initialisation_expression)
- )
- {
- return parse_define_string_statement(var_name,initialisation_expression);
- }
- expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
- scope_element& se = sem_.get_element(var_name);
- if (se.name == var_name)
- {
- if (se.active)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
- exprtk_error_location));
- free_node(node_allocator_, initialisation_expression);
- return error_node();
- }
- else if (scope_element::e_variable == se.type)
- {
- var_node = se.var_node;
- se.active = true;
- se.depth = state_.scope_depth;
- se.ref_count++;
- }
- }
- if (0 == var_node)
- {
- scope_element nse;
- nse.name = var_name;
- nse.active = true;
- nse.ref_count = 1;
- nse.type = scope_element::e_variable;
- nse.depth = state_.scope_depth;
- nse.data = new T(T(0));
- nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
- if (!sem_.add_element(nse))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR166 - Failed to add new local variable '" + var_name + "' to SEM",
- exprtk_error_location));
- free_node(node_allocator_, initialisation_expression);
- sem_.free_element(nse);
- return error_node();
- }
- var_node = nse.var_node;
- exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
- }
- state_.activate_side_effect("parse_define_var_statement()");
- lodge_symbol(var_name, e_st_local_variable);
- expression_node_ptr branch[2] = {0};
- branch[0] = var_node;
- branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
- return expression_generator_(details::e_assign,branch);
- }
- inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
- {
- if (
- !token_is(token_t::e_lcrlbracket) ||
- !token_is(token_t::e_rcrlbracket)
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR167 - Expected a '{}' for uninitialised var definition",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR168 - Expected ';' after uninitialised variable definition",
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
- scope_element& se = sem_.get_element(var_name);
- if (se.name == var_name)
- {
- if (se.active)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR169 - Illegal redefinition of local variable: '" + var_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else if (scope_element::e_variable == se.type)
- {
- var_node = se.var_node;
- se.active = true;
- se.ref_count++;
- }
- }
- if (0 == var_node)
- {
- scope_element nse;
- nse.name = var_name;
- nse.active = true;
- nse.ref_count = 1;
- nse.type = scope_element::e_variable;
- nse.depth = state_.scope_depth;
- nse.ip_index = sem_.next_ip_index();
- nse.data = new T(T(0));
- nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
- if (!sem_.add_element(nse))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR170 - Failed to add new local variable '" + var_name + "' to SEM",
- exprtk_error_location));
- sem_.free_element(nse);
- return error_node();
- }
- exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
- nse.name.c_str()));
- }
- lodge_symbol(var_name, e_st_local_variable);
- state_.activate_side_effect("parse_uninitialised_var_statement()");
- return expression_generator_(T(0));
- }
- inline expression_node_ptr parse_swap_statement()
- {
- if (!details::imatch(current_token().value,"swap"))
- {
- return error_node();
- }
- else
- next_token();
- if (!token_is(token_t::e_lbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR171 - Expected '(' at start of swap statement",
- exprtk_error_location));
- return error_node();
- }
- expression_node_ptr variable0 = error_node();
- expression_node_ptr variable1 = error_node();
- bool variable0_generated = false;
- bool variable1_generated = false;
- const std::string var0_name = current_token().value;
- if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR172 - Expected a symbol for variable or vector element definition",
- exprtk_error_location));
- return error_node();
- }
- else if (peek_token_is(token_t::e_lsqrbracket))
- {
- if (0 == (variable0 = parse_vector()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR173 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
- exprtk_error_location));
- return error_node();
- }
- variable0_generated = true;
- }
- else
- {
- if (symtab_store_.is_variable(var0_name))
- {
- variable0 = symtab_store_.get_variable(var0_name);
- }
- scope_element& se = sem_.get_element(var0_name);
- if (
- (se.active) &&
- (se.name == var0_name) &&
- (scope_element::e_variable == se.type)
- )
- {
- variable0 = se.var_node;
- }
- lodge_symbol(var0_name, e_st_variable);
- if (0 == variable0)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR174 - First parameter to swap is an invalid variable: '" + var0_name + "'",
- exprtk_error_location));
- return error_node();
- }
- else
- next_token();
- }
- if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR175 - Expected ',' between parameters to swap",
- exprtk_error_location));
- if (variable0_generated)
- {
- free_node(node_allocator_,variable0);
- }
- return error_node();
- }
- const std::string var1_name = current_token().value;
- if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR176 - Expected a symbol for variable or vector element definition",
- exprtk_error_location));
- if (variable0_generated)
- {
- free_node(node_allocator_,variable0);
- }
- return error_node();
- }
- else if (peek_token_is(token_t::e_lsqrbracket))
- {
- if (0 == (variable1 = parse_vector()))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR177 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
- exprtk_error_location));
- if (variable0_generated)
- {
- free_node(node_allocator_,variable0);
- }
- return error_node();
- }
- variable1_generated = true;
- }
- else
- {
- if (symtab_store_.is_variable(var1_name))
- {
- variable1 = symtab_store_.get_variable(var1_name);
- }
- scope_element& se = sem_.get_element(var1_name);
- if (
- (se.active) &&
- (se.name == var1_name) &&
- (scope_element::e_variable == se.type)
- )
- {
- variable1 = se.var_node;
- }
- lodge_symbol(var1_name, e_st_variable);
- if (0 == variable1)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR178 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
- exprtk_error_location));
- if (variable0_generated)
- {
- free_node(node_allocator_,variable0);
- }
- return error_node();
- }
- else
- next_token();
- }
- if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR179 - Expected ')' at end of swap statement",
- exprtk_error_location));
- if (variable0_generated)
- {
- free_node(node_allocator_,variable0);
- }
- if (variable1_generated)
- {
- free_node(node_allocator_,variable1);
- }
- return error_node();
- }
- typedef details::variable_node<T>* variable_node_ptr;
- variable_node_ptr v0 = variable_node_ptr(0);
- variable_node_ptr v1 = variable_node_ptr(0);
- expression_node_ptr result = error_node();
- if (
- (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
- (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
- )
- {
- result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
- if (variable0_generated)
- {
- free_node(node_allocator_,variable0);
- }
- if (variable1_generated)
- {
- free_node(node_allocator_,variable1);
- }
- }
- else
- result = node_allocator_.allocate<details::swap_generic_node<T> >
- (variable0, variable1);
- state_.activate_side_effect("parse_swap_statement()");
- return result;
- }
- #ifndef exprtk_disable_return_statement
- inline expression_node_ptr parse_return_statement()
- {
- if (state_.parsing_return_stmt)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR180 - Return call within a return call is not allowed",
- exprtk_error_location));
- return error_node();
- }
- scoped_bool_negator sbn(state_.parsing_return_stmt);
- std::vector<expression_node_ptr> arg_list;
- scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
- if (!details::imatch(current_token().value,"return"))
- {
- return error_node();
- }
- else
- next_token();
- if (!token_is(token_t::e_lsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR181 - Expected '[' at start of return statement",
- exprtk_error_location));
- return error_node();
- }
- else if (!token_is(token_t::e_rsqrbracket))
- {
- for ( ; ; )
- {
- expression_node_ptr arg = parse_expression();
- if (0 == arg)
- return error_node();
- arg_list.push_back(arg);
- if (token_is(token_t::e_rsqrbracket))
- break;
- else if (!token_is(token_t::e_comma))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR182 - Expected ',' between values during call to return",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- else if (settings_.zero_return_disabled())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR183 - Zero parameter return statement not allowed",
- exprtk_error_location));
- return error_node();
- }
- const lexer::token prev_token = current_token();
- if (token_is(token_t::e_rsqrbracket))
- {
- if (!arg_list.empty())
- {
- set_error(
- make_error(parser_error::e_syntax,
- prev_token,
- "ERR184 - Invalid ']' found during return call",
- exprtk_error_location));
- return error_node();
- }
- }
- std::string ret_param_type_list;
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- if (0 == arg_list[i])
- return error_node();
- else if (is_ivector_node(arg_list[i]))
- ret_param_type_list += 'V';
- else if (is_generally_string_node(arg_list[i]))
- ret_param_type_list += 'S';
- else
- ret_param_type_list += 'T';
- }
- dec_.retparam_list_.push_back(ret_param_type_list);
- expression_node_ptr result = expression_generator_.return_call(arg_list);
- sdd.delete_ptr = (0 == result);
- state_.return_stmt_present = true;
- state_.activate_side_effect("parse_return_statement()");
- return result;
- }
- #else
- inline expression_node_ptr parse_return_statement()
- {
- return error_node();
- }
- #endif
- inline bool post_variable_process(const std::string& symbol)
- {
- if (
- peek_token_is(token_t::e_lbracket ) ||
- peek_token_is(token_t::e_lcrlbracket) ||
- peek_token_is(token_t::e_lsqrbracket)
- )
- {
- if (!settings_.commutative_check_enabled())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR185 - Invalid sequence of variable '"+ symbol + "' and bracket",
- exprtk_error_location));
- return false;
- }
- lexer().insert_front(token_t::e_mul);
- }
- return true;
- }
- inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
- {
- bool implied_mul = false;
- if (is_generally_string_node(branch))
- return true;
- const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
- switch (token)
- {
- case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
- token_is(token_t::e_lcrlbracket,hold) ||
- token_is(token_t::e_lsqrbracket,hold) ;
- break;
- case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
- token_is(token_t::e_lcrlbracket,hold) ||
- token_is(token_t::e_lsqrbracket,hold) ;
- break;
- case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
- token_is(token_t::e_lcrlbracket,hold) ||
- token_is(token_t::e_lsqrbracket,hold) ;
- break;
- default : return true;
- }
- if (implied_mul)
- {
- if (!settings_.commutative_check_enabled())
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR186 - Invalid sequence of brackets",
- exprtk_error_location));
- return false;
- }
- else if (token_t::e_eof != current_token().type)
- {
- lexer().insert_front(current_token().type);
- lexer().insert_front(token_t::e_mul);
- next_token();
- }
- }
- return true;
- }
- inline expression_node_ptr parse_symtab_symbol()
- {
- const std::string symbol = current_token().value;
- // Are we dealing with a variable or a special constant?
- expression_node_ptr variable = symtab_store_.get_variable(symbol);
- if (variable)
- {
- if (symtab_store_.is_constant_node(symbol))
- {
- variable = expression_generator_(variable->value());
- }
- if (!post_variable_process(symbol))
- return error_node();
- lodge_symbol(symbol, e_st_variable);
- next_token();
- return variable;
- }
- // Are we dealing with a locally defined variable, vector or string?
- if (!sem_.empty())
- {
- scope_element& se = sem_.get_active_element(symbol);
- if (se.active && details::imatch(se.name, symbol))
- {
- if (scope_element::e_variable == se.type)
- {
- se.active = true;
- lodge_symbol(symbol, e_st_local_variable);
- if (!post_variable_process(symbol))
- return error_node();
- next_token();
- return se.var_node;
- }
- else if (scope_element::e_vector == se.type)
- {
- return parse_vector();
- }
- #ifndef exprtk_disable_string_capabilities
- else if (scope_element::e_string == se.type)
- {
- return parse_string();
- }
- #endif
- }
- }
- #ifndef exprtk_disable_string_capabilities
- // Are we dealing with a string variable?
- if (symtab_store_.is_stringvar(symbol))
- {
- return parse_string();
- }
- #endif
- {
- // Are we dealing with a function?
- ifunction<T>* function = symtab_store_.get_function(symbol);
- if (function)
- {
- lodge_symbol(symbol, e_st_function);
- expression_node_ptr func_node =
- parse_function_invocation(function,symbol);
- if (func_node)
- return func_node;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR187 - Failed to generate node for function: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- {
- // Are we dealing with a vararg function?
- ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
- if (vararg_function)
- {
- lodge_symbol(symbol, e_st_function);
- expression_node_ptr vararg_func_node =
- parse_vararg_function_call(vararg_function, symbol);
- if (vararg_func_node)
- return vararg_func_node;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR188 - Failed to generate node for vararg function: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- {
- // Are we dealing with a vararg generic function?
- igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
- if (generic_function)
- {
- lodge_symbol(symbol, e_st_function);
- expression_node_ptr genericfunc_node =
- parse_generic_function_call(generic_function, symbol);
- if (genericfunc_node)
- return genericfunc_node;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR189 - Failed to generate node for generic function: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- #ifndef exprtk_disable_string_capabilities
- {
- // Are we dealing with a vararg string returning function?
- igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
- if (string_function)
- {
- lodge_symbol(symbol, e_st_function);
- expression_node_ptr stringfunc_node =
- parse_string_function_call(string_function, symbol);
- if (stringfunc_node)
- return stringfunc_node;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR190 - Failed to generate node for string function: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- {
- // Are we dealing with a vararg overloaded scalar/string returning function?
- igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
- if (overload_function)
- {
- lodge_symbol(symbol, e_st_function);
- expression_node_ptr overloadfunc_node =
- parse_overload_function_call(overload_function, symbol);
- if (overloadfunc_node)
- return overloadfunc_node;
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR191 - Failed to generate node for overload function: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- }
- #endif
- // Are we dealing with a vector?
- if (symtab_store_.is_vector(symbol))
- {
- lodge_symbol(symbol, e_st_vector);
- return parse_vector();
- }
- if (details::is_reserved_symbol(symbol))
- {
- if (
- settings_.function_enabled(symbol) ||
- !details::is_base_function(symbol)
- )
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR192 - Invalid use of reserved symbol '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- }
- // Should we handle unknown symbols?
- if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
- {
- if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
- {
- symbol_table_t& symtab = symtab_store_.get_symbol_table();
- std::string error_message;
- if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
- {
- T default_value = T(0);
- typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
- if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
- {
- bool create_result = false;
- switch (usr_symbol_type)
- {
- case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
- break;
- case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
- break;
- default : create_result = false;
- }
- if (create_result)
- {
- expression_node_ptr var = symtab_store_.get_variable(symbol);
- if (var)
- {
- if (symtab_store_.is_constant_node(symbol))
- {
- var = expression_generator_(var->value());
- }
- lodge_symbol(symbol, e_st_variable);
- if (!post_variable_process(symbol))
- return error_node();
- next_token();
- return var;
- }
- }
- }
- set_error(
- make_error(parser_error::e_symtab,
- current_token(),
- "ERR193 - Failed to create variable: '" + symbol + "'" +
- (error_message.empty() ? "" : " - " + error_message),
- exprtk_error_location));
- }
- else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
- {
- if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
- {
- expression_node_ptr result = parse_symtab_symbol();
- if (result)
- {
- return result;
- }
- }
- set_error(
- make_error(parser_error::e_symtab,
- current_token(),
- "ERR194 - Failed to resolve symbol: '" + symbol + "'" +
- (error_message.empty() ? "" : " - " + error_message),
- exprtk_error_location));
- }
- return error_node();
- }
- }
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR195 - Undefined symbol: '" + symbol + "'",
- exprtk_error_location));
- return error_node();
- }
- inline expression_node_ptr parse_symbol()
- {
- static const std::string symbol_if = "if" ;
- static const std::string symbol_while = "while" ;
- static const std::string symbol_repeat = "repeat" ;
- static const std::string symbol_for = "for" ;
- static const std::string symbol_switch = "switch" ;
- static const std::string symbol_null = "null" ;
- static const std::string symbol_break = "break" ;
- static const std::string symbol_continue = "continue";
- static const std::string symbol_var = "var" ;
- static const std::string symbol_swap = "swap" ;
- static const std::string symbol_return = "return" ;
- static const std::string symbol_not = "not" ;
- if (valid_vararg_operation(current_token().value))
- {
- return parse_vararg_function();
- }
- else if (details::imatch(current_token().value, symbol_not))
- {
- return parse_not_statement();
- }
- else if (valid_base_operation(current_token().value))
- {
- return parse_base_operation();
- }
- else if (
- details::imatch(current_token().value, symbol_if) &&
- settings_.control_struct_enabled(current_token().value)
- )
- {
- return parse_conditional_statement();
- }
- else if (
- details::imatch(current_token().value, symbol_while) &&
- settings_.control_struct_enabled(current_token().value)
- )
- {
- return parse_while_loop();
- }
- else if (
- details::imatch(current_token().value, symbol_repeat) &&
- settings_.control_struct_enabled(current_token().value)
- )
- {
- return parse_repeat_until_loop();
- }
- else if (
- details::imatch(current_token().value, symbol_for) &&
- settings_.control_struct_enabled(current_token().value)
- )
- {
- return parse_for_loop();
- }
- else if (
- details::imatch(current_token().value, symbol_switch) &&
- settings_.control_struct_enabled(current_token().value)
- )
- {
- return parse_switch_statement();
- }
- else if (details::is_valid_sf_symbol(current_token().value))
- {
- return parse_special_function();
- }
- else if (details::imatch(current_token().value, symbol_null))
- {
- return parse_null_statement();
- }
- #ifndef exprtk_disable_break_continue
- else if (details::imatch(current_token().value, symbol_break))
- {
- return parse_break_statement();
- }
- else if (details::imatch(current_token().value, symbol_continue))
- {
- return parse_continue_statement();
- }
- #endif
- else if (details::imatch(current_token().value, symbol_var))
- {
- return parse_define_var_statement();
- }
- else if (details::imatch(current_token().value, symbol_swap))
- {
- return parse_swap_statement();
- }
- #ifndef exprtk_disable_return_statement
- else if (
- details::imatch(current_token().value, symbol_return) &&
- settings_.control_struct_enabled(current_token().value)
- )
- {
- return parse_return_statement();
- }
- #endif
- else if (symtab_store_.valid() || !sem_.empty())
- {
- return parse_symtab_symbol();
- }
- else
- {
- set_error(
- make_error(parser_error::e_symtab,
- current_token(),
- "ERR196 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
- exprtk_error_location));
- return error_node();
- }
- }
- inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
- {
- expression_node_ptr branch = error_node();
- if (token_t::e_number == current_token().type)
- {
- T numeric_value = T(0);
- if (details::string_to_real(current_token().value, numeric_value))
- {
- expression_node_ptr literal_exp = expression_generator_(numeric_value);
- if (0 == literal_exp)
- {
- set_error(
- make_error(parser_error::e_numeric,
- current_token(),
- "ERR197 - Failed generate node for scalar: '" + current_token().value + "'",
- exprtk_error_location));
- return error_node();
- }
- next_token();
- branch = literal_exp;
- }
- else
- {
- set_error(
- make_error(parser_error::e_numeric,
- current_token(),
- "ERR198 - Failed to convert '" + current_token().value + "' to a number",
- exprtk_error_location));
- return error_node();
- }
- }
- else if (token_t::e_symbol == current_token().type)
- {
- branch = parse_symbol();
- }
- #ifndef exprtk_disable_string_capabilities
- else if (token_t::e_string == current_token().type)
- {
- branch = parse_const_string();
- }
- #endif
- else if (token_t::e_lbracket == current_token().type)
- {
- next_token();
- if (0 == (branch = parse_expression()))
- return error_node();
- else if (!token_is(token_t::e_rbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR199 - Expected ')' instead of: '" + current_token().value + "'",
- exprtk_error_location));
- free_node(node_allocator_,branch);
- return error_node();
- }
- else if (!post_bracket_process(token_t::e_lbracket,branch))
- {
- free_node(node_allocator_,branch);
- return error_node();
- }
- }
- else if (token_t::e_lsqrbracket == current_token().type)
- {
- next_token();
- if (0 == (branch = parse_expression()))
- return error_node();
- else if (!token_is(token_t::e_rsqrbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR200 - Expected ']' instead of: '" + current_token().value + "'",
- exprtk_error_location));
- free_node(node_allocator_,branch);
- return error_node();
- }
- else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
- {
- free_node(node_allocator_,branch);
- return error_node();
- }
- }
- else if (token_t::e_lcrlbracket == current_token().type)
- {
- next_token();
- if (0 == (branch = parse_expression()))
- return error_node();
- else if (!token_is(token_t::e_rcrlbracket))
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR201 - Expected '}' instead of: '" + current_token().value + "'",
- exprtk_error_location));
- free_node(node_allocator_,branch);
- return error_node();
- }
- else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
- {
- free_node(node_allocator_,branch);
- return error_node();
- }
- }
- else if (token_t::e_sub == current_token().type)
- {
- next_token();
- branch = parse_expression(e_level11);
- if (
- branch &&
- !(
- details::is_neg_unary_node (branch) &&
- simplify_unary_negation_branch(branch)
- )
- )
- {
- branch = expression_generator_(details::e_neg,branch);
- }
- }
- else if (token_t::e_add == current_token().type)
- {
- next_token();
- branch = parse_expression(e_level13);
- }
- else if (token_t::e_eof == current_token().type)
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR202 - Premature end of expression[1]",
- exprtk_error_location));
- return error_node();
- }
- else
- {
- set_error(
- make_error(parser_error::e_syntax,
- current_token(),
- "ERR203 - Premature end of expression[2]",
- exprtk_error_location));
- return error_node();
- }
- if (
- branch &&
- (e_level00 == precedence) &&
- token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
- )
- {
- branch = parse_ternary_conditional_statement(branch);
- }
- parse_pending_string_rangesize(branch);
- return branch;
- }
- template <typename Type>
- class expression_generator
- {
- public:
- typedef details::expression_node<Type>* expression_node_ptr;
- typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
- typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
- typedef typename exprtk::parser<Type> parser_t;
- typedef const Type& vtype;
- typedef const Type ctype;
- inline void init_synthesize_map()
- {
- #ifndef exprtk_disable_enhanced_features
- synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
- synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
- synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
- #define register_synthezier(S) \
- synthesize_map_[S ::node_type::id()] = S ::process; \
- register_synthezier(synthesize_vovov_expression0)
- register_synthezier(synthesize_vovov_expression1)
- register_synthezier(synthesize_vovoc_expression0)
- register_synthezier(synthesize_vovoc_expression1)
- register_synthezier(synthesize_vocov_expression0)
- register_synthezier(synthesize_vocov_expression1)
- register_synthezier(synthesize_covov_expression0)
- register_synthezier(synthesize_covov_expression1)
- register_synthezier(synthesize_covoc_expression0)
- register_synthezier(synthesize_covoc_expression1)
- register_synthezier(synthesize_cocov_expression1)
- register_synthezier(synthesize_vococ_expression0)
- register_synthezier(synthesize_vovovov_expression0)
- register_synthezier(synthesize_vovovoc_expression0)
- register_synthezier(synthesize_vovocov_expression0)
- register_synthezier(synthesize_vocovov_expression0)
- register_synthezier(synthesize_covovov_expression0)
- register_synthezier(synthesize_covocov_expression0)
- register_synthezier(synthesize_vocovoc_expression0)
- register_synthezier(synthesize_covovoc_expression0)
- register_synthezier(synthesize_vococov_expression0)
- register_synthezier(synthesize_vovovov_expression1)
- register_synthezier(synthesize_vovovoc_expression1)
- register_synthezier(synthesize_vovocov_expression1)
- register_synthezier(synthesize_vocovov_expression1)
- register_synthezier(synthesize_covovov_expression1)
- register_synthezier(synthesize_covocov_expression1)
- register_synthezier(synthesize_vocovoc_expression1)
- register_synthezier(synthesize_covovoc_expression1)
- register_synthezier(synthesize_vococov_expression1)
- register_synthezier(synthesize_vovovov_expression2)
- register_synthezier(synthesize_vovovoc_expression2)
- register_synthezier(synthesize_vovocov_expression2)
- register_synthezier(synthesize_vocovov_expression2)
- register_synthezier(synthesize_covovov_expression2)
- register_synthezier(synthesize_covocov_expression2)
- register_synthezier(synthesize_vocovoc_expression2)
- register_synthezier(synthesize_covovoc_expression2)
- register_synthezier(synthesize_vovovov_expression3)
- register_synthezier(synthesize_vovovoc_expression3)
- register_synthezier(synthesize_vovocov_expression3)
- register_synthezier(synthesize_vocovov_expression3)
- register_synthezier(synthesize_covovov_expression3)
- register_synthezier(synthesize_covocov_expression3)
- register_synthezier(synthesize_vocovoc_expression3)
- register_synthezier(synthesize_covovoc_expression3)
- register_synthezier(synthesize_vococov_expression3)
- register_synthezier(synthesize_vovovov_expression4)
- register_synthezier(synthesize_vovovoc_expression4)
- register_synthezier(synthesize_vovocov_expression4)
- register_synthezier(synthesize_vocovov_expression4)
- register_synthezier(synthesize_covovov_expression4)
- register_synthezier(synthesize_covocov_expression4)
- register_synthezier(synthesize_vocovoc_expression4)
- register_synthezier(synthesize_covovoc_expression4)
- #endif
- }
- inline void set_parser(parser_t& p)
- {
- parser_ = &p;
- }
- inline void set_uom(unary_op_map_t& unary_op_map)
- {
- unary_op_map_ = &unary_op_map;
- }
- inline void set_bom(binary_op_map_t& binary_op_map)
- {
- binary_op_map_ = &binary_op_map;
- }
- inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
- {
- inv_binary_op_map_ = &inv_binary_op_map;
- }
- inline void set_sf3m(sf3_map_t& sf3_map)
- {
- sf3_map_ = &sf3_map;
- }
- inline void set_sf4m(sf4_map_t& sf4_map)
- {
- sf4_map_ = &sf4_map;
- }
- inline void set_allocator(details::node_allocator& na)
- {
- node_allocator_ = &na;
- }
- inline void set_strength_reduction_state(const bool enabled)
- {
- strength_reduction_enabled_ = enabled;
- }
- inline bool strength_reduction_enabled() const
- {
- return strength_reduction_enabled_;
- }
- inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
- {
- typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
- if ((*binary_op_map_).end() == bop_itr)
- return false;
- bop = bop_itr->second;
- return true;
- }
- inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
- {
- typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
- if ((*unary_op_map_).end() == uop_itr)
- return false;
- uop = uop_itr->second;
- return true;
- }
- inline details::operator_type get_operator(const binary_functor_t& bop) const
- {
- return (*inv_binary_op_map_).find(bop)->second;
- }
- inline expression_node_ptr operator() (const Type& v) const
- {
- return node_allocator_->allocate<literal_node_t>(v);
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr operator() (const std::string& s) const
- {
- return node_allocator_->allocate<string_literal_node_t>(s);
- }
- inline expression_node_ptr operator() (std::string& s, range_t& rp) const
- {
- return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
- }
- inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
- {
- return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
- }
- inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
- {
- if (is_generally_string_node(branch))
- return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
- else
- return error_node();
- }
- #endif
- inline bool unary_optimisable(const details::operator_type& operation) const
- {
- return (details::e_abs == operation) || (details::e_acos == operation) ||
- (details::e_acosh == operation) || (details::e_asin == operation) ||
- (details::e_asinh == operation) || (details::e_atan == operation) ||
- (details::e_atanh == operation) || (details::e_ceil == operation) ||
- (details::e_cos == operation) || (details::e_cosh == operation) ||
- (details::e_exp == operation) || (details::e_expm1 == operation) ||
- (details::e_floor == operation) || (details::e_log == operation) ||
- (details::e_log10 == operation) || (details::e_log2 == operation) ||
- (details::e_log1p == operation) || (details::e_neg == operation) ||
- (details::e_pos == operation) || (details::e_round == operation) ||
- (details::e_sin == operation) || (details::e_sinc == operation) ||
- (details::e_sinh == operation) || (details::e_sqrt == operation) ||
- (details::e_tan == operation) || (details::e_tanh == operation) ||
- (details::e_cot == operation) || (details::e_sec == operation) ||
- (details::e_csc == operation) || (details::e_r2d == operation) ||
- (details::e_d2r == operation) || (details::e_d2g == operation) ||
- (details::e_g2d == operation) || (details::e_notl == operation) ||
- (details::e_sgn == operation) || (details::e_erf == operation) ||
- (details::e_erfc == operation) || (details::e_ncdf == operation) ||
- (details::e_frac == operation) || (details::e_trunc == operation) ;
- }
- inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
- {
- typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
- if (sf3_map_->end() == itr)
- return false;
- else
- tfunc = itr->second.first;
- return true;
- }
- inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
- {
- typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
- if (sf4_map_->end() == itr)
- return false;
- else
- qfunc = itr->second.first;
- return true;
- }
- inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
- {
- typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
- if (sf3_map_->end() == itr)
- return false;
- else
- operation = itr->second.second;
- return true;
- }
- inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
- {
- typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
- if (sf4_map_->end() == itr)
- return false;
- else
- operation = itr->second.second;
- return true;
- }
- inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
- {
- if (0 == branch[0])
- {
- return error_node();
- }
- else if (details::is_null_node(branch[0]))
- {
- return branch[0];
- }
- else if (details::is_break_node(branch[0]))
- {
- return error_node();
- }
- else if (details::is_continue_node(branch[0]))
- {
- return error_node();
- }
- else if (details::is_constant_node(branch[0]))
- {
- return synthesize_expression<unary_node_t,1>(operation,branch);
- }
- else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
- {
- return synthesize_uv_expression(operation,branch);
- }
- else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
- {
- return synthesize_uvec_expression(operation,branch);
- }
- else
- return synthesize_unary_expression(operation,branch);
- }
- inline bool is_assignment_operation(const details::operator_type& operation) const
- {
- return (
- (details::e_addass == operation) ||
- (details::e_subass == operation) ||
- (details::e_mulass == operation) ||
- (details::e_divass == operation) ||
- (details::e_modass == operation)
- ) &&
- parser_->settings_.assignment_enabled(operation);
- }
- #ifndef exprtk_disable_string_capabilities
- inline bool valid_string_operation(const details::operator_type& operation) const
- {
- return (details::e_add == operation) ||
- (details::e_lt == operation) ||
- (details::e_lte == operation) ||
- (details::e_gt == operation) ||
- (details::e_gte == operation) ||
- (details::e_eq == operation) ||
- (details::e_ne == operation) ||
- (details::e_in == operation) ||
- (details::e_like == operation) ||
- (details::e_ilike == operation) ||
- (details::e_assign == operation) ||
- (details::e_addass == operation) ||
- (details::e_swap == operation) ;
- }
- #else
- inline bool valid_string_operation(const details::operator_type&) const
- {
- return false;
- }
- #endif
- inline std::string to_str(const details::operator_type& operation) const
- {
- switch (operation)
- {
- case details::e_add : return "+" ;
- case details::e_sub : return "-" ;
- case details::e_mul : return "*" ;
- case details::e_div : return "/" ;
- case details::e_mod : return "%" ;
- case details::e_pow : return "^" ;
- case details::e_lt : return "<" ;
- case details::e_lte : return "<=" ;
- case details::e_gt : return ">" ;
- case details::e_gte : return ">=" ;
- case details::e_eq : return "==" ;
- case details::e_ne : return "!=" ;
- case details::e_and : return "and" ;
- case details::e_nand : return "nand" ;
- case details::e_or : return "or" ;
- case details::e_nor : return "nor" ;
- case details::e_xor : return "xor" ;
- case details::e_xnor : return "xnor" ;
- default : return "UNKNOWN";
- }
- }
- inline bool operation_optimisable(const details::operator_type& operation) const
- {
- return (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation) ||
- (details::e_mod == operation) ||
- (details::e_pow == operation) ||
- (details::e_lt == operation) ||
- (details::e_lte == operation) ||
- (details::e_gt == operation) ||
- (details::e_gte == operation) ||
- (details::e_eq == operation) ||
- (details::e_ne == operation) ||
- (details::e_and == operation) ||
- (details::e_nand == operation) ||
- (details::e_or == operation) ||
- (details::e_nor == operation) ||
- (details::e_xor == operation) ||
- (details::e_xnor == operation) ;
- }
- inline std::string branch_to_id(expression_node_ptr branch) const
- {
- static const std::string null_str ("(null)" );
- static const std::string const_str ("(c)" );
- static const std::string var_str ("(v)" );
- static const std::string vov_str ("(vov)" );
- static const std::string cov_str ("(cov)" );
- static const std::string voc_str ("(voc)" );
- static const std::string str_str ("(s)" );
- static const std::string strrng_str ("(rngs)" );
- static const std::string cs_str ("(cs)" );
- static const std::string cstrrng_str("(crngs)");
- if (details::is_null_node(branch))
- return null_str;
- else if (details::is_constant_node(branch))
- return const_str;
- else if (details::is_variable_node(branch))
- return var_str;
- else if (details::is_vov_node(branch))
- return vov_str;
- else if (details::is_cov_node(branch))
- return cov_str;
- else if (details::is_voc_node(branch))
- return voc_str;
- else if (details::is_string_node(branch))
- return str_str;
- else if (details::is_const_string_node(branch))
- return cs_str;
- else if (details::is_string_range_node(branch))
- return strrng_str;
- else if (details::is_const_string_range_node(branch))
- return cstrrng_str;
- else if (details::is_t0ot1ot2_node(branch))
- return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
- else if (details::is_t0ot1ot2ot3_node(branch))
- return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
- else
- return "ERROR";
- }
- inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
- {
- return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
- }
- inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return details::is_constant_node(branch[0]) &&
- details::is_variable_node(branch[1]) ;
- }
- inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return details::is_variable_node(branch[0]) &&
- details::is_constant_node(branch[1]) ;
- }
- inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return details::is_variable_node(branch[0]) &&
- details::is_variable_node(branch[1]) ;
- }
- inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return details::is_constant_node(branch[0]) &&
- !details::is_constant_node(branch[1]) ;
- }
- inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return !details::is_constant_node(branch[0]) &&
- details::is_constant_node(branch[1]) ;
- }
- inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
- (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
- }
- else
- return false;
- }
- inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
- (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
- }
- else
- return false;
- }
- inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return details::is_uv_node(branch[0]) &&
- details::is_uv_node(branch[1]) ;
- }
- inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return details::is_variable_node(branch[0]) &&
- !details::is_variable_node(branch[1]) ;
- }
- inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return !details::is_variable_node(branch[0]) &&
- details::is_variable_node(branch[1]) ;
- }
- inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!operation_optimisable(operation))
- return false;
- else
- return !details::is_constant_node(branch[0]) ||
- !details::is_constant_node(branch[1]) ;
- }
- inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (is_assignment_operation(operation))
- {
- const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
- if (details::is_string_node(branch[0]))
- return !b1_is_genstring;
- else
- return (
- !details::is_variable_node (branch[0]) &&
- !details::is_vector_elem_node (branch[0]) &&
- !details::is_rebasevector_elem_node (branch[0]) &&
- !details::is_rebasevector_celem_node(branch[0]) &&
- !details::is_vector_node (branch[0])
- )
- || b1_is_genstring;
- }
- else
- return false;
- }
- inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
- {
- if (
- !details::is_constant_node(branch[1]) ||
- details::is_constant_node(branch[0]) ||
- details::is_variable_node(branch[0]) ||
- details::is_vector_node (branch[0]) ||
- details::is_generally_string_node(branch[0])
- )
- return false;
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- return cardinal_pow_optimisable(operation, c);
- }
- inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
- {
- return (
- details::is_break_node (branch[0]) ||
- details::is_break_node (branch[1]) ||
- details::is_continue_node(branch[0]) ||
- details::is_continue_node(branch[1])
- );
- }
- inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- const bool b0_string = is_generally_string_node(branch[0]);
- const bool b1_string = is_generally_string_node(branch[1]);
- bool result = false;
- if (b0_string != b1_string)
- result = true;
- else if (!valid_string_operation(operation) && b0_string && b1_string)
- result = true;
- if (result)
- {
- parser_->set_synthesis_error("Invalid string operation");
- }
- return result;
- }
- inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
- {
- const bool b0_string = is_generally_string_node(branch[0]);
- const bool b1_string = is_generally_string_node(branch[1]);
- const bool b2_string = is_generally_string_node(branch[2]);
- bool result = false;
- if ((b0_string != b1_string) || (b1_string != b2_string))
- result = true;
- else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
- result = true;
- if (result)
- {
- parser_->set_synthesis_error("Invalid string operation");
- }
- return result;
- }
- inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- const bool b0_string = is_generally_string_node(branch[0]);
- const bool b1_string = is_generally_string_node(branch[1]);
- return (b0_string && b1_string && valid_string_operation(operation));
- }
- inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
- {
- const bool b0_string = is_generally_string_node(branch[0]);
- const bool b1_string = is_generally_string_node(branch[1]);
- const bool b2_string = is_generally_string_node(branch[2]);
- return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
- }
- #ifndef exprtk_disable_sc_andor
- inline bool is_shortcircuit_expression(const details::operator_type& operation) const
- {
- return (
- (details::e_scand == operation) ||
- (details::e_scor == operation)
- );
- }
- #else
- inline bool is_shortcircuit_expression(const details::operator_type&) const
- {
- return false;
- }
- #endif
- inline bool is_null_present(expression_node_ptr (&branch)[2]) const
- {
- return (
- details::is_null_node(branch[0]) ||
- details::is_null_node(branch[1])
- );
- }
- inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
- return false;
- else
- return (
- (details::e_lt == operation) ||
- (details::e_lte == operation) ||
- (details::e_gt == operation) ||
- (details::e_gte == operation) ||
- (details::e_eq == operation) ||
- (details::e_ne == operation) ||
- (details::e_equal == operation) ||
- (details::e_and == operation) ||
- (details::e_nand == operation) ||
- (details:: e_or == operation) ||
- (details:: e_nor == operation) ||
- (details:: e_xor == operation) ||
- (details::e_xnor == operation)
- );
- }
- inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
- {
- if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
- return false;
- else
- return (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation) ||
- (details::e_pow == operation)
- );
- }
- inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
- {
- if ((0 == branch[0]) || (0 == branch[1]))
- {
- return error_node();
- }
- else if (is_invalid_string_op(operation,branch))
- {
- return error_node();
- }
- else if (is_invalid_assignment_op(operation,branch))
- {
- return error_node();
- }
- else if (is_invalid_break_continue_op(branch))
- {
- return error_node();
- }
- else if (details::e_assign == operation)
- {
- return synthesize_assignment_expression(operation, branch);
- }
- else if (details::e_swap == operation)
- {
- return synthesize_swap_expression(branch);
- }
- else if (is_assignment_operation(operation))
- {
- return synthesize_assignment_operation_expression(operation, branch);
- }
- else if (is_vector_eqineq_logic_operation(operation, branch))
- {
- return synthesize_veceqineqlogic_operation_expression(operation, branch);
- }
- else if (is_vector_arithmetic_operation(operation, branch))
- {
- return synthesize_vecarithmetic_operation_expression(operation, branch);
- }
- else if (is_shortcircuit_expression(operation))
- {
- return synthesize_shortcircuit_expression(operation, branch);
- }
- else if (is_string_operation(operation, branch))
- {
- return synthesize_string_expression(operation, branch);
- }
- else if (is_null_present(branch))
- {
- return synthesize_null_expression(operation, branch);
- }
- #ifndef exprtk_disable_cardinal_pow_optimisation
- else if (is_constpow_operation(operation, branch))
- {
- return cardinal_pow_optimisation(branch);
- }
- #endif
- expression_node_ptr result = error_node();
- #ifndef exprtk_disable_enhanced_features
- if (synthesize_expression(operation, branch, result))
- {
- return result;
- }
- else
- #endif
- {
- /*
- Possible reductions:
- 1. c o cob -> cob
- 2. cob o c -> cob
- 3. c o boc -> boc
- 4. boc o c -> boc
- */
- result = error_node();
- if (cocob_optimisable(operation, branch))
- {
- result = synthesize_cocob_expression::process((*this), operation, branch);
- }
- else if (coboc_optimisable(operation, branch) && (0 == result))
- {
- result = synthesize_coboc_expression::process((*this), operation, branch);
- }
- if (result)
- return result;
- }
- if (uvouv_optimisable(operation, branch))
- {
- return synthesize_uvouv_expression(operation, branch);
- }
- else if (vob_optimisable(operation, branch))
- {
- return synthesize_vob_expression::process((*this), operation, branch);
- }
- else if (bov_optimisable(operation, branch))
- {
- return synthesize_bov_expression::process((*this), operation, branch);
- }
- else if (cob_optimisable(operation, branch))
- {
- return synthesize_cob_expression::process((*this), operation, branch);
- }
- else if (boc_optimisable(operation, branch))
- {
- return synthesize_boc_expression::process((*this), operation, branch);
- }
- #ifndef exprtk_disable_enhanced_features
- else if (cov_optimisable(operation, branch))
- {
- return synthesize_cov_expression::process((*this), operation, branch);
- }
- #endif
- else if (binext_optimisable(operation, branch))
- {
- return synthesize_binary_ext_expression::process((*this), operation, branch);
- }
- else
- return synthesize_expression<binary_node_t,2>(operation, branch);
- }
- inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
- {
- if (
- (0 == branch[0]) ||
- (0 == branch[1]) ||
- (0 == branch[2])
- )
- {
- details::free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- else if (is_invalid_string_op(operation, branch))
- {
- return error_node();
- }
- else if (is_string_operation(operation, branch))
- {
- return synthesize_string_expression(operation, branch);
- }
- else
- return synthesize_expression<trinary_node_t,3>(operation, branch);
- }
- inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
- {
- return synthesize_expression<quaternary_node_t,4>(operation,branch);
- }
- inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
- {
- expression_node_ptr branch[1] = { b0 };
- return (*this)(operation,branch);
- }
- inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
- {
- expression_node_ptr result = error_node();
- if ((0 != b0) && (0 != b1))
- {
- expression_node_ptr branch[2] = { b0, b1 };
- result = expression_generator<Type>::operator()(operation, branch);
- b0 = branch[0];
- b1 = branch[1];
- }
- return result;
- }
- inline expression_node_ptr conditional(expression_node_ptr condition,
- expression_node_ptr consequent,
- expression_node_ptr alternative) const
- {
- if ((0 == condition) || (0 == consequent))
- {
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, consequent);
- free_node(*node_allocator_, alternative);
- return error_node();
- }
- // Can the condition be immediately evaluated? if so optimise.
- else if (details::is_constant_node(condition))
- {
- // True branch
- if (details::is_true(condition))
- {
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, alternative);
- return consequent;
- }
- // False branch
- else
- {
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, consequent);
- if (alternative)
- return alternative;
- else
- return node_allocator_->allocate<details::null_node<T> >();
- }
- }
- else if ((0 != consequent) && (0 != alternative))
- {
- return node_allocator_->
- allocate<conditional_node_t>(condition, consequent, alternative);
- }
- else
- return node_allocator_->
- allocate<cons_conditional_node_t>(condition, consequent);
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr conditional_string(expression_node_ptr condition,
- expression_node_ptr consequent,
- expression_node_ptr alternative) const
- {
- if ((0 == condition) || (0 == consequent))
- {
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, consequent);
- free_node(*node_allocator_, alternative);
- return error_node();
- }
- // Can the condition be immediately evaluated? if so optimise.
- else if (details::is_constant_node(condition))
- {
- // True branch
- if (details::is_true(condition))
- {
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, alternative);
- return consequent;
- }
- // False branch
- else
- {
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, consequent);
- if (alternative)
- return alternative;
- else
- return node_allocator_->
- allocate_c<details::string_literal_node<Type> >("");
- }
- }
- else if ((0 != consequent) && (0 != alternative))
- return node_allocator_->
- allocate<conditional_string_node_t>(condition, consequent, alternative);
- else
- return error_node();
- }
- #else
- inline expression_node_ptr conditional_string(expression_node_ptr,
- expression_node_ptr,
- expression_node_ptr) const
- {
- return error_node();
- }
- #endif
- inline expression_node_ptr while_loop(expression_node_ptr& condition,
- expression_node_ptr& branch,
- const bool brkcont = false) const
- {
- if (!brkcont && details::is_constant_node(condition))
- {
- expression_node_ptr result = error_node();
- if (details::is_true(condition))
- // Infinite loops are not allowed.
- result = error_node();
- else
- result = node_allocator_->allocate<details::null_node<Type> >();
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, branch);
- return result;
- }
- else if (details::is_null_node(condition))
- {
- free_node(*node_allocator_,condition);
- return branch;
- }
- else if (!brkcont)
- return node_allocator_->allocate<while_loop_node_t>(condition,branch);
- #ifndef exprtk_disable_break_continue
- else
- return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
- #else
- return error_node();
- #endif
- }
- inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
- expression_node_ptr& branch,
- const bool brkcont = false) const
- {
- if (!brkcont && details::is_constant_node(condition))
- {
- if (
- details::is_true(condition) &&
- details::is_constant_node(branch)
- )
- {
- free_node(*node_allocator_,condition);
- return branch;
- }
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, branch);
- return error_node();
- }
- else if (details::is_null_node(condition))
- {
- free_node(*node_allocator_,condition);
- return branch;
- }
- else if (!brkcont)
- return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
- #ifndef exprtk_disable_break_continue
- else
- return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
- #else
- return error_node();
- #endif
- }
- inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
- expression_node_ptr& condition,
- expression_node_ptr& incrementor,
- expression_node_ptr& loop_body,
- bool brkcont = false) const
- {
- if (!brkcont && details::is_constant_node(condition))
- {
- expression_node_ptr result = error_node();
- if (details::is_true(condition))
- // Infinite loops are not allowed.
- result = error_node();
- else
- result = node_allocator_->allocate<details::null_node<Type> >();
- free_node(*node_allocator_, initialiser);
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, incrementor);
- free_node(*node_allocator_, loop_body);
- return result;
- }
- else if (details::is_null_node(condition) || (0 == condition))
- {
- free_node(*node_allocator_, initialiser);
- free_node(*node_allocator_, condition);
- free_node(*node_allocator_, incrementor);
- return loop_body;
- }
- else if (!brkcont)
- return node_allocator_->allocate<for_loop_node_t>
- (
- initialiser,
- condition,
- incrementor,
- loop_body
- );
- #ifndef exprtk_disable_break_continue
- else
- return node_allocator_->allocate<for_loop_bc_node_t>
- (
- initialiser,
- condition,
- incrementor,
- loop_body
- );
- #else
- return error_node();
- #endif
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- expression_node_ptr result = error_node();
- for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
- {
- expression_node_ptr condition = arg_list[(2 * i) ];
- expression_node_ptr consequent = arg_list[(2 * i) + 1];
- if ((0 == result) && details::is_true(condition))
- {
- result = consequent;
- break;
- }
- }
- if (0 == result)
- {
- result = arg_list.back();
- }
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- expression_node_ptr current_expr = arg_list[i];
- if (current_expr && (current_expr != result))
- {
- free_node(*node_allocator_,current_expr);
- }
- }
- return result;
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- expression_node_ptr result = error_node();
- for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
- {
- expression_node_ptr condition = arg_list[(2 * i) ];
- expression_node_ptr consequent = arg_list[(2 * i) + 1];
- if (details::is_true(condition))
- {
- result = consequent;
- }
- }
- if (0 == result)
- {
- T zero = T(0);
- result = node_allocator_->allocate<literal_node_t>(zero);
- }
- for (std::size_t i = 0; i < arg_list.size(); ++i)
- {
- expression_node_ptr& current_expr = arg_list[i];
- if (current_expr && (current_expr != result))
- {
- free_node(*node_allocator_,current_expr);
- }
- }
- return result;
- }
- struct switch_nodes
- {
- typedef std::vector<expression_node_ptr> arg_list_t;
- #define case_stmt(N) \
- if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
- struct switch_1
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0)
- return arg.back()->value();
- }
- };
- struct switch_2
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0) case_stmt(1)
- return arg.back()->value();
- }
- };
- struct switch_3
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0) case_stmt(1)
- case_stmt(2)
- return arg.back()->value();
- }
- };
- struct switch_4
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0) case_stmt(1)
- case_stmt(2) case_stmt(3)
- return arg.back()->value();
- }
- };
- struct switch_5
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0) case_stmt(1)
- case_stmt(2) case_stmt(3)
- case_stmt(4)
- return arg.back()->value();
- }
- };
- struct switch_6
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0) case_stmt(1)
- case_stmt(2) case_stmt(3)
- case_stmt(4) case_stmt(5)
- return arg.back()->value();
- }
- };
- struct switch_7
- {
- static inline T process(const arg_list_t& arg)
- {
- case_stmt(0) case_stmt(1)
- case_stmt(2) case_stmt(3)
- case_stmt(4) case_stmt(5)
- case_stmt(6)
- return arg.back()->value();
- }
- };
- #undef case_stmt
- };
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- if (arg_list.empty())
- return error_node();
- else if (
- !all_nodes_valid(arg_list) ||
- (arg_list.size() < 3) ||
- ((arg_list.size() % 2) != 1)
- )
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- else if (is_constant_foldable(arg_list))
- return const_optimise_switch(arg_list);
- switch ((arg_list.size() - 1) / 2)
- {
- #define case_stmt(N) \
- case N : \
- return node_allocator_-> \
- allocate<details::switch_n_node \
- <Type,typename switch_nodes::switch_##N> >(arg_list); \
- case_stmt(1)
- case_stmt(2)
- case_stmt(3)
- case_stmt(4)
- case_stmt(5)
- case_stmt(6)
- case_stmt(7)
- #undef case_stmt
- default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
- }
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- if (!all_nodes_valid(arg_list))
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- else if (is_constant_foldable(arg_list))
- return const_optimise_mswitch(arg_list);
- else
- return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
- }
- #define unary_opr_switch_statements \
- case_stmt(details:: e_abs, details:: abs_op) \
- case_stmt(details:: e_acos, details:: acos_op) \
- case_stmt(details::e_acosh, details::acosh_op) \
- case_stmt(details:: e_asin, details:: asin_op) \
- case_stmt(details::e_asinh, details::asinh_op) \
- case_stmt(details:: e_atan, details:: atan_op) \
- case_stmt(details::e_atanh, details::atanh_op) \
- case_stmt(details:: e_ceil, details:: ceil_op) \
- case_stmt(details:: e_cos, details:: cos_op) \
- case_stmt(details:: e_cosh, details:: cosh_op) \
- case_stmt(details:: e_exp, details:: exp_op) \
- case_stmt(details::e_expm1, details::expm1_op) \
- case_stmt(details::e_floor, details::floor_op) \
- case_stmt(details:: e_log, details:: log_op) \
- case_stmt(details::e_log10, details::log10_op) \
- case_stmt(details:: e_log2, details:: log2_op) \
- case_stmt(details::e_log1p, details::log1p_op) \
- case_stmt(details:: e_neg, details:: neg_op) \
- case_stmt(details:: e_pos, details:: pos_op) \
- case_stmt(details::e_round, details::round_op) \
- case_stmt(details:: e_sin, details:: sin_op) \
- case_stmt(details:: e_sinc, details:: sinc_op) \
- case_stmt(details:: e_sinh, details:: sinh_op) \
- case_stmt(details:: e_sqrt, details:: sqrt_op) \
- case_stmt(details:: e_tan, details:: tan_op) \
- case_stmt(details:: e_tanh, details:: tanh_op) \
- case_stmt(details:: e_cot, details:: cot_op) \
- case_stmt(details:: e_sec, details:: sec_op) \
- case_stmt(details:: e_csc, details:: csc_op) \
- case_stmt(details:: e_r2d, details:: r2d_op) \
- case_stmt(details:: e_d2r, details:: d2r_op) \
- case_stmt(details:: e_d2g, details:: d2g_op) \
- case_stmt(details:: e_g2d, details:: g2d_op) \
- case_stmt(details:: e_notl, details:: notl_op) \
- case_stmt(details:: e_sgn, details:: sgn_op) \
- case_stmt(details:: e_erf, details:: erf_op) \
- case_stmt(details:: e_erfc, details:: erfc_op) \
- case_stmt(details:: e_ncdf, details:: ncdf_op) \
- case_stmt(details:: e_frac, details:: frac_op) \
- case_stmt(details::e_trunc, details::trunc_op) \
- inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[1])
- {
- T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
- unary_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[1])
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate<typename details::unary_vector_node<Type,op1<Type> > > \
- (operation, branch[0]); \
- unary_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[1])
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
- unary_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
- expression_node_ptr (&branch)[3])
- {
- expression_node_ptr temp_node = error_node();
- switch (operation)
- {
- #define case_stmt(op) \
- case details::e_sf##op : temp_node = node_allocator_-> \
- allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
- (operation, branch); \
- break; \
- case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
- case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
- case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
- case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
- case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
- case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
- case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
- case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
- case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
- case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
- case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
- case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
- #undef case_stmt
- default : return error_node();
- }
- const T v = temp_node->value();
- details::free_node(*node_allocator_,temp_node);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
- {
- typedef details::variable_node<Type>* variable_ptr;
- const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
- const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
- const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
- switch (operation)
- {
- #define case_stmt(op) \
- case details::e_sf##op : return node_allocator_-> \
- allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
- (v0, v1, v2); \
- case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
- case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
- case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
- case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
- case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
- case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
- case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
- case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
- case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
- case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
- case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
- case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
- {
- if (!all_nodes_valid(branch))
- return error_node();
- else if (is_constant_foldable(branch))
- return const_optimise_sf3(operation,branch);
- else if (all_nodes_variables(branch))
- return varnode_optimise_sf3(operation,branch);
- else
- {
- switch (operation)
- {
- #define case_stmt(op) \
- case details::e_sf##op : return node_allocator_-> \
- allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
- (operation, branch); \
- case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
- case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
- case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
- case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
- case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
- case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
- case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
- case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
- case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
- case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
- case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
- case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
- #undef case_stmt
- default : return error_node();
- }
- }
- }
- inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
- {
- expression_node_ptr temp_node = error_node();
- switch (operation)
- {
- #define case_stmt(op) \
- case details::e_sf##op : temp_node = node_allocator_-> \
- allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
- (operation, branch); \
- break; \
- case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
- case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
- case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
- case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
- case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
- case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
- case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
- case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
- case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
- case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
- case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
- case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
- case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
- #undef case_stmt
- default : return error_node();
- }
- const T v = temp_node->value();
- details::free_node(*node_allocator_,temp_node);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
- {
- typedef details::variable_node<Type>* variable_ptr;
- const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
- const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
- const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
- const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
- switch (operation)
- {
- #define case_stmt(op) \
- case details::e_sf##op : return node_allocator_-> \
- allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
- (v0, v1, v2, v3); \
- case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
- case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
- case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
- case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
- case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
- case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
- case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
- case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
- case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
- case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
- case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
- case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
- case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
- {
- if (!all_nodes_valid(branch))
- return error_node();
- else if (is_constant_foldable(branch))
- return const_optimise_sf4(operation,branch);
- else if (all_nodes_variables(branch))
- return varnode_optimise_sf4(operation,branch);
- switch (operation)
- {
- #define case_stmt(op) \
- case details::e_sf##op : return node_allocator_-> \
- allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
- (operation, branch); \
- case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
- case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
- case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
- case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
- case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
- case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
- case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
- case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
- case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
- case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
- case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
- case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
- case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
- #undef case_stmt
- default : return error_node();
- }
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- expression_node_ptr temp_node = error_node();
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : temp_node = node_allocator_-> \
- allocate<details::vararg_node<Type,op1<Type> > > \
- (arg_list); \
- break; \
- case_stmt(details::e_sum , details::vararg_add_op )
- case_stmt(details::e_prod , details::vararg_mul_op )
- case_stmt(details::e_avg , details::vararg_avg_op )
- case_stmt(details::e_min , details::vararg_min_op )
- case_stmt(details::e_max , details::vararg_max_op )
- case_stmt(details::e_mand , details::vararg_mand_op )
- case_stmt(details::e_mor , details::vararg_mor_op )
- case_stmt(details::e_multi , details::vararg_multi_op)
- #undef case_stmt
- default : return error_node();
- }
- const T v = temp_node->value();
- details::free_node(*node_allocator_,temp_node);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- inline bool special_one_parameter_vararg(const details::operator_type& operation) const
- {
- return (
- (details::e_sum == operation) ||
- (details::e_prod == operation) ||
- (details::e_avg == operation) ||
- (details::e_min == operation) ||
- (details::e_max == operation)
- );
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
- case_stmt(details::e_sum , details::vararg_add_op )
- case_stmt(details::e_prod , details::vararg_mul_op )
- case_stmt(details::e_avg , details::vararg_avg_op )
- case_stmt(details::e_min , details::vararg_min_op )
- case_stmt(details::e_max , details::vararg_max_op )
- case_stmt(details::e_mand , details::vararg_mand_op )
- case_stmt(details::e_mor , details::vararg_mor_op )
- case_stmt(details::e_multi , details::vararg_multi_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- if (1 == arg_list.size())
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
- case_stmt(details::e_sum , details::vec_add_op)
- case_stmt(details::e_prod , details::vec_mul_op)
- case_stmt(details::e_avg , details::vec_avg_op)
- case_stmt(details::e_min , details::vec_min_op)
- case_stmt(details::e_max , details::vec_max_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else
- return error_node();
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
- {
- if (!all_nodes_valid(arg_list))
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- else if (is_constant_foldable(arg_list))
- return const_optimise_varargfunc(operation,arg_list);
- else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
- return vectorize_func(operation,arg_list);
- else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
- return arg_list[0];
- else if (all_nodes_variables(arg_list))
- return varnode_optimise_varargfunc(operation,arg_list);
- #ifndef exprtk_disable_string_capabilities
- if (details::e_smulti == operation)
- {
- return node_allocator_->
- allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
- }
- else
- #endif
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
- case_stmt(details::e_sum , details::vararg_add_op )
- case_stmt(details::e_prod , details::vararg_mul_op )
- case_stmt(details::e_avg , details::vararg_avg_op )
- case_stmt(details::e_min , details::vararg_min_op )
- case_stmt(details::e_max , details::vararg_max_op )
- case_stmt(details::e_mand , details::vararg_mand_op )
- case_stmt(details::e_mor , details::vararg_mor_op )
- case_stmt(details::e_multi , details::vararg_multi_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- }
- template <std::size_t N>
- inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
- {
- typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
- expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
- if (0 == result)
- return error_node();
- else
- {
- // Can the function call be completely optimised?
- if (details::is_constant_node(result))
- return result;
- else if (!all_nodes_valid(b))
- return error_node();
- else if (N != f->param_count)
- {
- details::free_all_nodes(*node_allocator_,b);
- return error_node();
- }
- function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
- if (func_node_ptr->init_branches(b))
- return result;
- else
- {
- details::free_all_nodes(*node_allocator_,b);
- return error_node();
- }
- }
- }
- inline expression_node_ptr function(ifunction_t* f)
- {
- typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
- return node_allocator_->allocate<function_N_node_t>(f);
- }
- inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
- std::vector<expression_node_ptr>& arg_list)
- {
- if (!all_nodes_valid(arg_list))
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
- expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
- if (
- !arg_list.empty() &&
- !vaf->has_side_effects() &&
- is_constant_foldable(arg_list)
- )
- {
- const Type v = result->value();
- details::free_node(*node_allocator_,result);
- result = node_allocator_->allocate<literal_node_t>(v);
- }
- parser_->state_.activate_side_effect("vararg_function_call()");
- return result;
- }
- inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
- std::vector<expression_node_ptr>& arg_list,
- const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
- {
- if (!all_nodes_valid(arg_list))
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1;
- typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
- const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
- expression_node_ptr result = error_node();
- if (no_psi == param_seq_index)
- result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
- else
- result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
- alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
- if (
- !arg_list.empty() &&
- !gf->has_side_effects() &&
- parser_->state_.type_check_enabled &&
- is_constant_foldable(arg_list)
- )
- {
- genfunc_node_ptr->init_branches();
- const Type v = result->value();
- details::free_node(*node_allocator_,result);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- else if (genfunc_node_ptr->init_branches())
- {
- parser_->state_.activate_side_effect("generic_function_call()");
- return result;
- }
- else
- {
- details::free_node(*node_allocator_, result);
- details::free_all_nodes(*node_allocator_, arg_list);
- return error_node();
- }
- }
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr string_function_call(igeneric_function_t* gf,
- std::vector<expression_node_ptr>& arg_list,
- const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
- {
- if (!all_nodes_valid(arg_list))
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- typedef details::string_function_node <Type,igeneric_function_t> alloc_type1;
- typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
- const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
- expression_node_ptr result = error_node();
- if (no_psi == param_seq_index)
- result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
- else
- result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
- alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
- if (
- !arg_list.empty() &&
- !gf->has_side_effects() &&
- is_constant_foldable(arg_list)
- )
- {
- strfunc_node_ptr->init_branches();
- const Type v = result->value();
- details::free_node(*node_allocator_,result);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- else if (strfunc_node_ptr->init_branches())
- {
- parser_->state_.activate_side_effect("string_function_call()");
- return result;
- }
- else
- {
- details::free_node (*node_allocator_,result );
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- }
- #endif
- #ifndef exprtk_disable_return_statement
- inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
- {
- if (!all_nodes_valid(arg_list))
- {
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- typedef details::return_node<Type> alloc_type;
- expression_node_ptr result = node_allocator_->
- allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
- alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
- if (return_node_ptr->init_branches())
- {
- parser_->state_.activate_side_effect("return_call()");
- return result;
- }
- else
- {
- details::free_node (*node_allocator_,result );
- details::free_all_nodes(*node_allocator_,arg_list);
- return error_node();
- }
- }
- inline expression_node_ptr return_envelope(expression_node_ptr body,
- results_context_t* rc,
- bool*& return_invoked)
- {
- typedef details::return_envelope_node<Type> alloc_type;
- expression_node_ptr result = node_allocator_->
- allocate_cr<alloc_type>(body,(*rc));
- return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
- return result;
- }
- #else
- inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
- {
- return error_node();
- }
- inline expression_node_ptr return_envelope(expression_node_ptr,
- results_context_t*,
- bool*&)
- {
- return error_node();
- }
- #endif
- inline expression_node_ptr vector_element(const std::string& symbol,
- vector_holder_ptr vector_base,
- expression_node_ptr index)
- {
- expression_node_ptr result = error_node();
- if (details::is_constant_node(index))
- {
- std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
- details::free_node(*node_allocator_,index);
- if (vector_base->rebaseable())
- {
- return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
- }
- scope_element& se = parser_->sem_.get_element(symbol,i);
- if (se.index == i)
- {
- result = se.var_node;
- }
- else
- {
- scope_element nse;
- nse.name = symbol;
- nse.active = true;
- nse.ref_count = 1;
- nse.type = scope_element::e_vecelem;
- nse.index = i;
- nse.depth = parser_->state_.scope_depth;
- nse.data = 0;
- nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
- if (!parser_->sem_.add_element(nse))
- {
- parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
- parser_->sem_.free_element(nse);
- result = error_node();
- }
- exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
- parser_->state_.activate_side_effect("vector_element()");
- result = nse.var_node;
- }
- }
- else if (vector_base->rebaseable())
- result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
- else
- result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
- return result;
- }
- private:
- template <std::size_t N, typename NodePtr>
- inline bool is_constant_foldable(NodePtr (&b)[N]) const
- {
- for (std::size_t i = 0; i < N; ++i)
- {
- if (0 == b[i])
- return false;
- else if (!details::is_constant_node(b[i]))
- return false;
- }
- return true;
- }
- template <typename NodePtr,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
- {
- for (std::size_t i = 0; i < b.size(); ++i)
- {
- if (0 == b[i])
- return false;
- else if (!details::is_constant_node(b[i]))
- return false;
- }
- return true;
- }
- void lodge_assignment(symbol_type cst, expression_node_ptr node)
- {
- parser_->state_.activate_side_effect("lodge_assignment()");
- if (!parser_->dec_.collect_assignments())
- return;
- std::string symbol_name;
- switch (cst)
- {
- case e_st_variable : symbol_name = parser_->symtab_store_
- .get_variable_name(node);
- break;
- #ifndef exprtk_disable_string_capabilities
- case e_st_string : symbol_name = parser_->symtab_store_
- .get_stringvar_name(node);
- break;
- #endif
- case e_st_vector : {
- typedef details::vector_holder<T> vector_holder_t;
- vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
- symbol_name = parser_->symtab_store_.get_vector_name(&vh);
- }
- break;
- case e_st_vecelem : {
- typedef details::vector_holder<T> vector_holder_t;
- vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
- symbol_name = parser_->symtab_store_.get_vector_name(&vh);
- cst = e_st_vector;
- }
- break;
- default : return;
- }
- if (!symbol_name.empty())
- {
- parser_->dec_.add_assignment(symbol_name,cst);
- }
- }
- inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
- {
- if (details::is_variable_node(branch[0]))
- {
- lodge_assignment(e_st_variable,branch[0]);
- return synthesize_expression<assignment_node_t,2>(operation,branch);
- }
- else if (details::is_vector_elem_node(branch[0]))
- {
- lodge_assignment(e_st_vecelem,branch[0]);
- return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
- }
- else if (details::is_rebasevector_elem_node(branch[0]))
- {
- lodge_assignment(e_st_vecelem,branch[0]);
- return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
- }
- else if (details::is_rebasevector_celem_node(branch[0]))
- {
- lodge_assignment(e_st_vecelem,branch[0]);
- return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
- }
- #ifndef exprtk_disable_string_capabilities
- else if (details::is_string_node(branch[0]))
- {
- lodge_assignment(e_st_string,branch[0]);
- return synthesize_expression<assignment_string_node_t,2>(operation, branch);
- }
- else if (details::is_string_range_node(branch[0]))
- {
- lodge_assignment(e_st_string,branch[0]);
- return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
- }
- #endif
- else if (details::is_vector_node(branch[0]))
- {
- lodge_assignment(e_st_vector,branch[0]);
- if (details::is_ivector_node(branch[1]))
- return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
- else
- return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
- }
- else
- {
- parser_->set_synthesis_error("Invalid assignment operation.[1]");
- return error_node();
- }
- }
- inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- if (details::is_variable_node(branch[0]))
- {
- lodge_assignment(e_st_variable,branch[0]);
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- case_stmt(details::e_addass,details::add_op)
- case_stmt(details::e_subass,details::sub_op)
- case_stmt(details::e_mulass,details::mul_op)
- case_stmt(details::e_divass,details::div_op)
- case_stmt(details::e_modass,details::mod_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (details::is_vector_elem_node(branch[0]))
- {
- lodge_assignment(e_st_vecelem,branch[0]);
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- case_stmt(details::e_addass,details::add_op)
- case_stmt(details::e_subass,details::sub_op)
- case_stmt(details::e_mulass,details::mul_op)
- case_stmt(details::e_divass,details::div_op)
- case_stmt(details::e_modass,details::mod_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (details::is_rebasevector_elem_node(branch[0]))
- {
- lodge_assignment(e_st_vecelem,branch[0]);
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- case_stmt(details::e_addass,details::add_op)
- case_stmt(details::e_subass,details::sub_op)
- case_stmt(details::e_mulass,details::mul_op)
- case_stmt(details::e_divass,details::div_op)
- case_stmt(details::e_modass,details::mod_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (details::is_rebasevector_celem_node(branch[0]))
- {
- lodge_assignment(e_st_vecelem,branch[0]);
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- case_stmt(details::e_addass,details::add_op)
- case_stmt(details::e_subass,details::sub_op)
- case_stmt(details::e_mulass,details::mul_op)
- case_stmt(details::e_divass,details::div_op)
- case_stmt(details::e_modass,details::mod_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (details::is_vector_node(branch[0]))
- {
- lodge_assignment(e_st_vector,branch[0]);
- if (details::is_ivector_node(branch[1]))
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- case_stmt(details::e_addass,details::add_op)
- case_stmt(details::e_subass,details::sub_op)
- case_stmt(details::e_mulass,details::mul_op)
- case_stmt(details::e_divass,details::div_op)
- case_stmt(details::e_modass,details::mod_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- case_stmt(details::e_addass,details::add_op)
- case_stmt(details::e_subass,details::sub_op)
- case_stmt(details::e_mulass,details::mul_op)
- case_stmt(details::e_divass,details::div_op)
- case_stmt(details::e_modass,details::mod_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- }
- #ifndef exprtk_disable_string_capabilities
- else if (
- (details::e_addass == operation) &&
- details::is_string_node(branch[0])
- )
- {
- typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
- lodge_assignment(e_st_string,branch[0]);
- return synthesize_expression<addass_t,2>(operation,branch);
- }
- #endif
- else
- {
- parser_->set_synthesis_error("Invalid assignment operation[2]");
- return error_node();
- }
- }
- inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const bool is_b0_ivec = details::is_ivector_node(branch[0]);
- const bool is_b1_ivec = details::is_ivector_node(branch[1]);
- #define batch_eqineq_logic_case \
- case_stmt(details:: e_lt, details:: lt_op) \
- case_stmt(details:: e_lte, details:: lte_op) \
- case_stmt(details:: e_gt, details:: gt_op) \
- case_stmt(details:: e_gte, details:: gte_op) \
- case_stmt(details:: e_eq, details:: eq_op) \
- case_stmt(details:: e_ne, details:: ne_op) \
- case_stmt(details::e_equal, details::equal_op) \
- case_stmt(details:: e_and, details:: and_op) \
- case_stmt(details:: e_nand, details:: nand_op) \
- case_stmt(details:: e_or, details:: or_op) \
- case_stmt(details:: e_nor, details:: nor_op) \
- case_stmt(details:: e_xor, details:: xor_op) \
- case_stmt(details:: e_xnor, details:: xnor_op) \
- if (is_b0_ivec && is_b1_ivec)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- batch_eqineq_logic_case
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (is_b0_ivec && !is_b1_ivec)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- batch_eqineq_logic_case
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (!is_b0_ivec && is_b1_ivec)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- batch_eqineq_logic_case
- #undef case_stmt
- default : return error_node();
- }
- }
- else
- return error_node();
- #undef batch_eqineq_logic_case
- }
- inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const bool is_b0_ivec = details::is_ivector_node(branch[0]);
- const bool is_b1_ivec = details::is_ivector_node(branch[1]);
- #define vector_ops \
- case_stmt(details::e_add,details::add_op) \
- case_stmt(details::e_sub,details::sub_op) \
- case_stmt(details::e_mul,details::mul_op) \
- case_stmt(details::e_div,details::div_op) \
- case_stmt(details::e_mod,details::mod_op) \
- if (is_b0_ivec && is_b1_ivec)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- vector_ops
- case_stmt(details::e_pow,details:: pow_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (is_b0_ivec && !is_b1_ivec)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- vector_ops
- case_stmt(details::e_pow,details:: pow_op)
- #undef case_stmt
- default : return error_node();
- }
- }
- else if (!is_b0_ivec && is_b1_ivec)
- {
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
- (operation, branch[0], branch[1]); \
- vector_ops
- #undef case_stmt
- default : return error_node();
- }
- }
- else
- return error_node();
- #undef vector_ops
- }
- inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
- {
- const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
- const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
- const bool v0_is_ivec = details::is_ivector_node (branch[0]);
- const bool v1_is_ivec = details::is_ivector_node (branch[1]);
- #ifndef exprtk_disable_string_capabilities
- const bool v0_is_str = details::is_generally_string_node(branch[0]);
- const bool v1_is_str = details::is_generally_string_node(branch[1]);
- #endif
- expression_node_ptr result = error_node();
- if (v0_is_ivar && v1_is_ivar)
- {
- typedef details::variable_node<T>* variable_node_ptr;
- variable_node_ptr v0 = variable_node_ptr(0);
- variable_node_ptr v1 = variable_node_ptr(0);
- if (
- (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
- (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
- )
- {
- result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
- }
- else
- result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
- }
- else if (v0_is_ivec && v1_is_ivec)
- {
- result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
- }
- #ifndef exprtk_disable_string_capabilities
- else if (v0_is_str && v1_is_str)
- {
- if (is_string_node(branch[0]) && is_string_node(branch[1]))
- result = node_allocator_->allocate<details::swap_string_node<T> >
- (branch[0], branch[1]);
- else
- result = node_allocator_->allocate<details::swap_genstrings_node<T> >
- (branch[0], branch[1]);
- }
- #endif
- else
- {
- parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
- return error_node();
- }
- parser_->state_.activate_side_effect("synthesize_swap_expression()");
- return result;
- }
- #ifndef exprtk_disable_sc_andor
- inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
- {
- expression_node_ptr result = error_node();
- if (details::is_constant_node(branch[0]))
- {
- if (
- (details::e_scand == operation) &&
- std::equal_to<T>()(T(0),branch[0]->value())
- )
- result = node_allocator_->allocate_c<literal_node_t>(T(0));
- else if (
- (details::e_scor == operation) &&
- std::not_equal_to<T>()(T(0),branch[0]->value())
- )
- result = node_allocator_->allocate_c<literal_node_t>(T(1));
- }
- if (details::is_constant_node(branch[1]) && (0 == result))
- {
- if (
- (details::e_scand == operation) &&
- std::equal_to<T>()(T(0),branch[1]->value())
- )
- result = node_allocator_->allocate_c<literal_node_t>(T(0));
- else if (
- (details::e_scor == operation) &&
- std::not_equal_to<T>()(T(0),branch[1]->value())
- )
- result = node_allocator_->allocate_c<literal_node_t>(T(1));
- }
- if (result)
- {
- free_node(*node_allocator_, branch[0]);
- free_node(*node_allocator_, branch[1]);
- return result;
- }
- else if (details::e_scand == operation)
- {
- return synthesize_expression<scand_node_t,2>(operation, branch);
- }
- else if (details::e_scor == operation)
- {
- return synthesize_expression<scor_node_t,2>(operation, branch);
- }
- else
- return error_node();
- }
- #else
- inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
- {
- return error_node();
- }
- #endif
- #define basic_opr_switch_statements \
- case_stmt(details::e_add, details::add_op) \
- case_stmt(details::e_sub, details::sub_op) \
- case_stmt(details::e_mul, details::mul_op) \
- case_stmt(details::e_div, details::div_op) \
- case_stmt(details::e_mod, details::mod_op) \
- case_stmt(details::e_pow, details::pow_op) \
- #define extended_opr_switch_statements \
- case_stmt(details:: e_lt, details:: lt_op) \
- case_stmt(details:: e_lte, details:: lte_op) \
- case_stmt(details:: e_gt, details:: gt_op) \
- case_stmt(details:: e_gte, details:: gte_op) \
- case_stmt(details:: e_eq, details:: eq_op) \
- case_stmt(details:: e_ne, details:: ne_op) \
- case_stmt(details:: e_and, details:: and_op) \
- case_stmt(details::e_nand, details::nand_op) \
- case_stmt(details:: e_or, details:: or_op) \
- case_stmt(details:: e_nor, details:: nor_op) \
- case_stmt(details:: e_xor, details:: xor_op) \
- case_stmt(details::e_xnor, details::xnor_op) \
- #ifndef exprtk_disable_cardinal_pow_optimisation
- template <typename TType, template <typename, typename> class IPowNode>
- inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
- {
- switch (p)
- {
- #define case_stmt(cp) \
- case cp : return node_allocator_-> \
- allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
- case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
- case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
- case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
- case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
- case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
- case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
- case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
- case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
- case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
- case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
- case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
- case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
- case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
- case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
- case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
- {
- const bool not_recipricol = (c >= T(0));
- const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
- if (0 == p)
- return node_allocator_->allocate_c<literal_node_t>(T(1));
- else if (std::equal_to<T>()(T(2),c))
- {
- return node_allocator_->
- template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
- }
- else
- {
- if (not_recipricol)
- return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
- else
- return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
- }
- }
- inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
- {
- return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
- }
- inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
- {
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const bool not_recipricol = (c >= T(0));
- const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
- node_allocator_->free(branch[1]);
- if (0 == p)
- {
- details::free_all_nodes(*node_allocator_, branch);
- return node_allocator_->allocate_c<literal_node_t>(T(1));
- }
- else if (not_recipricol)
- return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
- else
- return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
- }
- #else
- inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
- {
- return error_node();
- }
- inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
- {
- return false;
- }
- inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
- {
- return error_node();
- }
- #endif
- struct synthesize_binary_ext_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const bool left_neg = is_neg_unary_node(branch[0]);
- const bool right_neg = is_neg_unary_node(branch[1]);
- if (left_neg && right_neg)
- {
- if (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- if (
- !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
- !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
- )
- {
- details::free_all_nodes(*expr_gen.node_allocator_,branch);
- return error_node();
- }
- }
- switch (operation)
- {
- // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
- case details::e_add : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
- (branch[0],branch[1]));
- // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
- case details::e_sub : return expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
- (branch[1],branch[0]);
- default : break;
- }
- }
- else if (left_neg && !right_neg)
- {
- if (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
- {
- details::free_all_nodes(*expr_gen.node_allocator_,branch);
- return error_node();
- }
- switch (operation)
- {
- // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
- case details::e_add : return expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
- (branch[1], branch[0]);
- // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
- case details::e_sub : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
- (branch[0], branch[1]));
- // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
- case details::e_mul : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
- (branch[0], branch[1]));
- // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
- case details::e_div : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
- (branch[0], branch[1]));
- default : return error_node();
- }
- }
- }
- else if (!left_neg && right_neg)
- {
- if (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
- {
- details::free_all_nodes(*expr_gen.node_allocator_,branch);
- return error_node();
- }
- switch (operation)
- {
- // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
- case details::e_add : return expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
- (branch[0], branch[1]);
- // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
- case details::e_sub : return expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
- (branch[0], branch[1]);
- // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
- case details::e_mul : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
- (branch[0], branch[1]));
- // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
- case details::e_div : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
- (branch[0], branch[1]));
- default : return error_node();
- }
- }
- }
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
- (branch[0], branch[1]); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_vob_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- #ifndef exprtk_disable_enhanced_features
- if (details::is_sf3ext_node(branch[1]))
- {
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile_right<vtype>
- (expr_gen, v, operation, branch[1], result);
- if (synthesis_result)
- {
- free_node(*expr_gen.node_allocator_,branch[1]);
- return result;
- }
- }
- #endif
- if (
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- if (details::is_uv_node(branch[1]))
- {
- typedef details::uv_base_node<Type>* uvbn_ptr_t;
- details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
- if (details::e_neg == o)
- {
- const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
- free_node(*expr_gen.node_allocator_,branch[1]);
- switch (operation)
- {
- case details::e_mul : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate_rr<typename details::
- vov_node<Type,details::mul_op<Type> > >(v,v1));
- case details::e_div : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate_rr<typename details::
- vov_node<Type,details::div_op<Type> > >(v,v1));
- default : break;
- }
- }
- }
- }
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
- (v, branch[1]); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_bov_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- #ifndef exprtk_disable_enhanced_features
- if (details::is_sf3ext_node(branch[0]))
- {
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile_left<vtype>
- (expr_gen, v, operation, branch[0], result);
- if (synthesis_result)
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- return result;
- }
- }
- #endif
- if (
- (details::e_add == operation) ||
- (details::e_sub == operation) ||
- (details::e_mul == operation) ||
- (details::e_div == operation)
- )
- {
- if (details::is_uv_node(branch[0]))
- {
- typedef details::uv_base_node<Type>* uvbn_ptr_t;
- details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
- if (details::e_neg == o)
- {
- const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
- free_node(*expr_gen.node_allocator_,branch[0]);
- switch (operation)
- {
- case details::e_add : return expr_gen.node_allocator_->
- template allocate_rr<typename details::
- vov_node<Type,details::sub_op<Type> > >(v,v0);
- case details::e_sub : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate_rr<typename details::
- vov_node<Type,details::add_op<Type> > >(v0,v));
- case details::e_mul : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate_rr<typename details::
- vov_node<Type,details::mul_op<Type> > >(v0,v));
- case details::e_div : return expr_gen(details::e_neg,
- expr_gen.node_allocator_->
- template allocate_rr<typename details::
- vov_node<Type,details::div_op<Type> > >(v0,v));
- default : break;
- }
- }
- }
- }
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
- (branch[0], v); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_cob_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
- free_node(*expr_gen.node_allocator_,branch[0]);
- if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
- {
- free_node(*expr_gen.node_allocator_,branch[1]);
- return expr_gen(T(0));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[1]);
- return expr_gen(T(0));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
- return branch[1];
- else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
- return branch[1];
- if (details::is_cob_node(branch[1]))
- {
- // Simplify expressions of the form:
- // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
- // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
- if (
- (operation == details::e_mul) ||
- (operation == details::e_add)
- )
- {
- details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
- if (operation == cobnode->operation())
- {
- switch (operation)
- {
- case details::e_add : cobnode->set_c(c + cobnode->c()); break;
- case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
- default : return error_node();
- }
- return cobnode;
- }
- }
- if (operation == details::e_mul)
- {
- details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
- details::operator_type cob_opr = cobnode->operation();
- if (
- (details::e_div == cob_opr) ||
- (details::e_mul == cob_opr)
- )
- {
- switch (cob_opr)
- {
- case details::e_div : cobnode->set_c(c * cobnode->c()); break;
- case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
- default : return error_node();
- }
- return cobnode;
- }
- }
- else if (operation == details::e_div)
- {
- details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
- details::operator_type cob_opr = cobnode->operation();
- if (
- (details::e_div == cob_opr) ||
- (details::e_mul == cob_opr)
- )
- {
- details::expression_node<Type>* new_cobnode = error_node();
- switch (cob_opr)
- {
- case details::e_div : new_cobnode = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
- (c / cobnode->c(), cobnode->move_branch(0));
- break;
- case details::e_mul : new_cobnode = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
- (c / cobnode->c(), cobnode->move_branch(0));
- break;
- default : return error_node();
- }
- free_node(*expr_gen.node_allocator_,branch[1]);
- return new_cobnode;
- }
- }
- }
- #ifndef exprtk_disable_enhanced_features
- else if (details::is_sf3ext_node(branch[1]))
- {
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile_right<ctype>
- (expr_gen, c, operation, branch[1], result);
- if (synthesis_result)
- {
- free_node(*expr_gen.node_allocator_,branch[1]);
- return result;
- }
- }
- #endif
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
- (c, branch[1]); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_boc_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- details::free_node(*(expr_gen.node_allocator_), branch[1]);
- if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- return expr_gen(T(0));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- return expr_gen(std::numeric_limits<T>::quiet_NaN());
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
- return branch[0];
- else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
- return branch[0];
- if (details::is_boc_node(branch[0]))
- {
- // Simplify expressions of the form:
- // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
- // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
- if (
- (operation == details::e_mul) ||
- (operation == details::e_add)
- )
- {
- details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
- if (operation == bocnode->operation())
- {
- switch (operation)
- {
- case details::e_add : bocnode->set_c(c + bocnode->c()); break;
- case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
- default : return error_node();
- }
- return bocnode;
- }
- }
- else if (operation == details::e_div)
- {
- details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
- details::operator_type boc_opr = bocnode->operation();
- if (
- (details::e_div == boc_opr) ||
- (details::e_mul == boc_opr)
- )
- {
- switch (boc_opr)
- {
- case details::e_div : bocnode->set_c(c * bocnode->c()); break;
- case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
- default : return error_node();
- }
- return bocnode;
- }
- }
- else if (operation == details::e_pow)
- {
- // (v ^ c0) ^ c1 --> v ^(c0 * c1)
- details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
- details::operator_type boc_opr = bocnode->operation();
- if (details::e_pow == boc_opr)
- {
- bocnode->set_c(bocnode->c() * c);
- return bocnode;
- }
- }
- }
- #ifndef exprtk_disable_enhanced_features
- if (details::is_sf3ext_node(branch[0]))
- {
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile_left<ctype>
- (expr_gen, c, operation, branch[0], result);
- if (synthesis_result)
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- return result;
- }
- }
- #endif
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
- (branch[0], c); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_cocob_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- expression_node_ptr result = error_node();
- // (cob) o c --> cob
- if (details::is_cob_node(branch[0]))
- {
- details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- free_node(*expr_gen.node_allocator_, branch[1]);
- return expr_gen(T(0));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- free_node(*expr_gen.node_allocator_, branch[1]);
- return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[1]);
- return branch[0];
- }
- else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[1]);
- return branch[0];
- }
- else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[1]);
- return branch[0];
- }
- const bool op_addsub = (details::e_add == cobnode->operation()) ||
- (details::e_sub == cobnode->operation()) ;
- if (op_addsub)
- {
- switch (operation)
- {
- case details::e_add : cobnode->set_c(cobnode->c() + c); break;
- case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
- default : return error_node();
- }
- result = cobnode;
- }
- else if (details::e_mul == cobnode->operation())
- {
- switch (operation)
- {
- case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
- case details::e_div : cobnode->set_c(cobnode->c() / c); break;
- default : return error_node();
- }
- result = cobnode;
- }
- else if (details::e_div == cobnode->operation())
- {
- if (details::e_mul == operation)
- {
- cobnode->set_c(cobnode->c() * c);
- result = cobnode;
- }
- else if (details::e_div == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
- (cobnode->c() / c, cobnode->move_branch(0));
- free_node(*expr_gen.node_allocator_, branch[0]);
- }
- }
- if (result)
- {
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- // c o (cob) --> cob
- else if (details::is_cob_node(branch[1]))
- {
- details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
- if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- free_node(*expr_gen.node_allocator_, branch[1]);
- return expr_gen(T(0));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- free_node(*expr_gen.node_allocator_, branch[1]);
- return expr_gen(T(0));
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- return branch[1];
- }
- else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
- {
- free_node(*expr_gen.node_allocator_, branch[0]);
- return branch[1];
- }
- if (details::e_add == cobnode->operation())
- {
- if (details::e_add == operation)
- {
- cobnode->set_c(c + cobnode->c());
- result = cobnode;
- }
- else if (details::e_sub == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
- (c - cobnode->c(), cobnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- else if (details::e_sub == cobnode->operation())
- {
- if (details::e_add == operation)
- {
- cobnode->set_c(c + cobnode->c());
- result = cobnode;
- }
- else if (details::e_sub == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
- (c - cobnode->c(), cobnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- else if (details::e_mul == cobnode->operation())
- {
- if (details::e_mul == operation)
- {
- cobnode->set_c(c * cobnode->c());
- result = cobnode;
- }
- else if (details::e_div == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
- (c / cobnode->c(), cobnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- else if (details::e_div == cobnode->operation())
- {
- if (details::e_mul == operation)
- {
- cobnode->set_c(c * cobnode->c());
- result = cobnode;
- }
- else if (details::e_div == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
- (c / cobnode->c(), cobnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- if (result)
- {
- free_node(*expr_gen.node_allocator_,branch[0]);
- }
- }
- return result;
- }
- };
- struct synthesize_coboc_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- expression_node_ptr result = error_node();
- // (boc) o c --> boc
- if (details::is_boc_node(branch[0]))
- {
- details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- if (details::e_add == bocnode->operation())
- {
- switch (operation)
- {
- case details::e_add : bocnode->set_c(bocnode->c() + c); break;
- case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
- default : return error_node();
- }
- result = bocnode;
- }
- else if (details::e_mul == bocnode->operation())
- {
- switch (operation)
- {
- case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
- case details::e_div : bocnode->set_c(bocnode->c() / c); break;
- default : return error_node();
- }
- result = bocnode;
- }
- else if (details::e_sub == bocnode->operation())
- {
- if (details::e_add == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
- (bocnode->move_branch(0), c - bocnode->c());
- free_node(*expr_gen.node_allocator_,branch[0]);
- }
- else if (details::e_sub == operation)
- {
- bocnode->set_c(bocnode->c() + c);
- result = bocnode;
- }
- }
- else if (details::e_div == bocnode->operation())
- {
- switch (operation)
- {
- case details::e_div : bocnode->set_c(bocnode->c() * c); break;
- case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
- default : return error_node();
- }
- result = bocnode;
- }
- if (result)
- {
- free_node(*expr_gen.node_allocator_, branch[1]);
- }
- }
- // c o (boc) --> boc
- else if (details::is_boc_node(branch[1]))
- {
- details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
- if (details::e_add == bocnode->operation())
- {
- if (details::e_add == operation)
- {
- bocnode->set_c(c + bocnode->c());
- result = bocnode;
- }
- else if (details::e_sub == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
- (c - bocnode->c(), bocnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- else if (details::e_sub == bocnode->operation())
- {
- if (details::e_add == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
- (bocnode->move_branch(0), c - bocnode->c());
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- else if (details::e_sub == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
- (c + bocnode->c(), bocnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- else if (details::e_mul == bocnode->operation())
- {
- if (details::e_mul == operation)
- {
- bocnode->set_c(c * bocnode->c());
- result = bocnode;
- }
- else if (details::e_div == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
- (c / bocnode->c(), bocnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- else if (details::e_div == bocnode->operation())
- {
- if (details::e_mul == operation)
- {
- bocnode->set_c(bocnode->c() / c);
- result = bocnode;
- }
- else if (details::e_div == operation)
- {
- result = expr_gen.node_allocator_->
- template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
- (c * bocnode->c(), bocnode->move_branch(0));
- free_node(*expr_gen.node_allocator_,branch[1]);
- }
- }
- if (result)
- {
- free_node(*expr_gen.node_allocator_,branch[0]);
- }
- }
- return result;
- }
- };
- #ifndef exprtk_disable_enhanced_features
- inline bool synthesize_expression(const details::operator_type& operation,
- expression_node_ptr (&branch)[2],
- expression_node_ptr& result)
- {
- result = error_node();
- if (!operation_optimisable(operation))
- return false;
- const std::string node_id = branch_to_id(branch);
- const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
- if (synthesize_map_.end() != itr)
- {
- result = itr->second((*this), operation, branch);
- return true;
- }
- else
- return false;
- }
- struct synthesize_vov_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
- (v1, v2); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_cov_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value();
- const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref ();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
- return expr_gen(T(0));
- else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
- return expr_gen(T(0));
- else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
- return static_cast<details::variable_node<Type>*>(branch[1]);
- else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
- return static_cast<details::variable_node<Type>*>(branch[1]);
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
- (c, v); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_voc_expression
- {
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref ();
- const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value();
- details::free_node(*(expr_gen.node_allocator_), branch[1]);
- if (expr_gen.cardinal_pow_optimisable(operation,c))
- {
- if (std::equal_to<T>()(T(1),c))
- return branch[0];
- else
- return expr_gen.cardinal_pow_optimisation(v,c);
- }
- else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
- return expr_gen(T(0));
- else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
- return expr_gen(std::numeric_limits<T>::quiet_NaN());
- else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
- return static_cast<details::variable_node<Type>*>(branch[0]);
- else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
- return static_cast<details::variable_node<Type>*>(branch[0]);
- else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
- return static_cast<details::variable_node<Type>*>(branch[0]);
- switch (operation)
- {
- #define case_stmt(op0,op1) \
- case op0 : return expr_gen.node_allocator_-> \
- template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
- (v, c); \
- basic_opr_switch_statements
- extended_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- };
- struct synthesize_sf3ext_expression
- {
- template <typename T0, typename T1, typename T2>
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& sf3opr,
- T0 t0, T1 t1, T2 t2)
- {
- switch (sf3opr)
- {
- #define case_stmt(op) \
- case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
- allocate(*(expr_gen.node_allocator_), t0, t1, t2); \
- case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
- case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
- case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
- case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
- case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
- case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
- case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
- case_stmt(28) case_stmt(29) case_stmt(30)
- #undef case_stmt
- default : return error_node();
- }
- }
- template <typename T0, typename T1, typename T2>
- static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
- T0 t0, T1 t1, T2 t2,
- expression_node_ptr& result)
- {
- details::operator_type sf3opr;
- if (!expr_gen.sf3_optimisable(id,sf3opr))
- return false;
- else
- result = synthesize_sf3ext_expression::template process<T0, T1, T2>
- (expr_gen, sf3opr, t0, t1, t2);
- return true;
- }
- };
- struct synthesize_sf4ext_expression
- {
- template <typename T0, typename T1, typename T2, typename T3>
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& sf4opr,
- T0 t0, T1 t1, T2 t2, T3 t3)
- {
- switch (sf4opr)
- {
- #define case_stmt0(op) \
- case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
- allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
- #define case_stmt1(op) \
- case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
- allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
- case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
- case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
- case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
- case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
- case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
- case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
- case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
- case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
- case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
- case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
- case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
- case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
- case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
- case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
- case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
- case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
- case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
- case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
- case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
- case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
- case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
- case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
- case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
- case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
- case_stmt1(60) case_stmt1(61)
- #undef case_stmt0
- #undef case_stmt1
- default : return error_node();
- }
- }
- template <typename T0, typename T1, typename T2, typename T3>
- static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
- T0 t0, T1 t1, T2 t2, T3 t3,
- expression_node_ptr& result)
- {
- details::operator_type sf4opr;
- if (!expr_gen.sf4_optimisable(id,sf4opr))
- return false;
- else
- result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
- (expr_gen, sf4opr, t0, t1, t2, t3);
- return true;
- }
- // T o (sf3ext)
- template <typename ExternalType>
- static inline bool compile_right(expression_generator<Type>& expr_gen,
- ExternalType t,
- const details::operator_type& operation,
- expression_node_ptr& sf3node,
- expression_node_ptr& result)
- {
- if (!details::is_sf3ext_node(sf3node))
- return false;
- typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
- sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
- const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
- switch (n->type())
- {
- case details::expression_node<Type>::e_covoc : return compile_right_impl
- <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_covov : return compile_right_impl
- <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_vocov : return compile_right_impl
- <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_vovoc : return compile_right_impl
- <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_vovov : return compile_right_impl
- <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
- (expr_gen, id, t, sf3node, result);
- default : return false;
- }
- }
- // (sf3ext) o T
- template <typename ExternalType>
- static inline bool compile_left(expression_generator<Type>& expr_gen,
- ExternalType t,
- const details::operator_type& operation,
- expression_node_ptr& sf3node,
- expression_node_ptr& result)
- {
- if (!details::is_sf3ext_node(sf3node))
- return false;
- typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
- sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
- const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
- switch (n->type())
- {
- case details::expression_node<Type>::e_covoc : return compile_left_impl
- <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_covov : return compile_left_impl
- <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_vocov : return compile_left_impl
- <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_vovoc : return compile_left_impl
- <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
- (expr_gen, id, t, sf3node, result);
- case details::expression_node<Type>::e_vovov : return compile_left_impl
- <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
- (expr_gen, id, t, sf3node, result);
- default : return false;
- }
- }
- template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
- static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
- const std::string& id,
- ExternalType t,
- expression_node_ptr& node,
- expression_node_ptr& result)
- {
- SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
- if (n)
- {
- T0 t0 = n->t0();
- T1 t1 = n->t1();
- T2 t2 = n->t2();
- return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
- (expr_gen, id, t, t0, t1, t2, result);
- }
- else
- return false;
- }
- template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
- static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
- const std::string& id,
- ExternalType t,
- expression_node_ptr& node,
- expression_node_ptr& result)
- {
- SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
- if (n)
- {
- T0 t0 = n->t0();
- T1 t1 = n->t1();
- T2 t2 = n->t2();
- return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
- (expr_gen, id, t0, t1, t2, t, result);
- }
- else
- return false;
- }
- };
- struct synthesize_vovov_expression0
- {
- typedef typename vovov_t::type0 node_type;
- typedef typename vovov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 v1) o1 (v2)
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
- const Type& v0 = vov->v0();
- const Type& v1 = vov->v1();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = vov->operation();
- const details::operator_type o1 = operation;
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
- exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
- (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t";
- }
- };
- struct synthesize_vovov_expression1
- {
- typedef typename vovov_t::type1 node_type;
- typedef typename vovov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0) o0 (v1 o1 v2)
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vov->v0();
- const Type& v2 = vov->v1();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = vov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
- exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
- (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)";
- }
- };
- struct synthesize_vovoc_expression0
- {
- typedef typename vovoc_t::type0 node_type;
- typedef typename vovoc_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 v1) o1 (c)
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
- const Type& v0 = vov->v0();
- const Type& v1 = vov->v1();
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = vov->operation();
- const details::operator_type o1 = operation;
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
- exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
- (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t";
- }
- };
- struct synthesize_vovoc_expression1
- {
- typedef typename vovoc_t::type1 node_type;
- typedef typename vovoc_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0) o0 (v1 o1 c)
- const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = voc->v();
- const Type c = voc->c();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = voc->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
- exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
- (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)";
- }
- };
- struct synthesize_vocov_expression0
- {
- typedef typename vocov_t::type0 node_type;
- typedef typename vocov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 c) o1 (v1)
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
- const Type& v0 = voc->v();
- const Type c = voc->c();
- const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = voc->operation();
- const details::operator_type o1 = operation;
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
- exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
- (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t";
- }
- };
- struct synthesize_vocov_expression1
- {
- typedef typename vocov_t::type1 node_type;
- typedef typename vocov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0) o0 (c o1 v1)
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type c = cov->c();
- const Type& v1 = cov->v();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = cov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
- exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
- (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)";
- }
- };
- struct synthesize_covov_expression0
- {
- typedef typename covov_t::type0 node_type;
- typedef typename covov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c o0 v0) o1 (v1)
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
- const Type c = cov->c();
- const Type& v0 = cov->v();
- const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = cov->operation();
- const details::operator_type o1 = operation;
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c / v0) / v1 --> (covov) c / (v0 * v1)
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
- exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
- (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t";
- }
- };
- struct synthesize_covov_expression1
- {
- typedef typename covov_t::type1 node_type;
- typedef typename covov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c) o0 (v0 o1 v1)
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vov->v0();
- const Type& v1 = vov->v1();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = vov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // c / (v0 / v1) --> (covov) (c * v1) / v0
- if ((details::e_div == o0) && (details::e_div == o1))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
- exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
- (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)";
- }
- };
- struct synthesize_covoc_expression0
- {
- typedef typename covoc_t::type0 node_type;
- typedef typename covoc_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c0 o0 v) o1 (c1)
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
- const Type c0 = cov->c();
- const Type& v = cov->v();
- const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = cov->operation();
- const details::operator_type o1 = operation;
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c0 + v) + c1 --> (cov) (c0 + c1) + v
- if ((details::e_add == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
- }
- // (c0 + v) - c1 --> (cov) (c0 - c1) + v
- else if ((details::e_add == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
- }
- // (c0 - v) + c1 --> (cov) (c0 + c1) - v
- else if ((details::e_sub == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
- }
- // (c0 - v) - c1 --> (cov) (c0 - c1) - v
- else if ((details::e_sub == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
- }
- // (c0 * v) * c1 --> (cov) (c0 * c1) * v
- else if ((details::e_mul == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
- }
- // (c0 * v) / c1 --> (cov) (c0 / c1) * v
- else if ((details::e_mul == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
- }
- // (c0 / v) * c1 --> (cov) (c0 * c1) / v
- else if ((details::e_div == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
- }
- // (c0 / v) / c1 --> (cov) (c0 / c1) / v
- else if ((details::e_div == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
- (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t";
- }
- };
- struct synthesize_covoc_expression1
- {
- typedef typename covoc_t::type1 node_type;
- typedef typename covoc_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c0) o0 (v o1 c1)
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
- const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v = voc->v();
- const Type c1 = voc->c();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = voc->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c0) + (v + c1) --> (cov) (c0 + c1) + v
- if ((details::e_add == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
- }
- // (c0) + (v - c1) --> (cov) (c0 - c1) + v
- else if ((details::e_add == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
- }
- // (c0) - (v + c1) --> (cov) (c0 - c1) - v
- else if ((details::e_sub == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
- }
- // (c0) - (v - c1) --> (cov) (c0 + c1) - v
- else if ((details::e_sub == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
- }
- // (c0) * (v * c1) --> (voc) v * (c0 * c1)
- else if ((details::e_mul == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
- }
- // (c0) * (v / c1) --> (cov) (c0 / c1) * v
- else if ((details::e_mul == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
- }
- // (c0) / (v * c1) --> (cov) (c0 / c1) / v
- else if ((details::e_div == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
- }
- // (c0) / (v / c1) --> (cov) (c0 * c1) / v
- else if ((details::e_div == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
- (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)";
- }
- };
- struct synthesize_cocov_expression0
- {
- typedef typename cocov_t::type0 node_type;
- static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
- {
- // (c0 o0 c1) o1 (v) - Not possible.
- return error_node();
- }
- };
- struct synthesize_cocov_expression1
- {
- typedef typename cocov_t::type1 node_type;
- typedef typename cocov_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c0) o0 (c1 o1 v)
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
- const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type c1 = cov->c();
- const Type& v = cov->v();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = cov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
- if ((details::e_add == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
- }
- // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
- else if ((details::e_add == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
- }
- // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
- else if ((details::e_sub == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
- }
- // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
- else if ((details::e_sub == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
- }
- // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
- else if ((details::e_mul == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
- }
- // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
- else if ((details::e_mul == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
- }
- // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
- else if ((details::e_div == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
- }
- // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
- else if ((details::e_div == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
- return expr_gen.node_allocator_->
- template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
- (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)";
- }
- };
- struct synthesize_vococ_expression0
- {
- typedef typename vococ_t::type0 node_type;
- typedef typename vococ_t::sf3_type sf3_type;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v o0 c0) o1 (c1)
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
- const Type& v = voc->v();
- const Type& c0 = voc->c();
- const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = voc->operation();
- const details::operator_type o1 = operation;
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v + c0) + c1 --> (voc) v + (c0 + c1)
- if ((details::e_add == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
- }
- // (v + c0) - c1 --> (voc) v + (c0 - c1)
- else if ((details::e_add == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
- }
- // (v - c0) + c1 --> (voc) v - (c0 + c1)
- else if ((details::e_sub == o0) && (details::e_add == o1))
- {
- exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
- }
- // (v - c0) - c1 --> (voc) v - (c0 + c1)
- else if ((details::e_sub == o0) && (details::e_sub == o1))
- {
- exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
- }
- // (v * c0) * c1 --> (voc) v * (c0 * c1)
- else if ((details::e_mul == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
- }
- // (v * c0) / c1 --> (voc) v * (c0 / c1)
- else if ((details::e_mul == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
- }
- // (v / c0) * c1 --> (voc) v * (c1 / c0)
- else if ((details::e_div == o0) && (details::e_mul == o1))
- {
- exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
- }
- // (v / c0) / c1 --> (voc) v / (c0 * c1)
- else if ((details::e_div == o0) && (details::e_div == o1))
- {
- exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
- }
- // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
- else if ((details::e_pow == o0) && (details::e_pow == o1))
- {
- exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
- return expr_gen.node_allocator_->
- template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
- }
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
- (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0, const details::operator_type o1)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t";
- }
- };
- struct synthesize_vococ_expression1
- {
- typedef typename vococ_t::type0 node_type;
- static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
- {
- // (v) o0 (c0 o1 c1) - Not possible.
- exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
- return error_node();
- }
- };
- struct synthesize_vovovov_expression0
- {
- typedef typename vovovov_t::type0 node_type;
- typedef typename vovovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 v1) o1 (v2 o2 v3)
- const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
- const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
- const Type& v0 = vov0->v0();
- const Type& v1 = vov0->v1();
- const Type& v2 = vov1->v0();
- const Type& v3 = vov1->v1();
- const details::operator_type o0 = vov0->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = vov1->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
- if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
- exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
- exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
- else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
- exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
- else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
- exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
- exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vovovoc_expression0
- {
- typedef typename vovovoc_t::type0 node_type;
- typedef typename vovovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 v1) o1 (v2 o2 c)
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
- const Type& v0 = vov->v0();
- const Type& v1 = vov->v1();
- const Type& v2 = voc->v ();
- const Type c = voc->c ();
- const details::operator_type o0 = vov->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = voc->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
- if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
- exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
- if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
- exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vovocov_expression0
- {
- typedef typename vovocov_t::type0 node_type;
- typedef typename vovocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 v1) o1 (c o2 v2)
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
- const Type& v0 = vov->v0();
- const Type& v1 = vov->v1();
- const Type& v2 = cov->v ();
- const Type c = cov->c ();
- const details::operator_type o0 = vov->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = cov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
- if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
- exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
- if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
- exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vocovov_expression0
- {
- typedef typename vocovov_t::type0 node_type;
- typedef typename vocovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 c) o1 (v1 o2 v2)
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
- const Type c = voc->c ();
- const Type& v0 = voc->v ();
- const Type& v1 = vov->v0();
- const Type& v2 = vov->v1();
- const details::operator_type o0 = voc->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = vov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
- if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
- exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
- if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
- exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_covovov_expression0
- {
- typedef typename covovov_t::type0 node_type;
- typedef typename covovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c o0 v0) o1 (v1 o2 v2)
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
- const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
- const Type c = cov->c ();
- const Type& v0 = cov->v ();
- const Type& v1 = vov->v0();
- const Type& v2 = vov->v1();
- const details::operator_type o0 = cov->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = vov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
- if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
- exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
- if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
- exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_covocov_expression0
- {
- typedef typename covocov_t::type0 node_type;
- typedef typename covocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c0 o0 v0) o1 (c1 o2 v1)
- const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
- const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
- const Type c0 = cov0->c();
- const Type& v0 = cov0->v();
- const Type c1 = cov1->c();
- const Type& v1 = cov1->v();
- const details::operator_type o0 = cov0->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = cov1->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
- if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
- exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
- else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
- exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
- else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
- exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
- else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
- exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
- exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
- else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
- exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
- exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
- exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
- exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
- else if (
- (std::equal_to<T>()(c0,c1)) &&
- (details::e_mul == o0) &&
- (details::e_mul == o2) &&
- (
- (details::e_add == o1) ||
- (details::e_sub == o1)
- )
- )
- {
- std::string specfunc;
- switch (o1)
- {
- case details::e_add : specfunc = "t*(t+t)"; break;
- case details::e_sub : specfunc = "t*(t-t)"; break;
- default : return error_node();
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
- exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vocovoc_expression0
- {
- typedef typename vocovoc_t::type0 node_type;
- typedef typename vocovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 c0) o1 (v1 o2 c1)
- const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
- const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
- const Type c0 = voc0->c();
- const Type& v0 = voc0->v();
- const Type c1 = voc1->c();
- const Type& v1 = voc1->v();
- const details::operator_type o0 = voc0->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = voc1->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
- if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
- exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
- else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
- exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
- else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
- exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
- else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
- exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
- exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
- else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
- exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
- exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
- exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
- exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
- else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
- exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
- else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
- {
- const bool synthesis_result =
- synthesize_sf4ext_expression::
- template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
- exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
- else if (
- (std::equal_to<T>()(c0,c1)) &&
- (details::e_mul == o0) &&
- (details::e_mul == o2) &&
- (
- (details::e_add == o1) ||
- (details::e_sub == o1)
- )
- )
- {
- std::string specfunc;
- switch (o1)
- {
- case details::e_add : specfunc = "t*(t+t)"; break;
- case details::e_sub : specfunc = "t*(t-t)"; break;
- default : return error_node();
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
- exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
- else if (
- (std::equal_to<T>()(c0,c1)) &&
- (details::e_div == o0) &&
- (details::e_div == o2) &&
- (
- (details::e_add == o1) ||
- (details::e_sub == o1)
- )
- )
- {
- std::string specfunc;
- switch (o1)
- {
- case details::e_add : specfunc = "(t+t)/t"; break;
- case details::e_sub : specfunc = "(t-t)/t"; break;
- default : return error_node();
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
- exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_covovoc_expression0
- {
- typedef typename covovoc_t::type0 node_type;
- typedef typename covovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (c0 o0 v0) o1 (v1 o2 c1)
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
- const Type c0 = cov->c();
- const Type& v0 = cov->v();
- const Type c1 = voc->c();
- const Type& v1 = voc->v();
- const details::operator_type o0 = cov->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = voc->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
- if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
- exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
- else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
- exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
- else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
- exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
- else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
- exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
- exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
- else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
- exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
- exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
- exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
- exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
- else if (
- (std::equal_to<T>()(c0,c1)) &&
- (details::e_mul == o0) &&
- (details::e_mul == o2) &&
- (
- (details::e_add == o1) ||
- (details::e_sub == o1)
- )
- )
- {
- std::string specfunc;
- switch (o1)
- {
- case details::e_add : specfunc = "t*(t+t)"; break;
- case details::e_sub : specfunc = "t*(t-t)"; break;
- default : return error_node();
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
- exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vococov_expression0
- {
- typedef typename vococov_t::type0 node_type;
- typedef typename vococov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 c0) o1 (c1 o2 v1)
- const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
- const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
- const Type c0 = voc->c();
- const Type& v0 = voc->v();
- const Type c1 = cov->c();
- const Type& v1 = cov->v();
- const details::operator_type o0 = voc->operation();
- const details::operator_type o1 = operation;
- const details::operator_type o2 = cov->operation();
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (expr_gen.parser_->settings_.strength_reduction_enabled())
- {
- // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
- if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
- exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
- else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
- exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
- else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
- exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
- else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
- exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
- exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
- else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
- exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
- else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
- exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
- exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
- else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
- {
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
- exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
- return (synthesis_result) ? result : error_node();
- }
- // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
- else if (
- (std::equal_to<T>()(c0,c1)) &&
- (details::e_mul == o0) &&
- (details::e_mul == o2) &&
- (
- (details::e_add == o1) || (details::e_sub == o1)
- )
- )
- {
- std::string specfunc;
- switch (o1)
- {
- case details::e_add : specfunc = "t*(t+t)"; break;
- case details::e_sub : specfunc = "t*(t-t)"; break;
- default : return error_node();
- }
- const bool synthesis_result =
- synthesize_sf3ext_expression::
- template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
- exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
- return (synthesis_result) ? result : error_node();
- }
- }
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- else if (!expr_gen.valid_operator(o1,f1))
- return error_node();
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- else
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vovovov_expression1
- {
- typedef typename vovovov_t::type1 node_type;
- typedef typename vovovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 (v1 o1 (v2 o2 v3))
- typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vovov->t0();
- const Type& v2 = vovov->t1();
- const Type& v3 = vovov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovov->f0();
- binary_functor_t f2 = vovov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_vovovoc_expression1
- {
- typedef typename vovovoc_t::type1 node_type;
- typedef typename vovovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 (v1 o1 (v2 o2 c))
- typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
- const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vovoc->t0();
- const Type& v2 = vovoc->t1();
- const Type c = vovoc->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovoc->f0();
- binary_functor_t f2 = vovoc->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_vovocov_expression1
- {
- typedef typename vovocov_t::type1 node_type;
- typedef typename vovocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 (v1 o1 (c o2 v2))
- typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vocov->t0();
- const Type c = vocov->t1();
- const Type& v2 = vocov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vocov->f0();
- binary_functor_t f2 = vocov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
- if (synthesis_result)
- return result;
- if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_vocovov_expression1
- {
- typedef typename vocovov_t::type1 node_type;
- typedef typename vocovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 (c o1 (v1 o2 v2))
- typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
- const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type c = covov->t0();
- const Type& v1 = covov->t1();
- const Type& v2 = covov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(covov->f0());
- const details::operator_type o2 = expr_gen.get_operator(covov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = covov->f0();
- binary_functor_t f2 = covov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_covovov_expression1
- {
- typedef typename covovov_t::type1 node_type;
- typedef typename covovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // c o0 (v0 o1 (v1 o2 v2))
- typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vovov->t0();
- const Type& v1 = vovov->t1();
- const Type& v2 = vovov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovov->f0();
- binary_functor_t f2 = vovov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
- if (synthesis_result)
- return result;
- if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_covocov_expression1
- {
- typedef typename covocov_t::type1 node_type;
- typedef typename covocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // c0 o0 (v0 o1 (c1 o2 v1))
- typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
- const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vocov->t0();
- const Type c1 = vocov->t1();
- const Type& v1 = vocov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vocov->f0();
- binary_functor_t f2 = vocov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_vocovoc_expression1
- {
- typedef typename vocovoc_t::type1 node_type;
- typedef typename vocovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 (c0 o1 (v1 o2 c2))
- typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
- const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type c0 = covoc->t0();
- const Type& v1 = covoc->t1();
- const Type c1 = covoc->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
- const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = covoc->f0();
- binary_functor_t f2 = covoc->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_covovoc_expression1
- {
- typedef typename covovoc_t::type1 node_type;
- typedef typename covovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // c0 o0 (v0 o1 (v1 o2 c1))
- typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
- const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
- const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vovoc->t0();
- const Type& v1 = vovoc->t1();
- const Type c1 = vovoc->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovoc->f0();
- binary_functor_t f2 = vovoc->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_vococov_expression1
- {
- typedef typename vococov_t::type1 node_type;
- typedef typename vococov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 (c0 o1 (c1 o2 v1))
- typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
- const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type c0 = cocov->t0();
- const Type c1 = cocov->t1();
- const Type& v1 = cocov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
- const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = cocov->f0();
- binary_functor_t f2 = cocov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "(t" << expr_gen.to_str(o2)
- << "t))";
- }
- };
- struct synthesize_vovovov_expression2
- {
- typedef typename vovovov_t::type2 node_type;
- typedef typename vovovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 ((v1 o1 v2) o2 v3)
- typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vovov->t0();
- const Type& v2 = vovov->t1();
- const Type& v3 = vovov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovov->f0();
- binary_functor_t f2 = vovov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vovovoc_expression2
- {
- typedef typename vovovoc_t::type2 node_type;
- typedef typename vovovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 ((v1 o1 v2) o2 c)
- typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
- const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vovoc->t0();
- const Type& v2 = vovoc->t1();
- const Type c = vovoc->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovoc->f0();
- binary_functor_t f2 = vovoc->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vovocov_expression2
- {
- typedef typename vovocov_t::type2 node_type;
- typedef typename vovocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 ((v1 o1 c) o2 v2)
- typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type& v1 = vocov->t0();
- const Type c = vocov->t1();
- const Type& v2 = vocov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vocov->f0();
- binary_functor_t f2 = vocov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vocovov_expression2
- {
- typedef typename vocovov_t::type2 node_type;
- typedef typename vocovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 ((c o1 v1) o2 v2)
- typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
- const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type c = covov->t0();
- const Type& v1 = covov->t1();
- const Type& v2 = covov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(covov->f0());
- const details::operator_type o2 = expr_gen.get_operator(covov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = covov->f0();
- binary_functor_t f2 = covov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_covovov_expression2
- {
- typedef typename covovov_t::type2 node_type;
- typedef typename covovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // c o0 ((v1 o1 v2) o2 v3)
- typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
- const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vovov->t0();
- const Type& v1 = vovov->t1();
- const Type& v2 = vovov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovov->f0();
- binary_functor_t f2 = vovov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_covocov_expression2
- {
- typedef typename covocov_t::type2 node_type;
- typedef typename covocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // c0 o0 ((v0 o1 c1) o2 v1)
- typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
- const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vocov->t0();
- const Type c1 = vocov->t1();
- const Type& v1 = vocov->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vocov->f0();
- binary_functor_t f2 = vocov->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vocovoc_expression2
- {
- typedef typename vocovoc_t::type2 node_type;
- typedef typename vocovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // v0 o0 ((c0 o1 v1) o2 c1)
- typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
- const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
- const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
- const Type c0 = covoc->t0();
- const Type& v1 = covoc->t1();
- const Type c1 = covoc->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
- const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = covoc->f0();
- binary_functor_t f2 = covoc->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_covovoc_expression2
- {
- typedef typename covovoc_t::type2 node_type;
- typedef typename covovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // c0 o0 ((v0 o1 v1) o2 c1)
- typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
- const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
- const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
- const Type& v0 = vovoc->t0();
- const Type& v1 = vovoc->t1();
- const Type c1 = vovoc->t2();
- const details::operator_type o0 = operation;
- const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
- const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
- binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
- binary_functor_t f1 = vovoc->f0();
- binary_functor_t f2 = vovoc->f1();
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o0,f0))
- return error_node();
- exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "t" << expr_gen.to_str(o0)
- << "((t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t)";
- }
- };
- struct synthesize_vococov_expression2
- {
- typedef typename vococov_t::type2 node_type;
- static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
- {
- // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
- exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
- return error_node();
- }
- static inline std::string id(expression_generator<Type>&,
- const details::operator_type, const details::operator_type, const details::operator_type)
- {
- return "INVALID";
- }
- };
- struct synthesize_vovovov_expression3
- {
- typedef typename vovovov_t::type3 node_type;
- typedef typename vovovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 v1) o1 v2) o2 v3
- typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
- const Type& v0 = vovov->t0();
- const Type& v1 = vovov->t1();
- const Type& v2 = vovov->t2();
- const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vovov->f0();
- binary_functor_t f1 = vovov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vovovoc_expression3
- {
- typedef typename vovovoc_t::type3 node_type;
- typedef typename vovovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 v1) o1 v2) o2 c
- typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
- const Type& v0 = vovov->t0();
- const Type& v1 = vovov->t1();
- const Type& v2 = vovov->t2();
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vovov->f0();
- binary_functor_t f1 = vovov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vovocov_expression3
- {
- typedef typename vovocov_t::type3 node_type;
- typedef typename vovocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 v1) o1 c) o2 v2
- typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
- const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
- const Type& v0 = vovoc->t0();
- const Type& v1 = vovoc->t1();
- const Type c = vovoc->t2();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
- const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vovoc->f0();
- binary_functor_t f1 = vovoc->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vocovov_expression3
- {
- typedef typename vocovov_t::type3 node_type;
- typedef typename vocovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 c) o1 v1) o2 v2
- typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
- const Type& v0 = vocov->t0();
- const Type c = vocov->t1();
- const Type& v1 = vocov->t2();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vocov->f0();
- binary_functor_t f1 = vocov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_covovov_expression3
- {
- typedef typename covovov_t::type3 node_type;
- typedef typename covovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((c o0 v0) o1 v1) o2 v2
- typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
- const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
- const Type c = covov->t0();
- const Type& v0 = covov->t1();
- const Type& v1 = covov->t2();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(covov->f0());
- const details::operator_type o1 = expr_gen.get_operator(covov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = covov->f0();
- binary_functor_t f1 = covov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_covocov_expression3
- {
- typedef typename covocov_t::type3 node_type;
- typedef typename covocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((c0 o0 v0) o1 c1) o2 v1
- typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
- const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
- const Type c0 = covoc->t0();
- const Type& v0 = covoc->t1();
- const Type c1 = covoc->t2();
- const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
- const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = covoc->f0();
- binary_functor_t f1 = covoc->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vocovoc_expression3
- {
- typedef typename vocovoc_t::type3 node_type;
- typedef typename vocovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 c0) o1 v1) o2 c1
- typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
- const Type& v0 = vocov->t0();
- const Type c0 = vocov->t1();
- const Type& v1 = vocov->t2();
- const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vocov->f0();
- binary_functor_t f1 = vocov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_covovoc_expression3
- {
- typedef typename covovoc_t::type3 node_type;
- typedef typename covovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((c0 o0 v0) o1 v1) o2 c1
- typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
- const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
- const Type c0 = covov->t0();
- const Type& v0 = covov->t1();
- const Type& v1 = covov->t2();
- const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = expr_gen.get_operator(covov->f0());
- const details::operator_type o1 = expr_gen.get_operator(covov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = covov->f0();
- binary_functor_t f1 = covov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vococov_expression3
- {
- typedef typename vococov_t::type3 node_type;
- typedef typename vococov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 c0) o1 c1) o2 v1
- typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
- const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
- const Type& v0 = vococ->t0();
- const Type c0 = vococ->t1();
- const Type c1 = vococ->t2();
- const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
- const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vococ->f0();
- binary_functor_t f1 = vococ->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "((t" << expr_gen.to_str(o0)
- << "t)" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vovovov_expression4
- {
- typedef typename vovovov_t::type4 node_type;
- typedef typename vovovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // (v0 o0 (v1 o1 v2)) o2 v3
- typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
- const Type& v0 = vovov->t0();
- const Type& v1 = vovov->t1();
- const Type& v2 = vovov->t2();
- const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vovov->f0();
- binary_functor_t f1 = vovov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vovovoc_expression4
- {
- typedef typename vovovoc_t::type4 node_type;
- typedef typename vovovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 (v1 o1 v2)) o2 c)
- typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
- const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
- const Type& v0 = vovov->t0();
- const Type& v1 = vovov->t1();
- const Type& v2 = vovov->t2();
- const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vovov->f0();
- binary_functor_t f1 = vovov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vovocov_expression4
- {
- typedef typename vovocov_t::type4 node_type;
- typedef typename vovocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 (v1 o1 c)) o2 v1)
- typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
- const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
- const Type& v0 = vovoc->t0();
- const Type& v1 = vovoc->t1();
- const Type c = vovoc->t2();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
- const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vovoc->f0();
- binary_functor_t f1 = vovoc->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vocovov_expression4
- {
- typedef typename vocovov_t::type4 node_type;
- typedef typename vocovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 (c o1 v1)) o2 v2)
- typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
- const Type& v0 = vocov->t0();
- const Type c = vocov->t1();
- const Type& v1 = vocov->t2();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vocov->f0();
- binary_functor_t f1 = vocov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_covovov_expression4
- {
- typedef typename covovov_t::type4 node_type;
- typedef typename covovov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((c o0 (v0 o1 v1)) o2 v2)
- typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
- const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
- const Type c = covov->t0();
- const Type& v0 = covov->t1();
- const Type& v1 = covov->t2();
- const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(covov->f0());
- const details::operator_type o1 = expr_gen.get_operator(covov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = covov->f0();
- binary_functor_t f1 = covov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_covocov_expression4
- {
- typedef typename covocov_t::type4 node_type;
- typedef typename covocov_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((c0 o0 (v0 o1 c1)) o2 v1)
- typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
- const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
- const Type c0 = covoc->t0();
- const Type& v0 = covoc->t1();
- const Type c1 = covoc->t2();
- const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
- const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
- const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = covoc->f0();
- binary_functor_t f1 = covoc->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vocovoc_expression4
- {
- typedef typename vocovoc_t::type4 node_type;
- typedef typename vocovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((v0 o0 (c0 o1 v1)) o2 c1)
- typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
- const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
- const Type& v0 = vocov->t0();
- const Type c0 = vocov->t1();
- const Type& v1 = vocov->t2();
- const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
- const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = vocov->f0();
- binary_functor_t f1 = vocov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_covovoc_expression4
- {
- typedef typename covovoc_t::type4 node_type;
- typedef typename covovoc_t::sf4_type sf4_type;
- typedef typename node_type::T0 T0;
- typedef typename node_type::T1 T1;
- typedef typename node_type::T2 T2;
- typedef typename node_type::T3 T3;
- static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
- const details::operator_type& operation,
- expression_node_ptr (&branch)[2])
- {
- // ((c0 o0 (v0 o1 v1)) o2 c1)
- typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
- const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
- const Type c0 = covov->t0();
- const Type& v0 = covov->t1();
- const Type& v1 = covov->t2();
- const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
- const details::operator_type o0 = expr_gen.get_operator(covov->f0());
- const details::operator_type o1 = expr_gen.get_operator(covov->f1());
- const details::operator_type o2 = operation;
- binary_functor_t f0 = covov->f0();
- binary_functor_t f1 = covov->f1();
- binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
- details::free_node(*(expr_gen.node_allocator_),branch[0]);
- details::free_node(*(expr_gen.node_allocator_),branch[1]);
- expression_node_ptr result = error_node();
- const bool synthesis_result =
- synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
- (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
- if (synthesis_result)
- return result;
- else if (!expr_gen.valid_operator(o2,f2))
- return error_node();
- exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
- return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
- }
- static inline std::string id(expression_generator<Type>& expr_gen,
- const details::operator_type o0,
- const details::operator_type o1,
- const details::operator_type o2)
- {
- return details::build_string()
- << "(t" << expr_gen.to_str(o0)
- << "(t" << expr_gen.to_str(o1)
- << "t)" << expr_gen.to_str(o2)
- << "t";
- }
- };
- struct synthesize_vococov_expression4
- {
- typedef typename vococov_t::type4 node_type;
- static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
- {
- // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
- exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
- return error_node();
- }
- static inline std::string id(expression_generator<Type>&,
- const details::operator_type, const details::operator_type, const details::operator_type)
- {
- return "INVALID";
- }
- };
- #endif
- inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
- {
- // Definition: uv o uv
- details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
- details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
- const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
- const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
- unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
- unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
- binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
- if (!valid_operator(o0,u0))
- return error_node();
- else if (!valid_operator(o1,u1))
- return error_node();
- else if (!valid_operator(operation,f))
- return error_node();
- expression_node_ptr result = error_node();
- if (
- (details::e_neg == o0) &&
- (details::e_neg == o1)
- )
- {
- switch (operation)
- {
- // (-v0 + -v1) --> -(v0 + v1)
- case details::e_add : result = (*this)(details::e_neg,
- node_allocator_->
- allocate_rr<typename details::
- vov_node<Type,details::add_op<Type> > >(v0, v1));
- exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
- break;
- // (-v0 - -v1) --> (v1 - v0)
- case details::e_sub : result = node_allocator_->
- allocate_rr<typename details::
- vov_node<Type,details::sub_op<Type> > >(v1, v0);
- exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
- break;
- // (-v0 * -v1) --> (v0 * v1)
- case details::e_mul : result = node_allocator_->
- allocate_rr<typename details::
- vov_node<Type,details::mul_op<Type> > >(v0, v1);
- exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
- break;
- // (-v0 / -v1) --> (v0 / v1)
- case details::e_div : result = node_allocator_->
- allocate_rr<typename details::
- vov_node<Type,details::div_op<Type> > >(v0, v1);
- exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
- break;
- default : break;
- }
- }
- if (0 == result)
- {
- result = node_allocator_->
- allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
- }
- details::free_all_nodes(*node_allocator_,branch);
- return result;
- }
- #undef basic_opr_switch_statements
- #undef extended_opr_switch_statements
- #undef unary_opr_switch_statements
- #ifndef exprtk_disable_string_capabilities
- #define string_opr_switch_statements \
- case_stmt(details:: e_lt ,details:: lt_op) \
- case_stmt(details:: e_lte ,details:: lte_op) \
- case_stmt(details:: e_gt ,details:: gt_op) \
- case_stmt(details:: e_gte ,details:: gte_op) \
- case_stmt(details:: e_eq ,details:: eq_op) \
- case_stmt(details:: e_ne ,details:: ne_op) \
- case_stmt(details::e_in ,details:: in_op) \
- case_stmt(details::e_like ,details:: like_op) \
- case_stmt(details::e_ilike,details::ilike_op) \
- template <typename T0, typename T1>
- inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
- T0 s0, T1 s1,
- range_t rp0)
- {
- switch (opr)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
- (s0, s1, rp0); \
- string_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- template <typename T0, typename T1>
- inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
- T0 s0, T1 s1,
- range_t rp1)
- {
- switch (opr)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
- (s0, s1, rp1); \
- string_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- template <typename T0, typename T1>
- inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
- T0 s0, T1 s1,
- range_t rp0, range_t rp1)
- {
- switch (opr)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
- (s0, s1, rp0, rp1); \
- string_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- template <typename T0, typename T1>
- inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
- {
- switch (opr)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
- string_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
- std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
- return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
- }
- inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
- std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
- range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
- static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
- free_node(*node_allocator_,branch[0]);
- return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
- }
- inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
- std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
- range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
- static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
- free_node(*node_allocator_,branch[1]);
- return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
- }
- inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
- std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
- range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
- static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
- free_node(*node_allocator_,branch[1]);
- return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
- }
- inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
- std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
- range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
- range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
- static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
- static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
- details::free_node(*node_allocator_,branch[0]);
- details::free_node(*node_allocator_,branch[1]);
- return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
- }
- inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
- std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
- details::free_node(*node_allocator_,branch[1]);
- return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
- }
- inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
- std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
- details::free_node(*node_allocator_,branch[0]);
- return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
- }
- inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str ();
- std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
- range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
- static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
- details::free_node(*node_allocator_,branch[0]);
- details::free_node(*node_allocator_,branch[1]);
- return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
- }
- inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
- std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str ();
- range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
- static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
- details::free_node(*node_allocator_,branch[0]);
- details::free_node(*node_allocator_,branch[1]);
- return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
- }
- inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
- std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
- range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
- range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
- static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear();
- static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
- details::free_node(*node_allocator_,branch[0]);
- details::free_node(*node_allocator_,branch[1]);
- return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
- }
- inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
- const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
- expression_node_ptr result = error_node();
- if (details::e_add == opr)
- result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
- else if (details::e_in == opr)
- result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1));
- else if (details::e_like == opr)
- result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
- else if (details::e_ilike == opr)
- result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
- else
- {
- expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
- const Type v = temp->value();
- details::free_node(*node_allocator_,temp);
- result = node_allocator_->allocate<literal_node_t>(v);
- }
- details::free_all_nodes(*node_allocator_,branch);
- return result;
- }
- inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str ();
- std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
- range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
- static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
- free_node(*node_allocator_,branch[0]);
- free_node(*node_allocator_,branch[1]);
- return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
- }
- inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
- std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
- range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
- static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
- free_node(*node_allocator_,branch[0]);
- return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
- }
- inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
- std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
- const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
- const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
- static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
- static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear();
- free_node(*node_allocator_,branch[0]);
- free_node(*node_allocator_,branch[1]);
- return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
- }
- inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
- const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str ();
- const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
- static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
- details::free_all_nodes(*node_allocator_,branch);
- return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
- }
- inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
- const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
- const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
- const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
- static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
- static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
- details::free_all_nodes(*node_allocator_,branch);
- return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
- }
- inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- switch (opr)
- {
- #define case_stmt(op0,op1) \
- case op0 : return node_allocator_-> \
- allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \
- (opr, branch[0], branch[1]); \
- string_opr_switch_statements
- #undef case_stmt
- default : return error_node();
- }
- }
- #endif
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
- {
- if ((0 == branch[0]) || (0 == branch[1]))
- {
- details::free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- const bool b0_is_s = details::is_string_node (branch[0]);
- const bool b0_is_cs = details::is_const_string_node (branch[0]);
- const bool b0_is_sr = details::is_string_range_node (branch[0]);
- const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
- const bool b1_is_s = details::is_string_node (branch[1]);
- const bool b1_is_cs = details::is_const_string_node (branch[1]);
- const bool b1_is_sr = details::is_string_range_node (branch[1]);
- const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
- const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
- details::is_genricstring_range_node(branch[0]) ||
- details::is_string_concat_node (branch[0]) ||
- details::is_string_function_node (branch[0]) ||
- details::is_string_condition_node (branch[0]) ||
- details::is_string_ccondition_node (branch[0]) ||
- details::is_string_vararg_node (branch[0]) ;
- const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
- details::is_genricstring_range_node(branch[1]) ||
- details::is_string_concat_node (branch[1]) ||
- details::is_string_function_node (branch[1]) ||
- details::is_string_condition_node (branch[1]) ||
- details::is_string_ccondition_node (branch[1]) ||
- details::is_string_vararg_node (branch[1]) ;
- if (details::e_add == opr)
- {
- if (!b0_is_cs || !b1_is_cs)
- {
- return synthesize_expression<string_concat_node_t,2>(opr,branch);
- }
- }
- if (b0_is_gen || b1_is_gen)
- {
- return synthesize_strogen_expression(opr,branch);
- }
- else if (b0_is_s)
- {
- if (b1_is_s ) return synthesize_sos_expression (opr,branch);
- else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
- else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
- else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
- }
- else if (b0_is_cs)
- {
- if (b1_is_s ) return synthesize_csos_expression (opr,branch);
- else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
- else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
- else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
- }
- else if (b0_is_sr)
- {
- if (b1_is_s ) return synthesize_sros_expression (opr,branch);
- else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
- else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
- else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
- }
- else if (b0_is_csr)
- {
- if (b1_is_s ) return synthesize_csros_expression (opr,branch);
- else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
- else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
- else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
- }
- return error_node();
- }
- #else
- inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
- {
- details::free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- #endif
- #ifndef exprtk_disable_string_capabilities
- inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
- {
- if (details::e_inrange != opr)
- return error_node();
- else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
- {
- details::free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- else if (
- details::is_const_string_node(branch[0]) &&
- details::is_const_string_node(branch[1]) &&
- details::is_const_string_node(branch[2])
- )
- {
- const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
- const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
- const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
- const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
- details::free_all_nodes(*node_allocator_,branch);
- return node_allocator_->allocate_c<details::literal_node<Type> >(v);
- }
- else if (
- details::is_string_node(branch[0]) &&
- details::is_string_node(branch[1]) &&
- details::is_string_node(branch[2])
- )
- {
- std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
- std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
- std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
- typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
- return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
- }
- else if (
- details::is_const_string_node(branch[0]) &&
- details::is_string_node(branch[1]) &&
- details::is_const_string_node(branch[2])
- )
- {
- std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
- std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
- std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
- typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
- details::free_node(*node_allocator_,branch[0]);
- details::free_node(*node_allocator_,branch[2]);
- return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
- }
- else if (
- details::is_string_node(branch[0]) &&
- details::is_const_string_node(branch[1]) &&
- details::is_string_node(branch[2])
- )
- {
- std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
- std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
- std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
- typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
- details::free_node(*node_allocator_,branch[1]);
- return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
- }
- else if (
- details::is_string_node(branch[0]) &&
- details::is_string_node(branch[1]) &&
- details::is_const_string_node(branch[2])
- )
- {
- std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
- std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
- std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
- typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
- details::free_node(*node_allocator_,branch[2]);
- return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
- }
- else if (
- details::is_const_string_node(branch[0]) &&
- details:: is_string_node(branch[1]) &&
- details:: is_string_node(branch[2])
- )
- {
- std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
- std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
- std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
- typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
- details::free_node(*node_allocator_,branch[0]);
- return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
- }
- else
- return error_node();
- }
- #else
- inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
- {
- details::free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- #endif
- inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
- {
- /*
- Note: The following are the type promotion rules
- that relate to operations that include 'null':
- 0. null ==/!= null --> true false
- 1. null operation null --> null
- 2. x ==/!= null --> true/false
- 3. null ==/!= x --> true/false
- 4. x operation null --> x
- 5. null operation x --> x
- */
- typedef typename details::null_eq_node<T> nulleq_node_t;
- const bool b0_null = details::is_null_node(branch[0]);
- const bool b1_null = details::is_null_node(branch[1]);
- if (b0_null && b1_null)
- {
- expression_node_ptr result = error_node();
- if (details::e_eq == operation)
- result = node_allocator_->allocate_c<literal_node_t>(T(1));
- else if (details::e_ne == operation)
- result = node_allocator_->allocate_c<literal_node_t>(T(0));
- if (result)
- {
- details::free_node(*node_allocator_,branch[0]);
- details::free_node(*node_allocator_,branch[1]);
- return result;
- }
- details::free_node(*node_allocator_,branch[1]);
- return branch[0];
- }
- else if (details::e_eq == operation)
- {
- expression_node_ptr result = node_allocator_->
- allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
- details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
- return result;
- }
- else if (details::e_ne == operation)
- {
- expression_node_ptr result = node_allocator_->
- allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
- details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
- return result;
- }
- else if (b0_null)
- {
- details::free_node(*node_allocator_,branch[0]);
- branch[0] = branch[1];
- branch[1] = error_node();
- }
- else if (b1_null)
- {
- details::free_node(*node_allocator_,branch[1]);
- branch[1] = error_node();
- }
- if (
- (details::e_add == operation) || (details::e_sub == operation) ||
- (details::e_mul == operation) || (details::e_div == operation) ||
- (details::e_mod == operation) || (details::e_pow == operation)
- )
- {
- return branch[0];
- }
- else if (
- (details::e_lt == operation) || (details::e_lte == operation) ||
- (details::e_gt == operation) || (details::e_gte == operation) ||
- (details::e_and == operation) || (details::e_nand == operation) ||
- (details::e_or == operation) || (details::e_nor == operation) ||
- (details::e_xor == operation) || (details::e_xnor == operation) ||
- (details::e_in == operation) || (details::e_like == operation) ||
- (details::e_ilike == operation)
- )
- {
- return node_allocator_->allocate_c<literal_node_t>(T(0));
- }
- details::free_node(*node_allocator_,branch[0]);
- return node_allocator_->allocate<details::null_node<Type> >();
- }
- template <typename NodeType, std::size_t N>
- inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
- {
- if (
- (details::e_in == operation) ||
- (details::e_like == operation) ||
- (details::e_ilike == operation)
- )
- {
- free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- else if (!details::all_nodes_valid<N>(branch))
- {
- free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- else if ((details::e_default != operation))
- {
- // Attempt simple constant folding optimisation.
- expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
- if (is_constant_foldable<N>(branch))
- {
- const Type v = expression_point->value();
- details::free_node(*node_allocator_,expression_point);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- else
- return expression_point;
- }
- else
- return error_node();
- }
- template <typename NodeType, std::size_t N>
- inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
- {
- if (!details::all_nodes_valid<N>(branch))
- {
- free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
- // Attempt simple constant folding optimisation.
- expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
- function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
- if (0 == func_node_ptr)
- {
- free_all_nodes(*node_allocator_,branch);
- return error_node();
- }
- else
- func_node_ptr->init_branches(branch);
- if (is_constant_foldable<N>(branch) && !f->has_side_effects())
- {
- Type v = expression_point->value();
- details::free_node(*node_allocator_,expression_point);
- return node_allocator_->allocate<literal_node_t>(v);
- }
- parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
- return expression_point;
- }
- bool strength_reduction_enabled_;
- details::node_allocator* node_allocator_;
- synthesize_map_t synthesize_map_;
- unary_op_map_t* unary_op_map_;
- binary_op_map_t* binary_op_map_;
- inv_binary_op_map_t* inv_binary_op_map_;
- sf3_map_t* sf3_map_;
- sf4_map_t* sf4_map_;
- parser_t* parser_;
- };
- inline void set_error(const parser_error::type& error_type)
- {
- error_list_.push_back(error_type);
- }
- inline void remove_last_error()
- {
- if (!error_list_.empty())
- {
- error_list_.pop_back();
- }
- }
- inline void set_synthesis_error(const std::string& synthesis_error_message)
- {
- if (synthesis_error_.empty())
- {
- synthesis_error_ = synthesis_error_message;
- }
- }
- inline void register_local_vars(expression<T>& e)
- {
- for (std::size_t i = 0; i < sem_.size(); ++i)
- {
- scope_element& se = sem_.get_element(i);
- if (
- (scope_element::e_variable == se.type) ||
- (scope_element::e_vecelem == se.type)
- )
- {
- if (se.var_node)
- {
- e.register_local_var(se.var_node);
- }
- if (se.data)
- {
- e.register_local_data(se.data, 1, 0);
- }
- }
- else if (scope_element::e_vector == se.type)
- {
- if (se.vec_node)
- {
- e.register_local_var(se.vec_node);
- }
- if (se.data)
- {
- e.register_local_data(se.data, se.size, 1);
- }
- }
- #ifndef exprtk_disable_string_capabilities
- else if (scope_element::e_string == se.type)
- {
- if (se.str_node)
- {
- e.register_local_var(se.str_node);
- }
- if (se.data)
- {
- e.register_local_data(se.data, se.size, 2);
- }
- }
- #endif
- se.var_node = 0;
- se.vec_node = 0;
- #ifndef exprtk_disable_string_capabilities
- se.str_node = 0;
- #endif
- se.data = 0;
- se.ref_count = 0;
- se.active = false;
- }
- }
- inline void register_return_results(expression<T>& e)
- {
- e.register_return_results(results_context_);
- results_context_ = 0;
- }
- inline void load_unary_operations_map(unary_op_map_t& m)
- {
- #define register_unary_op(Op,UnaryFunctor) \
- m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
- register_unary_op(details:: e_abs, details:: abs_op)
- register_unary_op(details:: e_acos, details:: acos_op)
- register_unary_op(details::e_acosh, details::acosh_op)
- register_unary_op(details:: e_asin, details:: asin_op)
- register_unary_op(details::e_asinh, details::asinh_op)
- register_unary_op(details::e_atanh, details::atanh_op)
- register_unary_op(details:: e_ceil, details:: ceil_op)
- register_unary_op(details:: e_cos, details:: cos_op)
- register_unary_op(details:: e_cosh, details:: cosh_op)
- register_unary_op(details:: e_exp, details:: exp_op)
- register_unary_op(details::e_expm1, details::expm1_op)
- register_unary_op(details::e_floor, details::floor_op)
- register_unary_op(details:: e_log, details:: log_op)
- register_unary_op(details::e_log10, details::log10_op)
- register_unary_op(details:: e_log2, details:: log2_op)
- register_unary_op(details::e_log1p, details::log1p_op)
- register_unary_op(details:: e_neg, details:: neg_op)
- register_unary_op(details:: e_pos, details:: pos_op)
- register_unary_op(details::e_round, details::round_op)
- register_unary_op(details:: e_sin, details:: sin_op)
- register_unary_op(details:: e_sinc, details:: sinc_op)
- register_unary_op(details:: e_sinh, details:: sinh_op)
- register_unary_op(details:: e_sqrt, details:: sqrt_op)
- register_unary_op(details:: e_tan, details:: tan_op)
- register_unary_op(details:: e_tanh, details:: tanh_op)
- register_unary_op(details:: e_cot, details:: cot_op)
- register_unary_op(details:: e_sec, details:: sec_op)
- register_unary_op(details:: e_csc, details:: csc_op)
- register_unary_op(details:: e_r2d, details:: r2d_op)
- register_unary_op(details:: e_d2r, details:: d2r_op)
- register_unary_op(details:: e_d2g, details:: d2g_op)
- register_unary_op(details:: e_g2d, details:: g2d_op)
- register_unary_op(details:: e_notl, details:: notl_op)
- register_unary_op(details:: e_sgn, details:: sgn_op)
- register_unary_op(details:: e_erf, details:: erf_op)
- register_unary_op(details:: e_erfc, details:: erfc_op)
- register_unary_op(details:: e_ncdf, details:: ncdf_op)
- register_unary_op(details:: e_frac, details:: frac_op)
- register_unary_op(details::e_trunc, details::trunc_op)
- #undef register_unary_op
- }
- inline void load_binary_operations_map(binary_op_map_t& m)
- {
- typedef typename binary_op_map_t::value_type value_type;
- #define register_binary_op(Op,BinaryFunctor) \
- m.insert(value_type(Op,BinaryFunctor<T>::process)); \
- register_binary_op(details:: e_add, details:: add_op)
- register_binary_op(details:: e_sub, details:: sub_op)
- register_binary_op(details:: e_mul, details:: mul_op)
- register_binary_op(details:: e_div, details:: div_op)
- register_binary_op(details:: e_mod, details:: mod_op)
- register_binary_op(details:: e_pow, details:: pow_op)
- register_binary_op(details:: e_lt, details:: lt_op)
- register_binary_op(details:: e_lte, details:: lte_op)
- register_binary_op(details:: e_gt, details:: gt_op)
- register_binary_op(details:: e_gte, details:: gte_op)
- register_binary_op(details:: e_eq, details:: eq_op)
- register_binary_op(details:: e_ne, details:: ne_op)
- register_binary_op(details:: e_and, details:: and_op)
- register_binary_op(details::e_nand, details::nand_op)
- register_binary_op(details:: e_or, details:: or_op)
- register_binary_op(details:: e_nor, details:: nor_op)
- register_binary_op(details:: e_xor, details:: xor_op)
- register_binary_op(details::e_xnor, details::xnor_op)
- #undef register_binary_op
- }
- inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
- {
- typedef typename inv_binary_op_map_t::value_type value_type;
- #define register_binary_op(Op,BinaryFunctor) \
- m.insert(value_type(BinaryFunctor<T>::process,Op)); \
- register_binary_op(details:: e_add, details:: add_op)
- register_binary_op(details:: e_sub, details:: sub_op)
- register_binary_op(details:: e_mul, details:: mul_op)
- register_binary_op(details:: e_div, details:: div_op)
- register_binary_op(details:: e_mod, details:: mod_op)
- register_binary_op(details:: e_pow, details:: pow_op)
- register_binary_op(details:: e_lt, details:: lt_op)
- register_binary_op(details:: e_lte, details:: lte_op)
- register_binary_op(details:: e_gt, details:: gt_op)
- register_binary_op(details:: e_gte, details:: gte_op)
- register_binary_op(details:: e_eq, details:: eq_op)
- register_binary_op(details:: e_ne, details:: ne_op)
- register_binary_op(details:: e_and, details:: and_op)
- register_binary_op(details::e_nand, details::nand_op)
- register_binary_op(details:: e_or, details:: or_op)
- register_binary_op(details:: e_nor, details:: nor_op)
- register_binary_op(details:: e_xor, details:: xor_op)
- register_binary_op(details::e_xnor, details::xnor_op)
- #undef register_binary_op
- }
- inline void load_sf3_map(sf3_map_t& sf3_map)
- {
- typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
- #define register_sf3(Op) \
- sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
- register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
- register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
- register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
- register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
- register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
- register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
- register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
- register_sf3(28) register_sf3(29) register_sf3(30)
- #undef register_sf3
- #define register_sf3_extid(Id, Op) \
- sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
- register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t)
- #undef register_sf3_extid
- }
- inline void load_sf4_map(sf4_map_t& sf4_map)
- {
- typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
- #define register_sf4(Op) \
- sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
- register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
- register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
- register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
- register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
- register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
- register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
- register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
- register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
- register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
- #undef register_sf4
- #define register_sf4ext(Op) \
- sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
- register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
- register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
- register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
- register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
- register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
- register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
- register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
- register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
- register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
- register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
- register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
- register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
- register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
- register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
- register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
- register_sf4ext(60) register_sf4ext(61)
- #undef register_sf4ext
- }
- inline results_context_t& results_ctx()
- {
- if (0 == results_context_)
- {
- results_context_ = new results_context_t();
- }
- return (*results_context_);
- }
- inline void return_cleanup()
- {
- #ifndef exprtk_disable_return_statement
- if (results_context_)
- {
- delete results_context_;
- results_context_ = 0;
- }
- state_.return_stmt_present = false;
- #endif
- }
- private:
- parser(const parser<T>&);
- parser<T>& operator=(const parser<T>&);
- settings_store settings_;
- expression_generator<T> expression_generator_;
- details::node_allocator node_allocator_;
- symtab_store symtab_store_;
- dependent_entity_collector dec_;
- std::deque<parser_error::type> error_list_;
- std::deque<bool> brkcnt_list_;
- parser_state state_;
- bool resolve_unknown_symbol_;
- results_context_t* results_context_;
- unknown_symbol_resolver* unknown_symbol_resolver_;
- unknown_symbol_resolver default_usr_;
- base_ops_map_t base_ops_map_;
- unary_op_map_t unary_op_map_;
- binary_op_map_t binary_op_map_;
- inv_binary_op_map_t inv_binary_op_map_;
- sf3_map_t sf3_map_;
- sf4_map_t sf4_map_;
- std::string synthesis_error_;
- scope_element_manager sem_;
- lexer::helper::helper_assembly helper_assembly_;
- lexer::helper::commutative_inserter commutative_inserter_;
- lexer::helper::operator_joiner operator_joiner_2_;
- lexer::helper::operator_joiner operator_joiner_3_;
- lexer::helper::symbol_replacer symbol_replacer_;
- lexer::helper::bracket_checker bracket_checker_;
- lexer::helper::numeric_checker numeric_checker_;
- lexer::helper::sequence_validator sequence_validator_;
- lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
- template <typename ParserType>
- friend void details::disable_type_checking(ParserType& p);
- };
- namespace details
- {
- template <typename T>
- struct collector_helper
- {
- typedef exprtk::symbol_table<T> symbol_table_t;
- typedef exprtk::expression<T> expression_t;
- typedef exprtk::parser<T> parser_t;
- typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
- typedef typename parser_t::unknown_symbol_resolver usr_t;
- struct resolve_as_vector : public parser_t::unknown_symbol_resolver
- {
- typedef exprtk::parser<T> parser_t;
- resolve_as_vector()
- : usr_t(usr_t::e_usrmode_extended)
- {}
- virtual bool process(const std::string& unknown_symbol,
- symbol_table_t& symbol_table,
- std::string&)
- {
- static T v[1];
- symbol_table.add_vector(unknown_symbol,v);
- return true;
- }
- };
- static inline bool collection_pass(const std::string& expression_string,
- std::set<std::string>& symbol_set,
- const bool collect_variables,
- const bool collect_functions,
- const bool vector_pass,
- symbol_table_t& ext_symbol_table)
- {
- symbol_table_t symbol_table;
- expression_t expression;
- parser_t parser;
- resolve_as_vector vect_resolver;
- expression.register_symbol_table(symbol_table );
- expression.register_symbol_table(ext_symbol_table);
- if (vector_pass)
- parser.enable_unknown_symbol_resolver(&vect_resolver);
- else
- parser.enable_unknown_symbol_resolver();
- if (collect_variables)
- parser.dec().collect_variables() = true;
- if (collect_functions)
- parser.dec().collect_functions() = true;
- bool pass_result = false;
- details::disable_type_checking(parser);
- if (parser.compile(expression_string, expression))
- {
- pass_result = true;
- std::deque<symbol_t> symb_list;
- parser.dec().symbols(symb_list);
- for (std::size_t i = 0; i < symb_list.size(); ++i)
- {
- symbol_set.insert(symb_list[i].first);
- }
- }
- return pass_result;
- }
- };
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline bool collect_variables(const std::string& expression,
- Sequence<std::string, Allocator>& symbol_list)
- {
- typedef double T;
- typedef details::collector_helper<T> collect_t;
- collect_t::symbol_table_t null_symbol_table;
- std::set<std::string> symbol_set;
- const bool variable_pass = collect_t::collection_pass
- (expression, symbol_set, true, false, false, null_symbol_table);
- const bool vector_pass = collect_t::collection_pass
- (expression, symbol_set, true, false, true, null_symbol_table);
- if (!variable_pass && !vector_pass)
- return false;
- std::set<std::string>::iterator itr = symbol_set.begin();
- while (symbol_set.end() != itr)
- {
- symbol_list.push_back(*itr);
- ++itr;
- }
- return true;
- }
- template <typename T,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline bool collect_variables(const std::string& expression,
- exprtk::symbol_table<T>& extrnl_symbol_table,
- Sequence<std::string, Allocator>& symbol_list)
- {
- typedef details::collector_helper<T> collect_t;
- std::set<std::string> symbol_set;
- const bool variable_pass = collect_t::collection_pass
- (expression, symbol_set, true, false, false, extrnl_symbol_table);
- const bool vector_pass = collect_t::collection_pass
- (expression, symbol_set, true, false, true, extrnl_symbol_table);
- if (!variable_pass && !vector_pass)
- return false;
- std::set<std::string>::iterator itr = symbol_set.begin();
- while (symbol_set.end() != itr)
- {
- symbol_list.push_back(*itr);
- ++itr;
- }
- return true;
- }
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline bool collect_functions(const std::string& expression,
- Sequence<std::string, Allocator>& symbol_list)
- {
- typedef double T;
- typedef details::collector_helper<T> collect_t;
- collect_t::symbol_table_t null_symbol_table;
- std::set<std::string> symbol_set;
- const bool variable_pass = collect_t::collection_pass
- (expression, symbol_set, false, true, false, null_symbol_table);
- const bool vector_pass = collect_t::collection_pass
- (expression, symbol_set, false, true, true, null_symbol_table);
- if (!variable_pass && !vector_pass)
- return false;
- std::set<std::string>::iterator itr = symbol_set.begin();
- while (symbol_set.end() != itr)
- {
- symbol_list.push_back(*itr);
- ++itr;
- }
- return true;
- }
- template <typename T,
- typename Allocator,
- template <typename, typename> class Sequence>
- inline bool collect_functions(const std::string& expression,
- exprtk::symbol_table<T>& extrnl_symbol_table,
- Sequence<std::string, Allocator>& symbol_list)
- {
- typedef details::collector_helper<T> collect_t;
- std::set<std::string> symbol_set;
- const bool variable_pass = collect_t::collection_pass
- (expression, symbol_set, false, true, false, extrnl_symbol_table);
- const bool vector_pass = collect_t::collection_pass
- (expression, symbol_set, false, true, true, extrnl_symbol_table);
- if (!variable_pass && !vector_pass)
- return false;
- std::set<std::string>::iterator itr = symbol_set.begin();
- while (symbol_set.end() != itr)
- {
- symbol_list.push_back(*itr);
- ++itr;
- }
- return true;
- }
- template <typename T>
- inline T integrate(const expression<T>& e,
- T& x,
- const T& r0, const T& r1,
- const std::size_t number_of_intervals = 1000000)
- {
- if (r0 > r1)
- return T(0);
- const T h = (r1 - r0) / (T(2) * number_of_intervals);
- T total_area = T(0);
- for (std::size_t i = 0; i < number_of_intervals; ++i)
- {
- x = r0 + T(2) * i * h;
- const T y0 = e.value(); x += h;
- const T y1 = e.value(); x += h;
- const T y2 = e.value(); x += h;
- total_area += h * (y0 + T(4) * y1 + y2) / T(3);
- }
- return total_area;
- }
- template <typename T>
- inline T integrate(const expression<T>& e,
- const std::string& variable_name,
- const T& r0, const T& r1,
- const std::size_t number_of_intervals = 1000000)
- {
- const symbol_table<T>& sym_table = e.get_symbol_table();
- if (!sym_table.valid())
- return std::numeric_limits<T>::quiet_NaN();
- details::variable_node<T>* var = sym_table.get_variable(variable_name);
- if (var)
- {
- T& x = var->ref();
- T x_original = x;
- T result = integrate(e, x, r0, r1, number_of_intervals);
- x = x_original;
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <typename T>
- inline T derivative(const expression<T>& e,
- T& x,
- const T& h = T(0.00000001))
- {
- const T x_init = x;
- const T _2h = T(2) * h;
- x = x_init + _2h;
- const T y0 = e.value();
- x = x_init + h;
- const T y1 = e.value();
- x = x_init - h;
- const T y2 = e.value();
- x = x_init - _2h;
- const T y3 = e.value();
- x = x_init;
- return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
- }
- template <typename T>
- inline T second_derivative(const expression<T>& e,
- T& x,
- const T& h = T(0.00001))
- {
- const T x_init = x;
- const T _2h = T(2) * h;
- const T y = e.value();
- x = x_init + _2h;
- const T y0 = e.value();
- x = x_init + h;
- const T y1 = e.value();
- x = x_init - h;
- const T y2 = e.value();
- x = x_init - _2h;
- const T y3 = e.value();
- x = x_init;
- return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
- }
- template <typename T>
- inline T third_derivative(const expression<T>& e,
- T& x,
- const T& h = T(0.0001))
- {
- const T x_init = x;
- const T _2h = T(2) * h;
- x = x_init + _2h;
- const T y0 = e.value();
- x = x_init + h;
- const T y1 = e.value();
- x = x_init - h;
- const T y2 = e.value();
- x = x_init - _2h;
- const T y3 = e.value();
- x = x_init;
- return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
- }
- template <typename T>
- inline T derivative(const expression<T>& e,
- const std::string& variable_name,
- const T& h = T(0.00000001))
- {
- const symbol_table<T>& sym_table = e.get_symbol_table();
- if (!sym_table.valid())
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- details::variable_node<T>* var = sym_table.get_variable(variable_name);
- if (var)
- {
- T& x = var->ref();
- T x_original = x;
- T result = derivative(e, x, h);
- x = x_original;
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <typename T>
- inline T second_derivative(const expression<T>& e,
- const std::string& variable_name,
- const T& h = T(0.00001))
- {
- const symbol_table<T>& sym_table = e.get_symbol_table();
- if (!sym_table.valid())
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- details::variable_node<T>* var = sym_table.get_variable(variable_name);
- if (var)
- {
- T& x = var->ref();
- const T x_original = x;
- const T result = second_derivative(e, x, h);
- x = x_original;
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- template <typename T>
- inline T third_derivative(const expression<T>& e,
- const std::string& variable_name,
- const T& h = T(0.0001))
- {
- const symbol_table<T>& sym_table = e.get_symbol_table();
- if (!sym_table.valid())
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- details::variable_node<T>* var = sym_table.get_variable(variable_name);
- if (var)
- {
- T& x = var->ref();
- const T x_original = x;
- const T result = third_derivative(e, x, h);
- x = x_original;
- return result;
- }
- else
- return std::numeric_limits<T>::quiet_NaN();
- }
- /*
- Note: The following 'compute' routines are simple helpers,
- for quickly setting up the required pieces of code in order
- to evaluate an expression. By virtue of how they operate
- there will be an overhead with regards to their setup and
- teardown and hence should not be used in time critical
- sections of code.
- Furthermore they only assume a small sub set of variables,
- no string variables or user defined functions.
- */
- template <typename T>
- inline bool compute(const std::string& expression_string, T& result)
- {
- // No variables
- symbol_table<T> symbol_table;
- symbol_table.add_constants();
- expression<T> expression;
- expression.register_symbol_table(symbol_table);
- parser<T> parser;
- if (parser.compile(expression_string,expression))
- {
- result = expression.value();
- return true;
- }
- else
- return false;
- }
- template <typename T>
- inline bool compute(const std::string& expression_string,
- const T& x,
- T& result)
- {
- // Only 'x'
- static const std::string x_var("x");
- symbol_table<T> symbol_table;
- symbol_table.add_constants();
- symbol_table.add_constant(x_var,x);
- expression<T> expression;
- expression.register_symbol_table(symbol_table);
- parser<T> parser;
- if (parser.compile(expression_string,expression))
- {
- result = expression.value();
- return true;
- }
- else
- return false;
- }
- template <typename T>
- inline bool compute(const std::string& expression_string,
- const T&x, const T& y,
- T& result)
- {
- // Only 'x' and 'y'
- static const std::string x_var("x");
- static const std::string y_var("y");
- symbol_table<T> symbol_table;
- symbol_table.add_constants();
- symbol_table.add_constant(x_var,x);
- symbol_table.add_constant(y_var,y);
- expression<T> expression;
- expression.register_symbol_table(symbol_table);
- parser<T> parser;
- if (parser.compile(expression_string,expression))
- {
- result = expression.value();
- return true;
- }
- else
- return false;
- }
- template <typename T>
- inline bool compute(const std::string& expression_string,
- const T& x, const T& y, const T& z,
- T& result)
- {
- // Only 'x', 'y' or 'z'
- static const std::string x_var("x");
- static const std::string y_var("y");
- static const std::string z_var("z");
- symbol_table<T> symbol_table;
- symbol_table.add_constants();
- symbol_table.add_constant(x_var,x);
- symbol_table.add_constant(y_var,y);
- symbol_table.add_constant(z_var,z);
- expression<T> expression;
- expression.register_symbol_table(symbol_table);
- parser<T> parser;
- if (parser.compile(expression_string,expression))
- {
- result = expression.value();
- return true;
- }
- else
- return false;
- }
- template <typename T, std::size_t N>
- class polynomial : public ifunction<T>
- {
- private:
- template <typename Type, std::size_t NumberOfCoefficients>
- struct poly_impl { };
- template <typename Type>
- struct poly_impl <Type,12>
- {
- static inline T evaluate(const Type x,
- const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
- const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
- const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,11>
- {
- static inline T evaluate(const Type x,
- const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
- const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
- const Type c1, const Type c0)
- {
- // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,10>
- {
- static inline T evaluate(const Type x,
- const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
- const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
- const Type c0)
- {
- // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,9>
- {
- static inline T evaluate(const Type x,
- const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
- const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,8>
- {
- static inline T evaluate(const Type x,
- const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
- const Type c3, const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,7>
- {
- static inline T evaluate(const Type x,
- const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
- const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,6>
- {
- static inline T evaluate(const Type x,
- const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
- const Type c1, const Type c0)
- {
- // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,5>
- {
- static inline T evaluate(const Type x,
- const Type c5, const Type c4, const Type c3, const Type c2,
- const Type c1, const Type c0)
- {
- // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,4>
- {
- static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,3>
- {
- static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
- return (((c3 * x + c2) * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,2>
- {
- static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
- {
- // p(x) = c_2x^2 + c_1x^1 + c_0x^0
- return ((c2 * x + c1) * x + c0);
- }
- };
- template <typename Type>
- struct poly_impl <Type,1>
- {
- static inline T evaluate(const Type x, const Type c1, const Type c0)
- {
- // p(x) = c_1x^1 + c_0x^0
- return (c1 * x + c0);
- }
- };
- public:
- using ifunction<T>::operator();
- polynomial()
- : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
- {
- disable_has_side_effects(*this);
- }
- virtual ~polynomial()
- {}
- #define poly_rtrn(NN) \
- return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
- inline virtual T operator() (const T& x, const T& c1, const T& c0)
- {
- poly_rtrn(1) poly_impl<T,1>::evaluate(x, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(2) poly_impl<T,2>::evaluate(x, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(3) poly_impl<T,3>::evaluate(x, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(4) poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(5) poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(6) poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(7) poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(8) poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(9) poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(10) poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(11) poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
- }
- inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
- {
- poly_rtrn(12) poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
- }
- #undef poly_rtrn
- inline virtual T operator() ()
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline virtual T operator() (const T&)
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- inline virtual T operator() (const T&, const T&)
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- };
- template <typename T>
- class function_compositor
- {
- public:
- typedef exprtk::expression<T> expression_t;
- typedef exprtk::symbol_table<T> symbol_table_t;
- typedef exprtk::parser<T> parser_t;
- typedef typename parser_t::settings_store settings_t;
- struct function
- {
- function()
- {}
- function(const std::string& n)
- : name_(n)
- {}
- function(const std::string& name,
- const std::string& expression)
- : name_(name),
- expression_(expression)
- {}
- function(const std::string& name,
- const std::string& expression,
- const std::string& v0)
- : name_(name),
- expression_(expression)
- {
- v_.push_back(v0);
- }
- function(const std::string& name,
- const std::string& expression,
- const std::string& v0, const std::string& v1)
- : name_(name),
- expression_(expression)
- {
- v_.push_back(v0); v_.push_back(v1);
- }
- function(const std::string& name,
- const std::string& expression,
- const std::string& v0, const std::string& v1,
- const std::string& v2)
- : name_(name),
- expression_(expression)
- {
- v_.push_back(v0); v_.push_back(v1);
- v_.push_back(v2);
- }
- function(const std::string& name,
- const std::string& expression,
- const std::string& v0, const std::string& v1,
- const std::string& v2, const std::string& v3)
- : name_(name),
- expression_(expression)
- {
- v_.push_back(v0); v_.push_back(v1);
- v_.push_back(v2); v_.push_back(v3);
- }
- function(const std::string& name,
- const std::string& expression,
- const std::string& v0, const std::string& v1,
- const std::string& v2, const std::string& v3,
- const std::string& v4)
- : name_(name),
- expression_(expression)
- {
- v_.push_back(v0); v_.push_back(v1);
- v_.push_back(v2); v_.push_back(v3);
- v_.push_back(v4);
- }
- inline function& name(const std::string& n)
- {
- name_ = n;
- return (*this);
- }
- inline function& expression(const std::string& e)
- {
- expression_ = e;
- return (*this);
- }
- inline function& var(const std::string& v)
- {
- v_.push_back(v);
- return (*this);
- }
- std::string name_;
- std::string expression_;
- std::deque<std::string> v_;
- };
- private:
- struct base_func : public exprtk::ifunction<T>
- {
- typedef const T& type;
- typedef exprtk::ifunction<T> function_t;
- typedef std::vector<T*> varref_t;
- typedef std::vector<T> var_t;
- typedef std::pair<T*,std::size_t> lvarref_t;
- typedef std::vector<lvarref_t> lvr_vec_t;
- using exprtk::ifunction<T>::operator();
- base_func(const std::size_t& pc = 0)
- : exprtk::ifunction<T>(pc),
- local_var_stack_size(0),
- stack_depth(0)
- {
- v.resize(pc);
- }
- virtual ~base_func()
- {}
- inline void update(const T& v0)
- {
- (*v[0]) = v0;
- }
- inline void update(const T& v0, const T& v1)
- {
- (*v[0]) = v0; (*v[1]) = v1;
- }
- inline void update(const T& v0, const T& v1, const T& v2)
- {
- (*v[0]) = v0; (*v[1]) = v1;
- (*v[2]) = v2;
- }
- inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
- {
- (*v[0]) = v0; (*v[1]) = v1;
- (*v[2]) = v2; (*v[3]) = v3;
- }
- inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
- {
- (*v[0]) = v0; (*v[1]) = v1;
- (*v[2]) = v2; (*v[3]) = v3;
- (*v[4]) = v4;
- }
- inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
- {
- (*v[0]) = v0; (*v[1]) = v1;
- (*v[2]) = v2; (*v[3]) = v3;
- (*v[4]) = v4; (*v[5]) = v5;
- }
- inline function_t& setup(expression_t& expr)
- {
- expression = expr;
- typedef typename expression_t::control_block::local_data_list_t ldl_t;
- ldl_t ldl = expr.local_data_list();
- std::vector<std::size_t> index_list;
- for (std::size_t i = 0; i < ldl.size(); ++i)
- {
- if (ldl[i].size)
- {
- index_list.push_back(i);
- }
- }
- std::size_t input_param_count = 0;
- for (std::size_t i = 0; i < index_list.size(); ++i)
- {
- const std::size_t index = index_list[i];
- if (i < (index_list.size() - v.size()))
- {
- lv.push_back(
- std::make_pair(
- reinterpret_cast<T*>(ldl[index].pointer),
- ldl[index].size));
- local_var_stack_size += ldl[index].size;
- }
- else
- v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
- }
- clear_stack();
- return (*this);
- }
- inline void pre()
- {
- if (stack_depth++)
- {
- if (!v.empty())
- {
- var_t var_stack(v.size(),T(0));
- copy(v,var_stack);
- param_stack.push_back(var_stack);
- }
- if (!lv.empty())
- {
- var_t local_var_stack(local_var_stack_size,T(0));
- copy(lv,local_var_stack);
- local_stack.push_back(local_var_stack);
- }
- }
- }
- inline void post()
- {
- if (--stack_depth)
- {
- if (!v.empty())
- {
- copy(param_stack.back(),v);
- param_stack.pop_back();
- }
- if (!lv.empty())
- {
- copy(local_stack.back(),lv);
- local_stack.pop_back();
- }
- }
- }
- void copy(const varref_t& src_v, var_t& dest_v)
- {
- for (std::size_t i = 0; i < src_v.size(); ++i)
- {
- dest_v[i] = (*src_v[i]);
- }
- }
- void copy(const var_t& src_v, varref_t& dest_v)
- {
- for (std::size_t i = 0; i < src_v.size(); ++i)
- {
- (*dest_v[i]) = src_v[i];
- }
- }
- void copy(const lvr_vec_t& src_v, var_t& dest_v)
- {
- typename var_t::iterator itr = dest_v.begin();
- typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
- for (std::size_t i = 0; i < src_v.size(); ++i)
- {
- lvarref_t vr = src_v[i];
- if (1 == vr.second)
- *itr++ = (*vr.first);
- else
- {
- std::copy(vr.first, vr.first + vr.second, itr);
- itr += static_cast<diff_t>(vr.second);
- }
- }
- }
- void copy(const var_t& src_v, lvr_vec_t& dest_v)
- {
- typename var_t::const_iterator itr = src_v.begin();
- typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
- for (std::size_t i = 0; i < src_v.size(); ++i)
- {
- lvarref_t vr = dest_v[i];
- if (1 == vr.second)
- (*vr.first) = *itr++;
- else
- {
- std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
- itr += static_cast<diff_t>(vr.second);
- }
- }
- }
- inline void clear_stack()
- {
- for (std::size_t i = 0; i < v.size(); ++i)
- {
- (*v[i]) = 0;
- }
- }
- inline virtual T value(expression_t& e)
- {
- return e.value();
- }
- expression_t expression;
- varref_t v;
- lvr_vec_t lv;
- std::size_t local_var_stack_size;
- std::size_t stack_depth;
- std::deque<var_t> param_stack;
- std::deque<var_t> local_stack;
- };
- typedef std::map<std::string,base_func*> funcparam_t;
- struct func_0param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_0param() : base_func(0) {}
- inline T operator() ()
- {
- return this->value(base_func::expression);
- }
- };
- typedef const T& type;
- template <typename BaseFuncType>
- struct scoped_bft
- {
- scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
- ~scoped_bft() { bft_.post(); }
- BaseFuncType& bft_;
- private:
- scoped_bft(scoped_bft&);
- scoped_bft& operator=(scoped_bft&);
- };
- struct func_1param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_1param() : base_func(1) {}
- inline T operator() (type v0)
- {
- scoped_bft<func_1param> sb(*this);
- base_func::update(v0);
- return this->value(base_func::expression);
- }
- };
- struct func_2param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_2param() : base_func(2) {}
- inline T operator() (type v0, type v1)
- {
- scoped_bft<func_2param> sb(*this);
- base_func::update(v0, v1);
- return this->value(base_func::expression);
- }
- };
- struct func_3param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_3param() : base_func(3) {}
- inline T operator() (type v0, type v1, type v2)
- {
- scoped_bft<func_3param> sb(*this);
- base_func::update(v0, v1, v2);
- return this->value(base_func::expression);
- }
- };
- struct func_4param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_4param() : base_func(4) {}
- inline T operator() (type v0, type v1, type v2, type v3)
- {
- scoped_bft<func_4param> sb(*this);
- base_func::update(v0, v1, v2, v3);
- return this->value(base_func::expression);
- }
- };
- struct func_5param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_5param() : base_func(5) {}
- inline T operator() (type v0, type v1, type v2, type v3, type v4)
- {
- scoped_bft<func_5param> sb(*this);
- base_func::update(v0, v1, v2, v3, v4);
- return this->value(base_func::expression);
- }
- };
- struct func_6param : public base_func
- {
- using exprtk::ifunction<T>::operator();
- func_6param() : base_func(6) {}
- inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
- {
- scoped_bft<func_6param> sb(*this);
- base_func::update(v0, v1, v2, v3, v4, v5);
- return this->value(base_func::expression);
- }
- };
- static T return_value(expression_t& e)
- {
- typedef exprtk::results_context<T> results_context_t;
- typedef typename results_context_t::type_store_t type_t;
- typedef typename type_t::scalar_view scalar_t;
- T result = e.value();
- if (e.return_invoked())
- {
- // Due to the post compilation checks, it can be safely
- // assumed that there will be at least one parameter
- // and that the first parameter will always be scalar.
- return scalar_t(e.results()[0])();
- }
- return result;
- }
- #define def_fp_retval(N) \
- struct func_##N##param_retval : public func_##N##param \
- { \
- inline T value(expression_t& e) \
- { \
- return return_value(e); \
- } \
- }; \
- def_fp_retval(0)
- def_fp_retval(1)
- def_fp_retval(2)
- def_fp_retval(3)
- def_fp_retval(4)
- def_fp_retval(5)
- def_fp_retval(6)
- template <typename Allocator,
- template <typename, typename> class Sequence>
- inline bool add(const std::string& name,
- const std::string& expression,
- const Sequence<std::string,Allocator>& var_list,
- const bool override = false)
- {
- const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
- if (expr_map_.end() != itr)
- {
- if (!override)
- {
- exprtk_debug(("Compositor error(add): function '%s' already defined\n",
- name.c_str()));
- return false;
- }
- remove(name, var_list.size());
- }
- if (compile_expression(name,expression,var_list))
- {
- const std::size_t n = var_list.size();
- fp_map_[n][name]->setup(expr_map_[name]);
- return true;
- }
- else
- {
- exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
- name.c_str()));
- return false;
- }
- }
- public:
- function_compositor()
- : parser_(settings_t::compile_all_opts +
- settings_t::e_disable_zero_return),
- fp_map_(7)
- {}
- function_compositor(const symbol_table_t& st)
- : symbol_table_(st),
- parser_(settings_t::compile_all_opts +
- settings_t::e_disable_zero_return),
- fp_map_(7)
- {}
- ~function_compositor()
- {
- clear();
- }
- inline symbol_table_t& symbol_table()
- {
- return symbol_table_;
- }
- inline void add_auxiliary_symtab(symbol_table_t& symtab)
- {
- auxiliary_symtab_list_.push_back(&symtab);
- }
- void clear()
- {
- symbol_table_.clear();
- expr_map_ .clear();
- for (std::size_t i = 0; i < fp_map_.size(); ++i)
- {
- typename funcparam_t::iterator itr = fp_map_[i].begin();
- typename funcparam_t::iterator end = fp_map_[i].end ();
- while (itr != end)
- {
- delete itr->second;
- ++itr;
- }
- fp_map_[i].clear();
- }
- }
- inline bool add(const function& f, const bool override = false)
- {
- return add(f.name_, f.expression_, f.v_,override);
- }
- private:
- template <typename Allocator,
- template <typename, typename> class Sequence>
- bool compile_expression(const std::string& name,
- const std::string& expression,
- const Sequence<std::string,Allocator>& input_var_list,
- bool return_present = false)
- {
- expression_t compiled_expression;
- symbol_table_t local_symbol_table;
- local_symbol_table.load_from(symbol_table_);
- local_symbol_table.add_constants();
- if (!valid(name,input_var_list.size()))
- return false;
- if (!forward(name,
- input_var_list.size(),
- local_symbol_table,
- return_present))
- return false;
- compiled_expression.register_symbol_table(local_symbol_table);
- for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
- {
- compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
- }
- std::string mod_expression;
- for (std::size_t i = 0; i < input_var_list.size(); ++i)
- {
- mod_expression += " var " + input_var_list[i] + "{};\n";
- }
- if (
- ('{' == details::front(expression)) &&
- ('}' == details::back (expression))
- )
- mod_expression += "~" + expression + ";";
- else
- mod_expression += "~{" + expression + "};";
- if (!parser_.compile(mod_expression,compiled_expression))
- {
- exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
- exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
- remove(name,input_var_list.size());
- return false;
- }
- if (!return_present && parser_.dec().return_present())
- {
- remove(name,input_var_list.size());
- return compile_expression(name, expression, input_var_list, true);
- }
- // Make sure every return point has a scalar as its first parameter
- if (parser_.dec().return_present())
- {
- typedef std::vector<std::string> str_list_t;
- str_list_t ret_param_list = parser_.dec().return_param_type_list();
- for (std::size_t i = 0; i < ret_param_list.size(); ++i)
- {
- const std::string& params = ret_param_list[i];
- if (params.empty() || ('T' != params[0]))
- {
- exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
- name.c_str()));
- remove(name,input_var_list.size());
- return false;
- }
- }
- }
- expr_map_[name] = compiled_expression;
- exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
- if (symbol_table_.add_function(name,ifunc))
- return true;
- else
- {
- exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
- name.c_str()));
- return false;
- }
- }
- inline bool symbol_used(const std::string& symbol) const
- {
- return (
- symbol_table_.is_variable (symbol) ||
- symbol_table_.is_stringvar (symbol) ||
- symbol_table_.is_function (symbol) ||
- symbol_table_.is_vector (symbol) ||
- symbol_table_.is_vararg_function(symbol)
- );
- }
- inline bool valid(const std::string& name,
- const std::size_t& arg_count) const
- {
- if (arg_count > 6)
- return false;
- else if (symbol_used(name))
- return false;
- else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
- return false;
- else
- return true;
- }
- inline bool forward(const std::string& name,
- const std::size_t& arg_count,
- symbol_table_t& sym_table,
- const bool ret_present = false)
- {
- switch (arg_count)
- {
- #define case_stmt(N) \
- case N : (fp_map_[arg_count])[name] = \
- (!ret_present) ? static_cast<base_func*> \
- (new func_##N##param) : \
- static_cast<base_func*> \
- (new func_##N##param_retval) ; \
- break; \
- case_stmt(0) case_stmt(1) case_stmt(2)
- case_stmt(3) case_stmt(4) case_stmt(5)
- case_stmt(6)
- #undef case_stmt
- }
- exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
- return sym_table.add_function(name,ifunc);
- }
- inline void remove(const std::string& name, const std::size_t& arg_count)
- {
- if (arg_count > 6)
- return;
- const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
- if (expr_map_.end() != em_itr)
- {
- expr_map_.erase(em_itr);
- }
- const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
- if (fp_map_[arg_count].end() != fp_itr)
- {
- delete fp_itr->second;
- fp_map_[arg_count].erase(fp_itr);
- }
- symbol_table_.remove_function(name);
- }
- private:
- symbol_table_t symbol_table_;
- parser_t parser_;
- std::map<std::string,expression_t> expr_map_;
- std::vector<funcparam_t> fp_map_;
- std::vector<symbol_table_t*> auxiliary_symtab_list_;
- };
- template <typename T>
- inline bool pgo_primer()
- {
- static const std::string expression_list[] =
- {
- "(y + x)",
- "2 * (y + x)",
- "(2 * y + 2 * x)",
- "(y + x / y) * (x - y / x)",
- "x / ((x + y) * (x - y)) / y",
- "1 - ((x * y) + (y / x)) - 3",
- "sin(2 * x) + cos(pi / y)",
- "1 - sin(2 * x) + cos(pi / y)",
- "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
- "(x^2 / sin(2 * pi / y)) -x / 2",
- "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
- "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
- "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
- "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
- "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
- "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
- "(yy + xx)",
- "2 * (yy + xx)",
- "(2 * yy + 2 * xx)",
- "(yy + xx / yy) * (xx - yy / xx)",
- "xx / ((xx + yy) * (xx - yy)) / yy",
- "1 - ((xx * yy) + (yy / xx)) - 3",
- "sin(2 * xx) + cos(pi / yy)",
- "1 - sin(2 * xx) + cos(pi / yy)",
- "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
- "(xx^2 / sin(2 * pi / yy)) -xx / 2",
- "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
- "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
- "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
- "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
- "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
- "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
- "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
- "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
- "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
- "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
- "(x + 2) * 3", "x + (2 * 3)",
- "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
- "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
- "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
- "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
- "2 + (x * (y / 3))", "x + (2 * (3 / y))",
- "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
- "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
- "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
- "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
- "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
- "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
- "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
- "((x + (2 * 3)) / y)",
- "(xx + yy) * zz", "xx + (yy * zz)",
- "(xx + yy) * 7", "xx + (yy * 7)",
- "(xx + 7) * yy", "xx + (7 * yy)",
- "(7 + xx) * yy", "7 + (xx * yy)",
- "(2 + x) * 3", "2 + (x * 3)",
- "(2 + 3) * x", "2 + (3 * x)",
- "(x + 2) * 3", "x + (2 * 3)",
- "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
- "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
- "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
- "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
- "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
- "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
- "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
- "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
- "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
- "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
- "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
- "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
- "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
- "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
- "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
- "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
- "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
- "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
- "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
- "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
- "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
- "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
- "((xx + (2 * 3)) / yy)"
- };
- static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
- T x = T(0);
- T y = T(0);
- T z = T(0);
- T w = T(0);
- T xx = T(0);
- T yy = T(0);
- T zz = T(0);
- T ww = T(0);
- exprtk::symbol_table<T> symbol_table;
- symbol_table.add_constants();
- symbol_table.add_variable( "x", x);
- symbol_table.add_variable( "y", y);
- symbol_table.add_variable( "z", z);
- symbol_table.add_variable( "w", w);
- symbol_table.add_variable("xx",xx);
- symbol_table.add_variable("yy",yy);
- symbol_table.add_variable("zz",zz);
- symbol_table.add_variable("ww",ww);
- typedef typename std::deque<exprtk::expression<T> > expr_list_t;
- expr_list_t expr_list;
- const std::size_t rounds = 50;
- {
- for (std::size_t r = 0; r < rounds; ++r)
- {
- expr_list.clear();
- exprtk::parser<T> parser;
- for (std::size_t i = 0; i < expression_list_size; ++i)
- {
- exprtk::expression<T> expression;
- expression.register_symbol_table(symbol_table);
- if (!parser.compile(expression_list[i],expression))
- {
- return false;
- }
- expr_list.push_back(expression);
- }
- }
- }
- struct execute
- {
- static inline T process(T& x, T& y, expression<T>& expression)
- {
- static const T lower_bound = T(-20);
- static const T upper_bound = T(+20);
- static const T delta = T(0.1);
- T total = T(0);
- for (x = lower_bound; x <= upper_bound; x += delta)
- {
- for (y = lower_bound; y <= upper_bound; y += delta)
- {
- total += expression.value();
- }
- }
- return total;
- }
- };
- for (std::size_t i = 0; i < expr_list.size(); ++i)
- {
- execute::process( x, y, expr_list[i]);
- execute::process(xx, yy, expr_list[i]);
- }
- {
- for (std::size_t i = 0; i < 10000; ++i)
- {
- const T v = T(123.456 + i);
- if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
- return false;
- #define else_stmt(N) \
- else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
- return false; \
- else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
- else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
- else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
- else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
- else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
- else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
- else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
- else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
- else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
- else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
- else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
- else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
- else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
- else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
- else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
- }
- }
- return true;
- }
- }
- #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
- # ifndef NOMINMAX
- # define NOMINMAX
- # endif
- # ifndef WIN32_LEAN_AND_MEAN
- # define WIN32_LEAN_AND_MEAN
- # endif
- # include <windows.h>
- # include <ctime>
- #else
- # include <ctime>
- # include <sys/time.h>
- # include <sys/types.h>
- #endif
- namespace exprtk
- {
- class timer
- {
- public:
- #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
- timer()
- : in_use_(false)
- {
- QueryPerformanceFrequency(&clock_frequency_);
- }
- inline void start()
- {
- in_use_ = true;
- QueryPerformanceCounter(&start_time_);
- }
- inline void stop()
- {
- QueryPerformanceCounter(&stop_time_);
- in_use_ = false;
- }
- inline double time() const
- {
- return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
- }
- #else
- timer()
- : in_use_(false)
- {
- start_time_.tv_sec = 0;
- start_time_.tv_usec = 0;
- stop_time_.tv_sec = 0;
- stop_time_.tv_usec = 0;
- }
- inline void start()
- {
- in_use_ = true;
- gettimeofday(&start_time_,0);
- }
- inline void stop()
- {
- gettimeofday(&stop_time_, 0);
- in_use_ = false;
- }
- inline unsigned long long int usec_time() const
- {
- if (!in_use_)
- {
- if (stop_time_.tv_sec >= start_time_.tv_sec)
- {
- return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) +
- static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
- }
- else
- return std::numeric_limits<details::_uint64_t>::max();
- }
- else
- return std::numeric_limits<details::_uint64_t>::max();
- }
- inline double time() const
- {
- return usec_time() * 0.000001;
- }
- #endif
- inline bool in_use() const
- {
- return in_use_;
- }
- private:
- bool in_use_;
- #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
- LARGE_INTEGER start_time_;
- LARGE_INTEGER stop_time_;
- LARGE_INTEGER clock_frequency_;
- #else
- struct timeval start_time_;
- struct timeval stop_time_;
- #endif
- };
- } // namespace exprtk
- #ifndef exprtk_disable_rtl_io
- namespace exprtk
- {
- namespace rtl { namespace io { namespace details
- {
- template <typename T>
- inline void print_type(const std::string& fmt,
- const T v,
- exprtk::details::numeric::details::real_type_tag)
- {
- printf(fmt.c_str(),v);
- }
- template <typename T>
- struct print_impl
- {
- typedef typename igeneric_function<T>::generic_type generic_type;
- typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- typedef typename generic_type::string_view string_t;
- typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
- static void process(const std::string& scalar_format, parameter_list_t parameters)
- {
- for (std::size_t i = 0; i < parameters.size(); ++i)
- {
- generic_type& gt = parameters[i];
- switch (gt.type)
- {
- case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
- break;
- case generic_type::e_vector : print(scalar_format,vector_t(gt));
- break;
- case generic_type::e_string : print(string_t(gt));
- break;
- default : continue;
- }
- }
- }
- static inline void print(const std::string& scalar_format, const scalar_t& s)
- {
- print_type(scalar_format,s(),num_type());
- }
- static inline void print(const std::string& scalar_format, const vector_t& v)
- {
- for (std::size_t i = 0; i < v.size(); ++i)
- {
- print_type(scalar_format,v[i],num_type());
- if ((i + 1) < v.size())
- printf(" ");
- }
- }
- static inline void print(const string_t& s)
- {
- printf("%s",to_str(s).c_str());
- }
- };
- } // namespace exprtk::rtl::io::details
- template <typename T>
- struct print : public exprtk::igeneric_function<T>
- {
- typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
- using exprtk::igeneric_function<T>::operator();
- print(const std::string& scalar_format = "%10.5f")
- : scalar_format_(scalar_format)
- {
- exprtk::enable_zero_parameters(*this);
- }
- inline T operator() (parameter_list_t parameters)
- {
- details::print_impl<T>::process(scalar_format_,parameters);
- return T(0);
- }
- std::string scalar_format_;
- };
- template <typename T>
- struct println : public exprtk::igeneric_function<T>
- {
- typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
- using exprtk::igeneric_function<T>::operator();
- println(const std::string& scalar_format = "%10.5f")
- : scalar_format_(scalar_format)
- {
- exprtk::enable_zero_parameters(*this);
- }
- inline T operator() (parameter_list_t parameters)
- {
- details::print_impl<T>::process(scalar_format_,parameters);
- printf("\n");
- return T(0);
- }
- std::string scalar_format_;
- };
- template <typename T>
- struct package
- {
- print <T> p;
- println<T> pl;
- bool register_package(exprtk::symbol_table<T>& symtab)
- {
- #define exprtk_register_function(FunctionName,FunctionType) \
- if (!symtab.add_function(FunctionName,FunctionType)) \
- { \
- exprtk_debug(( \
- "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
- FunctionName)); \
- return false; \
- } \
- exprtk_register_function("print" , p)
- exprtk_register_function("println", pl)
- #undef exprtk_register_function
- return true;
- }
- };
- } // namespace exprtk::rtl::io
- } // namespace exprtk::rtl
- } // namespace exprtk
- #endif
- #ifndef exprtk_disable_rtl_io_file
- #include <fstream>
- namespace exprtk
- {
- namespace rtl { namespace io { namespace file { namespace details
- {
- enum file_mode
- {
- e_error = 0,
- e_read = 1,
- e_write = 2,
- e_rdwrt = 4
- };
- struct file_descriptor
- {
- file_descriptor(const std::string& fname, const std::string& access)
- : stream_ptr(0),
- mode(get_file_mode(access)),
- file_name(fname)
- {}
- void* stream_ptr;
- file_mode mode;
- std::string file_name;
- bool open()
- {
- if (e_read == mode)
- {
- std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
- if (!(*stream))
- {
- file_name.clear();
- delete stream;
- return false;
- }
- else
- stream_ptr = stream;
- return true;
- }
- else if (e_write == mode)
- {
- std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
- if (!(*stream))
- {
- file_name.clear();
- delete stream;
- return false;
- }
- else
- stream_ptr = stream;
- return true;
- }
- else if (e_rdwrt == mode)
- {
- std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
- if (!(*stream))
- {
- file_name.clear();
- delete stream;
- return false;
- }
- else
- stream_ptr = stream;
- return true;
- }
- else
- return false;
- }
- template <typename Stream, typename Ptr>
- void close(Ptr& p)
- {
- Stream* stream = reinterpret_cast<Stream*>(p);
- stream->close();
- delete stream;
- p = reinterpret_cast<Ptr>(0);
- }
- bool close()
- {
- switch (mode)
- {
- case e_read : close<std::ifstream>(stream_ptr);
- break;
- case e_write : close<std::ofstream>(stream_ptr);
- break;
- case e_rdwrt : close<std::fstream> (stream_ptr);
- break;
- default : return false;
- }
- return true;
- }
- template <typename View>
- bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
- {
- switch (mode)
- {
- case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
- write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
- break;
- case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
- write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
- break;
- default : return false;
- }
- return true;
- }
- template <typename View>
- bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
- {
- switch (mode)
- {
- case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
- read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
- break;
- case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
- read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
- break;
- default : return false;
- }
- return true;
- }
- bool getline(std::string& s)
- {
- switch (mode)
- {
- case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
- case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
- default : return false;
- }
- }
- bool eof() const
- {
- switch (mode)
- {
- case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
- case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
- case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
- default : return true;
- }
- }
- file_mode get_file_mode(const std::string& access) const
- {
- if (access.empty() || access.size() > 2)
- return e_error;
- std::size_t w_cnt = 0;
- std::size_t r_cnt = 0;
- for (std::size_t i = 0; i < access.size(); ++i)
- {
- switch (std::tolower(access[i]))
- {
- case 'r' : r_cnt++; break;
- case 'w' : w_cnt++; break;
- default : return e_error;
- }
- }
- if ((0 == r_cnt) && (0 == w_cnt))
- return e_error;
- else if ((r_cnt > 1) || (w_cnt > 1))
- return e_error;
- else if ((1 == r_cnt) && (1 == w_cnt))
- return e_rdwrt;
- else if (1 == r_cnt)
- return e_read;
- else
- return e_write;
- }
- };
- template <typename T>
- file_descriptor* make_handle(T v)
- {
- file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
- std::memcpy(reinterpret_cast<char*>(&fd),
- reinterpret_cast<const char*>(&v),
- sizeof(fd));
- return fd;
- }
- template <typename T>
- void perform_check()
- {
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable: 4127)
- #endif
- if (sizeof(T) < sizeof(void*))
- {
- throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- }
- } // namespace exprtk::rtl::io::file::details
- template <typename T>
- class open : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::string_view string_t;
- using exprtk::igeneric_function<T>::operator();
- open()
- : exprtk::igeneric_function<T>("S|SS")
- { details::perform_check<T>(); }
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- std::string file_name = to_str(string_t(parameters[0]));
- std::string access;
- if (file_name.empty())
- return T(0);
- if (0 == ps_index)
- access = "r";
- else if (0 == string_t(parameters[1]).size())
- return T(0);
- else
- access = to_str(string_t(parameters[1]));
- details::file_descriptor* fd = new details::file_descriptor(file_name,access);
- if (fd->open())
- {
- T t = T(0);
- std::memcpy(reinterpret_cast<char*>(&t ),
- reinterpret_cast<char*>(&fd),
- sizeof(fd));
- return t;
- }
- else
- {
- delete fd;
- return T(0);
- }
- }
- };
- template <typename T>
- struct close : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- close()
- : exprtk::ifunction<T>(1)
- { details::perform_check<T>(); }
- inline T operator() (const T& v)
- {
- details::file_descriptor* fd = details::make_handle(v);
- if (!fd->close())
- return T(0);
- delete fd;
- return T(1);
- }
- };
- template <typename T>
- class write : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::string_view string_t;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- write()
- : igfun_t("TS|TST|TV|TVT")
- { details::perform_check<T>(); }
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
- std::size_t amount = 0;
- switch (ps_index)
- {
- case 0 : {
- const string_t buffer(parameters[1]);
- amount = buffer.size();
- return T(fd->write(buffer, amount) ? 1 : 0);
- }
- case 1 : {
- const string_t buffer(parameters[1]);
- amount = std::min(buffer.size(),
- static_cast<std::size_t>(scalar_t(parameters[2])()));
- return T(fd->write(buffer, amount) ? 1 : 0);
- }
- case 2 : {
- const vector_t vec(parameters[1]);
- amount = vec.size();
- return T(fd->write(vec, amount) ? 1 : 0);
- }
- case 3 : {
- const vector_t vec(parameters[1]);
- amount = std::min(vec.size(),
- static_cast<std::size_t>(scalar_t(parameters[2])()));
- return T(fd->write(vec, amount) ? 1 : 0);
- }
- }
- return T(0);
- }
- };
- template <typename T>
- class read : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::string_view string_t;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- read()
- : igfun_t("TS|TST|TV|TVT")
- { details::perform_check<T>(); }
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
- std::size_t amount = 0;
- switch (ps_index)
- {
- case 0 : {
- string_t buffer(parameters[1]);
- amount = buffer.size();
- return T(fd->read(buffer,amount) ? 1 : 0);
- }
- case 1 : {
- string_t buffer(parameters[1]);
- amount = std::min(buffer.size(),
- static_cast<std::size_t>(scalar_t(parameters[2])()));
- return T(fd->read(buffer,amount) ? 1 : 0);
- }
- case 2 : {
- vector_t vec(parameters[1]);
- amount = vec.size();
- return T(fd->read(vec,amount) ? 1 : 0);
- }
- case 3 : {
- vector_t vec(parameters[1]);
- amount = std::min(vec.size(),
- static_cast<std::size_t>(scalar_t(parameters[2])()));
- return T(fd->read(vec,amount) ? 1 : 0);
- }
- }
- return T(0);
- }
- };
- template <typename T>
- class getline : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::string_view string_t;
- typedef typename generic_type::scalar_view scalar_t;
- using exprtk::igeneric_function<T>::operator();
- getline()
- : igfun_t("T",igfun_t::e_rtrn_string)
- { details::perform_check<T>(); }
- inline T operator() (std::string& result,
- parameter_list_t parameters)
- {
- details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
- return T(fd->getline(result) ? 1 : 0);
- }
- };
- template <typename T>
- struct eof : public exprtk::ifunction<T>
- {
- using exprtk::ifunction<T>::operator();
- eof()
- : exprtk::ifunction<T>(1)
- { details::perform_check<T>(); }
- inline T operator() (const T& v)
- {
- details::file_descriptor* fd = details::make_handle(v);
- return (fd->eof() ? T(1) : T(0));
- }
- };
- template <typename T>
- struct package
- {
- open <T> o;
- close <T> c;
- write <T> w;
- read <T> r;
- getline<T> g;
- eof <T> e;
- bool register_package(exprtk::symbol_table<T>& symtab)
- {
- #define exprtk_register_function(FunctionName,FunctionType) \
- if (!symtab.add_function(FunctionName,FunctionType)) \
- { \
- exprtk_debug(( \
- "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
- FunctionName)); \
- return false; \
- } \
- exprtk_register_function("open" ,o)
- exprtk_register_function("close" ,c)
- exprtk_register_function("write" ,w)
- exprtk_register_function("read" ,r)
- exprtk_register_function("getline",g)
- exprtk_register_function("eof" ,e)
- #undef exprtk_register_function
- return true;
- }
- };
- } // namespace exprtk::rtl::io::file
- } // namespace exprtk::rtl::io
- } // namespace exprtk::rtl
- } // namespace exprtk
- #endif
- #ifndef exprtk_disable_rtl_vecops
- namespace exprtk
- {
- namespace rtl { namespace vecops {
- namespace helper
- {
- template <typename Vector>
- inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
- {
- if (r0 > (v.size() - 1))
- return true;
- else if (r1 > (v.size() - 1))
- return true;
- else if (r1 < r0)
- return true;
- else
- return false;
- }
- template <typename T>
- struct load_vector_range
- {
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- static inline bool process(parameter_list_t& parameters,
- std::size_t& r0, std::size_t& r1,
- const std::size_t& r0_prmidx,
- const std::size_t& r1_prmidx,
- const std::size_t vec_idx = 0)
- {
- if (r0_prmidx >= parameters.size())
- return false;
- if (r1_prmidx >= parameters.size())
- return false;
- if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
- return false;
- if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
- return false;
- return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
- }
- };
- }
- namespace details
- {
- template <typename T>
- inline void kahan_sum(T& sum, T& error, const T v)
- {
- const T x = v - error;
- const T y = sum + x;
- error = (y - sum) - x;
- sum = y;
- }
- } // namespace exprtk::rtl::details
- template <typename T>
- class all_true : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- all_true()
- : exprtk::igeneric_function<T>("V|VTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
- )
- return std::numeric_limits<T>::quiet_NaN();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- if (vec[i] == T(0))
- {
- return T(0);
- }
- }
- return T(1);
- }
- };
- template <typename T>
- class all_false : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- all_false()
- : exprtk::igeneric_function<T>("V|VTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
- )
- return std::numeric_limits<T>::quiet_NaN();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- if (vec[i] != T(0))
- {
- return T(0);
- }
- }
- return T(1);
- }
- };
- template <typename T>
- class any_true : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- any_true()
- : exprtk::igeneric_function<T>("V|VTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
- )
- return std::numeric_limits<T>::quiet_NaN();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- if (vec[i] != T(0))
- {
- return T(1);
- }
- }
- return T(0);
- }
- };
- template <typename T>
- class any_false : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- any_false()
- : exprtk::igeneric_function<T>("V|VTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
- )
- return std::numeric_limits<T>::quiet_NaN();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- if (vec[i] == T(0))
- {
- return T(1);
- }
- }
- return T(0);
- }
- };
- template <typename T>
- class count : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- count()
- : exprtk::igeneric_function<T>("V|VTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
- )
- return std::numeric_limits<T>::quiet_NaN();
- std::size_t cnt = 0;
- for (std::size_t i = r0; i <= r1; ++i)
- {
- if (vec[i] != T(0)) ++cnt;
- }
- return T(cnt);
- }
- };
- template <typename T>
- class copy : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- copy()
- : exprtk::igeneric_function<T>("VV|VTTVTT")
- /*
- Overloads:
- 0. VV - x(vector), y(vector)
- 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[0]);
- vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
- std::size_t xr0 = 0;
- std::size_t xr1 = x.size() - 1;
- std::size_t yr0 = 0;
- std::size_t yr1 = y.size() - 1;
- if (1 == ps_index)
- {
- if (
- !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
- !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
- )
- return T(0);
- }
- const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
- std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
- return T(n);
- }
- };
- template <typename T>
- class rol : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- rol()
- : exprtk::igeneric_function<T>("VT|VTTT")
- /*
- Overloads:
- 0. VT - vector, N
- 1. VTTT - vector, N, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- std::size_t n = 0;
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (!scalar_t(parameters[1]).to_uint(n))
- return T(0);
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
- )
- return T(0);
- std::size_t dist = r1 - r0 + 1;
- std::size_t shift = n % dist;
- std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
- return T(1);
- }
- };
- template <typename T>
- class ror : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- ror()
- : exprtk::igeneric_function<T>("VT|VTTT")
- /*
- Overloads:
- 0. VT - vector, N
- 1. VTTT - vector, N, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- std::size_t n = 0;
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (!scalar_t(parameters[1]).to_uint(n))
- return T(0);
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
- )
- return T(0);
- std::size_t dist = r1 - r0 + 1;
- std::size_t shift = (dist - (n % dist)) % dist;
- std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
- return T(1);
- }
- };
- template <typename T>
- class shift_left : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- shift_left()
- : exprtk::igeneric_function<T>("VT|VTTT")
- /*
- Overloads:
- 0. VT - vector, N
- 1. VTTT - vector, N, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- std::size_t n = 0;
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (!scalar_t(parameters[1]).to_uint(n))
- return T(0);
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
- )
- return T(0);
- std::size_t dist = r1 - r0 + 1;
- if (n > dist)
- return T(0);
- std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);
- for (std::size_t i = r1 - n + 1; i <= r1; ++i)
- {
- vec[i] = T(0);
- }
- return T(1);
- }
- };
- template <typename T>
- class shift_right : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- shift_right()
- : exprtk::igeneric_function<T>("VT|VTTT")
- /*
- Overloads:
- 0. VT - vector, N
- 1. VTTT - vector, N, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- std::size_t n = 0;
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (!scalar_t(parameters[1]).to_uint(n))
- return T(0);
- if (
- (1 == ps_index) &&
- !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
- )
- return T(0);
- std::size_t dist = r1 - r0 + 1;
- if (n > dist)
- return T(0);
- std::size_t shift = (dist - (n % dist)) % dist;
- std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
- for (std::size_t i = r0; i < r0 + n; ++i)
- {
- vec[i] = T(0);
- }
- return T(1);
- }
- };
- template <typename T>
- class sort : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::string_view string_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- sort()
- : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- 2. VS - vector, string
- 3. VSTT - vector, string, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
- return T(0);
- if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
- return T(0);
- bool ascending = true;
- if ((2 == ps_index) || (3 == ps_index))
- {
- if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
- ascending = true;
- else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
- ascending = false;
- else
- return T(0);
- }
- if (ascending)
- std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T> ());
- else
- std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
- return T(1);
- }
- };
- template <typename T>
- class nthelement : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- nthelement()
- : exprtk::igeneric_function<T>("VT|VTTT")
- /*
- Overloads:
- 0. VT - vector, nth-element
- 1. VTTT - vector, nth-element, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- std::size_t n = 0;
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if (!scalar_t(parameters[1]).to_uint(n))
- return T(0);
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
- return std::numeric_limits<T>::quiet_NaN();
- std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
- return T(1);
- }
- };
- template <typename T>
- class iota : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- iota()
- : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
- /*
- Overloads:
- 0. VT - vector, increment
- 1. VTT - vector, increment, base
- 2. VTTTT - vector, increment, r0, r1
- 3. VTTTT - vector, increment, base, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- vector_t vec(parameters[0]);
- T increment = scalar_t(parameters[1])();
- T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
- return std::numeric_limits<T>::quiet_NaN();
- else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
- return std::numeric_limits<T>::quiet_NaN();
- else
- {
- long long j = 0;
- for (std::size_t i = r0; i <= r1; ++i, ++j)
- {
- vec[i] = base + (increment * j);
- }
- }
- return T(1);
- }
- };
- template <typename T>
- class sumk : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- sumk()
- : exprtk::igeneric_function<T>("V|VTT")
- /*
- Overloads:
- 0. V - vector
- 1. VTT - vector, r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t vec(parameters[0]);
- std::size_t r0 = 0;
- std::size_t r1 = vec.size() - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
- return std::numeric_limits<T>::quiet_NaN();
- T result = T(0);
- T error = T(0);
- for (std::size_t i = r0; i <= r1; ++i)
- {
- details::kahan_sum(result, error, vec[i]);
- }
- return result;
- }
- };
- template <typename T>
- class axpy : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- axpy()
- : exprtk::igeneric_function<T>("TVV|TVVTT")
- /*
- y <- ax + y
- Overloads:
- 0. TVV - a, x(vector), y(vector)
- 1. TVVTT - a, x(vector), y(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[1]);
- vector_t y(parameters[2]);
- std::size_t r0 = 0;
- std::size_t r1 = std::min(x.size(),y.size()) - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(y, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- const T a = scalar_t(parameters[0])();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- y[i] = (a * x[i]) + y[i];
- }
- return T(1);
- }
- };
- template <typename T>
- class axpby : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- axpby()
- : exprtk::igeneric_function<T>("TVTV|TVTVTT")
- /*
- y <- ax + by
- Overloads:
- 0. TVTV - a, x(vector), b, y(vector)
- 1. TVTVTT - a, x(vector), b, y(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[1]);
- vector_t y(parameters[3]);
- std::size_t r0 = 0;
- std::size_t r1 = std::min(x.size(),y.size()) - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(y, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- const T a = scalar_t(parameters[0])();
- const T b = scalar_t(parameters[2])();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- y[i] = (a * x[i]) + (b * y[i]);
- }
- return T(1);
- }
- };
- template <typename T>
- class axpyz : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- axpyz()
- : exprtk::igeneric_function<T>("TVVV|TVVVTT")
- /*
- z <- ax + y
- Overloads:
- 0. TVVV - a, x(vector), y(vector), z(vector)
- 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[1]);
- const vector_t y(parameters[2]);
- vector_t z(parameters[3]);
- std::size_t r0 = 0;
- std::size_t r1 = std::min(x.size(),y.size()) - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(y, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(z, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- const T a = scalar_t(parameters[0])();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- z[i] = (a * x[i]) + y[i];
- }
- return T(1);
- }
- };
- template <typename T>
- class axpbyz : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- axpbyz()
- : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
- /*
- z <- ax + by
- Overloads:
- 0. TVTVV - a, x(vector), b, y(vector), z(vector)
- 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[1]);
- const vector_t y(parameters[3]);
- vector_t z(parameters[4]);
- std::size_t r0 = 0;
- std::size_t r1 = std::min(x.size(),y.size()) - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(y, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(z, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- const T a = scalar_t(parameters[0])();
- const T b = scalar_t(parameters[2])();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- z[i] = (a * x[i]) + (b * y[i]);
- }
- return T(1);
- }
- };
- template <typename T>
- class axpbz : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- axpbz()
- : exprtk::igeneric_function<T>("TVTV|TVTVTT")
- /*
- z <- ax + b
- Overloads:
- 0. TVTV - a, x(vector), b, z(vector)
- 1. TVTVTT - a, x(vector), b, z(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[1]);
- vector_t z(parameters[3]);
- std::size_t r0 = 0;
- std::size_t r1 = x.size() - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(z, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- const T a = scalar_t(parameters[0])();
- const T b = scalar_t(parameters[2])();
- for (std::size_t i = r0; i <= r1; ++i)
- {
- z[i] = (a * x[i]) + b;
- }
- return T(1);
- }
- };
- template <typename T>
- class dot : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- dot()
- : exprtk::igeneric_function<T>("VV|VVTT")
- /*
- Overloads:
- 0. VV - x(vector), y(vector)
- 1. VVTT - x(vector), y(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[0]);
- const vector_t y(parameters[1]);
- std::size_t r0 = 0;
- std::size_t r1 = std::min(x.size(),y.size()) - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(y, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- T result = T(0);
- for (std::size_t i = r0; i <= r1; ++i)
- {
- result += (x[i] * y[i]);
- }
- return result;
- }
- };
- template <typename T>
- class dotk : public exprtk::igeneric_function<T>
- {
- public:
- typedef typename exprtk::igeneric_function<T> igfun_t;
- typedef typename igfun_t::parameter_list_t parameter_list_t;
- typedef typename igfun_t::generic_type generic_type;
- typedef typename generic_type::scalar_view scalar_t;
- typedef typename generic_type::vector_view vector_t;
- using exprtk::igeneric_function<T>::operator();
- dotk()
- : exprtk::igeneric_function<T>("VV|VVTT")
- /*
- Overloads:
- 0. VV - x(vector), y(vector)
- 1. VVTT - x(vector), y(vector), r0, r1
- */
- {}
- inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
- {
- const vector_t x(parameters[0]);
- const vector_t y(parameters[1]);
- std::size_t r0 = 0;
- std::size_t r1 = std::min(x.size(),y.size()) - 1;
- if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
- return std::numeric_limits<T>::quiet_NaN();
- else if (helper::invalid_range(y, r0, r1))
- return std::numeric_limits<T>::quiet_NaN();
- T result = T(0);
- T error = T(0);
- for (std::size_t i = r0; i <= r1; ++i)
- {
- details::kahan_sum(result, error, (x[i] * y[i]));
- }
- return result;
- }
- };
- template <typename T>
- struct package
- {
- all_true <T> at;
- all_false <T> af;
- any_true <T> nt;
- any_false <T> nf;
- count <T> c;
- copy <T> cp;
- rol <T> rl;
- ror <T> rr;
- shift_left <T> sl;
- shift_right<T> sr;
- sort <T> st;
- nthelement <T> ne;
- iota <T> ia;
- sumk <T> sk;
- axpy <T> b1_axpy;
- axpby <T> b1_axpby;
- axpyz <T> b1_axpyz;
- axpbyz <T> b1_axpbyz;
- axpbz <T> b1_axpbz;
- dot <T> dt;
- dotk <T> dtk;
- bool register_package(exprtk::symbol_table<T>& symtab)
- {
- #define exprtk_register_function(FunctionName,FunctionType) \
- if (!symtab.add_function(FunctionName,FunctionType)) \
- { \
- exprtk_debug(( \
- "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
- FunctionName)); \
- return false; \
- } \
- exprtk_register_function("all_true" ,at)
- exprtk_register_function("all_false" ,af)
- exprtk_register_function("any_true" ,nt)
- exprtk_register_function("any_false" ,nf)
- exprtk_register_function("count" , c)
- exprtk_register_function("copy" ,cp)
- exprtk_register_function("rotate_left" ,rl)
- exprtk_register_function("rol" ,rl)
- exprtk_register_function("rotate_right" ,rr)
- exprtk_register_function("ror" ,rr)
- exprtk_register_function("shftl" ,sl)
- exprtk_register_function("shftr" ,sr)
- exprtk_register_function("sort" ,st)
- exprtk_register_function("nth_element" ,ne)
- exprtk_register_function("iota" ,ia)
- exprtk_register_function("sumk" ,sk)
- exprtk_register_function("axpy" ,b1_axpy)
- exprtk_register_function("axpby" ,b1_axpby)
- exprtk_register_function("axpyz" ,b1_axpyz)
- exprtk_register_function("axpbyz",b1_axpbyz)
- exprtk_register_function("axpbz" ,b1_axpbz)
- exprtk_register_function("dot" ,dt)
- exprtk_register_function("dotk" ,dtk)
- #undef exprtk_register_function
- return true;
- }
- };
- } // namespace exprtk::rtl::vecops
- } // namespace exprtk::rtl
- } // namespace exprtk
- #endif
- namespace exprtk
- {
- namespace information
- {
- static const char* library = "Mathematical Expression Toolkit";
- static const char* version = "2.7182818284590452353602874713526624977572470936999595749"
- "669676277240766303535475945713821785251664274274663919320";
- static const char* date = "20200101";
- static inline std::string data()
- {
- static const std::string info_str = std::string(library) +
- std::string(" v") + std::string(version) +
- std::string(" (") + date + std::string(")");
- return info_str;
- }
- } // namespace information
- #ifdef exprtk_debug
- #undef exprtk_debug
- #endif
- #ifdef exprtk_error_location
- #undef exprtk_error_location
- #endif
- #ifdef exprtk_disable_fallthrough_begin
- #undef exprtk_disable_fallthrough_begin
- #endif
- #ifdef exprtk_disable_fallthrough_end
- #undef exprtk_disable_fallthrough_end
- #endif
- } // namespace exprtk
- #endif
|