| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126 |
- /*
- * This file is a part of TTMath Bignum Library
- * and is distributed under the (new) BSD licence.
- * Author: Tomasz Sowa <[email protected]>
- */
- /*
- * Copyright (c) 2006-2011, Tomasz Sowa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name Tomasz Sowa nor the names of contributors to this
- * project may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef headerfilettmathuint
- #define headerfilettmathuint
- /*!
- \file ttmathuint.h
- \brief template class UInt<uint>
- */
- #include <iostream>
- #include <iomanip>
- #include "ttmathtypes.h"
- #include "ttmathmisc.h"
- /*!
- \brief a namespace for the TTMath library
- */
- namespace ttmath
- {
- /*!
- \brief UInt implements a big integer value without a sign
- value_size - how many bytes specify our value
- on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
- on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits
- value_size = 1,2,3,4,5,6....
- */
- template<uint value_size>
- class UInt
- {
- public:
- /*!
- buffer for the integer value
- table[0] - the lowest word of the value
- */
- uint table[value_size];
- /*!
- some methods used for debugging purposes
- */
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len)
- {
- output << msg << std::endl;
- for(uint i=0 ; i<vector_len ; ++i)
- output << " table[" << i << "]: " << vector[i] << std::endl;
- }
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len)
- {
- PrintVectorLog(msg, output, vector, vector_len);
- output << " carry: " << carry << std::endl;
- }
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- void PrintLog(const char_type * msg, ostream_type & output) const
- {
- PrintVectorLog(msg, output, table, value_size);
- }
- /*!
- this method is used when macro TTMATH_DEBUG_LOG is defined
- */
- template<class char_type, class ostream_type>
- void PrintLog(const char_type * msg, uint carry, ostream_type & output) const
- {
- PrintVectorLog(msg, output, table, value_size);
- output << " carry: " << carry << std::endl;
- }
- /*!
- this method returns the size of the table
- */
- uint Size() const
- {
- return value_size;
- }
- /*!
- this method sets zero
- */
- void SetZero()
- {
- // in the future here can be 'memset'
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0;
- TTMATH_LOG("UInt::SetZero")
- }
- /*!
- this method sets one
- */
- void SetOne()
- {
- SetZero();
- table[0] = 1;
- TTMATH_LOG("UInt::SetOne")
- }
- /*!
- this method sets the max value which this class can hold
- (all bits will be one)
- */
- void SetMax()
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = TTMATH_UINT_MAX_VALUE;
- TTMATH_LOG("UInt::SetMax")
- }
- /*!
- this method sets the min value which this class can hold
- (for an unsigned integer value the zero is the smallest value)
- */
- void SetMin()
- {
- SetZero();
- TTMATH_LOG("UInt::SetMin")
- }
- /*!
- this method swappes this for an argument
- */
- void Swap(UInt<value_size> & ss2)
- {
- for(uint i=0 ; i<value_size ; ++i)
- {
- uint temp = table[i];
- table[i] = ss2.table[i];
- ss2.table[i] = temp;
- }
- }
- #ifdef TTMATH_PLATFORM32
- /*!
- this method copies the value stored in an another table
- (warning: first values in temp_table are the highest words -- it's different
- from our table)
- we copy as many words as it is possible
-
- if temp_table_len is bigger than value_size we'll try to round
- the lowest word from table depending on the last not used bit in temp_table
- (this rounding isn't a perfect rounding -- look at the description below)
- and if temp_table_len is smaller than value_size we'll clear the rest words
- in the table
- */
- void SetFromTable(const uint * temp_table, uint temp_table_len)
- {
- uint temp_table_index = 0;
- sint i; // 'i' with a sign
- for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
- table[i] = temp_table[ temp_table_index ];
- // rounding mantissa
- if( temp_table_index < temp_table_len )
- {
- if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- /*
- very simply rounding
- if the bit from not used last word from temp_table is set to one
- we're rouding the lowest word in the table
- in fact there should be a normal addition but
- we don't use Add() or AddTwoInts() because these methods
- can set a carry and then there'll be a small problem
- for optimization
- */
- if( table[0] != TTMATH_UINT_MAX_VALUE )
- ++table[0];
- }
- }
- // cleaning the rest of the mantissa
- for( ; i>=0 ; --i)
- table[i] = 0;
- TTMATH_LOG("UInt::SetFromTable")
- }
- #endif
- #ifdef TTMATH_PLATFORM64
- /*!
- this method copies the value stored in an another table
- (warning: first values in temp_table are the highest words -- it's different
- from our table)
- ***this method is created only on a 64bit platform***
- we copy as many words as it is possible
-
- if temp_table_len is bigger than value_size we'll try to round
- the lowest word from table depending on the last not used bit in temp_table
- (this rounding isn't a perfect rounding -- look at the description below)
- and if temp_table_len is smaller than value_size we'll clear the rest words
- in the table
- warning: we're using 'temp_table' as a pointer at 32bit words
- */
- void SetFromTable(const unsigned int * temp_table, uint temp_table_len)
- {
- uint temp_table_index = 0;
- sint i; // 'i' with a sign
- for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
- {
- table[i] = uint(temp_table[ temp_table_index ]) << 32;
- ++temp_table_index;
- if( temp_table_index<temp_table_len )
- table[i] |= temp_table[ temp_table_index ];
- }
- // rounding mantissa
- if( temp_table_index < temp_table_len )
- {
- if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
- {
- /*
- very simply rounding
- if the bit from not used last word from temp_table is set to one
- we're rouding the lowest word in the table
- in fact there should be a normal addition but
- we don't use Add() or AddTwoInts() because these methods
- can set a carry and then there'll be a small problem
- for optimization
- */
- if( table[0] != TTMATH_UINT_MAX_VALUE )
- ++table[0];
- }
- }
- // cleaning the rest of the mantissa
- for( ; i >= 0 ; --i)
- table[i] = 0;
- TTMATH_LOG("UInt::SetFromTable")
- }
- #endif
- /*!
- *
- * basic mathematic functions
- *
- */
- /*!
- this method adds one to the existing value
- */
- uint AddOne()
- {
- return AddInt(1);
- }
- /*!
- this method subtracts one from the existing value
- */
- uint SubOne()
- {
- return SubInt(1);
- }
- private:
- /*!
- an auxiliary method for moving bits into the left hand side
- this method moves only words
- */
- void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c)
- {
- rest_bits = bits % TTMATH_BITS_PER_UINT;
- uint all_words = bits / TTMATH_BITS_PER_UINT;
- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0;
- if( all_words >= value_size )
- {
- if( all_words == value_size && rest_bits == 0 )
- last_c = table[0] & 1;
- // else: last_c is default set to 0
- // clearing
- for(uint i = 0 ; i<value_size ; ++i)
- table[i] = mask;
- rest_bits = 0;
- }
- else
- if( all_words > 0 )
- {
- // 0 < all_words < value_size
-
- sint first, second;
- last_c = table[value_size - all_words] & 1; // all_words is greater than 0
- // copying the first part of the value
- for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
- table[first] = table[second];
- // setting the rest to 'c'
- for( ; first>=0 ; --first )
- table[first] = mask;
- }
- TTMATH_LOG("UInt::RclMoveAllWords")
- }
-
- public:
- /*!
- moving all bits into the left side 'bits' times
- return value <- this <- C
- bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
- or it can be even bigger then all bits will be set to 'c'
- the value c will be set into the lowest bits
- and the method returns state of the last moved bit
- */
- uint Rcl(uint bits, uint c=0)
- {
- uint last_c = 0;
- uint rest_bits = bits;
- if( bits == 0 )
- return 0;
- if( bits >= TTMATH_BITS_PER_UINT )
- RclMoveAllWords(rest_bits, last_c, bits, c);
- if( rest_bits == 0 )
- {
- TTMATH_LOG("UInt::Rcl")
- return last_c;
- }
- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now
- if( rest_bits == 1 )
- {
- last_c = Rcl2_one(c);
- }
- else if( rest_bits == 2 )
- {
- // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c)
- Rcl2_one(c);
- last_c = Rcl2_one(c);
- }
- else
- {
- last_c = Rcl2(rest_bits, c);
- }
- TTMATH_LOGC("UInt::Rcl", last_c)
- return last_c;
- }
- private:
- /*!
- an auxiliary method for moving bits into the right hand side
- this method moves only words
- */
- void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c)
- {
- rest_bits = bits % TTMATH_BITS_PER_UINT;
- uint all_words = bits / TTMATH_BITS_PER_UINT;
- uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0;
- if( all_words >= value_size )
- {
- if( all_words == value_size && rest_bits == 0 )
- last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
- // else: last_c is default set to 0
- // clearing
- for(uint i = 0 ; i<value_size ; ++i)
- table[i] = mask;
- rest_bits = 0;
- }
- else if( all_words > 0 )
- {
- // 0 < all_words < value_size
- uint first, second;
- last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0
- // copying the first part of the value
- for(first=0, second=all_words ; second<value_size ; ++first, ++second)
- table[first] = table[second];
- // setting the rest to 'c'
- for( ; first<value_size ; ++first )
- table[first] = mask;
- }
- TTMATH_LOG("UInt::RcrMoveAllWords")
- }
- public:
- /*!
- moving all bits into the right side 'bits' times
- c -> this -> return value
- bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
- or it can be even bigger then all bits will be set to 'c'
- the value c will be set into the highest bits
- and the method returns state of the last moved bit
- */
- uint Rcr(uint bits, uint c=0)
- {
- uint last_c = 0;
- uint rest_bits = bits;
-
- if( bits == 0 )
- return 0;
- if( bits >= TTMATH_BITS_PER_UINT )
- RcrMoveAllWords(rest_bits, last_c, bits, c);
- if( rest_bits == 0 )
- {
- TTMATH_LOG("UInt::Rcr")
- return last_c;
- }
- // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now
- if( rest_bits == 1 )
- {
- last_c = Rcr2_one(c);
- }
- else if( rest_bits == 2 )
- {
- // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c)
- Rcr2_one(c);
- last_c = Rcr2_one(c);
- }
- else
- {
- last_c = Rcr2(rest_bits, c);
- }
- TTMATH_LOGC("UInt::Rcr", last_c)
- return last_c;
- }
- /*!
- this method moves all bits into the left side
- (it returns value how many bits have been moved)
- */
- uint CompensationToLeft()
- {
- uint moving = 0;
- // a - index a last word which is different from zero
- sint a;
- for(a=value_size-1 ; a>=0 && table[a]==0 ; --a);
- if( a < 0 )
- return moving; // all words in table have zero
- if( a != value_size-1 )
- {
- moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT;
- // moving all words
- sint i;
- for(i=value_size-1 ; a>=0 ; --i, --a)
- table[i] = table[a];
- // setting the rest word to zero
- for(; i>=0 ; --i)
- table[i] = 0;
- }
- uint moving2 = FindLeadingBitInWord( table[value_size-1] );
- // moving2 is different from -1 because the value table[value_size-1]
- // is not zero
- moving2 = TTMATH_BITS_PER_UINT - moving2 - 1;
- Rcl(moving2);
- TTMATH_LOG("UInt::CompensationToLeft")
- return moving + moving2;
- }
- /*!
- this method looks for the highest set bit
-
- result:
- if 'this' is not zero:
- return value - true
- 'table_id' - the index of a word <0..value_size-1>
- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
- if 'this' is zero:
- return value - false
- both 'table_id' and 'index' are zero
- */
- bool FindLeadingBit(uint & table_id, uint & index) const
- {
- for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id);
- if( table_id==0 && table[table_id]==0 )
- {
- // is zero
- index = 0;
- return false;
- }
-
- // table[table_id] is different from 0
- index = FindLeadingBitInWord( table[table_id] );
- return true;
- }
- /*!
- this method looks for the smallest set bit
-
- result:
- if 'this' is not zero:
- return value - true
- 'table_id' - the index of a word <0..value_size-1>
- 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
- if 'this' is zero:
- return value - false
- both 'table_id' and 'index' are zero
- */
- bool FindLowestBit(uint & table_id, uint & index) const
- {
- for(table_id=0 ; table_id<value_size && table[table_id]==0 ; ++table_id);
- if( table_id >= value_size )
- {
- // is zero
- index = 0;
- table_id = 0;
- return false;
- }
-
- // table[table_id] is different from 0
- index = FindLowestBitInWord( table[table_id] );
- return true;
- }
- /*!
- getting the 'bit_index' bit
- bit_index bigger or equal zero
- */
- uint GetBit(uint bit_index) const
- {
- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
- uint index = bit_index / TTMATH_BITS_PER_UINT;
- uint bit = bit_index % TTMATH_BITS_PER_UINT;
- uint temp = table[index];
- uint res = SetBitInWord(temp, bit);
- return res;
- }
- /*!
- setting the 'bit_index' bit
- and returning the last state of the bit
- bit_index bigger or equal zero
- */
- uint SetBit(uint bit_index)
- {
- TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
- uint index = bit_index / TTMATH_BITS_PER_UINT;
- uint bit = bit_index % TTMATH_BITS_PER_UINT;
- uint res = SetBitInWord(table[index], bit);
- TTMATH_LOG("UInt::SetBit")
- return res;
- }
- /*!
- this method performs a bitwise operation AND
- */
- void BitAnd(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] &= ss2.table[x];
- TTMATH_LOG("UInt::BitAnd")
- }
- /*!
- this method performs a bitwise operation OR
- */
- void BitOr(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] |= ss2.table[x];
- TTMATH_LOG("UInt::BitOr")
- }
- /*!
- this method performs a bitwise operation XOR
- */
- void BitXor(const UInt<value_size> & ss2)
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] ^= ss2.table[x];
- TTMATH_LOG("UInt::BitXor")
- }
- /*!
- this method performs a bitwise operation NOT
- */
- void BitNot()
- {
- for(uint x=0 ; x<value_size ; ++x)
- table[x] = ~table[x];
- TTMATH_LOG("UInt::BitNot")
- }
- /*!
- this method performs a bitwise operation NOT but only
- on the range of <0, leading_bit>
- for example:
- BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7
- */
- void BitNot2()
- {
- uint table_id, index;
- if( FindLeadingBit(table_id, index) )
- {
- for(uint x=0 ; x<table_id ; ++x)
- table[x] = ~table[x];
- uint mask = TTMATH_UINT_MAX_VALUE;
- uint shift = TTMATH_BITS_PER_UINT - index - 1;
- if(shift)
- mask >>= shift;
- table[table_id] ^= mask;
- }
- else
- table[0] = 1;
- TTMATH_LOG("UInt::BitNot2")
- }
- /*!
- *
- * Multiplication
- *
- *
- */
- public:
- /*!
- multiplication: this = this * ss2
- it can return a carry
- */
- uint MulInt(uint ss2)
- {
- uint r1, r2, x1;
- uint c = 0;
- UInt<value_size> u(*this);
- SetZero();
- if( ss2 == 0 )
- {
- TTMATH_LOGC("UInt::MulInt(uint)", 0)
- return 0;
- }
- for(x1=0 ; x1<value_size-1 ; ++x1)
- {
- MulTwoWords(u.table[x1], ss2, &r2, &r1);
- c += AddTwoInts(r2,r1,x1);
- }
- // x1 = value_size-1 (last word)
- MulTwoWords(u.table[x1], ss2, &r2, &r1);
- c += (r2!=0) ? 1 : 0;
- c += AddInt(r1, x1);
- TTMATH_LOGC("UInt::MulInt(uint)", c)
- return (c==0)? 0 : 1;
- }
- /*!
- multiplication: result = this * ss2
- we're using this method only when result_size is greater than value_size
- if so there will not be a carry
- */
- template<uint result_size>
- void MulInt(uint ss2, UInt<result_size> & result) const
- {
- TTMATH_ASSERT( result_size > value_size )
- uint r2,r1;
- uint x1size=value_size;
- uint x1start=0;
- result.SetZero();
- if( ss2 == 0 )
- {
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
- return;
- }
- if( value_size > 2 )
- {
- // if the value_size is smaller than or equal to 2
- // there is no sense to set x1size and x1start to another values
- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
- if( x1size == 0 )
- {
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
- return;
- }
- for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
- }
- for(uint x1=x1start ; x1<x1size ; ++x1)
- {
- MulTwoWords(table[x1], ss2, &r2, &r1 );
- result.AddTwoInts(r2,r1,x1);
- }
- TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size)
- return;
- }
- /*!
- the multiplication 'this' = 'this' * ss2
- algorithm: 100 - means automatically choose the fastest algorithm
- */
- uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
- {
- switch( algorithm )
- {
- case 1:
- return Mul1(ss2);
- case 2:
- return Mul2(ss2);
- case 3:
- return Mul3(ss2);
- case 100:
- default:
- return MulFastest(ss2);
- }
- }
- /*!
- the multiplication 'result' = 'this' * ss2
- since the 'result' is twice bigger than 'this' and 'ss2'
- this method never returns a carry
- algorithm: 100 - means automatically choose the fastest algorithm
- */
- void MulBig(const UInt<value_size> & ss2,
- UInt<value_size*2> & result,
- uint algorithm = 100)
- {
- switch( algorithm )
- {
- case 1:
- return Mul1Big(ss2, result);
- case 2:
- return Mul2Big(ss2, result);
- case 3:
- return Mul3Big(ss2, result);
- case 100:
- default:
- return MulFastestBig(ss2, result);
- }
- }
- /*!
- the first version of the multiplication algorithm
- */
- private:
- /*!
- multiplication: this = this * ss2
- it returns carry if it has been
- */
- uint Mul1Ref(const UInt<value_size> & ss2)
- {
- TTMATH_REFERENCE_ASSERT( ss2 )
- UInt<value_size> ss1( *this );
- SetZero();
- for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i)
- {
- if( Add(*this) )
- {
- TTMATH_LOGC("UInt::Mul1", 1)
- return 1;
- }
- if( ss1.Rcl(1) )
- if( Add(ss2) )
- {
- TTMATH_LOGC("UInt::Mul1", 1)
- return 1;
- }
- }
- TTMATH_LOGC("UInt::Mul1", 0)
- return 0;
- }
- public:
- /*!
- multiplication: this = this * ss2
- can return carry
- */
- uint Mul1(const UInt<value_size> & ss2)
- {
- if( this == &ss2 )
- {
- UInt<value_size> copy_ss2(ss2);
- return Mul1Ref(copy_ss2);
- }
- else
- {
- return Mul1Ref(ss2);
- }
- }
-
- /*!
- multiplication: result = this * ss2
- result is twice bigger than 'this' and 'ss2'
- this method never returns carry
- */
- void Mul1Big(const UInt<value_size> & ss2_, UInt<value_size*2> & result)
- {
- UInt<value_size*2> ss2;
- uint i;
- // copying *this into result and ss2_ into ss2
- for(i=0 ; i<value_size ; ++i)
- {
- result.table[i] = table[i];
- ss2.table[i] = ss2_.table[i];
- }
- // cleaning the highest bytes in result and ss2
- for( ; i < value_size*2 ; ++i)
- {
- result.table[i] = 0;
- ss2.table[i] = 0;
- }
- // multiply
- // (there will not be a carry)
- result.Mul1( ss2 );
- TTMATH_LOG("UInt::Mul1Big")
- }
- /*!
- the second version of the multiplication algorithm
- this algorithm is similar to the 'schoolbook method' which is done by hand
- */
- /*!
- multiplication: this = this * ss2
- it returns carry if it has been
- */
- uint Mul2(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
- Mul2Big(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
- TTMATH_LOGC("UInt::Mul2", c)
- return c;
- }
- /*!
- multiplication: result = this * ss2
- result is twice bigger than this and ss2
- this method never returns carry
- */
- void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- Mul2Big2<value_size>(table, ss2.table, result);
- TTMATH_LOG("UInt::Mul2Big")
- }
- private:
- /*!
- an auxiliary method for calculating the multiplication
- arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding
- unnecessary copying objects), the result should be taken as a pointer too,
- but at the moment there is no method AddTwoInts() which can operate on pointers
- */
- template<uint ss_size>
- void Mul2Big2(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result)
- {
- uint x1size = ss_size, x2size = ss_size;
- uint x1start = 0, x2start = 0;
- if( ss_size > 2 )
- {
- // if the ss_size is smaller than or equal to 2
- // there is no sense to set x1size (and others) to another values
- for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size);
- for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size);
- for(x1start=0 ; x1start<x1size && ss1[x1start]==0 ; ++x1start);
- for(x2start=0 ; x2start<x2size && ss2[x2start]==0 ; ++x2start);
- }
- Mul2Big3<ss_size>(ss1, ss2, result, x1start, x1size, x2start, x2size);
- }
- /*!
- an auxiliary method for calculating the multiplication
- */
- template<uint ss_size>
- void Mul2Big3(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result, uint x1start, uint x1size, uint x2start, uint x2size)
- {
- uint r2, r1;
- result.SetZero();
- if( x1size==0 || x2size==0 )
- return;
- for(uint x1=x1start ; x1<x1size ; ++x1)
- {
- for(uint x2=x2start ; x2<x2size ; ++x2)
- {
- MulTwoWords(ss1[x1], ss2[x2], &r2, &r1);
- result.AddTwoInts(r2, r1, x2+x1);
- // here will never be a carry
- }
- }
- }
- public:
- /*!
- multiplication: this = this * ss2
- This is Karatsuba Multiplication algorithm, we're using it when value_size is greater than
- or equal to TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE macro (defined in ttmathuint.h).
- If value_size is smaller then we're using Mul2Big() instead.
- Karatsuba multiplication:
- Assume we have:
- this = x = x1*B^m + x0
- ss2 = y = y1*B^m + y0
- where x0 and y0 are less than B^m
- the product from multiplication we can show as:
- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
- where
- z2 = x1*y1
- z1 = x1*y0 + x0*y1
- z0 = x0*y0
- this is standard schoolbook algorithm with O(n^2), Karatsuba observed that z1 can be given in other form:
- z1 = (x1 + x0)*(y1 + y0) - z2 - z0 / z1 = (x1*y1 + x1*y0 + x0*y1 + x0*y0) - x1*y1 - x0*y0 = x1*y0 + x0*y1 /
- and to calculate the multiplication we need only three multiplications (with some additions and subtractions)
- Our objects 'this' and 'ss2' we divide into two parts and by using recurrence we calculate the multiplication.
- Karatsuba multiplication has O( n^(ln(3)/ln(2)) )
- */
- uint Mul3(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
- Mul3Big(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
- TTMATH_LOGC("UInt::Mul3", c)
- return c;
- }
- /*!
- multiplication: result = this * ss2
- result is twice bigger than this and ss2,
- this method never returns carry,
- (Karatsuba multiplication)
- */
- void Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- Mul3Big2<value_size>(table, ss2.table, result.table);
- TTMATH_LOG("UInt::Mul3Big")
- }
- private:
- /*!
- an auxiliary method for calculating the Karatsuba multiplication
- result_size is equal ss_size*2
- */
- template<uint ss_size>
- void Mul3Big2(const uint * ss1, const uint * ss2, uint * result)
- {
- const uint * x1, * x0, * y1, * y0;
- if( ss_size>1 && ss_size<TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
- {
- UInt<ss_size*2> res;
- Mul2Big2<ss_size>(ss1, ss2, res);
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wtautological-compare"
- #endif
- for(uint i=0 ; i<ss_size*2 ; ++i)
- result[i] = res.table[i];
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
- return;
- }
- else
- if( ss_size == 1 )
- {
- return MulTwoWords(*ss1, *ss2, &result[1], &result[0]);
- }
- if( (ss_size & 1) == 1 )
- {
- // ss_size is odd
- x0 = ss1;
- y0 = ss2;
- x1 = ss1 + ss_size / 2 + 1;
- y1 = ss2 + ss_size / 2 + 1;
- // the second vectors (x1 and y1) are smaller about one from the first ones (x0 and y0)
- Mul3Big3<ss_size/2 + 1, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
- }
- else
- {
- // ss_size is even
- x0 = ss1;
- y0 = ss2;
- x1 = ss1 + ss_size / 2;
- y1 = ss2 + ss_size / 2;
-
- // all four vectors (x0 x1 y0 y1) are equal in size
- Mul3Big3<ss_size/2, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
- }
- }
- #ifdef _MSC_VER
- #pragma warning (disable : 4717)
- //warning C4717: recursive on all control paths, function will cause runtime stack overflow
- //we have the stop point in Mul3Big2() method
- #endif
- /*!
- an auxiliary method for calculating the Karatsuba multiplication
- x = x1*B^m + x0
- y = y1*B^m + y0
- first_size - is the size of vectors: x0 and y0
- second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size)
- x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
- where
- z0 = x0*y0
- z2 = x1*y1
- z1 = (x1 + x0)*(y1 + y0) - z2 - z0
- */
- template<uint first_size, uint second_size, uint result_size>
- uint Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result)
- {
- uint i, c, xc, yc;
- UInt<first_size> temp, temp2;
- UInt<first_size*3> z1;
- // z0 and z2 we store directly in the result (we don't use any temporary variables)
- Mul3Big2<first_size>(x0, y0, result); // z0
- Mul3Big2<second_size>(x1, y1, result+first_size*2); // z2
- // now we calculate z1
- // temp = (x0 + x1)
- // temp2 = (y0 + y1)
- // we're using temp and temp2 with UInt<first_size>, although there can be a carry but
- // we simple remember it in xc and yc (xc and yc can be either 0 or 1),
- // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm):
- //
- // xc | temp
- // yc | temp2
- // --------------------
- // (temp * temp2)
- // xc*temp2 |
- // yc*temp |
- // xc*yc |
- // ---------- z1 --------
- //
- // and the result is never larger in size than 3*first_size
- xc = AddVector(x0, x1, first_size, second_size, temp.table);
- yc = AddVector(y0, y1, first_size, second_size, temp2.table);
- Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wtautological-compare"
- #endif
- // clearing the rest of z1
- for(i=first_size*2 ; i<first_size*3 ; ++i)
- z1.table[i] = 0;
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
-
- if( xc )
- {
- c = AddVector(z1.table+first_size, temp2.table, first_size*3-first_size, first_size, z1.table+first_size);
- TTMATH_ASSERT( c==0 )
- }
- if( yc )
- {
- c = AddVector(z1.table+first_size, temp.table, first_size*3-first_size, first_size, z1.table+first_size);
- TTMATH_ASSERT( c==0 )
- }
- if( xc && yc )
- {
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wtautological-compare"
- #endif
- for( i=first_size*2 ; i<first_size*3 ; ++i )
- if( ++z1.table[i] != 0 )
- break; // break if there was no carry
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
- }
- // z1 = z1 - z2
- c = SubVector(z1.table, result+first_size*2, first_size*3, second_size*2, z1.table);
- TTMATH_ASSERT(c==0)
- // z1 = z1 - z0
- c = SubVector(z1.table, result, first_size*3, first_size*2, z1.table);
- TTMATH_ASSERT(c==0)
- // here we've calculated the z1
- // now we're adding it to the result
- if( first_size > second_size )
- {
- uint z1_size = result_size - first_size;
- TTMATH_ASSERT( z1_size <= first_size*3 )
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wtautological-compare"
- #endif
- for(i=z1_size ; i<first_size*3 ; ++i)
- {
- TTMATH_ASSERT( z1.table[i] == 0 )
- }
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
-
- c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
- TTMATH_ASSERT(c==0)
- }
- else
- {
- c = AddVector(result+first_size, z1.table, result_size-first_size, first_size*3, result+first_size);
- TTMATH_ASSERT(c==0)
- }
- return c;
- }
- #ifdef _MSC_VER
- #pragma warning (default : 4717)
- #endif
- public:
- /*!
- multiplication this = this * ss2
- */
- uint MulFastest(const UInt<value_size> & ss2)
- {
- UInt<value_size*2> result;
- uint i, c = 0;
- MulFastestBig(ss2, result);
-
- // copying result
- for(i=0 ; i<value_size ; ++i)
- table[i] = result.table[i];
- // testing carry
- for( ; i<value_size*2 ; ++i)
- if( result.table[i] != 0 )
- {
- c = 1;
- break;
- }
- TTMATH_LOGC("UInt::MulFastest", c)
- return c;
- }
- /*!
- multiplication result = this * ss2
- this method is trying to select the fastest algorithm
- (in the future this method can be improved)
- */
- void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
- {
- if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
- return Mul2Big(ss2, result);
- uint x1size = value_size, x2size = value_size;
- uint x1start = 0, x2start = 0;
- for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
- for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
- if( x1size==0 || x2size==0 )
- {
- // either 'this' or 'ss2' is equal zero - the result is zero too
- result.SetZero();
- return;
- }
- for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
- for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
- uint distancex1 = x1size - x1start;
- uint distancex2 = x2size - x2start;
- if( distancex1 < 3 || distancex2 < 3 )
- // either 'this' or 'ss2' have only 2 (or 1) items different from zero (side by side)
- // (this condition in the future can be improved)
- return Mul2Big3<value_size>(table, ss2.table, result, x1start, x1size, x2start, x2size);
- // Karatsuba multiplication
- Mul3Big(ss2, result);
- TTMATH_LOG("UInt::MulFastestBig")
- }
- /*!
- *
- * Division
- *
- *
- */
-
- public:
- /*!
- division by one unsigned word
- returns 1 when divisor is zero
- */
- uint DivInt(uint divisor, uint * remainder = 0)
- {
- if( divisor == 0 )
- {
- if( remainder )
- *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized
- TTMATH_LOG("UInt::DivInt")
- return 1;
- }
- if( divisor == 1 )
- {
- if( remainder )
- *remainder = 0;
- TTMATH_LOG("UInt::DivInt")
- return 0;
- }
- UInt<value_size> dividend(*this);
- SetZero();
-
- sint i; // i must be with a sign
- uint r = 0;
- // we're looking for the last word in ss1
- for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i);
- for( ; i>=0 ; --i)
- DivTwoWords(r, dividend.table[i], divisor, &table[i], &r);
- if( remainder )
- *remainder = r;
- TTMATH_LOG("UInt::DivInt")
- return 0;
- }
- uint DivInt(uint divisor, uint & remainder)
- {
- return DivInt(divisor, &remainder);
- }
- /*!
- division this = this / ss2
-
- return values:
- 0 - ok
- 1 - division by zero
- 'this' will be the quotient
- 'remainder' - remainder
- */
- uint Div( const UInt<value_size> & divisor,
- UInt<value_size> * remainder = 0,
- uint algorithm = 3)
- {
- switch( algorithm )
- {
- case 1:
- return Div1(divisor, remainder);
- case 2:
- return Div2(divisor, remainder);
- case 3:
- default:
- return Div3(divisor, remainder);
- }
- }
- uint Div(const UInt<value_size> & divisor, UInt<value_size> & remainder, uint algorithm = 3)
- {
- return Div(divisor, &remainder, algorithm);
- }
- private:
- /*!
- return values:
- 0 - none has to be done
- 1 - division by zero
- 2 - division should be made
- */
- uint Div_StandardTest( const UInt<value_size> & v,
- uint & m, uint & n,
- UInt<value_size> * remainder = 0)
- {
- switch( Div_CalculatingSize(v, m, n) )
- {
- case 4: // 'this' is equal v
- if( remainder )
- remainder->SetZero();
- SetOne();
- TTMATH_LOG("UInt::Div_StandardTest")
- return 0;
- case 3: // 'this' is smaller than v
- if( remainder )
- *remainder = *this;
- SetZero();
- TTMATH_LOG("UInt::Div_StandardTest")
- return 0;
- case 2: // 'this' is zero
- if( remainder )
- remainder->SetZero();
- SetZero();
- TTMATH_LOG("UInt::Div_StandardTest")
- return 0;
- case 1: // v is zero
- TTMATH_LOG("UInt::Div_StandardTest")
- return 1;
- }
- TTMATH_LOG("UInt::Div_StandardTest")
- return 2;
- }
- /*!
- return values:
- 0 - ok
- 'm' - is the index (from 0) of last non-zero word in table ('this')
- 'n' - is the index (from 0) of last non-zero word in v.table
- 1 - v is zero
- 2 - 'this' is zero
- 3 - 'this' is smaller than v
- 4 - 'this' is equal v
- if the return value is different than zero the 'm' and 'n' are undefined
- */
- uint Div_CalculatingSize(const UInt<value_size> & v, uint & m, uint & n)
- {
- m = n = value_size-1;
- for( ; n!=0 && v.table[n]==0 ; --n);
- if( n==0 && v.table[n]==0 )
- return 1;
- for( ; m!=0 && table[m]==0 ; --m);
- if( m==0 && table[m]==0 )
- return 2;
- if( m < n )
- return 3;
- else
- if( m == n )
- {
- uint i;
- for(i = n ; i!=0 && table[i]==v.table[i] ; --i);
-
- if( table[i] < v.table[i] )
- return 3;
- else
- if (table[i] == v.table[i] )
- return 4;
- }
- return 0;
- }
- public:
- /*!
- the first division algorithm
- radix 2
- */
- uint Div1(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- uint m,n, test;
- test = Div_StandardTest(divisor, m, n, remainder);
- if( test < 2 )
- return test;
- if( !remainder )
- {
- UInt<value_size> rem;
-
- return Div1_Calculate(divisor, rem);
- }
- return Div1_Calculate(divisor, *remainder);
- }
- /*!
- the first division algorithm
- radix 2
- */
- uint Div1(const UInt<value_size> & divisor, UInt<value_size> & remainder)
- {
- return Div1(divisor, &remainder);
- }
- private:
- uint Div1_Calculate(const UInt<value_size> & divisor, UInt<value_size> & rest)
- {
- if( this == &divisor )
- {
- UInt<value_size> divisor_copy(divisor);
- return Div1_CalculateRef(divisor_copy, rest);
- }
- else
- {
- return Div1_CalculateRef(divisor, rest);
- }
- }
- uint Div1_CalculateRef(const UInt<value_size> & divisor, UInt<value_size> & rest)
- {
- TTMATH_REFERENCE_ASSERT( divisor )
-
- sint loop;
- sint c;
- rest.SetZero();
- loop = value_size * TTMATH_BITS_PER_UINT;
- c = 0;
-
- div_a:
- c = Rcl(1, c);
- c = rest.Add(rest,c);
- c = rest.Sub(divisor,c);
- c = !c;
- if(!c)
- goto div_d;
- div_b:
- --loop;
- if(loop)
- goto div_a;
- c = Rcl(1, c);
- TTMATH_LOG("UInt::Div1_Calculate")
- return 0;
- div_c:
- c = Rcl(1, c);
- c = rest.Add(rest,c);
- c = rest.Add(divisor);
- if(c)
- goto div_b;
- div_d:
- --loop;
- if(loop)
- goto div_c;
- c = Rcl(1, c);
- c = rest.Add(divisor);
- TTMATH_LOG("UInt::Div1_Calculate")
- return 0;
- }
-
- public:
- /*!
- the second division algorithm
- return values:
- 0 - ok
- 1 - division by zero
- */
- uint Div2(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- if( this == &divisor )
- {
- UInt<value_size> divisor_copy(divisor);
- return Div2Ref(divisor_copy, remainder);
- }
- else
- {
- return Div2Ref(divisor, remainder);
- }
- }
- /*!
- the second division algorithm
- return values:
- 0 - ok
- 1 - division by zero
- */
- uint Div2(const UInt<value_size> & divisor, UInt<value_size> & remainder)
- {
- return Div2(divisor, &remainder);
- }
- private:
- /*!
- the second division algorithm
- return values:
- 0 - ok
- 1 - division by zero
- */
- uint Div2Ref(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
- {
- uint bits_diff;
- uint status = Div2_Calculate(divisor, remainder, bits_diff);
- if( status < 2 )
- return status;
- if( CmpBiggerEqual(divisor) )
- {
- Div2(divisor, remainder);
- SetBit(bits_diff);
- }
- else
- {
- if( remainder )
- *remainder = *this;
- SetZero();
- SetBit(bits_diff);
- }
- TTMATH_LOG("UInt::Div2")
- return 0;
- }
- /*!
- return values:
- 0 - we've calculated the division
- 1 - division by zero
- 2 - we have to still calculate
- */
- uint Div2_Calculate(const UInt<value_size> & divisor, UInt<value_size> * remainder,
- uint & bits_diff)
- {
- uint table_id, index;
- uint divisor_table_id, divisor_index;
- uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder,
- table_id, index,
- divisor_table_id, divisor_index);
- if( status < 2 )
- {
- TTMATH_LOG("UInt::Div2_Calculate")
- return status;
- }
-
- // here we know that 'this' is greater than divisor
- // then 'index' is greater or equal 'divisor_index'
- bits_diff = index - divisor_index;
- UInt<value_size> divisor_copy(divisor);
- divisor_copy.Rcl(bits_diff, 0);
- if( CmpSmaller(divisor_copy, table_id) )
- {
- divisor_copy.Rcr(1);
- --bits_diff;
- }
- Sub(divisor_copy, 0);
- TTMATH_LOG("UInt::Div2_Calculate")
- return 2;
- }
- /*!
- return values:
- 0 - we've calculated the division
- 1 - division by zero
- 2 - we have to still calculate
- */
- uint Div2_FindLeadingBitsAndCheck( const UInt<value_size> & divisor,
- UInt<value_size> * remainder,
- uint & table_id, uint & index,
- uint & divisor_table_id, uint & divisor_index)
- {
- if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) )
- {
- // division by zero
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 1;
- }
- if( !FindLeadingBit(table_id, index) )
- {
- // zero is divided by something
-
- SetZero();
- if( remainder )
- remainder->SetZero();
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 0;
- }
-
- divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT;
- index += table_id * TTMATH_BITS_PER_UINT;
- if( divisor_table_id == 0 )
- {
- // dividor has only one 32-bit word
- uint r;
- DivInt(divisor.table[0], &r);
- if( remainder )
- {
- remainder->SetZero();
- remainder->table[0] = r;
- }
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 0;
- }
-
- if( Div2_DivisorGreaterOrEqual( divisor, remainder,
- table_id, index,
- divisor_index) )
- {
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 0;
- }
- TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
- return 2;
- }
- /*!
- return values:
- true if divisor is equal or greater than 'this'
- */
- bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
- UInt<value_size> * remainder,
- uint table_id, uint index,
- uint divisor_index )
- {
- if( divisor_index > index )
- {
- // divisor is greater than this
- if( remainder )
- *remainder = *this;
- SetZero();
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
- return true;
- }
- if( divisor_index == index )
- {
- // table_id == divisor_table_id as well
- uint i;
- for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i);
-
- if( table[i] < divisor.table[i] )
- {
- // divisor is greater than 'this'
- if( remainder )
- *remainder = *this;
- SetZero();
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
- return true;
- }
- else
- if( table[i] == divisor.table[i] )
- {
- // divisor is equal 'this'
- if( remainder )
- remainder->SetZero();
- SetOne();
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
- return true;
- }
- }
- TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual")
- return false;
- }
- public:
- /*!
- the third division algorithm
- */
- uint Div3(const UInt<value_size> & ss2, UInt<value_size> * remainder = 0)
- {
- if( this == &ss2 )
- {
- UInt<value_size> copy_ss2(ss2);
- return Div3Ref(copy_ss2, remainder);
- }
- else
- {
- return Div3Ref(ss2, remainder);
- }
- }
- /*!
- the third division algorithm
- */
- uint Div3(const UInt<value_size> & ss2, UInt<value_size> & remainder)
- {
- return Div3(ss2, &remainder);
- }
- private:
- /*!
- the third division algorithm
- this algorithm is described in the following book:
- "The art of computer programming 2" (4.3.1 page 272)
- Donald E. Knuth
- !! give the description here (from the book)
- */
- uint Div3Ref(const UInt<value_size> & v, UInt<value_size> * remainder = 0)
- {
- uint m,n, test;
- test = Div_StandardTest(v, m, n, remainder);
- if( test < 2 )
- return test;
- if( n == 0 )
- {
- uint r;
- DivInt( v.table[0], &r );
- if( remainder )
- {
- remainder->SetZero();
- remainder->table[0] = r;
- }
- TTMATH_LOG("UInt::Div3")
- return 0;
- }
- // we can only use the third division algorithm when
- // the divisor is greater or equal 2^32 (has more than one 32-bit word)
- ++m;
- ++n;
- m = m - n;
- Div3_Division(v, remainder, m, n);
- TTMATH_LOG("UInt::Div3")
- return 0;
- }
- private:
- void Div3_Division(UInt<value_size> v, UInt<value_size> * remainder, uint m, uint n)
- {
- TTMATH_ASSERT( n>=2 )
- UInt<value_size+1> uu, vv;
- UInt<value_size> q;
- uint d, u_value_size, u0, u1, u2, v1, v0, j=m;
-
- u_value_size = Div3_Normalize(v, n, d);
- if( j+n == value_size )
- u2 = u_value_size;
- else
- u2 = table[j+n];
- Div3_MakeBiggerV(v, vv);
- for(uint i = j+1 ; i<value_size ; ++i)
- q.table[i] = 0;
- while( true )
- {
- u1 = table[j+n-1];
- u0 = table[j+n-2];
- v1 = v.table[n-1];
- v0 = v.table[n-2];
- uint qp = Div3_Calculate(u2,u1,u0, v1,v0);
- Div3_MakeNewU(uu, j, n, u2);
- Div3_MultiplySubtract(uu, vv, qp);
- Div3_CopyNewU(uu, j, n);
- q.table[j] = qp;
- // the next loop
- if( j-- == 0 )
- break;
- u2 = table[j+n];
- }
- if( remainder )
- Div3_Unnormalize(remainder, n, d);
- *this = q;
- TTMATH_LOG("UInt::Div3_Division")
- }
- void Div3_MakeNewU(UInt<value_size+1> & uu, uint j, uint n, uint u_max)
- {
- uint i;
- for(i=0 ; i<n ; ++i, ++j)
- uu.table[i] = table[j];
- // 'n' is from <1..value_size> so and 'i' is from <0..value_size>
- // then table[i] is always correct (look at the declaration of 'uu')
- uu.table[i] = u_max;
- for( ++i ; i<value_size+1 ; ++i)
- uu.table[i] = 0;
- TTMATH_LOG("UInt::Div3_MakeNewU")
- }
- void Div3_CopyNewU(const UInt<value_size+1> & uu, uint j, uint n)
- {
- uint i;
- for(i=0 ; i<n ; ++i)
- table[i+j] = uu.table[i];
- if( i+j < value_size )
- table[i+j] = uu.table[i];
- TTMATH_LOG("UInt::Div3_CopyNewU")
- }
- /*!
- we're making the new 'vv'
- the value is actually the same but the 'table' is bigger (value_size+1)
- */
- void Div3_MakeBiggerV(const UInt<value_size> & v, UInt<value_size+1> & vv)
- {
- for(uint i=0 ; i<value_size ; ++i)
- vv.table[i] = v.table[i];
- vv.table[value_size] = 0;
- TTMATH_LOG("UInt::Div3_MakeBiggerV")
- }
-
- /*!
- we're moving all bits from 'v' into the left side of the n-1 word
- (the highest bit at v.table[n-1] will be equal one,
- the bits from 'this' we're moving the same times as 'v')
- return values:
- d - how many times we've moved
- return - the next-left value from 'this' (that after table[value_size-1])
- */
- uint Div3_Normalize(UInt<value_size> & v, uint n, uint & d)
- {
- // v.table[n-1] is != 0
- uint bit = (uint)FindLeadingBitInWord(v.table[n-1]);
- uint move = (TTMATH_BITS_PER_UINT - bit - 1);
- uint res = table[value_size-1];
- d = move;
- if( move > 0 )
- {
- v.Rcl(move, 0);
- Rcl(move, 0);
- res = res >> (bit + 1);
- }
- else
- {
- res = 0;
- }
- TTMATH_LOG("UInt::Div3_Normalize")
- return res;
- }
- void Div3_Unnormalize(UInt<value_size> * remainder, uint n, uint d)
- {
- for(uint i=n ; i<value_size ; ++i)
- table[i] = 0;
- Rcr(d,0);
- *remainder = *this;
- TTMATH_LOG("UInt::Div3_Unnormalize")
- }
- uint Div3_Calculate(uint u2, uint u1, uint u0, uint v1, uint v0)
- {
- UInt<2> u_temp;
- uint rp;
- bool next_test;
- TTMATH_ASSERT( v1 != 0 )
- u_temp.table[1] = u2;
- u_temp.table[0] = u1;
- u_temp.DivInt(v1, &rp);
- TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 )
- do
- {
- bool decrease = false;
- if( u_temp.table[1] == 1 )
- decrease = true;
- else
- {
- UInt<2> temp1, temp2;
- UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table);
- temp2.table[1] = rp;
- temp2.table[0] = u0;
- if( temp1 > temp2 )
- decrease = true;
- }
- next_test = false;
- if( decrease )
- {
- u_temp.SubOne();
- rp += v1;
- if( rp >= v1 ) // it means that there wasn't a carry (r<b from the book)
- next_test = true;
- }
- }
- while( next_test );
- TTMATH_LOG("UInt::Div3_Calculate")
- return u_temp.table[0];
- }
- void Div3_MultiplySubtract( UInt<value_size+1> & uu,
- const UInt<value_size+1> & vv, uint & qp)
- {
- // D4 (in the book)
- UInt<value_size+1> vv_temp(vv);
- vv_temp.MulInt(qp);
- if( uu.Sub(vv_temp) )
- {
- // there was a carry
-
- //
- // !!! this part of code was not tested
- //
- --qp;
- uu.Add(vv);
- // can be a carry from this additions but it should be ignored
- // because it cancels with the borrow from uu.Sub(vv_temp)
- }
- TTMATH_LOG("UInt::Div3_MultiplySubtract")
- }
- public:
- /*!
- power this = this ^ pow
- binary algorithm (r-to-l)
- return values:
- 0 - ok
- 1 - carry
- 2 - incorrect argument (0^0)
- */
- uint Pow(UInt<value_size> pow)
- {
- if(pow.IsZero() && IsZero())
- // we don't define zero^zero
- return 2;
- UInt<value_size> start(*this);
- UInt<value_size> result;
- result.SetOne();
- uint c = 0;
- while( !c )
- {
- if( pow.table[0] & 1 )
- c += result.Mul(start);
- pow.Rcr2_one(0);
- if( pow.IsZero() )
- break;
- c += start.Mul(start);
- }
- *this = result;
- TTMATH_LOGC("UInt::Pow(UInt<>)", c)
- return (c==0)? 0 : 1;
- }
- /*!
- square root
- e.g. Sqrt(9) = 3
- ('digit-by-digit' algorithm)
- */
- void Sqrt()
- {
- UInt<value_size> bit, temp;
- if( IsZero() )
- return;
- UInt<value_size> value(*this);
- SetZero();
- bit.SetZero();
- bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1);
-
- while( bit > value )
- bit.Rcr(2);
- while( !bit.IsZero() )
- {
- temp = *this;
- temp.Add(bit);
- if( value >= temp )
- {
- value.Sub(temp);
- Rcr(1);
- Add(bit);
- }
- else
- {
- Rcr(1);
- }
- bit.Rcr(2);
- }
- TTMATH_LOG("UInt::Sqrt")
- }
- /*!
- this method sets n first bits to value zero
- For example:
- let n=2 then if there's a value 111 (bin) there'll be '100' (bin)
- */
- void ClearFirstBits(uint n)
- {
- if( n >= value_size*TTMATH_BITS_PER_UINT )
- {
- SetZero();
- TTMATH_LOG("UInt::ClearFirstBits")
- return;
- }
- uint * p = table;
- // first we're clearing the whole words
- while( n >= TTMATH_BITS_PER_UINT )
- {
- *p++ = 0;
- n -= TTMATH_BITS_PER_UINT;
- }
- if( n == 0 )
- {
- TTMATH_LOG("UInt::ClearFirstBits")
- return;
- }
- // and then we're clearing one word which has left
- // mask -- all bits are set to one
- uint mask = TTMATH_UINT_MAX_VALUE;
- mask = mask << n;
- (*p) &= mask;
- TTMATH_LOG("UInt::ClearFirstBits")
- }
- /*!
- this method returns true if the highest bit of the value is set
- */
- bool IsTheHighestBitSet() const
- {
- return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0;
- }
- /*!
- this method returns true if the lowest bit of the value is set
- */
- bool IsTheLowestBitSet() const
- {
- return (*table & 1) != 0;
- }
- /*!
- returning true if only the highest bit is set
- */
- bool IsOnlyTheHighestBitSet() const
- {
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wtautological-compare"
- #endif
- for(uint i=0 ; i<value_size-1 ; ++i)
- if( table[i] != 0 )
- return false;
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
- if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
- return false;
- return true;
- }
- /*!
- returning true if only the lowest bit is set
- */
- bool IsOnlyTheLowestBitSet() const
- {
- if( table[0] != 1 )
- return false;
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return false;
- return true;
- }
- /*!
- this method returns true if the value is equal zero
- */
- bool IsZero() const
- {
- for(uint i=0 ; i<value_size ; ++i)
- if(table[i] != 0)
- return false;
- return true;
- }
- /*!
- returning true if first 'bits' bits are equal zero
- */
- bool AreFirstBitsZero(uint bits) const
- {
- TTMATH_ASSERT( bits <= value_size * TTMATH_BITS_PER_UINT )
- uint index = bits / TTMATH_BITS_PER_UINT;
- uint rest = bits % TTMATH_BITS_PER_UINT;
- uint i;
- for(i=0 ; i<index ; ++i)
- if(table[i] != 0 )
- return false;
- if( rest == 0 )
- return true;
- uint mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
- return (table[i] & mask) == 0;
- }
- /*!
- *
- * conversion methods
- *
- */
- /*!
- this method converts an UInt<another_size> type to this class
- this operation has mainly sense if the value from p is
- equal or smaller than that one which is returned from UInt<value_size>::SetMax()
- it returns a carry if the value 'p' is too big
- */
- template<uint argument_size>
- uint FromUInt(const UInt<argument_size> & p)
- {
- uint min_size = (value_size < argument_size)? value_size : argument_size;
- uint i;
- for(i=0 ; i<min_size ; ++i)
- table[i] = p.table[i];
- if( value_size > argument_size )
- {
- // 'this' is longer than 'p'
- for( ; i<value_size ; ++i)
- table[i] = 0;
- }
- else
- {
- for( ; i<argument_size ; ++i)
- if( p.table[i] != 0 )
- {
- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 1)
- return 1;
- }
- }
- TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0)
- return 0;
- }
- /*!
- this method converts an UInt<another_size> type to this class
- this operation has mainly sense if the value from p is
- equal or smaller than that one which is returned from UInt<value_size>::SetMax()
- it returns a carry if the value 'p' is too big
- */
- template<uint argument_size>
- uint FromInt(const UInt<argument_size> & p)
- {
- return FromUInt(p);
- }
- /*!
- this method converts the uint type to this class
- */
- uint FromUInt(uint value)
- {
- for(uint i=1 ; i<value_size ; ++i)
- table[i] = 0;
- table[0] = value;
- TTMATH_LOG("UInt::FromUInt(uint)")
- // there'll never be a carry here
- return 0;
- }
- /*!
- this method converts the uint type to this class
- */
- uint FromInt(uint value)
- {
- return FromUInt(value);
- }
- /*!
- this method converts the sint type to this class
- */
- uint FromInt(sint value)
- {
- uint c = FromUInt(uint(value));
- if( c || value < 0 )
- return 1;
- return 0;
- }
- /*!
- this operator converts an UInt<another_size> type to this class
- it doesn't return a carry
- */
- /* template<uint argument_size>
- UInt<value_size> & operator=(const UInt<argument_size> & p)
- {
- FromUInt(p);
- return *this;
- }
- */
- /*!
- the assignment operator
- */
- /* UInt<value_size> & operator=(const UInt<value_size> & p)
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = p.table[i];
- TTMATH_LOG("UInt::operator=(UInt<>)")
- return *this;
- }
- */
- /*!
- this method converts the uint type to this class
- */
- UInt<value_size> & operator=(uint i)
- {
- FromUInt(i);
- return *this;
- }
- /*!
- a constructor for converting the uint to this class
- */
- /* UInt(uint i)
- {
- FromUInt(i);
- }
- */
- /*!
- this method converts the sint type to this class
- */
- UInt<value_size> & operator=(sint i)
- {
- FromInt(i);
- return *this;
- }
- /*!
- a constructor for converting the sint to this class
- look at the description of UInt::operator=(sint)
- */
- /* UInt(sint i)
- {
- FromInt(i);
- }
- */
- #ifdef TTMATH_PLATFORM32
- /*!
- this method converts unsigned 64 bit int type to this class
- ***this method is created only on a 32bit platform***
- */
- uint FromUInt(ulint n)
- {
- table[0] = (uint)n;
- if( value_size == 1 )
- {
- uint c = ((n >> TTMATH_BITS_PER_UINT) == 0) ? 0 : 1;
- TTMATH_LOGC("UInt::FromUInt(ulint)", c)
- return c;
- }
- table[1] = (uint)(n >> TTMATH_BITS_PER_UINT);
- for(uint i=2 ; i<value_size ; ++i)
- table[i] = 0;
- TTMATH_LOG("UInt::FromUInt(ulint)")
- return 0;
- }
- /*!
- this method converts unsigned 64 bit int type to this class
- ***this method is created only on a 32bit platform***
- */
- uint FromInt(ulint n)
- {
- return FromUInt(n);
- }
- /*!
- this method converts signed 64 bit int type to this class
- ***this method is created only on a 32bit platform***
- */
- uint FromInt(slint n)
- {
- uint c = FromUInt(ulint(n));
- if( c || n < 0 )
- return 1;
- return 0;
- }
- /*!
- this operator converts unsigned 64 bit int type to this class
- ***this operator is created only on a 32bit platform***
- */
- UInt<value_size> & operator=(ulint n)
- {
- FromUInt(n);
- return *this;
- }
- /*!
- a constructor for converting unsigned 64 bit int to this class
- ***this constructor is created only on a 32bit platform***
- */
- /* UInt(ulint n)
- {
- FromUInt(n);
- }
- */
- /*!
- this operator converts signed 64 bit int type to this class
- ***this operator is created only on a 32bit platform***
- */
- UInt<value_size> & operator=(slint n)
- {
- FromInt(n);
- return *this;
- }
- /*!
- a constructor for converting signed 64 bit int to this class
- ***this constructor is created only on a 32bit platform***
- */
- /* UInt(slint n)
- {
- FromInt(n);
- }
- */
- #endif
- #ifdef TTMATH_PLATFORM64
- /*!
- this method converts 32 bit unsigned int type to this class
- ***this operator is created only on a 64bit platform***
- */
- uint FromUInt(unsigned int i)
- {
- return FromUInt(uint(i));
- }
- /*!
- this method converts 32 bit unsigned int type to this class
- ***this operator is created only on a 64bit platform***
- */
- uint FromInt(unsigned int i)
- {
- return FromUInt(uint(i));
- }
- /*!
- this method converts 32 bit signed int type to this class
- ***this operator is created only on a 64bit platform***
- */
- uint FromInt(signed int i)
- {
- return FromInt(sint(i));
- }
- /*!
- this operator converts 32 bit unsigned int type to this class
- ***this operator is created only on a 64bit platform***
- */
- UInt<value_size> & operator=(unsigned int i)
- {
- FromUInt(i);
- return *this;
- }
- /*!
- a constructor for converting 32 bit unsigned int to this class
- ***this constructor is created only on a 64bit platform***
- */
- /* UInt(unsigned int i)
- {
- FromUInt(i);
- }
- */
- /*!
- an operator for converting 32 bit signed int to this class
- ***this constructor is created only on a 64bit platform***
- */
- UInt<value_size> & operator=(signed int i)
- {
- FromInt(i);
- return *this;
- }
- /*!
- a constructor for converting 32 bit signed int to this class
- ***this constructor is created only on a 64bit platform***
- */
- /* UInt(signed int i)
- {
- FromInt(i);
- }
- */
- #endif
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- /* UInt(const char * s)
- {
- FromString(s);
- }
- */
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- /* UInt(const std::string & s)
- {
- FromString( s.c_str() );
- }
- */
- #ifndef TTMATH_DONT_USE_WCHAR
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- UInt(const wchar_t * s)
- {
- FromString(s);
- }
- /*!
- a constructor for converting a string to this class (with the base=10)
- */
- UInt(const std::wstring & s)
- {
- FromString( s.c_str() );
- }
- #endif
- /*!
- a default constructor
- we don't clear the table
- */
- /* UInt()
- {
- // when macro TTMATH_DEBUG_LOG is defined
- // we set special values to the table
- // in order to be everywhere the same value of the UInt object
- // without this it would be difficult to analyse the log file
- #ifdef TTMATH_DEBUG_LOG
- #ifdef TTMATH_PLATFORM32
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0xc1c1c1c1;
- #else
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = 0xc1c1c1c1c1c1c1c1;
- #endif
- #endif
- }
- */
- /*!
- a copy constructor
- */
- /* UInt(const UInt<value_size> & u)
- {
- for(uint i=0 ; i<value_size ; ++i)
- table[i] = u.table[i];
- TTMATH_LOG("UInt::UInt(UInt<>)")
- }
- */
- /*!
- a template for producting constructors for copying from another types
- */
- /* template<uint argument_size>
- UInt(const UInt<argument_size> & u)
- {
- // look that 'size' we still set as 'value_size' and not as u.value_size
- FromUInt(u);
- }
- */
- /*!
- a destructor
- */
- /* ~UInt()
- {
- }
- */
- /*!
- this method returns the lowest value from table
- we must be sure when we using this method whether the value
- will hold in an uint type or not (the rest value from the table must be zero)
- */
- uint ToUInt() const
- {
- return table[0];
- }
- /*!
- this method converts the value to uint type
- can return a carry if the value is too long to store it in uint type
- */
- uint ToUInt(uint & result) const
- {
- result = table[0];
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
- return 0;
- }
- /*!
- this method converts the value to uint type
- can return a carry if the value is too long to store it in uint type
- */
- uint ToInt(uint & result) const
- {
- return ToUInt(result);
- }
- /*!
- this method converts the value to sint type (signed integer)
- can return a carry if the value is too long to store it in sint type
- */
- uint ToInt(sint & result) const
- {
- result = sint(table[0]);
- if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
- return 1;
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
- return 0;
- }
- #ifdef TTMATH_PLATFORM32
- /*!
- this method converts the value to ulint type (64 bit unsigned integer)
- can return a carry if the value is too long to store it in ulint type
- *** this method is created only on a 32 bit platform ***
- */
- uint ToUInt(ulint & result) const
- {
- if( value_size == 1 )
- {
- result = table[0];
- }
- else
- {
- uint low = table[0];
- uint high = table[1];
- result = low;
- result |= (ulint(high) << TTMATH_BITS_PER_UINT);
- for(uint i=2 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
- }
- return 0;
- }
- /*!
- this method converts the value to ulint type (64 bit unsigned integer)
- can return a carry if the value is too long to store it in ulint type
- *** this method is created only on a 32 bit platform ***
- */
- uint ToInt(ulint & result) const
- {
- return ToUInt(result);
- }
- /*!
- this method converts the value to slint type (64 bit signed integer)
- can return a carry if the value is too long to store it in slint type
- *** this method is created only on a 32 bit platform ***
- */
- uint ToInt(slint & result) const
- {
- ulint temp;
- uint c = ToUInt(temp);
- result = slint(temp);
- if( c || result < 0 )
- return 1;
- return 0;
- }
- #endif
- #ifdef TTMATH_PLATFORM64
- /*!
- this method converts the value to a 32 unsigned integer
- can return a carry if the value is too long to store it in this type
- *** this method is created only on a 64 bit platform ***
- */
- uint ToUInt(unsigned int & result) const
- {
- result = (unsigned int)table[0];
- if( (table[0] >> 32) != 0 )
- return 1;
- for(uint i=1 ; i<value_size ; ++i)
- if( table[i] != 0 )
- return 1;
- return 0;
- }
- /*!
- this method converts the value to a 32 unsigned integer
- can return a carry if the value is too long to store it in this type
- *** this method is created only on a 64 bit platform ***
- */
- uint ToInt(unsigned int & result) const
- {
- return ToUInt(result);
- }
- /*!
- this method converts the value to a 32 signed integer
- can return a carry if the value is too long to store it in this type
- *** this method is created only on a 64 bit platform ***
- */
- uint ToInt(int & result) const
- {
- unsigned int temp;
- uint c = ToUInt(temp);
- result = int(temp);
- if( c || result < 0 )
- return 1;
- return 0;
- }
- #endif
- protected:
- /*!
- an auxiliary method for converting into the string
- it returns the log (with the base 2) from x
- where x is in <2;16>
- */
- double ToStringLog2(uint x) const
- {
- static double log_tab[] = {
- 1.000000000000000000,
- 0.630929753571457437,
- 0.500000000000000000,
- 0.430676558073393050,
- 0.386852807234541586,
- 0.356207187108022176,
- 0.333333333333333333,
- 0.315464876785728718,
- 0.301029995663981195,
- 0.289064826317887859,
- 0.278942945651129843,
- 0.270238154427319741,
- 0.262649535037193547,
- 0.255958024809815489,
- 0.250000000000000000
- };
- if( x<2 || x>16 )
- return 0;
- return log_tab[x-2];
- }
- public:
- /*!
- an auxiliary method for converting to a string
- it's used from Int::ToString() too (negative is set true then)
- */
- template<class string_type>
- void ToStringBase(string_type & result, uint b = 10, bool negative = false) const
- {
- UInt<value_size> temp(*this);
- uint rest, table_id, index, digits;
- double digits_d;
- char character;
- result.clear();
- if( b<2 || b>16 )
- return;
- if( !FindLeadingBit(table_id, index) )
- {
- result = '0';
- return;
- }
- if( negative )
- result = '-';
- digits_d = table_id; // for not making an overflow in uint type
- digits_d *= TTMATH_BITS_PER_UINT;
- digits_d += index + 1;
- digits_d *= ToStringLog2(b);
- digits = static_cast<uint>(digits_d) + 3; // plus some epsilon
- if( result.capacity() < digits )
- result.reserve(digits);
- do
- {
- temp.DivInt(b, &rest);
- character = static_cast<char>(Misc::DigitToChar(rest));
- result.insert(result.end(), character);
- }
- while( !temp.IsZero() );
- size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true)
- size_t i2 = result.size() - 1;
- for( ; i1 < i2 ; ++i1, --i2 )
- {
- char tempc = static_cast<char>(result[i1]);
- result[i1] = result[i2];
- result[i2] = tempc;
- }
- }
- /*!
- this method converts the value to a string with a base equal 'b'
- */
- void ToString(std::string & result, uint b = 10) const
- {
- return ToStringBase(result, b);
- }
- std::string ToString(uint b = 10) const
- {
- std::string result;
- ToStringBase(result, b);
-
- return result;
- }
- #ifndef TTMATH_DONT_USE_WCHAR
- void ToString(std::wstring & result, uint b = 10) const
- {
- return ToStringBase(result, b);
- }
- std::wstring ToWString(uint b = 10) const
- {
- std::wstring result;
- ToStringBase(result, b);
-
- return result;
- }
- #endif
- private:
- /*!
- an auxiliary method for converting from a string
- */
- template<class char_type>
- uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
- {
- UInt<value_size> base;
- base.FromUInt( b );
- UInt<value_size> temp;
- sint z;
- uint c = 0;
- SetZero();
- temp.SetZero();
- Misc::SkipWhiteCharacters(s);
- if( after_source )
- *after_source = s;
- if( value_read )
- *value_read = false;
- if( b<2 || b>16 )
- return 1;
- for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s)
- {
- if( value_read )
- *value_read = true;
- if( c == 0 )
- {
- temp.table[0] = z;
- c += Mul(base); // !! IMPROVE ME: there can be used MulInt here
- c += Add(temp);
- }
- }
- if( after_source )
- *after_source = s;
- TTMATH_LOGC("UInt::FromString", c)
- return (c==0)? 0 : 1;
- }
- public:
- /*!
- this method converts a string into its value
- it returns carry=1 if the value will be too big or an incorrect base 'b' is given
- string is ended with a non-digit value, for example:
- "12" will be translated to 12
- as well as:
- "12foo" will be translated to 12 too
- existing first white characters will be ommited
- if the value from s is too large the rest digits will be skipped
- after_source (if exists) is pointing at the end of the parsed string
- value_read (if exists) tells whether something has actually been read (at least one digit)
- */
- uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(s, b, after_source, value_read);
- }
- /*!
- this method converts a string into its value
- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
- */
- uint FromString(const std::string & s, uint b = 10)
- {
- return FromString( s.c_str(), b );
- }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const char * s)
- {
- FromString(s);
- return *this;
- }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const std::string & s)
- {
- FromString( s.c_str() );
- return *this;
- }
- #ifndef TTMATH_DONT_USE_WCHAR
- /*!
- this method converts a string into its value
- */
- uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
- {
- return FromStringBase(s, b, after_source, value_read);
- }
- /*!
- this method converts a string into its value
- (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
- */
- uint FromString(const std::wstring & s, uint b = 10)
- {
- return FromString( s.c_str(), b );
- }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const wchar_t * s)
- {
- FromString(s);
- return *this;
- }
- /*!
- this operator converts a string into its value (with base = 10)
- */
- UInt<value_size> & operator=(const std::wstring & s)
- {
- FromString( s.c_str() );
- return *this;
- }
- #endif
- /*!
- *
- * methods for comparing
- *
- */
- /*!
- this method returns true if 'this' is smaller than 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- I introduced it for some kind of optimization made in the second division algorithm (Div2)
- */
- bool CmpSmaller(const UInt<value_size> & l, sint index = -1) const
- {
- sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] < l.table[i];
- }
- // they're equal
- return false;
- }
- /*!
- this method returns true if 'this' is bigger than 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- I introduced it for some kind of optimization made in the second division algorithm (Div2)
- */
- bool CmpBigger(const UInt<value_size> & l, sint index = -1) const
- {
- sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] > l.table[i];
- }
- // they're equal
- return false;
- }
- /*!
- this method returns true if 'this' is equal 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- */
- bool CmpEqual(const UInt<value_size> & l, sint index = -1) const
- {
- sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
- for( ; i>=0 ; --i)
- if( table[i] != l.table[i] )
- return false;
- return true;
- }
- /*!
- this method returns true if 'this' is smaller than or equal 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- */
- bool CmpSmallerEqual(const UInt<value_size> & l, sint index=-1) const
- {
- sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] < l.table[i];
- }
- // they're equal
- return true;
- }
- /*!
- this method returns true if 'this' is bigger than or equal 'l'
- 'index' is an index of the first word from will be the comparison performed
- (note: we start the comparison from back - from the last word, when index is -1 /default/
- it is automatically set into the last word)
- */
- bool CmpBiggerEqual(const UInt<value_size> & l, sint index=-1) const
- {
- sint i;
- if( index==-1 || index>=sint(value_size) )
- i = value_size - 1;
- else
- i = index;
- for( ; i>=0 ; --i)
- {
- if( table[i] != l.table[i] )
- return table[i] > l.table[i];
- }
- // they're equal
- return true;
- }
- /*
- operators for comparising
- */
- bool operator<(const UInt<value_size> & l) const
- {
- return CmpSmaller(l);
- }
- bool operator>(const UInt<value_size> & l) const
- {
- return CmpBigger(l);
- }
- bool operator==(const UInt<value_size> & l) const
- {
- return CmpEqual(l);
- }
- bool operator!=(const UInt<value_size> & l) const
- {
- return !operator==(l);
- }
- bool operator<=(const UInt<value_size> & l) const
- {
- return CmpSmallerEqual(l);
- }
- bool operator>=(const UInt<value_size> & l) const
- {
- return CmpBiggerEqual(l);
- }
- /*!
- *
- * standard mathematical operators
- *
- */
- UInt<value_size> operator-(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- temp.Sub(p2);
- return temp;
- }
- UInt<value_size> & operator-=(const UInt<value_size> & p2)
- {
- Sub(p2);
- return *this;
- }
- UInt<value_size> operator+(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- temp.Add(p2);
- return temp;
- }
- UInt<value_size> & operator+=(const UInt<value_size> & p2)
- {
- Add(p2);
- return *this;
- }
- UInt<value_size> operator*(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- temp.Mul(p2);
- return temp;
- }
- UInt<value_size> & operator*=(const UInt<value_size> & p2)
- {
- Mul(p2);
- return *this;
- }
- UInt<value_size> operator/(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- temp.Div(p2);
- return temp;
- }
- UInt<value_size> & operator/=(const UInt<value_size> & p2)
- {
- Div(p2);
- return *this;
- }
- UInt<value_size> operator%(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp(*this);
- UInt<value_size> remainder;
-
- temp.Div( p2, remainder );
- return remainder;
- }
- UInt<value_size> & operator%=(const UInt<value_size> & p2)
- {
- UInt<value_size> remainder;
-
- Div( p2, remainder );
- operator=(remainder);
- return *this;
- }
- /*!
- Prefix operator e.g ++variable
- */
- UInt<value_size> & operator++()
- {
- AddOne();
- return *this;
- }
- /*!
- Postfix operator e.g variable++
- */
- UInt<value_size> operator++(int)
- {
- UInt<value_size> temp( *this );
- AddOne();
- return temp;
- }
- UInt<value_size> & operator--()
- {
- SubOne();
- return *this;
- }
- UInt<value_size> operator--(int)
- {
- UInt<value_size> temp( *this );
- SubOne();
- return temp;
- }
- /*!
- *
- * bitwise operators
- *
- */
- UInt<value_size> operator~() const
- {
- UInt<value_size> temp( *this );
- temp.BitNot();
- return temp;
- }
- UInt<value_size> operator&(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp( *this );
- temp.BitAnd(p2);
- return temp;
- }
- UInt<value_size> & operator&=(const UInt<value_size> & p2)
- {
- BitAnd(p2);
- return *this;
- }
- UInt<value_size> operator|(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp( *this );
- temp.BitOr(p2);
- return temp;
- }
- UInt<value_size> & operator|=(const UInt<value_size> & p2)
- {
- BitOr(p2);
- return *this;
- }
- UInt<value_size> operator^(const UInt<value_size> & p2) const
- {
- UInt<value_size> temp( *this );
- temp.BitXor(p2);
- return temp;
- }
- UInt<value_size> & operator^=(const UInt<value_size> & p2)
- {
- BitXor(p2);
- return *this;
- }
- UInt<value_size> operator>>(int move) const
- {
- UInt<value_size> temp( *this );
- temp.Rcr(move);
- return temp;
- }
- UInt<value_size> & operator>>=(int move)
- {
- Rcr(move);
- return *this;
- }
- UInt<value_size> operator<<(int move) const
- {
- UInt<value_size> temp( *this );
- temp.Rcl(move);
- return temp;
- }
- UInt<value_size> & operator<<=(int move)
- {
- Rcl(move);
- return *this;
- }
- /*!
- *
- * input/output operators for standard streams
- *
- * (they are very simple, in the future they should be changed)
- *
- */
- private:
- /*!
- an auxiliary method for outputing to standard streams
- */
- template<class ostream_type, class string_type>
- static ostream_type & OutputToStream(ostream_type & s, const UInt<value_size> & l)
- {
- string_type ss;
- l.ToString(ss);
- s << ss;
- return s;
- }
- public:
- /*!
- output to standard streams
- */
- friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l)
- {
- return OutputToStream<std::ostream, std::string>(s, l);
- }
- #ifndef TTMATH_DONT_USE_WCHAR
- /*!
- output to standard streams
- */
- friend std::wostream & operator<<(std::wostream & s, const UInt<value_size> & l)
- {
- return OutputToStream<std::wostream, std::wstring>(s, l);
- }
- #endif
- private:
- /*!
- an auxiliary method for reading from standard streams
- */
- template<class istream_type, class string_type, class char_type>
- static istream_type & InputFromStream(istream_type & s, UInt<value_size> & l)
- {
- string_type ss;
-
- // char or wchar_t for operator>>
- char_type z;
-
- // operator>> omits white characters if they're set for ommiting
- s >> z;
- // we're reading only digits (base=10)
- while( s.good() && Misc::CharToDigit(z, 10)>=0 )
- {
- ss += z;
- z = static_cast<char_type>(s.get());
- }
- // we're leaving the last read character
- // (it's not belonging to the value)
- s.unget();
- l.FromString(ss);
- return s;
- }
- public:
- /*!
- input from standard streams
- */
- friend std::istream & operator>>(std::istream & s, UInt<value_size> & l)
- {
- return InputFromStream<std::istream, std::string, char>(s, l);
- }
- #ifndef TTMATH_DONT_USE_WCHAR
- /*!
- input from standard streams
- */
- friend std::wistream & operator>>(std::wistream & s, UInt<value_size> & l)
- {
- return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
- }
- #endif
- /*
- Following methods are defined in:
- ttmathuint_x86.h
- ttmathuint_x86_64.h
- ttmathuint_noasm.h
- */
- #ifdef TTMATH_NOASM
- static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
- static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
- #ifdef TTMATH_PLATFORM64
- union uint_
- {
- struct
- {
- unsigned int low; // 32 bit
- unsigned int high; // 32 bit
- } u_;
- uint u; // 64 bit
- };
- static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest);
- static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_);
- static uint DivTwoWordsUnnormalize(uint u, uint d);
- static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_);
- static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
- #endif // TTMATH_PLATFORM64
- #endif // TTMATH_NOASM
- private:
- uint Rcl2_one(uint c);
- uint Rcr2_one(uint c);
- uint Rcl2(uint bits, uint c);
- uint Rcr2(uint bits, uint c);
- public:
- static const char * LibTypeStr();
- static LibTypeCode LibType();
- uint Add(const UInt<value_size> & ss2, uint c=0);
- uint AddInt(uint value, uint index = 0);
- uint AddTwoInts(uint x2, uint x1, uint index);
- static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
- uint Sub(const UInt<value_size> & ss2, uint c=0);
- uint SubInt(uint value, uint index = 0);
- static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
- static sint FindLeadingBitInWord(uint x);
- static sint FindLowestBitInWord(uint x);
- static uint SetBitInWord(uint & value, uint bit);
- static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
- static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest);
- };
- /*!
- this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array"
- when compiling Mul3Big2() method
- */
- template<>
- class UInt<0>
- {
- public:
- uint table[1];
- void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) };
- void SetZero() { TTMATH_ASSERT(false) };
- uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; };
- };
- } //namespace
- #include "ttmathuint_x86.h"
- #include "ttmathuint_x86_64.h"
- #include "ttmathuint_noasm.h"
- #endif
|