fmtbcd.pp 111 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2005-2006 by the Free Pascal development team
  4. and Gehard Scholz
  5. It contains the Free Pascal BCD implementation
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { "Programming is the time between two bugs" }
  13. { (last words of the unknown programmer) }
  14. (* this program was a good test for the compiler: some bugs have been found.
  15. 1. WITH in inline funcs produces a compiler error AFTER producing an .exe file
  16. (was already known; I didn't see it in the bug list)
  17. 2. macro names were checked for being a keyword, even when starting with
  18. an '_' (produces range check when compiler is compiled with { $r+ }-mode
  19. fixed.
  20. 3. { $define program } was not possible in { $macro on } mode
  21. (keywords not allowed: doesn't make sense here)
  22. fixed.
  23. 4. the Inc/Dec ( unsigned, signed ) problem (has been similar in the
  24. bug list already)
  25. 5. when the result of an overloaded (inline) operator is ABSOLUTEd:
  26. compiler error 200110205
  27. happens only when operator is defined in a unit.
  28. 6. two range check errors in scanner.pas
  29. a) array subscripting
  30. b) value out ouf range
  31. *)
  32. { $define debug_version}
  33. {$r+,q+,s+}
  34. { $r-,q-,s-}
  35. {$mode objfpc}
  36. {$h-}
  37. {$inline on}
  38. {$macro on}
  39. {$define BCDMaxDigits := 64 } { should be even }
  40. { the next defines must be defined by hand,
  41. unless someone shows me a way how to to it with macros }
  42. {$define BCDgr4} { define this if MCDMaxDigits is greater 4, else undefine! }
  43. {$define BCDgr9} { define this if MCDMaxDigits is greater 9, else undefine! }
  44. {$define BCDgr18} { define this if MCDMaxDigits is greater 18, else undefine! }
  45. { $define BCDgr64} { define this if MCDMaxDigits is greater 64, else undefine! }
  46. { $define BCDgr180} { define this if MCDMaxDigits is greater 180, else undefine! }
  47. {$ifdef BCDgr4}
  48. {$hint BCD Digits > 4}
  49. {$endif}
  50. {$ifdef BCDgr9}
  51. {$hint BCD Digits > 9}
  52. {$endif}
  53. {$ifdef BCDgr18}
  54. {$hint BCD Digits > 18}
  55. {$endif}
  56. {$ifdef BCDgr64}
  57. {$hint BCD Digits > 64}
  58. {$endif}
  59. {$ifdef BCDgr180}
  60. {$hint BCD Digits > 180}
  61. {$endif}
  62. {$ifndef NO_SMART_LINK}
  63. { $smartlink on}
  64. {$endif}
  65. {$define some_packed} { enable this to keep some local structures PACKED }
  66. { $define as_object} { to define the tBCD record as object instead;
  67. fields then are private }
  68. { not done yet! }
  69. {$define additional_routines} { to create additional routines and operators }
  70. (* only define one of them! *)
  71. { $define integ32}
  72. {$define integ64}
  73. (* only define one of them! *)
  74. { $define real8}
  75. {$define real10}
  76. {check}
  77. {$ifndef integ32}
  78. {$ifndef integ64}
  79. {$define integ64}
  80. {$endif}
  81. {$endif}
  82. {$ifdef integ32}
  83. {$ifdef integ64}
  84. {$undef integ32}
  85. {$endif}
  86. {$endif}
  87. {check}
  88. {$ifndef real8}
  89. {$ifndef real10}
  90. {$define real8}
  91. {$endif}
  92. {$endif}
  93. {$ifdef real8}
  94. {$ifdef real10}
  95. {$undef real10}
  96. {$endif}
  97. {$endif}
  98. {$ifdef some_packed}
  99. {$define maybe_packed := packed}
  100. {$else}
  101. {$define maybe_packed := (**)}
  102. {$endif}
  103. UNIT FmtBCD;
  104. INTERFACE
  105. USES
  106. SysUtils,
  107. { dateutils,}
  108. Variants;
  109. const
  110. MaxStringDigits = 100; { not used ! }
  111. _NoDecimal = -255; { not used ! }
  112. _DefaultDecimals = 10; { not used ! }
  113. { From DB.pas }
  114. { Max supported by Midas } { must be EVEN }
  115. MaxFmtBCDFractionSize = BCDMaxDigits + Ord ( Odd ( BCDMaxDigits ) );
  116. { Max supported by Midas }
  117. MaxFmtBCDDigits = 32; { not used ! }
  118. DefaultFmtBCDScale = 6; { not used ! }
  119. MaxBCDPrecision = 18; { not used ! }
  120. MaxBCDScale = 4; { not used ! }
  121. {$ifdef BCDgr64}
  122. { $fatal big 1}
  123. {$define bigger_BCD} { must be defined
  124. if MaxFmtBCDFractionSize > 64 }
  125. { not usable in the moment }
  126. {$endif}
  127. {$ifdef BCDgr180}
  128. { $fatal big 2}
  129. type
  130. FmtBCDStringtype = AnsiString;
  131. {$define use_Ansistring}
  132. {$else}
  133. type
  134. FmtBCDStringtype = string [ 255 ];
  135. {$undef use_Ansistring}
  136. {$endif}
  137. {$ifdef use_ansistring}
  138. {$hint ansi}
  139. {$else}
  140. {$hint -ansi}
  141. {$endif}
  142. {$ifdef integ32}
  143. {$define myInttype := LongInt}
  144. {$endif}
  145. {$ifdef integ64}
  146. {$define myInttype := int64}
  147. {$endif}
  148. {$ifndef FPUNONE}
  149. {$ifdef real8}
  150. {$define myRealtype := double}
  151. {$endif}
  152. {$ifdef real10}
  153. {$define myRealtype := extended}
  154. {$endif}
  155. {$endif}
  156. {$ifdef SUPPORT_COMP}
  157. {$define comproutines}
  158. {$endif SUPPORT_COMP}
  159. {$define __low_Fraction := 0 }
  160. {$define __high_Fraction := ( ( MaxFmtBCDFractionSize DIV 2 ) - 1 ) }
  161. type
  162. pBCD = ^ tBCD;
  163. tBCD = packed {$ifdef as_object} OBJECT {$else} record {$endif}
  164. {$ifdef as_object} PRIVATE {$endif}
  165. Precision : 0..maxfmtbcdfractionsize; { 1 (joke?)..64 }
  166. {$ifndef bigger_BCD}
  167. SignSpecialPlaces : Byte; { Sign:1, Special:1, Places:6 }
  168. {$else}
  169. Negativ : Boolean;
  170. {
  171. Special : Boolean;
  172. }
  173. Places : 0..maxfmtbcdfractionsize - 1;
  174. {$endif}
  175. Fraction : packed array [ __low_Fraction..__high_Fraction ] of Byte;
  176. { BCD Nibbles, 00..99 per Byte, high Nibble 1st }
  177. end;
  178. type
  179. tDecimalPoint = ( DecimalPoint_is_Point, DecimalPoint_is_Comma, DecimalPoint_is_System );
  180. { Exception classes }
  181. type
  182. eBCDException = CLASS ( Exception );
  183. eBCDOverflowException = CLASS ( eBCDException );
  184. eBCDNotImplementedException = CLASS ( eBCDException );
  185. var
  186. DecimalPoint : tDecimalPoint = DecimalPoint_is_System;
  187. { Utility functions for TBCD access }
  188. function BCDPrecision ( const BCD : tBCD ) : Word; Inline;
  189. function BCDScale ( const BCD : tBCD ) : Word; Inline;
  190. function IsBCDNegative ( const BCD : tBCD ) : Boolean; Inline;
  191. { BCD Arithmetic}
  192. procedure BCDNegate ( var BCD : tBCD ); Inline;
  193. { !!!!!!!!!! most routines are intentionally NOT inline !!!!!!!!!! }
  194. { Returns True if successful, False if Int Digits needed to be truncated }
  195. function NormalizeBCD ( const InBCD : tBCD;
  196. var OutBCD : tBCD;
  197. const Prec,
  198. Scale : Word ) : Boolean;
  199. procedure BCDAdd ( const BCDin1,
  200. BCDin2 : tBCD;
  201. var BCDout : tBCD );
  202. procedure BCDSubtract ( const BCDin1,
  203. BCDin2 : tBCD;
  204. var BCDout : tBCD );
  205. procedure BCDMultiply ( const BCDin1,
  206. BCDin2 : tBCD;
  207. var BCDout : tBCD );
  208. {$ifndef FPUNONE}
  209. procedure BCDMultiply ( const BCDIn : tBCD;
  210. const DoubleIn : myRealtype;
  211. var BCDout : tBCD ); Inline;
  212. {$endif}
  213. procedure BCDMultiply ( const BCDIn : tBCD;
  214. const StringIn : FmtBCDStringtype;
  215. var BCDout : tBCD ); Inline;
  216. { !!! params changed to const, shouldn't give a problem }
  217. procedure BCDMultiply ( const StringIn1,
  218. StringIn2 : FmtBCDStringtype;
  219. var BCDout : tBCD ); Inline;
  220. procedure BCDDivide ( const Dividend,
  221. Divisor : tBCD;
  222. var BCDout : tBCD );
  223. {$ifndef FPUNONE}
  224. procedure BCDDivide ( const Dividend : tBCD;
  225. const Divisor : myRealtype;
  226. var BCDout : tBCD ); Inline;
  227. {$endif}
  228. procedure BCDDivide ( const Dividend : tBCD;
  229. const Divisor : FmtBCDStringtype;
  230. var BCDout : tBCD ); Inline;
  231. { !!! params changed to const, shouldn't give a problem }
  232. procedure BCDDivide ( const Dividend,
  233. Divisor : FmtBCDStringtype;
  234. var BCDout : tBCD ); Inline;
  235. { TBCD variant creation utils }
  236. procedure VarFmtBCDCreate ( var aDest : Variant;
  237. const aBCD : tBCD );
  238. function VarFmtBCDCreate : Variant;
  239. function VarFmtBCDCreate ( const aValue : FmtBCDStringtype;
  240. Precision,
  241. Scale : Word ) : Variant;
  242. {$ifndef FPUNONE}
  243. function VarFmtBCDCreate ( const aValue : myRealtype;
  244. Precision : Word = 18;
  245. Scale : Word = 4 ) : Variant;
  246. {$endif}
  247. function VarFmtBCDCreate ( const aBCD : tBCD ) : Variant;
  248. function VarIsFmtBCD ( const aValue : Variant ) : Boolean;
  249. function VarFmtBCD : TVartype;
  250. { Convert string/Double/Integer to BCD struct }
  251. function StrToBCD ( const aValue : FmtBCDStringtype ) : tBCD;
  252. function TryStrToBCD ( const aValue : FmtBCDStringtype;
  253. var BCD : tBCD ) : Boolean;
  254. {$ifndef FPUNONE}
  255. function DoubleToBCD ( const aValue : myRealtype ) : tBCD; Inline;
  256. procedure DoubleToBCD ( const aValue : myRealtype;
  257. var BCD : tBCD );
  258. {$endif}
  259. function IntegerToBCD ( const aValue : myInttype ) : tBCD;
  260. function VarToBCD ( const aValue : Variant ) : tBCD;
  261. { From DB.pas }
  262. function CurrToBCD ( const Curr : currency;
  263. var BCD : tBCD;
  264. Precision : Integer = 32;
  265. Decimals : Integer = 4 ) : Boolean;
  266. { Convert BCD struct to string/Double/Integer }
  267. function BCDToStr ( const BCD : tBCD ) : FmtBCDStringtype;
  268. {$ifndef FPUNONE}
  269. function BCDToDouble ( const BCD : tBCD ) : myRealtype;
  270. {$endif}
  271. function BCDToInteger ( const BCD : tBCD;
  272. Truncate : Boolean = False ) : myInttype;
  273. { From DB.pas }
  274. function BCDToCurr ( const BCD : tBCD;
  275. var Curr : currency ) : Boolean;
  276. { Formatting BCD as string }
  277. function BCDToStrF ( const BCD : tBCD;
  278. Format : TFloatFormat;
  279. const Precision,
  280. Digits : Integer ) : FmtBCDStringtype;
  281. function FormatBCD ( const Format : string;
  282. BCD : tBCD ) : FmtBCDStringtype;
  283. { returns -1 if BCD1 < BCD2, 0 if BCD1 = BCD2, 1 if BCD1 > BCD2 }
  284. function BCDCompare ( const BCD1,
  285. BCD2 : tBCD ) : Integer;
  286. {$ifdef additional_routines}
  287. function CurrToBCD ( const Curr : currency ) : tBCD; Inline;
  288. {$ifdef comproutines}
  289. function CompToBCD ( const Curr : Comp ) : tBCD; Inline;
  290. function BCDToComp ( const BCD : tBCD ) : Comp; Inline;
  291. {$endif}
  292. procedure BCDAdd ( const BCDIn : tBCD;
  293. const IntIn : myInttype;
  294. var BCDout : tBCD );
  295. procedure BCDAdd ( const IntIn : myInttype;
  296. const BCDIn : tBCD;
  297. var BCDout : tBCD ); Inline;
  298. {$ifndef FPUNONE}
  299. procedure BCDAdd ( const BCDIn : tBCD;
  300. const DoubleIn : myRealtype;
  301. var BCDout : tBCD ); Inline;
  302. procedure BCDAdd ( const DoubleIn : myRealtype;
  303. const BCDIn : tBCD;
  304. var BCDout : tBCD ); Inline;
  305. {$endif}
  306. procedure BCDAdd ( const BCDIn : tBCD;
  307. const Currin : currency;
  308. var BCDout : tBCD ); Inline;
  309. procedure BCDAdd ( const Currin : currency;
  310. const BCDIn : tBCD;
  311. var BCDout : tBCD ); Inline;
  312. {$ifdef comproutines}
  313. procedure BCDAdd ( const BCDIn : tBCD;
  314. const Compin : Comp;
  315. var BCDout : tBCD ); Inline;
  316. procedure BCDAdd ( const Compin : Comp;
  317. const BCDIn : tBCD;
  318. var BCDout : tBCD ); Inline;
  319. {$endif}
  320. procedure BCDAdd ( const BCDIn : tBCD;
  321. const StringIn : FmtBCDStringtype;
  322. var BCDout : tBCD ); Inline;
  323. procedure BCDAdd ( const StringIn : FmtBCDStringtype;
  324. const BCDIn : tBCD;
  325. var BCDout : tBCD ); Inline;
  326. procedure BCDAdd ( const StringIn1,
  327. StringIn2 : FmtBCDStringtype;
  328. var BCDout : tBCD ); Inline;
  329. procedure BCDSubtract ( const BCDIn : tBCD;
  330. const IntIn : myInttype;
  331. var BCDout : tBCD );
  332. procedure BCDSubtract ( const IntIn : myInttype;
  333. const BCDIn : tBCD;
  334. var BCDout : tBCD ); Inline;
  335. {$ifndef FPUNONE}
  336. procedure BCDSubtract ( const BCDIn : tBCD;
  337. const DoubleIn : myRealtype;
  338. var BCDout : tBCD ); Inline;
  339. procedure BCDSubtract ( const DoubleIn : myRealtype;
  340. const BCDIn : tBCD;
  341. var BCDout : tBCD ); Inline;
  342. {$endif}
  343. procedure BCDSubtract ( const BCDIn : tBCD;
  344. const Currin : currency;
  345. var BCDout : tBCD ); Inline;
  346. procedure BCDSubtract ( const Currin : currency;
  347. const BCDIn : tBCD;
  348. var BCDout : tBCD ); Inline;
  349. {$ifdef comproutines}
  350. procedure BCDSubtract ( const BCDIn : tBCD;
  351. const Compin : Comp;
  352. var BCDout : tBCD ); Inline;
  353. procedure BCDSubtract ( const Compin : Comp;
  354. const BCDIn : tBCD;
  355. var BCDout : tBCD ); Inline;
  356. {$endif}
  357. procedure BCDSubtract ( const BCDIn : tBCD;
  358. const StringIn : FmtBCDStringtype;
  359. var BCDout : tBCD ); Inline;
  360. procedure BCDSubtract ( const StringIn : FmtBCDStringtype;
  361. const BCDIn : tBCD;
  362. var BCDout : tBCD ); Inline;
  363. procedure BCDSubtract ( const StringIn1,
  364. StringIn2 : FmtBCDStringtype;
  365. var BCDout : tBCD ); Inline;
  366. procedure BCDMultiply ( const BCDIn : tBCD;
  367. const IntIn : myInttype;
  368. var BCDout : tBCD );
  369. procedure BCDMultiply ( const IntIn : myInttype;
  370. const BCDIn : tBCD;
  371. var BCDout : tBCD ); Inline;
  372. {$ifndef FPUNONE}
  373. procedure BCDMultiply ( const DoubleIn : myRealtype;
  374. const BCDIn : tBCD;
  375. var BCDout : tBCD ); Inline;
  376. {$endif}
  377. procedure BCDMultiply ( const BCDIn : tBCD;
  378. const Currin : currency;
  379. var BCDout : tBCD ); Inline;
  380. procedure BCDMultiply ( const Currin : currency;
  381. const BCDIn : tBCD;
  382. var BCDout : tBCD ); Inline;
  383. {$ifdef comproutines}
  384. procedure BCDMultiply ( const BCDIn : tBCD;
  385. const Compin : Comp;
  386. var BCDout : tBCD ); Inline;
  387. procedure BCDMultiply ( const Compin : Comp;
  388. const BCDIn : tBCD;
  389. var BCDout : tBCD ); Inline;
  390. {$endif}
  391. procedure BCDMultiply ( const StringIn : FmtBCDStringtype;
  392. const BCDIn : tBCD;
  393. var BCDout : tBCD ); Inline;
  394. procedure BCDDivide ( const Dividend : tBCD;
  395. const Divisor : myInttype;
  396. var BCDout : tBCD ); Inline;
  397. procedure BCDDivide ( const Dividend : myInttype;
  398. const Divisor : tBCD;
  399. var BCDout : tBCD ); Inline;
  400. {$ifndef FPUNONE}
  401. procedure BCDDivide ( const Dividend : myRealtype;
  402. const Divisor : tBCD;
  403. var BCDout : tBCD ); Inline;
  404. {$endif}
  405. procedure BCDDivide ( const BCDIn : tBCD;
  406. const Currin : currency;
  407. var BCDout : tBCD ); Inline;
  408. procedure BCDDivide ( const Currin : currency;
  409. const BCDIn : tBCD;
  410. var BCDout : tBCD ); Inline;
  411. {$ifdef comproutines}
  412. procedure BCDDivide ( const BCDIn : tBCD;
  413. const Compin : Comp;
  414. var BCDout : tBCD ); Inline;
  415. procedure BCDDivide ( const Compin : Comp;
  416. const BCDIn : tBCD;
  417. var BCDout : tBCD ); Inline;
  418. {$endif}
  419. procedure BCDDivide ( const Dividend : FmtBCDStringtype;
  420. const Divisor : tBCD;
  421. var BCDout : tBCD ); Inline;
  422. operator = ( const BCD1,
  423. BCD2 : tBCD ) z : Boolean; Inline;
  424. operator < ( const BCD1,
  425. BCD2 : tBCD ) z : Boolean; Inline;
  426. operator > ( const BCD1,
  427. BCD2 : tBCD ) z : Boolean; Inline;
  428. operator <= ( const BCD1,
  429. BCD2 : tBCD ) z : Boolean; Inline;
  430. operator >= ( const BCD1,
  431. BCD2 : tBCD ) z : Boolean; Inline;
  432. (* ######################## not allowed: why?
  433. operator + ( const BCD : tBCD ) z : tBCD; make_Inline
  434. ##################################################### *)
  435. operator - ( const BCD : tBCD ) z : tBCD; Inline;
  436. operator + ( const BCD1,
  437. BCD2 : tBCD ) z : tBCD; Inline;
  438. operator + ( const BCD : tBCD;
  439. const i : myInttype ) z : tBCD; Inline;
  440. operator + ( const i : myInttype;
  441. const BCD : tBCD ) z : tBCD; Inline;
  442. {$ifndef FPUNONE}
  443. operator + ( const BCD : tBCD;
  444. const r : myRealtype ) z : tBCD; Inline;
  445. operator + ( const r : myRealtype;
  446. const BCD : tBCD ) z : tBCD; Inline;
  447. {$endif}
  448. operator + ( const BCD : tBCD;
  449. const c : currency ) z : tBCD; Inline;
  450. operator + ( const c : currency;
  451. const BCD : tBCD ) z : tBCD; Inline;
  452. {$ifdef comproutines}
  453. operator + ( const BCD : tBCD;
  454. const c : Comp ) z : tBCD; Inline;
  455. operator + ( const c : Comp;
  456. const BCD : tBCD ) z : tBCD; Inline;
  457. {$endif}
  458. operator + ( const BCD : tBCD;
  459. const s : FmtBCDStringtype ) z : tBCD; Inline;
  460. operator + ( const s : FmtBCDStringtype;
  461. const BCD : tBCD ) z : tBCD; Inline;
  462. operator - ( const BCD1,
  463. BCD2 : tBCD ) z : tBCD; Inline;
  464. operator - ( const BCD : tBCD;
  465. const i : myInttype ) z : tBCD; Inline;
  466. operator - ( const i : myInttype;
  467. const BCD : tBCD ) z : tBCD; Inline;
  468. {$ifndef FPUNONE}
  469. operator - ( const BCD : tBCD;
  470. const r : myRealtype ) z : tBCD; Inline;
  471. operator - ( const r : myRealtype;
  472. const BCD : tBCD ) z : tBCD; Inline;
  473. {$endif}
  474. operator - ( const BCD : tBCD;
  475. const c : currency ) z : tBCD; Inline;
  476. operator - ( const c : currency;
  477. const BCD : tBCD ) z : tBCD; Inline;
  478. {$ifdef comproutines}
  479. operator - ( const BCD : tBCD;
  480. const c : Comp ) z : tBCD; Inline;
  481. operator - ( const c : Comp;
  482. const BCD : tBCD ) z : tBCD; Inline;
  483. {$endif}
  484. operator - ( const BCD : tBCD;
  485. const s : FmtBCDStringtype ) z : tBCD; Inline;
  486. operator - ( const s : FmtBCDStringtype;
  487. const BCD : tBCD ) z : tBCD; Inline;
  488. operator * ( const BCD1,
  489. BCD2 : tBCD ) z : tBCD; Inline;
  490. operator * ( const BCD : tBCD;
  491. const i : myInttype ) z : tBCD; Inline;
  492. operator * ( const i : myInttype;
  493. const BCD : tBCD ) z : tBCD; Inline;
  494. {$ifndef FPUNONE}
  495. operator * ( const BCD : tBCD;
  496. const r : myRealtype ) z : tBCD; Inline;
  497. operator * ( const r : myRealtype;
  498. const BCD : tBCD ) z : tBCD; Inline;
  499. {$endif}
  500. operator * ( const BCD : tBCD;
  501. const c : currency ) z : tBCD; Inline;
  502. operator * ( const c : currency;
  503. const BCD : tBCD ) z : tBCD; Inline;
  504. {$ifdef comproutines}
  505. operator * ( const BCD : tBCD;
  506. const c : Comp ) z : tBCD; Inline;
  507. operator * ( const c : Comp;
  508. const BCD : tBCD ) z : tBCD; Inline;
  509. {$endif}
  510. operator * ( const BCD : tBCD;
  511. const s : FmtBCDStringtype ) z : tBCD; Inline;
  512. operator * ( const s : FmtBCDStringtype;
  513. const BCD : tBCD ) z : tBCD; Inline;
  514. operator / ( const BCD1,
  515. BCD2 : tBCD ) z : tBCD; Inline;
  516. operator / ( const BCD : tBCD;
  517. const i : myInttype ) z : tBCD; Inline;
  518. operator / ( const i : myInttype;
  519. const BCD : tBCD ) z : tBCD; Inline;
  520. {$ifndef FPUNONE}
  521. operator / ( const BCD : tBCD;
  522. const r : myRealtype ) z : tBCD; Inline;
  523. operator / ( const r : myRealtype;
  524. const BCD : tBCD ) z : tBCD; Inline;
  525. {$endif}
  526. operator / ( const BCD : tBCD;
  527. const c : currency ) z : tBCD; Inline;
  528. operator / ( const c : currency;
  529. const BCD : tBCD ) z : tBCD; Inline;
  530. {$ifdef comproutines}
  531. operator / ( const BCD : tBCD;
  532. const c : Comp ) z : tBCD; Inline;
  533. operator / ( const c : Comp;
  534. const BCD : tBCD ) z : tBCD; Inline;
  535. {$endif}
  536. operator / ( const BCD : tBCD;
  537. const s : FmtBCDStringtype ) z : tBCD; Inline;
  538. operator / ( const s : FmtBCDStringtype;
  539. const BCD : tBCD ) z : tBCD; Inline;
  540. operator := ( const i : Byte ) z : tBCD; Inline;
  541. operator := ( const BCD : tBCD ) z : Byte; Inline;
  542. operator := ( const i : Word ) z : tBCD; Inline;
  543. operator := ( const BCD : tBCD ) z : Word; Inline;
  544. operator := ( const i : longword ) z : tBCD; Inline;
  545. operator := ( const BCD : tBCD ) z : longword; Inline;
  546. {$if declared ( qword ) }
  547. operator := ( const i : qword ) z : tBCD; Inline;
  548. operator := ( const BCD : tBCD ) z : qword; Inline;
  549. {$endif}
  550. operator := ( const i : ShortInt ) z : tBCD; Inline;
  551. operator := ( const BCD : tBCD ) z : ShortInt; Inline;
  552. operator := ( const i : smallint ) z : tBCD; Inline;
  553. operator := ( const BCD : tBCD ) z : smallint; Inline;
  554. operator := ( const i : LongInt ) z : tBCD; Inline;
  555. operator := ( const BCD : tBCD ) z : LongInt; Inline;
  556. {$if declared ( int64 ) }
  557. operator := ( const i : int64 ) z : tBCD; Inline;
  558. operator := ( const BCD : tBCD ) z : int64; Inline;
  559. {$endif}
  560. {$ifndef FPUNONE}
  561. operator := ( const r : Single ) z : tBCD; Inline;
  562. operator := ( const BCD : tBCD ) z : Single; Inline;
  563. operator := ( const r : Double ) z : tBCD; Inline;
  564. operator := ( const BCD : tBCD ) z : Double; Inline;
  565. {$if sizeof ( extended ) <> sizeof ( double )}
  566. operator := ( const r : Extended ) z : tBCD; Inline;
  567. operator := ( const BCD : tBCD ) z : Extended; Inline;
  568. {$endif}
  569. {$endif}
  570. operator := ( const c : currency ) z : tBCD; Inline;
  571. operator := ( const BCD : tBCD ) z : currency; Inline;
  572. {$ifdef comproutines}
  573. operator := ( const c : Comp ) z : tBCD; Inline;
  574. operator := ( const BCD : tBCD ) z : Comp; Inline;
  575. {$endif}
  576. operator := ( const s : string ) z : tBCD; Inline;
  577. operator := ( const BCD : tBCD ) z : string; Inline;
  578. operator := ( const s : AnsiString ) z : tBCD; Inline;
  579. operator := ( const BCD : tBCD ) z : AnsiString; Inline;
  580. {$endif}
  581. function __get_null : tBCD; Inline;
  582. function __get_one : tBCD; Inline;
  583. PROPERTY
  584. NullBCD : tBCD Read __get_null;
  585. OneBCD : tBCD Read __get_one;
  586. //{$define __lo_bh := 1 * ( -( MaxFmtBCDFractionSize * 1 + 2 ) ) }
  587. //{$define __hi_bh := 1 * ( MaxFmtBCDFractionSize * 1 + 1 ) }
  588. {$define helper_declarations :=
  589. const
  590. __lo_bh = -( MaxFmtBCDFractionSize + 2 );
  591. __hi_bh = ( MaxFmtBCDFractionSize + 1 );
  592. type
  593. tBCD_helper = Maybe_Packed record
  594. Prec : {$ifopt r+} 0..( __hi_bh - __lo_bh + 1 ) {$else} Integer {$endif};
  595. Plac : {$ifopt r+} 0..( __hi_bh - __lo_bh + 1 ) {$else} Integer {$endif};
  596. FDig,
  597. LDig : {$ifopt r+} __lo_bh..__hi_bh {$else} Integer {$endif};
  598. Singles : Maybe_packed array [ __lo_bh..__hi_bh ]
  599. of {$ifopt r+} 0..9 {$else} Byte {$endif};
  600. Neg : Boolean;
  601. end;
  602. { in the tBCD_helper the bcd is stored for computations,
  603. shifted to the right position }
  604. // {$define __lo_bhb := 1 * ( __lo_bh + __lo_bh ) }
  605. // {$define __hi_bhb := 1 * ( __hi_bh + __hi_bh + 1 ) }
  606. const
  607. __lo_bhb = __lo_bh + __lo_bh - 1;
  608. __hi_bhb = __hi_bh + __hi_bh;
  609. type
  610. tBCD_helper_big = Maybe_Packed record
  611. Prec : {$ifopt r+} 0.. ( __hi_bhb - __lo_bhb + 1 ) {$else} Integer {$endif};
  612. Plac : {$ifopt r+} 0.. ( __hi_bhb - __lo_bhb + 1 ) {$else} Integer {$endif};
  613. FDig,
  614. LDig : {$ifopt r+} __lo_bhb..__hi_bhb {$else} Integer {$endif};
  615. Singles : Maybe_packed array [ __lo_bhb..__hi_bhb ]
  616. of {$ifopt r+} 0 * 0..9 * 9 * Pred ( MaxFmtBCDDigits ) {$else} Integer {$endif};
  617. Neg : Boolean;
  618. end;
  619. }
  620. {$ifdef debug_version}
  621. helper_declarations
  622. procedure unpack_BCD ( const BCD : tBCD;
  623. var bh : tBCD_helper );
  624. function pack_BCD ( var bh : tBCD_helper;
  625. var BCD : tBCD ) : Boolean;
  626. procedure dumpBCD ( const v : tBCD );
  627. {$endif}
  628. IMPLEMENTATION
  629. USES
  630. classes {$ifopt r+}, sysconst {$endif};
  631. type
  632. TFMTBcdFactory = CLASS(TPublishableVarianttype)
  633. PROTECTED
  634. function GetInstance(const v : TVarData): tObject; OVERRIDE;
  635. PUBLIC
  636. procedure BinaryOp(var Left: TVarData; const Right: TVarData; const Operation: TVarOp); override;
  637. procedure Clear(var V: TVarData); override;
  638. procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean); override;
  639. function CompareOp(const Left, Right: TVarData; const Operation: TVarOp): Boolean; override;
  640. procedure Compare(const Left, Right: TVarData; var Relationship: TVarCompareResult); override;
  641. procedure Cast(var Dest: TVarData; const Source: TVarData); override;
  642. procedure CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType); override;
  643. end;
  644. TFMTBcdVarData = CLASS(TPersistent)
  645. PRIVATE
  646. FBcd : tBCD;
  647. PUBLIC
  648. constructor create;
  649. constructor create(const BCD : tBCD);
  650. PROPERTY BCD : tBCD Read FBcd Write FBcd;
  651. end;
  652. var
  653. NullBCD_ : tBCD;
  654. OneBCD_ : tBCD;
  655. function __get_null : tBCD; Inline;
  656. begin
  657. __get_null := NullBCD_;
  658. end;
  659. function __get_one : tBCD; Inline;
  660. begin
  661. __get_one := OneBCD_;
  662. end;
  663. type
  664. range_digits = 1..maxfmtbcdfractionsize;
  665. range_digits0 = 0..maxfmtbcdfractionsize;
  666. range_fracdigits = 0..pred ( MaxFmtBCDFractionSize );
  667. {$ifopt r+}
  668. procedure RangeError;
  669. begin
  670. raise ERangeError.Create(SRangeError);
  671. end;
  672. {$endif}
  673. {$ifndef debug_version}
  674. helper_declarations
  675. {$endif}
  676. var
  677. null_ : record
  678. case Boolean of
  679. False: ( bh : tBCD_helper );
  680. True: ( bhb : tBCD_helper_big );
  681. end;
  682. FMTBcdFactory : TFMTBcdFactory = NIL;
  683. {$ifndef bigger_BCD}
  684. const
  685. NegBit = 1 SHL 7;
  686. SpecialBit = 1 SHL 6;
  687. PlacesMask = $ff XOR ( NegBit OR SpecialBit );
  688. {$endif}
  689. {$define _select := {$define _when := if {$define _when := end else if } }
  690. {$define _then := then begin }
  691. {$define _whenother := end else begin }
  692. {$define _endselect := end } }
  693. {$ifdef debug_version}
  694. procedure dumpBCD ( const v : tBCD );
  695. var
  696. i,
  697. j : Integer;
  698. const
  699. ft : ARRAY [ Boolean ] of Char = ( 'f', 't' );
  700. begin
  701. {$ifndef bigger_BCD}
  702. Write ( 'Prec:', v.Precision, ' ',
  703. 'Neg:', ft[( v.SignSpecialPlaces AND NegBit ) <> 0], ' ',
  704. 'Special:', ft[( v.SignSpecialPlaces AND SpecialBit ) <> 0], ' ',
  705. 'Places:', v.SignSpecialPlaces AND PlacesMask, ' ' );
  706. {$else}
  707. Write ( 'Prec:', v.Precision, ' ',
  708. 'Neg:', ft[v.Negativ], ' ',
  709. 'Places:', v.Places, ' ' );
  710. {$endif}
  711. j := 0;
  712. for i := 1 TO v.Precision do
  713. if Odd ( i )
  714. then Write ( ( v.Fraction[j] AND $f0 ) SHR 4 )
  715. else begin
  716. Write ( v.Fraction[j] AND $0f );
  717. Inc ( j );
  718. end;
  719. WriteLn;
  720. end;
  721. procedure dumpbh ( const v : tBCD_helper );
  722. var
  723. i : Integer;
  724. const
  725. ft : ARRAY [ Boolean ] of Char = ( 'f', 't' );
  726. begin
  727. Write ( 'Prec:', v.Prec, ' ',
  728. 'Neg:', ft[v.Neg], ' ',
  729. 'Places:', v.Plac, ' ',
  730. 'FDig:', v.FDig, ' ',
  731. 'LDig:', v.LDig, ' ',
  732. 'Digits:', v.LDig - v.FDig + 1, ' ' );
  733. for i := v.FDig TO v.LDig do
  734. Write ( v.Singles[i] );
  735. WriteLn;
  736. end;
  737. {$endif}
  738. {$if sizeof ( integer ) = 2 }
  739. {$ifdef BCDgr4 }
  740. var
  741. myMinIntBCD : tBCD;
  742. {$endif}
  743. {$else}
  744. {$if sizeof ( integer ) = 4 }
  745. {$ifdef BCDgr9 }
  746. var
  747. myMinIntBCD : tBCD;
  748. {$endif}
  749. {$else}
  750. {$if sizeof ( integer ) = 8 }
  751. {$ifdef BCDgr18 }
  752. var
  753. myMinIntBCD : tBCD;
  754. {$endif}
  755. {$else}
  756. {$fatal You have an interesting integer type! Sorry, not supported}
  757. {$endif}
  758. {$endif}
  759. {$endif}
  760. procedure not_implemented;
  761. begin
  762. RAISE eBCDNotImplementedException.create ( 'not implemented' );
  763. end;
  764. procedure unpack_BCD ( const BCD : tBCD;
  765. var bh : tBCD_helper );
  766. var
  767. i : {$ifopt r+} __lo_bh + 1 ..__hi_bh {$else} Integer {$endif};
  768. j : {$ifopt r+} -1..__high_fraction {$else} Integer {$endif};
  769. vv : {$ifopt r+} $00..$99 {$else} Integer {$endif};
  770. begin
  771. bh := null_.bh;
  772. WITH bh,
  773. BCD do
  774. begin
  775. Prec := Precision;
  776. if Prec > 0
  777. then begin
  778. {$ifndef bigger_BCD}
  779. Plac := SignSpecialPlaces AND PlacesMask;
  780. Neg := ( SignSpecialPlaces AND NegBit ) <> 0;
  781. {$else}
  782. Plac := Places;
  783. Neg := Negativ;
  784. {$endif}
  785. LDig := Plac;
  786. FDig := LDig - Prec + 1;
  787. j := -1;
  788. i := FDig;
  789. while i <= LDig do
  790. begin
  791. Inc ( j );
  792. vv := Fraction[j];
  793. Singles[i] := ( vv {AND $f0} ) SHR 4;
  794. if i < LDig
  795. then Singles[i+1] := vv AND $0f;
  796. Inc ( i, 2 );
  797. end;
  798. end;
  799. end;
  800. end;
  801. function pack_BCD ( var bh : tBCD_helper;
  802. var BCD : tBCD ) : Boolean;
  803. { return TRUE if successful (BCD valid) }
  804. var
  805. pre : {$ifopt r+} 0..__hi_bh - __lo_bh + 1 {$else} Integer {$endif};
  806. fra : {$ifopt r+} -1 * ( __hi_bh - __lo_bh + 1 )..__hi_bh - __lo_bh + 1 {$else} Integer {$endif};
  807. tm : {$ifopt r+} 0..__hi_bh - __lo_bh + 1 - Pred ( MaxFmtBCDFractionSize ) {$else} Integer {$endif};
  808. i : {$ifopt r+} low ( bh.FDig ) - 1..high ( bh.LDig ) {$else} Integer {$endif};
  809. rp : {$ifopt r+} low ( BCD.Fraction )..high ( BCD.Fraction ) + 1 {$else} Integer {$endif};
  810. ue : {$ifopt r+} 0..1 {$else} Integer {$endif};
  811. v : {$ifopt r+} 0..10 {$else} Integer {$endif};
  812. lnz : {$ifopt r+} low ( bh.FDig )..high ( bh.LDig ) {$else} Integer {$endif};
  813. doround,
  814. lnzf : Boolean;
  815. begin
  816. pack_BCD := False;
  817. BCD := NullBCD;
  818. WITH BCD,
  819. bh do
  820. begin
  821. lnzf := FDig < 0;
  822. while lnzf do
  823. if Singles[FDig] = 0
  824. then begin
  825. Inc ( FDig );
  826. if FDig = 0
  827. then lnzf := False;
  828. end
  829. else lnzf := False;
  830. pre := LDig - FDig + 1;
  831. fra := Plac;
  832. doround := False;
  833. if fra >= MaxFmtBCDFractionSize
  834. then begin
  835. doround := True;
  836. tm := fra - Pred ( MaxFmtBCDFractionSize );
  837. { dec ( pre, tm ); Dec/Inc error? }
  838. pre := pre - tm;
  839. { Dec ( fra, tm ); Dec/Inc error? }
  840. fra := fra - tm;
  841. { Dec ( LDig, tm ); Dec/Inc error? }
  842. LDig := LDig - tm;
  843. end;
  844. if pre > MaxFmtBCDFractionSize
  845. then begin
  846. doround := True;
  847. tm := pre - MaxFmtBCDFractionSize;
  848. { Dec ( pre, tm ); Dec/Inc error? }
  849. pre := pre - tm;
  850. { Dec ( fra, tm ); Dec/Inc error? }
  851. fra := fra - tm;
  852. { Dec ( LDig, tm ); Dec/Inc error? }
  853. LDig := LDig - tm;
  854. end;
  855. if fra < 0
  856. then EXIT;
  857. if doround
  858. then begin
  859. v := Singles[fra + 1];
  860. if v > 4
  861. then begin
  862. ue := 1;
  863. i := LDig;
  864. while ( i >= FDig ) AND ( ue <> 0 ) do
  865. begin
  866. v := Singles[i] + ue;
  867. ue := v DIV 10;
  868. Singles[i] := v MOD 10;
  869. Dec ( i );
  870. end;
  871. if ue <> 0
  872. then begin
  873. Dec ( FDig );
  874. Singles[FDig] := ue;
  875. Dec ( LDig );
  876. Dec ( fra );
  877. if fra < 0
  878. then EXIT;
  879. end;
  880. end;
  881. end;
  882. lnzf := False;
  883. i := LDig;
  884. while ( i >= FDig ) AND ( NOT lnzf ) do
  885. begin
  886. if Singles[i] <> 0
  887. then begin
  888. lnz := i;
  889. lnzf := True;
  890. end;
  891. Dec ( i );
  892. end;
  893. if lnzf
  894. then begin
  895. tm := LDig - lnz;
  896. if tm <> 0
  897. then begin
  898. { Dec ( pre, tm ); Dec/Inc error? }
  899. pre := pre - tm;
  900. { Dec ( fra, tm ); Dec/Inc error? }
  901. fra := fra - tm;
  902. { Dec ( LDig, tm ); Dec/Inc error? }
  903. LDig := LDig - tm;
  904. if fra < 0
  905. then begin
  906. { Dec ( pre, fra ); Dec/Inc error? }
  907. pre := pre - fra;
  908. { Dec ( LDig, fra ); Dec/Inc error? }
  909. LDig := LDig - fra;
  910. fra := 0;
  911. end;
  912. end;
  913. end
  914. else begin
  915. LDig := FDig;
  916. fra := 0;
  917. pre := 0;
  918. Neg := False;
  919. end;
  920. if pre <> 0
  921. then begin
  922. Precision := pre;
  923. rp := 0;
  924. i := FDig;
  925. while i <= LDig do
  926. begin
  927. if i < LDig
  928. then Fraction[rp] := ( Singles[i] SHL 4 ) OR Singles[i + 1]
  929. else Fraction[rp] := Singles[i] SHL 4;
  930. Inc ( rp );
  931. Inc ( i, 2 );
  932. end;
  933. {$ifndef bigger_BCD}
  934. if Neg
  935. then SignSpecialPlaces := NegBit;
  936. SignSpecialPlaces := SignSpecialPlaces OR fra;
  937. {$else}
  938. Negativ := Neg;
  939. Places := fra;
  940. {$endif}
  941. end;
  942. end;
  943. pack_BCD := True;
  944. end;
  945. procedure SetDecimals ( out dp,
  946. dc : Char );
  947. begin
  948. case DecimalPoint of
  949. DecimalPoint_is_Point: begin
  950. dp := '.';
  951. dc := ',';
  952. end;
  953. DecimalPoint_is_Comma: begin
  954. dp := ',';
  955. dc := '.';
  956. end;
  957. { find out language-specific ? }
  958. DecimalPoint_is_System: begin
  959. dp := DefaultFormatSettings.DecimalSeparator;
  960. dc := DefaultFormatSettings.ThousandSeparator;
  961. end;
  962. end;
  963. end;
  964. function BCDPrecision ( const BCD : tBCD ) : Word; Inline;
  965. begin
  966. BCDPrecision := BCD.Precision;
  967. end;
  968. function BCDScale ( const BCD : tBCD ) : Word; Inline;
  969. begin
  970. {$ifndef bigger_BCD}
  971. BCDScale := BCD.SignSpecialPlaces AND PlacesMask;
  972. {$else}
  973. BCDScale := BCD.Places;
  974. {$endif}
  975. end;
  976. function IsBCDNegative ( const BCD : tBCD ) : Boolean; Inline;
  977. begin
  978. {$ifndef bigger_BCD}
  979. IsBCDNegative := ( BCD.SignSpecialPlaces AND NegBit ) <> 0;
  980. {$else}
  981. IsBCDNegative := BCD.Negativ;
  982. {$endif}
  983. end;
  984. { BCD Arithmetic}
  985. procedure BCDNegate ( var BCD : tBCD ); Inline;
  986. begin
  987. { with-statement geht nicht !!
  988. with bcd do
  989. if precision <> 0
  990. then signspecialplaces := signspecialplaces xor negbit;
  991. }
  992. if BCD.Precision <> 0
  993. then
  994. {$ifndef bigger_BCD}
  995. BCD.SignSpecialPlaces := BCD.SignSpecialPlaces XOR NegBit;
  996. {$else}
  997. BCD.Negativ := NOT BCD.Negativ;
  998. {$endif}
  999. end;
  1000. { returns -1 if BCD1 < BCD2, 0 if BCD1 = BCD2, 1 if BCD1 > BCD2 }
  1001. function BCDCompare ( const BCD1,
  1002. BCD2 : tBCD ) : Integer;
  1003. var
  1004. pl1 : {$ifopt r+} 0..maxfmtbcdfractionsize - 1 {$else} Integer {$endif};
  1005. pl2 : {$ifopt r+} 0..maxfmtbcdfractionsize - 1 {$else} Integer {$endif};
  1006. pr1 : {$ifopt r+} 0..maxfmtbcdfractionsize {$else} Integer {$endif};
  1007. pr2 : {$ifopt r+} 0..maxfmtbcdfractionsize {$else} Integer {$endif};
  1008. pr : {$ifopt r+} 0..maxfmtbcdfractionsize {$else} Integer {$endif};
  1009. idig1 : {$ifopt r+} 0..maxfmtbcdfractionsize {$else} Integer {$endif};
  1010. idig2 : {$ifopt r+} 0..maxfmtbcdfractionsize {$else} Integer {$endif};
  1011. i : {$ifopt r+} __low_Fraction..__high_Fraction + 1 {$else} Integer {$endif};
  1012. f1 : {$ifopt r+} $00..$99 {$else} Integer {$endif};
  1013. f2 : {$ifopt r+} $00..$99 {$else} Integer {$endif};
  1014. res : {$ifopt r+} -1..1 {$else} Integer {$endif};
  1015. neg1,
  1016. neg2 : Boolean;
  1017. begin
  1018. {$ifndef bigger_BCD}
  1019. neg1 := ( BCD1.SignSpecialPlaces AND NegBit ) <> 0;
  1020. neg2 := ( BCD2.SignSpecialPlaces AND NegBit ) <> 0;
  1021. {$else}
  1022. neg1 := BCD1.Negativ;
  1023. neg2 := BCD2.Negativ;
  1024. {$endif}
  1025. _SELECT
  1026. _WHEN neg1 AND ( NOT neg2 )
  1027. _THEN result := -1;
  1028. _WHEN ( NOT neg1 ) AND neg2
  1029. _THEN result := +1;
  1030. _WHENOTHER
  1031. pr1 := BCD1.Precision;
  1032. pr2 := BCD2.Precision;
  1033. {$ifndef bigger_BCD}
  1034. pl1 := BCD1.SignSpecialPlaces AND PlacesMask;
  1035. pl2 := BCD2.SignSpecialPlaces AND PlacesMask;
  1036. {$else}
  1037. pl1 := BCD1.Places;
  1038. pl2 := BCD2.Places;
  1039. {$endif}
  1040. idig1 := pr1 - pl1;
  1041. idig2 := pr2 - pl2;
  1042. if idig1 <> idig2
  1043. then begin
  1044. if ( idig1 > idig2 ) = neg1
  1045. then result := -1
  1046. else result := +1;
  1047. end
  1048. else begin
  1049. if pr1 < pr2
  1050. then pr := pr1
  1051. else pr := pr2;
  1052. res := 0;
  1053. i := __low_Fraction;
  1054. while ( res = 0 ) AND ( i < ( __low_Fraction + ( pr DIV 2 ) ) ) do
  1055. begin
  1056. {
  1057. if BCD1.Fraction[i] < BCD2.Fraction[i]
  1058. then res := -1
  1059. else
  1060. if BCD1.Fraction[i] > BCD2.Fraction[i]
  1061. then res := +1;
  1062. }
  1063. _SELECT
  1064. _WHEN BCD1.Fraction[i] < BCD2.Fraction[i]
  1065. _THEN res := -1
  1066. _WHEN BCD1.Fraction[i] > BCD2.Fraction[i]
  1067. _THEN res := +1;
  1068. _WHENOTHER
  1069. _endSELECT;
  1070. Inc ( i );
  1071. end;
  1072. if res = 0
  1073. then begin
  1074. if Odd ( pr )
  1075. then begin
  1076. f1 := BCD1.Fraction[i] AND $f0;
  1077. f2 := BCD2.Fraction[i] AND $f0;
  1078. {
  1079. if f1 < f2
  1080. then res := -1
  1081. else
  1082. if f1 > f2
  1083. then res := +1;
  1084. }
  1085. _SELECT
  1086. _WHEN f1 < f2
  1087. _THEN res := -1
  1088. _WHEN f1 > f2
  1089. _THEN res := +1;
  1090. _endSELECT;
  1091. end;
  1092. end;
  1093. if neg1
  1094. then result := 0 - res
  1095. else result := res;
  1096. end;
  1097. _endSELECT
  1098. end;
  1099. { Convert string/Double/Integer to BCD struct }
  1100. function TryStrToBCD ( const aValue : FmtBCDStringtype;
  1101. var BCD : tBCD ) : Boolean;
  1102. { shall this return TRUE when error and FALSE when o.k. or the other way round ? }
  1103. var
  1104. {$ifndef use_ansistring}
  1105. lav : {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1106. i : {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1107. {$else}
  1108. lav : {$ifopt r+} longword {$else} longword {$endif};
  1109. i : {$ifopt r+} longword {$else} longword {$endif};
  1110. {$endif}
  1111. ch : Char;
  1112. dp,
  1113. dc : Char;
  1114. type
  1115. ife = ( inint, infrac, inexp );
  1116. {$define max_exp_scanned := 9999 }
  1117. var
  1118. inife : ife;
  1119. lvars : record
  1120. fp,
  1121. lp : ARRAY [ ife ]
  1122. {$ifndef use_ansistring}
  1123. of {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1124. pfnb : {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1125. ps : {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1126. pse : {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1127. errp : {$ifopt r+} 0..high ( aValue ) {$else} Integer {$endif};
  1128. {$else}
  1129. of {$ifopt r+} longword {$else} longword {$endif};
  1130. pfnb : {$ifopt r+} longword {$else} longword {$endif};
  1131. ps : {$ifopt r+} longword {$else} longword {$endif};
  1132. pse : {$ifopt r+} longword {$else} longword {$endif};
  1133. errp : {$ifopt r+} longword {$else} longword {$endif};
  1134. {$endif}
  1135. exp : {$ifopt r+} -max_exp_scanned..max_exp_scanned {$else} Integer {$endif};
  1136. p : {$ifopt r+} -max_exp_scanned..max_exp_scanned {$else} Integer {$endif};
  1137. bh : tBCD_helper;
  1138. nbf : Boolean;
  1139. end;
  1140. begin
  1141. result := True;
  1142. FillChar ( lvars, SizeOf ( lvars ), #0 );
  1143. BCD := NullBCD;
  1144. lav := Length ( aValue );
  1145. if lav <> 0
  1146. then
  1147. WITH lvars,
  1148. bh do
  1149. begin
  1150. SetDecimals ( dp, dc );
  1151. while ( pfnb < lav ) AND ( NOT nbf ) do
  1152. begin
  1153. Inc ( pfnb );
  1154. nbf := aValue[pfnb] <> ' ';
  1155. end;
  1156. if nbf
  1157. then begin
  1158. if aValue[pfnb] IN [ '+', '-' ]
  1159. then begin
  1160. ps := pfnb;
  1161. Inc ( pfnb );
  1162. end;
  1163. inife := low ( inife );
  1164. for i := pfnb TO lav do
  1165. begin
  1166. ch := aValue[i];
  1167. case ch of
  1168. '0'..'9': begin
  1169. case inife of
  1170. inint,
  1171. inexp: if fp[inife] = 0
  1172. then begin
  1173. if ch <> '0'
  1174. then begin
  1175. fp[inife] := i;
  1176. lp[inife] := i;
  1177. end;
  1178. end
  1179. else lp[inife] := i;
  1180. infrac: begin
  1181. if fp[infrac] = 0
  1182. then fp[infrac] := i;
  1183. if ch <> '0'
  1184. then lp[infrac] := i;
  1185. end;
  1186. end;
  1187. end;
  1188. ',',
  1189. '.': if ch = dp
  1190. then begin
  1191. if inife <> inint
  1192. then result := False
  1193. else inife := infrac;
  1194. end;
  1195. 'e',
  1196. 'E': if inife = inexp
  1197. then result := False
  1198. else inife := inexp;
  1199. '+',
  1200. '-': if ( inife = inexp ) AND ( fp[inexp] = 0 )
  1201. then pse := i
  1202. else result := False;
  1203. else begin
  1204. result := False;
  1205. errp := i;
  1206. end;
  1207. end;
  1208. end;
  1209. if not result
  1210. then begin
  1211. result := True;
  1212. for i := errp TO lav do
  1213. if aValue[i] <> ' '
  1214. then result := False;
  1215. end;
  1216. if not result
  1217. then EXIT;
  1218. if ps <> 0
  1219. then Neg := aValue[ps] = '-';
  1220. if lp[infrac] = 0
  1221. then fp[infrac] := 0;
  1222. if fp[inexp] <> 0
  1223. then begin
  1224. exp := 0;
  1225. for i := fp[inexp] TO lp[inexp] do
  1226. if result
  1227. then
  1228. if aValue[i] <> dc
  1229. then begin
  1230. exp := exp * 10 + ( Ord ( aValue[i] ) - Ord ( '0' ) );
  1231. if exp > 999
  1232. then result := False;
  1233. end;
  1234. if not result
  1235. then EXIT;
  1236. if pse <> 0
  1237. then
  1238. if aValue[pse] = '-'
  1239. then exp := -exp;
  1240. end;
  1241. p := -exp;
  1242. if fp[infrac] <> 0
  1243. then begin
  1244. for i := fp[infrac] TO lp[infrac] do
  1245. if aValue[i] <> dc
  1246. then begin
  1247. if p < ( MaxFmtBCDFractionSize + 2 )
  1248. then begin
  1249. Inc ( p );
  1250. Singles[p] := Ord ( aValue[i] ) - Ord ( '0' );
  1251. end;
  1252. end;
  1253. end;
  1254. LDig := p;
  1255. p := 1 - exp;
  1256. if fp[inint] <> 0
  1257. then
  1258. for i := lp[inint] DOWNTO fp[inint] do
  1259. if aValue[i] <> dc
  1260. then begin
  1261. if p > - ( MaxFmtBCDFractionSize + 2 )
  1262. then begin
  1263. Dec ( p );
  1264. Singles[p] := Ord ( aValue[i] ) - Ord ( '0' );
  1265. end
  1266. else result := False;
  1267. end;
  1268. if not result
  1269. then EXIT;
  1270. FDig := p;
  1271. if LDig < 0
  1272. then LDig := 0;
  1273. Plac := LDig;
  1274. result := pack_BCD ( bh, BCD );
  1275. end;
  1276. end;
  1277. end;
  1278. function StrToBCD ( const aValue : FmtBCDStringtype ) : tBCD;
  1279. var
  1280. BCD : tBCD;
  1281. begin
  1282. if not TryStrToBCD ( aValue, BCD )
  1283. then begin
  1284. RAISE eBCDOverflowException.create ( 'in StrToBCD' );
  1285. end
  1286. else StrToBCD := BCD;
  1287. end;
  1288. {$ifndef FPUNONE}
  1289. procedure DoubleToBCD ( const aValue : myRealtype;
  1290. var BCD : tBCD );
  1291. var
  1292. s : string [ 30 ];
  1293. dp : tDecimalPoint;
  1294. begin
  1295. Str ( aValue : 25, s );
  1296. dp := DecimalPoint;
  1297. DecimalPoint := DecimalPoint_is_Point;
  1298. BCD := StrToBCD ( s );
  1299. DecimalPoint := dp;
  1300. end;
  1301. function DoubleToBCD ( const aValue : myRealtype ) : tBCD; Inline;
  1302. begin
  1303. DoubleToBCD ( aValue, result );
  1304. end;
  1305. {$endif}
  1306. function IntegerToBCD ( const aValue : myInttype ) : tBCD;
  1307. var
  1308. bh : tBCD_helper;
  1309. v : {$ifopt r+} 0..high ( myInttype ) {$else} Integer {$endif};
  1310. p : {$ifopt r+} low ( bh.Singles ) - 1..0 {$else} Integer {$endif};
  1311. exitloop : Boolean;
  1312. begin
  1313. _SELECT
  1314. _WHEN aValue = 0
  1315. _THEN result := NullBCD;
  1316. _WHEN aValue = 1
  1317. _THEN result := OneBCD;
  1318. _WHEN aValue = low ( myInttype )
  1319. _THEN
  1320. {$if declared ( myMinIntBCD ) }
  1321. result := myMinIntBCD;
  1322. {$else}
  1323. RAISE eBCDOverflowException.create ( 'in IntegerToBCD' );
  1324. {$endif}
  1325. _WHENOTHER
  1326. bh := null_.bh;
  1327. WITH bh do
  1328. begin
  1329. Neg := aValue < 0;
  1330. if Neg
  1331. then v := -aValue
  1332. else v := +aValue;
  1333. LDig := 0;
  1334. p := 0;
  1335. REPEAT
  1336. Singles[p] := v MOD 10;
  1337. v := v DIV 10;
  1338. exitloop := v = 0;
  1339. Dec ( p );
  1340. if p < low ( Singles )
  1341. then begin
  1342. exitloop := True;
  1343. (* what to do if error occured? *)
  1344. RAISE eBCDOverflowException.create ( 'in IntegerToBCD' );
  1345. end;
  1346. UNTIL exitloop;
  1347. FDig := p + 1;
  1348. end;
  1349. pack_BCD ( bh, result );
  1350. _endSELECT;
  1351. end;
  1352. function CurrToBCD ( const Curr : currency;
  1353. var BCD : tBCD;
  1354. Precision : Integer = 32;
  1355. Decimals : Integer = 4 ) : Boolean;
  1356. {
  1357. this works under the assumption that a currency is an int64,
  1358. except for scale of 10000
  1359. }
  1360. var
  1361. i : int64 absolute Curr;
  1362. begin
  1363. BCD := IntegerToBCD ( i );
  1364. {$ifndef bigger_BCD}
  1365. BCD.SignSpecialPlaces := 4 OR ( BCD.SignSpecialPlaces AND NegBit );
  1366. {$else}
  1367. BCD.Places := 4;
  1368. {$endif}
  1369. if Decimals <> 4 then
  1370. Result := NormalizeBCD ( BCD, BCD, Precision, Decimals )
  1371. else
  1372. CurrToBCD := True;
  1373. end;
  1374. {$ifdef comproutines}
  1375. function CompToBCD ( const Curr : Comp ) : tBCD; Inline;
  1376. var
  1377. cc : int64 absolute Curr;
  1378. begin
  1379. result := IntegerToBCD ( cc );
  1380. end;
  1381. function BCDToComp ( const BCD : tBCD ) : Comp; Inline;
  1382. var
  1383. zz : record
  1384. case Boolean of
  1385. False: ( i : int64 );
  1386. True: ( c : Comp );
  1387. end;
  1388. begin
  1389. zz.i := BCDToInteger ( BCD );
  1390. BCDToComp := zz.c;
  1391. end;
  1392. {$endif}
  1393. { Convert BCD struct to string/Double/Integer }
  1394. function BCDToStr ( const BCD : tBCD ) : FmtBCDStringtype;
  1395. var
  1396. bh : tBCD_helper;
  1397. l : {$ifopt r+} 0..maxfmtbcdfractionsize + 1 + 1 {$else} Integer {$endif};
  1398. i : {$ifopt r+} low ( bh.FDig )..high ( bh.LDig ) {$else} Integer {$endif};
  1399. pp : {$ifopt r+} low ( bh.FDig ) - 1..1 {$else} Integer {$endif};
  1400. dp, dc : Char;
  1401. begin
  1402. {$ifdef use_ansistring}
  1403. result := '';
  1404. {$endif}
  1405. unpack_BCD ( BCD, bh );
  1406. WITH bh do
  1407. begin
  1408. SetDecimals ( dp, dc );
  1409. l := 0;
  1410. if Neg
  1411. then begin
  1412. {$ifndef use_ansistring}
  1413. Inc ( l );
  1414. result[1] := '-';
  1415. {$else}
  1416. result := result + '-';
  1417. {$endif}
  1418. end;
  1419. if Prec = Plac
  1420. then begin
  1421. {$ifndef use_ansistring}
  1422. Inc ( l );
  1423. if Neg then
  1424. result[2] := '0'
  1425. else
  1426. result[1] := '0'
  1427. {$else}
  1428. result := result + '0';
  1429. {$endif}
  1430. end;
  1431. if Prec > 0
  1432. then begin
  1433. pp := low ( bh.FDig ) - 1;
  1434. if Plac > 0
  1435. then pp := 1;
  1436. for i := FDig TO LDig do
  1437. begin
  1438. if i = pp
  1439. then begin
  1440. {$ifndef use_ansistring}
  1441. Inc ( l );
  1442. result[l] := dp;
  1443. {$else}
  1444. result := result + dp;
  1445. {$endif}
  1446. end;
  1447. {$ifndef use_ansistring}
  1448. Inc ( l );
  1449. result[l] := Chr ( Singles[i] + Ord ( '0' ) );
  1450. {$else}
  1451. result := result + Chr ( Singles[i] + Ord ( '0' ) );
  1452. {$endif}
  1453. end;
  1454. end;
  1455. end;
  1456. {$ifndef use_ansistring}
  1457. result[0] := Chr ( l );
  1458. {$endif}
  1459. end;
  1460. {$ifndef FPUNONE}
  1461. function BCDToDouble ( const BCD : tBCD ) : myRealtype;
  1462. var
  1463. bh : tBCD_helper;
  1464. i : {$ifopt r+} low ( bh.FDig )..high ( bh.LDig ) {$else} Integer {$endif};
  1465. r,
  1466. e : myRealtype;
  1467. begin
  1468. unpack_BCD ( BCD, bh );
  1469. WITH bh do
  1470. begin
  1471. r := 0;
  1472. e := 1;
  1473. for i := 0 DOWNTO FDig do
  1474. begin
  1475. r := r + Singles[i] * e;
  1476. e := e * 10;
  1477. end;
  1478. e := 1;
  1479. for i := 1 TO LDig do
  1480. begin
  1481. e := e / 10;
  1482. r := r + Singles[i] * e;
  1483. end;
  1484. if Neg
  1485. then BCDToDouble := -r
  1486. else BCDToDouble := +r;
  1487. end;
  1488. end;
  1489. {$endif}
  1490. function BCDToInteger ( const BCD : tBCD;
  1491. Truncate : Boolean = False ) : myInttype;
  1492. var
  1493. bh : tBCD_helper;
  1494. res : myInttype;
  1495. i : {$ifopt r+} low ( bh.FDig )..0 {$else} Integer {$endif};
  1496. {
  1497. unclear: behaviour if overflow: abort? return 0? return something?
  1498. so: checks are missing yet
  1499. }
  1500. begin
  1501. unpack_BCD ( BCD, bh );
  1502. res := 0;
  1503. WITH bh do
  1504. begin
  1505. for i := FDig TO 0 do
  1506. res := res * 10 - Singles[i];
  1507. if NOT Truncate
  1508. then
  1509. if Plac > 0
  1510. then
  1511. if Singles[1] > 4
  1512. then Dec ( res );
  1513. if Neg
  1514. then BCDToInteger := +res
  1515. else BCDToInteger := -res;
  1516. end;
  1517. end;
  1518. { From DB.pas }
  1519. function BCDToCurr ( const BCD : tBCD;
  1520. var Curr : currency ) : Boolean;
  1521. var
  1522. bh : tBCD_helper;
  1523. res : int64;
  1524. c : currency absolute res;
  1525. i : {$ifopt r+} low ( bh.FDig )..4 {$else} Integer {$endif};
  1526. {
  1527. unclear: behaviour if overflow: abort? return 0? return something?
  1528. }
  1529. begin
  1530. BCDToCurr := True;
  1531. unpack_BCD ( BCD, bh );
  1532. res := 0;
  1533. WITH bh do
  1534. begin
  1535. for i := FDig TO 4 do
  1536. res := res * 10 + Singles[i];
  1537. if Plac > 4
  1538. then
  1539. if Singles[5] > 4
  1540. then Inc ( res );
  1541. if Neg
  1542. then Curr := -c
  1543. else Curr := +c;
  1544. end;
  1545. end;
  1546. procedure BCDAdd ( const BCDin1,
  1547. BCDin2 : tBCD;
  1548. var BCDout : tBCD );
  1549. var
  1550. bhr,
  1551. bh1,
  1552. bh2 : tBCD_helper;
  1553. ue : {$ifopt r+} 0..1 {$else} Integer {$endif};
  1554. i : {$ifopt r+} low ( bh1.FDig )..high ( bh1.LDig ) {$else} Integer {$endif};
  1555. v : {$ifopt r+} 0..9 + 9 + 1 {$else} Integer {$endif};
  1556. BCD : tBCD;
  1557. negate : Boolean;
  1558. begin
  1559. negate := IsBCDNegative ( BCDin1 );
  1560. if negate <> IsBCDNegative ( BCDin2 )
  1561. then begin
  1562. if negate
  1563. then begin
  1564. BCD := BCDin1;
  1565. BCDNegate ( BCD );
  1566. BCDSubtract ( BCDin2, BCD, BCDout );
  1567. EXIT;
  1568. end;
  1569. BCD := BCDin2;
  1570. BCDNegate ( BCD );
  1571. BCDSubtract ( BCDin1, BCD, BCDout );
  1572. EXIT;
  1573. end;
  1574. bhr := null_.bh;
  1575. WITH bhr do
  1576. begin
  1577. unpack_BCD ( BCDin1, bh1 );
  1578. unpack_BCD ( BCDin2, bh2 );
  1579. if bh1.FDig < bh2.FDig
  1580. then FDig := bh1.FDig
  1581. else FDig := bh2.FDig;
  1582. if bh1.LDig > bh2.LDig
  1583. then LDig := bh1.LDig
  1584. else LDig := bh2.LDig;
  1585. Plac := LDig;
  1586. ue := 0;
  1587. for i := LDig DOWNTO FDig do
  1588. begin
  1589. v := bh1.Singles[i] + bh2.Singles[i] + ue;
  1590. ue := v DIV 10;
  1591. Singles[i] := v MOD 10;
  1592. end;
  1593. if ue <> 0
  1594. then begin
  1595. Dec ( FDig );
  1596. Singles[FDig] := ue;
  1597. end;
  1598. Neg := negate;
  1599. end;
  1600. if NOT pack_BCD ( bhr, BCDout )
  1601. then begin
  1602. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  1603. end;
  1604. end;
  1605. procedure BCDSubtract ( const BCDin1,
  1606. BCDin2 : tBCD;
  1607. var BCDout : tBCD );
  1608. var
  1609. bhr,
  1610. bh1,
  1611. bh2 : tBCD_helper;
  1612. cmp : {$ifopt r+} -1..1 {$else} Integer {$endif};
  1613. ue : {$ifopt r+} 0..1 {$else} Integer {$endif};
  1614. i : {$ifopt r+} low ( bh1.FDig )..high ( bh1.LDig ) {$else} Integer {$endif};
  1615. v : {$ifopt r+} 0 - 9 - 1..9 - 0 - 0 {$else} Integer {$endif};
  1616. negate : Boolean;
  1617. BCD : tBCD;
  1618. begin
  1619. negate := IsBCDNegative ( BCDin1 );
  1620. if negate <> IsBCDNegative ( BCDin2 )
  1621. then begin
  1622. if negate
  1623. then begin
  1624. BCD := BCDin1;
  1625. BCDNegate ( BCD );
  1626. BCDAdd ( BCDin2, BCD, BCDout );
  1627. BCDNegate ( BCDout );
  1628. EXIT;
  1629. end;
  1630. BCD := BCDin2;
  1631. BCDNegate ( BCD );
  1632. BCDAdd ( BCDin1, BCD, BCDout );
  1633. EXIT;
  1634. end;
  1635. cmp := BCDCompare ( BCDin1, BCDin2 );
  1636. if cmp = 0
  1637. then begin
  1638. BCDout := NullBCD;
  1639. EXIT;
  1640. end;
  1641. bhr := null_.bh; { n n }
  1642. WITH bhr do { > < > < }
  1643. begin { }
  1644. if ( cmp > 0 ) = negate { +123 +12 -12 -123 }
  1645. then begin { - +12 - +123 - -123 - -12 }
  1646. unpack_BCD ( BCDin1, bh2 ); { x x }
  1647. unpack_BCD ( BCDin2, bh1 ); { s s s s }
  1648. negate := NOT negate; { nn n nn n }
  1649. end
  1650. else begin
  1651. unpack_BCD ( BCDin1, bh1 );
  1652. unpack_BCD ( BCDin2, bh2 );
  1653. end;
  1654. if bh1.FDig < bh2.FDig
  1655. then FDig := bh1.FDig
  1656. else FDig := bh2.FDig;
  1657. if bh1.LDig > bh2.LDig
  1658. then LDig := bh1.LDig
  1659. else LDig := bh2.LDig;
  1660. Plac := LDig;
  1661. ue := 0;
  1662. for i := LDig DOWNTO FDig do
  1663. begin
  1664. v := Integer ( bh1.Singles[i] ) - bh2.Singles[i] - ue;
  1665. ue := 0;
  1666. if v < 0
  1667. then begin
  1668. ue := 1;
  1669. Inc ( v, 10 );
  1670. end;
  1671. Singles[i] := v;
  1672. end;
  1673. Neg := negate;
  1674. if NOT pack_BCD ( bhr, BCDout )
  1675. then begin
  1676. {should never occur!}
  1677. RAISE eBCDOverflowException.create ( 'in BCDSubtract' );
  1678. end;
  1679. end;
  1680. end;
  1681. { Returns True if successful, False if Int Digits needed to be truncated }
  1682. function NormalizeBCD ( const InBCD : tBCD;
  1683. var OutBCD : tBCD;
  1684. const Prec,
  1685. Scale : Word ) : Boolean;
  1686. var
  1687. bh : tBCD_helper;
  1688. tm : {$ifopt r+} 1..maxfmtbcdfractionsize - 1 {$else} Integer {$endif};
  1689. begin
  1690. NormalizeBCD := True;
  1691. {$ifopt r+}
  1692. if ( Prec < 0 ) OR ( Prec > MaxFmtBCDFractionSize ) then RangeError;
  1693. if ( Scale < 0 ) OR ( Prec >= MaxFmtBCDFractionSize ) then RangeError;
  1694. {$endif}
  1695. if BCDScale ( InBCD ) > Scale
  1696. then begin
  1697. unpack_BCD ( InBCD, bh );
  1698. WITH bh do
  1699. begin
  1700. tm := Plac - Scale;
  1701. Plac := Scale;
  1702. { dec ( prec, tm ); Dec/Inc error? }
  1703. Prec := Prec - tm;
  1704. { dec ( ldig, tm ); Dec/Inc error? }
  1705. LDig := LDig - tm;
  1706. NormalizeBCD := False;
  1707. end;
  1708. if NOT pack_BCD ( bh, OutBCD )
  1709. then begin
  1710. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  1711. end;
  1712. end;
  1713. end;
  1714. procedure BCDMultiply ( const BCDin1,
  1715. BCDin2 : tBCD;
  1716. var BCDout : tBCD );
  1717. var
  1718. bh1,
  1719. bh2,
  1720. bhr : tBCD_helper;
  1721. bhrr : tBCD_helper_big;
  1722. i1 : {$ifopt r+} low ( bh1.FDig )..high ( bh1.LDig ) {$else} Integer {$endif};
  1723. i2 : {$ifopt r+} low ( bh2.FDig )..high ( bh2.LDig ) {$else} Integer {$endif};
  1724. i3 : {$ifopt r+} low ( bhrr.FDig )..high ( bhrr.LDig ) {$else} Integer {$endif};
  1725. v : {$ifopt r+} low ( bhrr.Singles[0] )..high ( bhrr.Singles[0] ) {$else} Integer {$endif};
  1726. ue : {$ifopt r+} low ( bhrr.Singles[0] ) DIV 10..high ( bhrr.Singles[0] ) DIV 10 {$else} Integer {$endif};
  1727. begin
  1728. unpack_BCD ( BCDin1, bh1 );
  1729. unpack_BCD ( BCDin2, bh2 );
  1730. if ( bh1.Prec = 0 ) OR ( bh2.Prec = 0 )
  1731. then begin
  1732. BCDout := NullBCD;
  1733. EXIT;
  1734. end;
  1735. bhr := null_.bh;
  1736. bhrr := null_.bhb;
  1737. WITH bhrr do
  1738. begin
  1739. Neg := bh1.Neg XOR bh2.Neg;
  1740. {
  1741. writeln ( __lo_bhb, ' ', __hi_bhb, ' ', bh1.fdig, ' ', bh2.fdig, ' ', low ( fdig ), ' ', low ( ldig ) );
  1742. }
  1743. FDig := bh1.FDig + bh2.FDig;
  1744. LDig := bh1.LDig + bh2.LDig;
  1745. for i1 := bh1.FDig TO bh1.LDig do
  1746. for i2 := bh2.FDig TO bh2.LDig do
  1747. begin
  1748. Inc ( Singles[i1 + i2],
  1749. bh1.Singles[i1]
  1750. * bh2.Singles[i2] );
  1751. {
  1752. write ( Singles[i1 + i2], ' ', bh1.Singles[i1], ' ', bh2.Singles[i2], ' : ' );
  1753. writeln ( Singles[i1 + i2] + bh1.Singles[i1] + bh2.Singles[i2] );
  1754. }
  1755. {
  1756. Singles[i1 + i2] := Singles[i1 + i2]
  1757. + bh1.Singles[i1]
  1758. * bh2.Singles[i2];
  1759. }
  1760. end;
  1761. {
  1762. for i3 := fdig to ldig do
  1763. write ( ' ', singles[i3] );
  1764. writeln;
  1765. }
  1766. if FDig < low ( bhr.Singles )
  1767. then RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  1768. ue := 0;
  1769. for i3 := LDig DOWNTO FDig do
  1770. begin
  1771. v := Singles[i3] + ue;
  1772. ue := v DIV 10;
  1773. v := v MOD 10;
  1774. bhr.Singles[i3] := v;
  1775. end;
  1776. while ue <> 0 do
  1777. begin
  1778. Dec ( FDig );
  1779. if FDig < low ( bhr.Singles )
  1780. then RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  1781. bhr.Singles[FDig] := ue MOD 10;
  1782. ue := ue DIV 10;
  1783. end;
  1784. bhr.Plac := LDig;
  1785. bhr.FDig := FDig;
  1786. if LDig > high ( bhr.Singles )
  1787. then bhr.LDig := high ( bhr.Singles )
  1788. else bhr.LDig := LDig;
  1789. end;
  1790. if NOT pack_BCD ( bhr, BCDout )
  1791. then begin
  1792. RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  1793. end;
  1794. end;
  1795. {$ifndef FPUNONE}
  1796. procedure BCDMultiply ( const BCDIn : tBCD;
  1797. const DoubleIn : myRealtype;
  1798. var BCDout : tBCD ); Inline;
  1799. begin
  1800. BCDMultiply ( BCDIn, DoubleToBCD ( DoubleIn ), BCDout );
  1801. end;
  1802. {$endif}
  1803. procedure BCDMultiply ( const BCDIn : tBCD;
  1804. const StringIn : FmtBCDStringtype;
  1805. var BCDout : tBCD ); Inline;
  1806. begin
  1807. BCDMultiply ( BCDIn, StrToBCD ( StringIn ), BCDout );
  1808. end;
  1809. procedure BCDMultiply ( const StringIn1,
  1810. StringIn2 : FmtBCDStringtype;
  1811. var BCDout : tBCD ); Inline;
  1812. begin
  1813. BCDMultiply ( StrToBCD ( StringIn1 ), StrToBCD ( StringIn2 ), BCDout );
  1814. end;
  1815. procedure BCDDivide ( const Dividend,
  1816. Divisor : tBCD;
  1817. var BCDout : tBCD );
  1818. var
  1819. bh1 : ARRAY [ Boolean ] of tBCD_helper;
  1820. bh2,
  1821. bh : tBCD_helper;
  1822. p : {$ifopt r+} low ( bh.FDig ) - high ( bh.FDig )..high ( bh.FDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1823. v1 : {$ifopt r+} low ( bh.Singles[0] )..high ( bh.Singles[0] ) {$else} Integer {$endif};
  1824. v2 : {$ifopt r+} low ( bh.Singles[0] )..high ( bh.Singles[0] ) {$else} Integer {$endif};
  1825. lFDig : {$ifopt r+} low ( bh.FDig )..high ( bh.FDig ) {$else} Integer {$endif};
  1826. d1 : {$ifopt r+} low ( bh.LDig ) - high ( bh.FDig )..high ( bh.LDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1827. d2 : {$ifopt r+} low ( bh.LDig ) - high ( bh.FDig )..high ( bh.LDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1828. d : {$ifopt r+} low ( bh.LDig ) - high ( bh.FDig )..high ( bh.LDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1829. lLdig : {$ifopt r+} low ( lFDig ) + low ( d )..high ( lFDig ) + high ( d ) {$else} Integer {$endif};
  1830. tm : {$ifopt r+} low ( lLdig ) - high ( bh2.Singles )..high ( lLdig ) - high ( bh2.Singles ) {$else} Integer {$endif};
  1831. i2 : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1832. i3 : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1833. ie : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1834. i4 : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1835. nFDig : {$ifopt r+} low ( i2 )..high ( i2 ) {$else} Integer {$endif};
  1836. nLDig : {$ifopt r+} low ( i2 )..high ( i2 ) {$else} Integer {$endif};
  1837. dd : {$ifopt r+} 0..9 {$else} Integer {$endif};
  1838. Add : {$ifopt r+} 0..99 {$else} Integer {$endif};
  1839. ue : {$ifopt r+} 0..99 {$else} Integer {$endif};
  1840. v3 : {$ifopt r+} low ( bh.Singles[0] ) - high ( bh2.singles[9] ) * high ( dd ) - high ( ue )..high ( bh.Singles[0] ) - low ( bh2.singles[9] ) * low ( dd ) - low ( ue ) {$else} Integer {$endif};
  1841. v4 : {$ifopt r+} low ( bh.Singles[0] ) + low ( add )..high ( bh.Singles[0] ) + high ( add ) {$else} Integer {$endif};
  1842. FlipFlop,
  1843. nz,
  1844. sf,
  1845. sh,
  1846. fdset : Boolean;
  1847. {
  1848. bh1p : ARRAY [ Boolean ] of ^ tBCD_helper;
  1849. }
  1850. begin
  1851. { test:
  1852. bh1p[false] := @ bh1[false];
  1853. bh1p[true] := @ bh1[true];
  1854. v := bh1[false].singles[0];
  1855. v := bh1[true].singles[0];
  1856. v := bh1p[false]^.singles[0];
  1857. v := bh1p[true]^.singles[0];
  1858. v := bh1[nz].singles[0];
  1859. v := bh1p[nz]^.singles[0];
  1860. }
  1861. unpack_BCD ( Divisor, bh2 );
  1862. unpack_BCD ( Dividend, bh1[False] );
  1863. p := bh1[False].FDig - bh2.FDig;
  1864. _SELECT
  1865. _WHEN bh2.Prec = 0
  1866. _THEN RAISE eBCDException.create ( 'Division by zero' );
  1867. _WHEN bh1[False].Prec = 0
  1868. _THEN BCDout := NullBCD;
  1869. _WHEN p < low ( bh2.Singles )
  1870. _THEN RAISE eBCDOverflowException.create ( 'in BCDDivide' );
  1871. _WHENOTHER
  1872. bh := null_.bh;
  1873. bh.Neg := bh1[False].Neg XOR bh2.Neg;
  1874. if p <= high ( bh.Singles )
  1875. then begin
  1876. bh1[True] := null_.bh;
  1877. FlipFlop := False;
  1878. fdset := p > 0;
  1879. if fdset
  1880. then bh.FDig := 0;
  1881. add := 0;
  1882. nz := True;
  1883. while nz do
  1884. WITH bh1[FlipFlop] do
  1885. begin
  1886. {
  1887. WriteLn('#####');
  1888. dumpbh ( bh1[flipflop] );
  1889. dumpbh ( bh2 );
  1890. dumpbh ( bh );
  1891. }
  1892. if ( Singles[FDig] + bh2.Singles[bh2.FDig] ) = 0
  1893. then begin
  1894. if ( FDig >= LDig )
  1895. OR ( bh2.FDig >= bh2.LDig )
  1896. then nz := False
  1897. else begin
  1898. Inc ( FDig );
  1899. Inc ( bh2.FDig );
  1900. end;
  1901. end
  1902. else begin
  1903. v1 := Singles[FDig];
  1904. v2 := bh2.Singles[bh2.FDig];
  1905. sh := v1 < v2;
  1906. if ( v1 = v2 )
  1907. then begin
  1908. nz := False;
  1909. i3 := Succ ( FDig );
  1910. ie := LDig;
  1911. while ( i3 <= ie ) AND ( NOT nz ) AND ( NOT sh ) do
  1912. begin
  1913. v1 := Singles[i3];
  1914. v2 := bh2.Singles[i3 - p];
  1915. if v1 <> v2
  1916. then begin
  1917. nz := True;
  1918. if v1 < v2
  1919. then sh := True;
  1920. end;
  1921. Inc ( i3 );
  1922. end;
  1923. end;
  1924. if NOT nz
  1925. then Add := 1
  1926. else begin
  1927. if sh
  1928. then begin
  1929. Inc ( p );
  1930. {
  1931. if p > 3 then halt;
  1932. }
  1933. if p > high ( bh.Singles )
  1934. then nz := False
  1935. else Dec ( bh2.FDig );
  1936. end
  1937. else begin
  1938. lFDig := FDig;
  1939. d1 := LDig - FDig;
  1940. d2 := bh2.LDig - bh2.FDig;
  1941. if d1 > d2
  1942. then d := d1
  1943. else d := d2;
  1944. lLdig := lFDig + d;
  1945. if lLdig > high ( bh2.Singles )
  1946. then begin
  1947. tm := ( lLdig ) - high ( bh2.Singles );
  1948. d := d - tm;
  1949. lLdig := lLdig - tm;
  1950. {runden?}
  1951. end;
  1952. sf := True;
  1953. Add := 0;
  1954. nFDig := 0;
  1955. nLDig := 0;
  1956. ue := 0;
  1957. dd := Singles[lFDig] DIV ( bh2.Singles[lFDig - p] + 1 );
  1958. {
  1959. dd := 1;
  1960. }
  1961. if dd < 1
  1962. then dd := 1;
  1963. {
  1964. writeln ( 'p=', p, ' dd=', dd, ' lFdig=', lfdig, ' lldig=', lldig );
  1965. }
  1966. for i2 := lLdig DOWNTO lFDig do
  1967. begin
  1968. v3 := Singles[i2] - bh2.Singles[i2 - p] * dd - ue;
  1969. ue := 0;
  1970. while v3 < 0 do
  1971. begin
  1972. Inc ( ue );;
  1973. v3 := v3 + 10;
  1974. end;
  1975. {
  1976. if v3 <> 0
  1977. then begin
  1978. }
  1979. bh1[NOT FlipFlop].Singles[i2] := v3;
  1980. {
  1981. nFDig := i2;
  1982. if sf
  1983. then begin
  1984. nLDig := i2;
  1985. sf := False;
  1986. end;
  1987. end;
  1988. }
  1989. end;
  1990. sf := False;
  1991. nfdig := lfdig;
  1992. nldig := lldig;
  1993. Inc ( Add, dd );
  1994. if NOT fdset
  1995. then begin
  1996. bh.FDig := p;
  1997. fdset := True;
  1998. end;
  1999. if bh.LDig < p
  2000. then begin
  2001. bh.LDig := p;
  2002. if ( bh.LDig - bh.FDig ) > Succ ( MaxFmtBCDFractionSize )
  2003. then nz := False;
  2004. end;
  2005. if sf
  2006. then nz := False
  2007. else begin
  2008. FillChar ( bh1[FlipFlop], SizeOf ( bh1[FlipFlop] ), #0 );
  2009. FlipFlop := NOT FlipFlop;
  2010. WITH bh1[FlipFlop] do
  2011. begin
  2012. FDig := nFDig;
  2013. LDig := nLDig;
  2014. end;
  2015. end;
  2016. end;
  2017. end;
  2018. if Add <> 0
  2019. then begin
  2020. i4 := p;
  2021. while ( Add <> 0 ) AND ( i4 >= bh.FDig ) do
  2022. begin
  2023. {
  2024. writeln ( '> ', i4, ' ', bh.Singles[i4], ' ', Add );
  2025. }
  2026. v4 := bh.Singles[i4] + Add;
  2027. Add := v4 DIV 10;
  2028. bh.Singles[i4] := v4 MOD 10;
  2029. Dec ( i4 );
  2030. end;
  2031. if Add <> 0
  2032. then begin
  2033. Dec ( bh.FDig );
  2034. bh.Singles[bh.FDig] := Add;
  2035. Add := 0;
  2036. end;
  2037. end;
  2038. end;
  2039. end;
  2040. end;
  2041. WITH bh do
  2042. begin
  2043. if LDig < 0
  2044. then LDig := 0;
  2045. if LDig > 0
  2046. then Plac := LDig
  2047. else Plac := 0;
  2048. end;
  2049. if NOT pack_BCD ( bh, BCDout )
  2050. then begin
  2051. RAISE eBCDOverflowException.create ( 'in BCDDivide' );
  2052. end;
  2053. _endSELECT
  2054. end;
  2055. procedure BCDDivide ( const Dividend,
  2056. Divisor : FmtBCDStringtype;
  2057. var BCDout : tBCD ); Inline;
  2058. begin
  2059. BCDDivide ( StrToBCD ( Dividend ), StrToBCD ( Divisor ), BCDout );
  2060. end;
  2061. {$ifndef FPUNONE}
  2062. procedure BCDDivide ( const Dividend : tBCD;
  2063. const Divisor : myRealtype;
  2064. var BCDout : tBCD ); Inline;
  2065. begin
  2066. BCDDivide ( Dividend, DoubleToBCD ( Divisor ), BCDout );
  2067. end;
  2068. {$endif}
  2069. procedure BCDDivide ( const Dividend : tBCD;
  2070. const Divisor : FmtBCDStringtype;
  2071. var BCDout : tBCD ); Inline;
  2072. begin
  2073. BCDDivide ( Dividend, StrToBCD ( Divisor ), BCDout );
  2074. end;
  2075. { TBCD variant creation utils }
  2076. procedure VarFmtBCDCreate ( var aDest : Variant;
  2077. const aBCD : tBCD );
  2078. begin
  2079. VarClear(aDest);
  2080. TVarData(aDest).Vtype:=FMTBcdFactory.Vartype;
  2081. TVarData(aDest).VPointer:=TFMTBcdVarData.create(aBCD);
  2082. end;
  2083. function VarFmtBCDCreate : Variant;
  2084. begin
  2085. VarFmtBCDCreate ( result, NullBCD );
  2086. end;
  2087. function VarFmtBCDCreate ( const aValue : FmtBCDStringtype;
  2088. Precision,
  2089. Scale : Word ) : Variant;
  2090. begin
  2091. VarFmtBCDCreate ( result, StrToBCD ( aValue ) );
  2092. end;
  2093. {$ifndef FPUNONE}
  2094. function VarFmtBCDCreate ( const aValue : myRealtype;
  2095. Precision : Word = 18;
  2096. Scale : Word = 4 ) : Variant;
  2097. begin
  2098. VarFmtBCDCreate ( result, DoubleToBCD ( aValue ) );
  2099. end;
  2100. {$endif}
  2101. function VarFmtBCDCreate ( const aBCD : tBCD ) : Variant;
  2102. begin
  2103. VarFmtBCDCreate ( result, aBCD );
  2104. end;
  2105. function VarIsFmtBCD ( const aValue : Variant ) : Boolean;
  2106. begin
  2107. Result:=TVarData(aValue).VType=FMTBcdFactory.VarType;
  2108. end;
  2109. function VarFmtBCD : TVartype;
  2110. begin
  2111. Result:=FMTBcdFactory.VarType;
  2112. end;
  2113. { Formatting BCD as string }
  2114. function BCDToStrF ( const BCD : tBCD;
  2115. Format : TFloatFormat;
  2116. const Precision,
  2117. Digits : Integer ) : FmtBCDStringtype;
  2118. begin
  2119. not_implemented;
  2120. result:='';
  2121. end;
  2122. function FormatBCD ( const Format : string;
  2123. BCD : tBCD ) : FmtBCDStringtype;
  2124. begin
  2125. not_implemented;
  2126. result:='';
  2127. end;
  2128. {$ifdef additional_routines}
  2129. function CurrToBCD ( const Curr : currency ) : tBCD; Inline;
  2130. begin
  2131. CurrToBCD ( Curr, result );
  2132. end;
  2133. procedure BCDAdd ( const BCDIn : tBCD;
  2134. const IntIn : myInttype;
  2135. var BCDout : tBCD );
  2136. var
  2137. BCD : tBCD;
  2138. bhr : tBCD_helper;
  2139. p : {$ifopt r+} low ( bhr.FDig ) - 1..0 {$else} Integer {$endif};
  2140. ue : {$ifopt r+} 0..high ( IntIn ) - 9 {$else} Integer {$endif};
  2141. v : {$ifopt r+} 0..{high ( ue ) + 9} high ( IntIn ) {$else} Integer {$endif};
  2142. nz : Boolean;
  2143. begin
  2144. if IntIn = 0
  2145. then begin
  2146. BCDout := BCDIn;
  2147. EXIT;
  2148. end;
  2149. if IntIn = low ( myInttype )
  2150. then begin
  2151. {$if declared ( myMinIntBCD ) }
  2152. BCDAdd ( BCDIn, myMinIntBCD, BCDout );
  2153. EXIT;
  2154. {$else}
  2155. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  2156. {$endif}
  2157. end;
  2158. if IsBCDNegative ( BCDIn )
  2159. then begin
  2160. BCD := BCDIn;
  2161. BCDNegate ( BCD );
  2162. if IntIn < 0
  2163. then BCDAdd ( BCD, -IntIn, BCDout )
  2164. else BCDSubtract ( BCD, IntIn, BCDout );
  2165. BCDNegate ( BCDout );
  2166. EXIT;
  2167. end;
  2168. if IntIn < 0
  2169. then begin
  2170. BCDSubtract ( BCDIn, -IntIn, BCDout );
  2171. EXIT;
  2172. end;
  2173. if IntIn > ( high ( IntIn ) - 9 )
  2174. then begin
  2175. BCDAdd ( BCDIn, IntegerToBCD ( IntIn ), BCDout );
  2176. EXIT;
  2177. end;
  2178. unpack_BCD ( BCDIn, bhr );
  2179. p := 0;
  2180. nz := True;
  2181. ue := IntIn;
  2182. while nz do
  2183. begin
  2184. v := bhr.Singles[p] + ue;
  2185. bhr.Singles[p] := v MOD 10;
  2186. ue := v DIV 10;
  2187. if ue = 0
  2188. then nz := False
  2189. else Dec ( p );
  2190. end;
  2191. if p < bhr.FDig
  2192. then begin
  2193. bhr.FDig := p;
  2194. bhr.Prec := bhr.Prec + ( bhr.FDig - p );
  2195. end;
  2196. if NOT pack_BCD ( bhr, BCDout )
  2197. then begin
  2198. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  2199. end;
  2200. end;
  2201. procedure BCDSubtract ( const BCDIn : tBCD;
  2202. const IntIn : myInttype;
  2203. var BCDout : tBCD );
  2204. {}
  2205. var
  2206. BCD : tBCD;
  2207. bhr : tBCD_helper;
  2208. p : {$ifopt r+} low ( bhr.FDig ) - 1..0 {$else} Integer {$endif};
  2209. ue : {$ifopt r+} 0..pred ( 100000000 ) {$else} Integer {$endif};
  2210. v : {$ifopt r+} -9..9 {$else} Integer {$endif};
  2211. direct : Boolean;
  2212. {}
  2213. begin
  2214. if IntIn = 0
  2215. then begin
  2216. BCDout := BCDIn;
  2217. EXIT;
  2218. end;
  2219. if IntIn = low ( myInttype )
  2220. then begin
  2221. {$if declared ( myMinIntBCD ) }
  2222. BCDSubtract ( BCDIn, myMinIntBCD, BCDout );
  2223. EXIT;
  2224. {$else}
  2225. RAISE eBCDOverflowException.create ( 'in BCDSubtract' );
  2226. {$endif}
  2227. end;
  2228. if IsBCDNegative ( BCDIn )
  2229. then begin
  2230. BCD := BCDIn;
  2231. BCDNegate ( BCD );
  2232. if IntIn < 0
  2233. then BCDSubtract ( BCD, -IntIn, BCDout )
  2234. else BCDAdd ( BCD, IntIn, BCDout );
  2235. BCDNegate ( BCDout );
  2236. EXIT;
  2237. end;
  2238. if IntIn < 0
  2239. then begin
  2240. BCDAdd ( BCDIn, -IntIn, BCDout );
  2241. EXIT;
  2242. end;
  2243. direct := False;
  2244. case BCDIn.Precision
  2245. -
  2246. {$ifndef bigger_BCD}
  2247. ( BCDIn.SignSpecialPlaces AND PlacesMask )
  2248. {$else}
  2249. BCDIn.Places
  2250. {$endif}
  2251. of
  2252. 2: direct := IntIn < 10;
  2253. 3: direct := IntIn < 100;
  2254. 4: direct := IntIn < 1000;
  2255. 5: direct := IntIn < 10000;
  2256. 6: direct := IntIn < 100000;
  2257. 7: direct := IntIn < 1000000;
  2258. 8: direct := IntIn < 10000000;
  2259. 9: direct := IntIn < 100000000;
  2260. end;
  2261. {
  2262. write(direct);dumpbcd(bcdin);write('[',intin,']');
  2263. }
  2264. if direct
  2265. then begin
  2266. unpack_BCD ( BCDIn, bhr );
  2267. WITH bhr do
  2268. begin
  2269. p := 0;
  2270. ue := IntIn;
  2271. while p >= FDig do
  2272. begin
  2273. v := Singles[p] - ue MOD 10;
  2274. ue := ue DIV 10;
  2275. if v < 0
  2276. then begin
  2277. v := v + 10;
  2278. ue := ue + 1;
  2279. end;
  2280. Singles[p] := v;
  2281. Dec ( p );
  2282. end;
  2283. end;
  2284. if NOT pack_BCD ( bhr, BCDout )
  2285. then begin
  2286. RAISE eBCDOverflowException.create ( 'in BCDSubtract' );
  2287. end;
  2288. end
  2289. else
  2290. {}
  2291. BCDSubtract ( BCDIn, IntegerToBCD ( IntIn ), BCDout );
  2292. end;
  2293. procedure BCDAdd ( const IntIn : myInttype;
  2294. const BCDIn : tBCD;
  2295. var BCDout : tBCD ); Inline;
  2296. begin
  2297. BCDAdd ( BCDIn, IntIn, BCDout );
  2298. end;
  2299. {$ifndef FPUNONE}
  2300. procedure BCDAdd ( const BCDIn : tBCD;
  2301. const DoubleIn : myRealtype;
  2302. var BCDout : tBCD ); Inline;
  2303. begin
  2304. BCDAdd ( BCDIn, DoubleToBCD ( DoubleIn ), BCDout );
  2305. end;
  2306. procedure BCDAdd ( const DoubleIn : myRealtype;
  2307. const BCDIn : tBCD;
  2308. var BCDout : tBCD ); Inline;
  2309. begin
  2310. BCDAdd ( DoubleToBCD ( DoubleIn ), BCDIn, BCDout );
  2311. end;
  2312. {$endif}
  2313. procedure BCDAdd ( const BCDIn : tBCD;
  2314. const Currin : currency;
  2315. var BCDout : tBCD ); Inline;
  2316. begin
  2317. BCDAdd ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2318. end;
  2319. procedure BCDAdd ( const Currin : currency;
  2320. const BCDIn : tBCD;
  2321. var BCDout : tBCD ); Inline;
  2322. begin
  2323. BCDAdd ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2324. end;
  2325. {$ifdef comproutines}
  2326. procedure BCDAdd ( const BCDIn : tBCD;
  2327. const Compin : Comp;
  2328. var BCDout : tBCD ); Inline;
  2329. begin
  2330. BCDAdd ( BCDIn, CompToBCD ( Compin ), BCDout );
  2331. end;
  2332. procedure BCDAdd ( const Compin : Comp;
  2333. const BCDIn : tBCD;
  2334. var BCDout : tBCD ); Inline;
  2335. begin
  2336. BCDAdd ( CompToBCD ( Compin ), BCDIn, BCDout );
  2337. end;
  2338. {$endif}
  2339. procedure BCDAdd ( const BCDIn : tBCD;
  2340. const StringIn : FmtBCDStringtype;
  2341. var BCDout : tBCD ); Inline;
  2342. begin
  2343. BCDAdd ( BCDIn, StrToBCD ( StringIn ), BCDout );
  2344. end;
  2345. procedure BCDAdd ( const StringIn : FmtBCDStringtype;
  2346. const BCDIn : tBCD;
  2347. var BCDout : tBCD ); Inline;
  2348. begin
  2349. BCDAdd ( StrToBCD ( StringIn ), BCDIn, BCDout );
  2350. end;
  2351. procedure BCDAdd ( const StringIn1,
  2352. StringIn2 : FmtBCDStringtype;
  2353. var BCDout : tBCD ); Inline;
  2354. begin
  2355. BCDAdd ( StrToBCD ( StringIn1 ), StrToBCD ( StringIn2 ), BCDout );
  2356. end;
  2357. procedure BCDSubtract ( const IntIn : myInttype;
  2358. const BCDIn : tBCD;
  2359. var BCDout : tBCD ); Inline;
  2360. begin
  2361. BCDSubtract ( BCDIn, IntIn, BCDout );
  2362. BCDNegate ( BCDout );
  2363. end;
  2364. {$ifndef FPUNONE}
  2365. procedure BCDSubtract ( const BCDIn : tBCD;
  2366. const DoubleIn : myRealtype;
  2367. var BCDout : tBCD ); Inline;
  2368. begin
  2369. BCDSubtract ( BCDIn, DoubleToBCD ( DoubleIn ), BCDout );
  2370. end;
  2371. procedure BCDSubtract ( const DoubleIn : myRealtype;
  2372. const BCDIn : tBCD;
  2373. var BCDout : tBCD ); Inline;
  2374. begin
  2375. BCDSubtract ( DoubleToBCD ( DoubleIn ), BCDIn, BCDout );
  2376. end;
  2377. {$endif}
  2378. procedure BCDSubtract ( const BCDIn : tBCD;
  2379. const Currin : currency;
  2380. var BCDout : tBCD ); Inline;
  2381. begin
  2382. BCDSubtract ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2383. end;
  2384. procedure BCDSubtract ( const Currin : currency;
  2385. const BCDIn : tBCD;
  2386. var BCDout : tBCD ); Inline;
  2387. begin
  2388. BCDSubtract ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2389. end;
  2390. {$ifdef comproutines}
  2391. procedure BCDSubtract ( const BCDIn : tBCD;
  2392. const Compin : Comp;
  2393. var BCDout : tBCD ); Inline;
  2394. begin
  2395. BCDSubtract ( BCDIn, CompToBCD ( Compin ), BCDout );
  2396. end;
  2397. procedure BCDSubtract ( const Compin : Comp;
  2398. const BCDIn : tBCD;
  2399. var BCDout : tBCD ); Inline;
  2400. begin
  2401. BCDSubtract ( CompToBCD ( Compin ), BCDIn, BCDout );
  2402. end;
  2403. {$endif}
  2404. procedure BCDSubtract ( const BCDIn : tBCD;
  2405. const StringIn : FmtBCDStringtype;
  2406. var BCDout : tBCD ); Inline;
  2407. begin
  2408. BCDSubtract ( BCDIn, StrToBCD ( StringIn ), BCDout );
  2409. end;
  2410. procedure BCDSubtract ( const StringIn : FmtBCDStringtype;
  2411. const BCDIn : tBCD;
  2412. var BCDout : tBCD ); Inline;
  2413. begin
  2414. BCDSubtract ( StrToBCD ( StringIn ), BCDIn, BCDout );
  2415. end;
  2416. procedure BCDSubtract ( const StringIn1,
  2417. StringIn2 : FmtBCDStringtype;
  2418. var BCDout : tBCD ); Inline;
  2419. begin
  2420. BCDSubtract ( StrToBCD ( StringIn1 ), StrToBCD ( StringIn2 ), BCDout );
  2421. end;
  2422. procedure BCDMultiply ( const BCDIn : tBCD;
  2423. const IntIn : myInttype;
  2424. var BCDout : tBCD );
  2425. var
  2426. bh : tBCD_helper;
  2427. bhr : tBCD_helper;
  2428. bhrr : tBCD_helper_big;
  2429. int : {$ifopt r+} 0..high ( bhrr.Singles[0] ) DIV 10 {$else} Integer {$endif};
  2430. i1 : {$ifopt r+} low ( bh.Singles )..high ( bh.Singles ) {$else} Integer {$endif};
  2431. i3 : {$ifopt r+} low ( bhr.Singles )..high ( bhr.Singles ) {$else} Integer {$endif};
  2432. v : {$ifopt r+} low ( bhrr.Singles[0] ) + low ( bhrr.Singles[0] ) DIV 10..high ( bhrr.Singles[0] ) + high ( bhrr.Singles[0] ) DIV 10 {$else} Integer {$endif};
  2433. ue : {$ifopt r+} 1 * ( low ( bhrr.Singles[0] ) + low ( bhrr.Singles[0] ) DIV 10 ) DIV 10
  2434. ..( high ( bhrr.Singles[0] ) + high ( bhrr.Singles[0] ) DIV 10 ) DIV 10 {$else} Integer {$endif};
  2435. begin
  2436. if IntIn = 0
  2437. then begin
  2438. BCDout := NullBCD;
  2439. EXIT;
  2440. end;
  2441. if IntIn = 1
  2442. then begin
  2443. BCDout := BCDIn;
  2444. EXIT;
  2445. end;
  2446. if IntIn = -1
  2447. then begin
  2448. BCDout := BCDIn;
  2449. BCDNegate ( BCDout );
  2450. EXIT;
  2451. end;
  2452. if IntIn = low ( myInttype )
  2453. then begin
  2454. {$if declared ( myMinIntBCD ) }
  2455. BCDMultiply ( BCDIn, myMinIntBCD, BCDout );
  2456. EXIT;
  2457. {$else}
  2458. RAISE eBCDOverflowException.create ( 'in BCDmultiply' );
  2459. {$endif}
  2460. end;
  2461. if Abs ( IntIn ) > low ( bhrr.Singles[0] ) DIV 10
  2462. then begin
  2463. BCDMultiply ( BCDIn, IntegerToBCD ( IntIn ), BCDout );
  2464. EXIT;
  2465. end;
  2466. unpack_BCD ( BCDIn, bh );
  2467. if bh.Prec = 0
  2468. then begin
  2469. BCDout := NullBCD;
  2470. EXIT;
  2471. end;
  2472. bhr := null_.bh;
  2473. bhrr := null_.bhb;
  2474. int := Abs ( IntIn );
  2475. WITH bhrr do
  2476. begin
  2477. Neg := bh.Neg XOR ( IntIn < 0 );
  2478. FDig := bh.FDig;
  2479. LDig := bh.LDig;
  2480. for i1 := bh.FDig TO bh.LDig do
  2481. Singles[i1] := bh.Singles[i1] * int;
  2482. {
  2483. for i3 := fdig to ldig do
  2484. write ( ' ', singles[i3] );
  2485. writeln;
  2486. }
  2487. ue := 0;
  2488. for i3 := LDig DOWNTO FDig do
  2489. begin
  2490. v := Singles[i3] + ue;
  2491. ue := v DIV 10;
  2492. v := v MOD 10;
  2493. bhr.Singles[i3] := v;
  2494. end;
  2495. while ue <> 0 do
  2496. begin
  2497. Dec ( FDig );
  2498. if FDig < low ( bhr.Singles )
  2499. then RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  2500. bhr.Singles[FDig] := ue MOD 10;
  2501. ue := ue DIV 10;
  2502. end;
  2503. bhr.Plac := LDig;
  2504. bhr.FDig := FDig;
  2505. if LDig > high ( bhr.Singles )
  2506. then bhr.LDig := high ( bhr.Singles )
  2507. else bhr.LDig := LDig;
  2508. end;
  2509. if NOT pack_BCD ( bhr, BCDout )
  2510. then begin
  2511. RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  2512. end;
  2513. end;
  2514. procedure BCDMultiply ( const IntIn : myInttype;
  2515. const BCDIn : tBCD;
  2516. var BCDout : tBCD ); Inline;
  2517. begin
  2518. BCDMultiply ( BCDIn, IntIn, BCDout );
  2519. end;
  2520. {$ifndef FPUNONE}
  2521. procedure BCDMultiply ( const DoubleIn : myRealtype;
  2522. const BCDIn : tBCD;
  2523. var BCDout : tBCD ); Inline;
  2524. begin
  2525. BCDMultiply ( DoubleToBCD ( DoubleIn ), BCDIn, BCDout );
  2526. end;
  2527. {$endif}
  2528. procedure BCDMultiply ( const BCDIn : tBCD;
  2529. const Currin : currency;
  2530. var BCDout : tBCD ); Inline;
  2531. begin
  2532. BCDMultiply ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2533. end;
  2534. procedure BCDMultiply ( const Currin : currency;
  2535. const BCDIn : tBCD;
  2536. var BCDout : tBCD ); Inline;
  2537. begin
  2538. BCDMultiply ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2539. end;
  2540. {$ifdef comproutines}
  2541. procedure BCDMultiply ( const BCDIn : tBCD;
  2542. const Compin : Comp;
  2543. var BCDout : tBCD ); Inline;
  2544. begin
  2545. BCDMultiply ( BCDIn, CompToBCD ( Compin ), BCDout );
  2546. end;
  2547. procedure BCDMultiply ( const Compin : Comp;
  2548. const BCDIn : tBCD;
  2549. var BCDout : tBCD ); Inline;
  2550. begin
  2551. BCDMultiply ( CompToBCD ( Compin ), BCDIn, BCDout );
  2552. end;
  2553. {$endif}
  2554. procedure BCDMultiply ( const StringIn : FmtBCDStringtype;
  2555. const BCDIn : tBCD;
  2556. var BCDout : tBCD ); Inline;
  2557. begin
  2558. BCDMultiply ( StrToBCD ( StringIn ), BCDIn, BCDout );
  2559. end;
  2560. procedure BCDDivide ( const Dividend : tBCD;
  2561. const Divisor : myInttype;
  2562. var BCDout : tBCD ); Inline;
  2563. begin
  2564. BCDDivide ( Dividend, IntegerToBCD ( Divisor ), BCDout );
  2565. end;
  2566. procedure BCDDivide ( const Dividend : myInttype;
  2567. const Divisor : tBCD;
  2568. var BCDout : tBCD ); Inline;
  2569. begin
  2570. BCDDivide ( IntegerToBCD ( Dividend ), Divisor, BCDout );
  2571. end;
  2572. {$ifndef FPUNONE}
  2573. procedure BCDDivide ( const Dividend : myRealtype;
  2574. const Divisor : tBCD;
  2575. var BCDout : tBCD ); Inline;
  2576. begin
  2577. BCDDivide ( DoubleToBCD ( Dividend ), Divisor, BCDout );
  2578. end;
  2579. {$endif}
  2580. procedure BCDDivide ( const BCDIn : tBCD;
  2581. const Currin : currency;
  2582. var BCDout : tBCD ); Inline;
  2583. begin
  2584. BCDDivide ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2585. end;
  2586. procedure BCDDivide ( const Currin : currency;
  2587. const BCDIn : tBCD;
  2588. var BCDout : tBCD ); Inline;
  2589. begin
  2590. BCDDivide ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2591. end;
  2592. {$ifdef comproutines}
  2593. procedure BCDDivide ( const BCDIn : tBCD;
  2594. const Compin : Comp;
  2595. var BCDout : tBCD ); Inline;
  2596. begin
  2597. BCDDivide ( BCDIn, CompToBCD ( Compin ), BCDout );
  2598. end;
  2599. procedure BCDDivide ( const Compin : Comp;
  2600. const BCDIn : tBCD;
  2601. var BCDout : tBCD ); Inline;
  2602. begin
  2603. BCDDivide ( CompToBCD ( Compin ), BCDIn, BCDout );
  2604. end;
  2605. {$endif}
  2606. procedure BCDDivide ( const Dividend : FmtBCDStringtype;
  2607. const Divisor : tBCD;
  2608. var BCDout : tBCD ); Inline;
  2609. begin
  2610. BCDDivide ( StrToBCD ( Dividend ), Divisor, BCDout );
  2611. end;
  2612. operator = ( const BCD1,
  2613. BCD2 : tBCD ) z : Boolean; Inline;
  2614. begin
  2615. z := BCDCompare ( BCD1, BCD2 ) = 0;
  2616. end;
  2617. operator < ( const BCD1,
  2618. BCD2 : tBCD ) z : Boolean; Inline;
  2619. begin
  2620. z := BCDCompare ( BCD1, BCD2 ) < 0;
  2621. end;
  2622. operator > ( const BCD1,
  2623. BCD2 : tBCD ) z : Boolean; Inline;
  2624. begin
  2625. z := BCDCompare ( BCD1, BCD2 ) > 0;
  2626. end;
  2627. operator <= ( const BCD1,
  2628. BCD2 : tBCD ) z : Boolean; Inline;
  2629. begin
  2630. z := BCDCompare ( BCD1, BCD2 ) <= 0;
  2631. end;
  2632. operator >= ( const BCD1,
  2633. BCD2 : tBCD ) z : Boolean; Inline;
  2634. begin
  2635. z := BCDCompare ( BCD1, BCD2 ) >= 0;
  2636. end;
  2637. (* ######################## not allowed: why?
  2638. operator + ( const BCD : tBCD ) z : tBCD; Inline;
  2639. begin
  2640. z := bcd;
  2641. end;
  2642. ##################################################### *)
  2643. operator - ( const BCD : tBCD ) z : tBCD; Inline;
  2644. begin
  2645. z := BCD;
  2646. BCDNegate ( z );
  2647. end;
  2648. operator + ( const BCD1,
  2649. BCD2 : tBCD ) z : tBCD; Inline;
  2650. begin
  2651. BCDAdd ( BCD1, BCD2, z );
  2652. end;
  2653. operator + ( const BCD : tBCD;
  2654. const i : myInttype ) z : tBCD; Inline;
  2655. begin
  2656. BCDAdd ( BCD, i, z );
  2657. end;
  2658. operator + ( const i : myInttype;
  2659. const BCD : tBCD ) z : tBCD; Inline;
  2660. begin
  2661. BCDAdd ( i, BCD, z );
  2662. end;
  2663. {$ifndef FPUNONE}
  2664. operator + ( const BCD : tBCD;
  2665. const r : myRealtype ) z : tBCD; Inline;
  2666. begin
  2667. BCDAdd ( BCD, DoubleToBCD ( r ), z );
  2668. end;
  2669. operator + ( const r : myRealtype;
  2670. const BCD : tBCD ) z : tBCD; Inline;
  2671. begin
  2672. BCDAdd ( DoubleToBCD ( r ), BCD, z );
  2673. end;
  2674. {$endif}
  2675. operator + ( const BCD : tBCD;
  2676. const c : currency ) z : tBCD; Inline;
  2677. begin
  2678. BCDAdd ( BCD, CurrToBCD ( c ), z );
  2679. end;
  2680. operator + ( const c : currency;
  2681. const BCD : tBCD ) z : tBCD; Inline;
  2682. begin
  2683. BCDAdd ( CurrToBCD ( c ), BCD, z );
  2684. end;
  2685. {$ifdef comproutines}
  2686. operator + ( const BCD : tBCD;
  2687. const c : Comp ) z : tBCD; Inline;
  2688. begin
  2689. BCDAdd ( BCD, CompToBCD ( c ), z );
  2690. end;
  2691. operator + ( const c : Comp;
  2692. const BCD : tBCD ) z : tBCD; Inline;
  2693. begin
  2694. BCDAdd ( CompToBCD ( c ), BCD, z );
  2695. end;
  2696. {$endif}
  2697. operator + ( const BCD : tBCD;
  2698. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2699. begin
  2700. BCDAdd ( BCD, StrToBCD ( s ), z );
  2701. end;
  2702. operator + ( const s : FmtBCDStringtype;
  2703. const BCD : tBCD ) z : tBCD; Inline;
  2704. begin
  2705. BCDAdd ( StrToBCD ( s ), BCD, z );
  2706. end;
  2707. operator - ( const BCD1,
  2708. BCD2 : tBCD ) z : tBCD; Inline;
  2709. begin
  2710. BCDSubtract ( BCD1, BCD2, z );
  2711. end;
  2712. operator - ( const BCD : tBCD;
  2713. const i : myInttype ) z : tBCD; Inline;
  2714. begin
  2715. BCDSubtract ( BCD, i, z );
  2716. end;
  2717. operator - ( const i : myInttype;
  2718. const BCD : tBCD ) z : tBCD; Inline;
  2719. begin
  2720. BCDSubtract ( BCD, i, z );
  2721. BCDNegate ( z );
  2722. end;
  2723. {$ifndef FPUNONE}
  2724. operator - ( const BCD : tBCD;
  2725. const r : myRealtype ) z : tBCD; Inline;
  2726. begin
  2727. BCDSubtract ( BCD, DoubleToBCD ( r ), z );
  2728. end;
  2729. operator - ( const r : myRealtype;
  2730. const BCD : tBCD ) z : tBCD; Inline;
  2731. begin
  2732. BCDSubtract ( DoubleToBCD ( r ), BCD, z );
  2733. end;
  2734. {$endif}
  2735. operator - ( const BCD : tBCD;
  2736. const c : currency ) z : tBCD; Inline;
  2737. begin
  2738. BCDSubtract ( BCD, CurrToBCD ( c ), z );
  2739. end;
  2740. operator - ( const c : currency;
  2741. const BCD : tBCD ) z : tBCD; Inline;
  2742. begin
  2743. BCDSubtract ( CurrToBCD ( c ), BCD, z );
  2744. end;
  2745. {$ifdef comproutines}
  2746. operator - ( const BCD : tBCD;
  2747. const c : Comp ) z : tBCD; Inline;
  2748. begin
  2749. BCDSubtract ( BCD, CompToBCD ( c ), z );
  2750. end;
  2751. operator - ( const c : Comp;
  2752. const BCD : tBCD ) z : tBCD; Inline;
  2753. begin
  2754. BCDSubtract ( CompToBCD ( c ), BCD, z );
  2755. end;
  2756. {$endif}
  2757. operator - ( const BCD : tBCD;
  2758. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2759. begin
  2760. BCDSubtract ( BCD, StrToBCD ( s ), z );
  2761. end;
  2762. operator - ( const s : FmtBCDStringtype;
  2763. const BCD : tBCD ) z : tBCD; Inline;
  2764. begin
  2765. BCDSubtract ( StrToBCD ( s ), BCD, z );
  2766. end;
  2767. operator * ( const BCD1,
  2768. BCD2 : tBCD ) z : tBCD; Inline;
  2769. begin
  2770. BCDMultiply ( BCD1, BCD2, z );
  2771. end;
  2772. operator * ( const BCD : tBCD;
  2773. const i : myInttype ) z : tBCD; Inline;
  2774. begin
  2775. BCDMultiply ( BCD, i, z );
  2776. end;
  2777. operator * ( const i : myInttype;
  2778. const BCD : tBCD ) z : tBCD; Inline;
  2779. begin
  2780. BCDMultiply ( BCD, i, z );
  2781. end;
  2782. {$ifndef FPUNONE}
  2783. operator * ( const BCD : tBCD;
  2784. const r : myRealtype ) z : tBCD; Inline;
  2785. begin
  2786. BCDMultiply ( BCD, DoubleToBCD ( r ), z );
  2787. end;
  2788. operator * ( const r : myRealtype;
  2789. const BCD : tBCD ) z : tBCD; Inline;
  2790. begin
  2791. BCDMultiply ( DoubleToBCD ( r ), BCD, z );
  2792. end;
  2793. {$endif}
  2794. operator * ( const BCD : tBCD;
  2795. const c : currency ) z : tBCD; Inline;
  2796. begin
  2797. BCDMultiply ( BCD, CurrToBCD ( c ), z );
  2798. end;
  2799. operator * ( const c : currency;
  2800. const BCD : tBCD ) z : tBCD; Inline;
  2801. begin
  2802. BCDMultiply ( CurrToBCD ( c ), BCD, z );
  2803. end;
  2804. {$ifdef comproutines}
  2805. operator * ( const BCD : tBCD;
  2806. const c : Comp ) z : tBCD; Inline;
  2807. begin
  2808. BCDMultiply ( BCD, CompToBCD ( c ), z );
  2809. end;
  2810. operator * ( const c : Comp;
  2811. const BCD : tBCD ) z : tBCD; Inline;
  2812. begin
  2813. BCDMultiply ( CompToBCD ( c ), BCD, z );
  2814. end;
  2815. {$endif}
  2816. operator * ( const BCD : tBCD;
  2817. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2818. begin
  2819. BCDMultiply ( BCD, StrToBCD ( s ), z );
  2820. end;
  2821. operator * ( const s : FmtBCDStringtype;
  2822. const BCD : tBCD ) z : tBCD; Inline;
  2823. begin
  2824. BCDMultiply ( StrToBCD ( s ), BCD, z );
  2825. end;
  2826. operator / ( const BCD1,
  2827. BCD2 : tBCD ) z : tBCD; Inline;
  2828. begin
  2829. BCDDivide ( BCD1, BCD2, z );
  2830. end;
  2831. operator / ( const BCD : tBCD;
  2832. const i : myInttype ) z : tBCD; Inline;
  2833. begin
  2834. BCDDivide ( BCD, i, z );
  2835. end;
  2836. operator / ( const i : myInttype;
  2837. const BCD : tBCD ) z : tBCD; Inline;
  2838. begin
  2839. BCDDivide ( IntegerToBCD ( i ), BCD, z );
  2840. end;
  2841. {$ifndef FPUNONE}
  2842. operator / ( const BCD : tBCD;
  2843. const r : myRealtype ) z : tBCD; Inline;
  2844. begin
  2845. BCDDivide ( BCD, DoubleToBCD ( r ), z );
  2846. end;
  2847. operator / ( const r : myRealtype;
  2848. const BCD : tBCD ) z : tBCD; Inline;
  2849. begin
  2850. BCDDivide ( DoubleToBCD ( r ), BCD, z );
  2851. end;
  2852. {$endif}
  2853. operator / ( const BCD : tBCD;
  2854. const c : currency ) z : tBCD; Inline;
  2855. begin
  2856. BCDDivide ( BCD, CurrToBCD ( c ), z );
  2857. end;
  2858. operator / ( const c : currency;
  2859. const BCD : tBCD ) z : tBCD; Inline;
  2860. begin
  2861. BCDDivide ( CurrToBCD ( c ), BCD, z );
  2862. end;
  2863. {$ifdef comproutines}
  2864. operator / ( const BCD : tBCD;
  2865. const c : Comp ) z : tBCD; Inline;
  2866. begin
  2867. BCDDivide ( BCD, CompToBCD ( c ), z );
  2868. end;
  2869. operator / ( const c : Comp;
  2870. const BCD : tBCD ) z : tBCD; Inline;
  2871. begin
  2872. BCDDivide ( CompToBCD ( c ), BCD, z );
  2873. end;
  2874. {$endif}
  2875. operator / ( const BCD : tBCD;
  2876. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2877. begin
  2878. BCDDivide ( BCD, StrToBCD ( s ), z );
  2879. end;
  2880. operator / ( const s : FmtBCDStringtype;
  2881. const BCD : tBCD ) z : tBCD; Inline;
  2882. begin
  2883. BCDDivide ( StrToBCD ( s ), BCD, z );
  2884. end;
  2885. operator := ( const i : Byte ) z : tBCD; Inline;
  2886. begin
  2887. z := IntegerToBCD ( myInttype ( i ) );
  2888. end;
  2889. operator := ( const BCD : tBCD ) z : Byte; Inline;
  2890. begin
  2891. z := BCDToInteger ( BCD );
  2892. end;
  2893. operator := ( const i : Word ) z : tBCD; Inline;
  2894. begin
  2895. z := IntegerToBCD ( myInttype ( i ) );
  2896. end;
  2897. operator := ( const BCD : tBCD ) z : Word; Inline;
  2898. begin
  2899. z := BCDToInteger ( BCD );
  2900. end;
  2901. operator := ( const i : longword ) z : tBCD; Inline;
  2902. begin
  2903. z := IntegerToBCD ( myInttype ( i ) );
  2904. end;
  2905. operator := ( const BCD : tBCD ) z : longword; Inline;
  2906. begin
  2907. z := BCDToInteger ( BCD );
  2908. end;
  2909. {$if declared ( qword ) }
  2910. operator := ( const i : qword ) z : tBCD; Inline;
  2911. begin
  2912. z := IntegerToBCD ( myInttype ( i ) );
  2913. end;
  2914. operator := ( const BCD : tBCD ) z : qword; Inline;
  2915. begin
  2916. z := BCDToInteger ( BCD );
  2917. end;
  2918. {$endif}
  2919. operator := ( const i : ShortInt ) z : tBCD; Inline;
  2920. begin
  2921. z := IntegerToBCD ( myInttype ( i ) );
  2922. end;
  2923. operator := ( const BCD : tBCD ) z : ShortInt; Inline;
  2924. begin
  2925. z := BCDToInteger ( BCD );
  2926. end;
  2927. operator := ( const i : smallint ) z : tBCD; Inline;
  2928. begin
  2929. z := IntegerToBCD ( myInttype ( i ) );
  2930. end;
  2931. operator := ( const BCD : tBCD ) z : smallint; Inline;
  2932. begin
  2933. z := BCDToInteger ( BCD );
  2934. end;
  2935. operator := ( const i : LongInt ) z : tBCD; Inline;
  2936. begin
  2937. z := IntegerToBCD ( myInttype ( i ) );
  2938. end;
  2939. operator := ( const BCD : tBCD ) z : LongInt; Inline;
  2940. begin
  2941. z := BCDToInteger ( BCD );
  2942. end;
  2943. {$if declared ( int64 ) }
  2944. operator := ( const i : int64 ) z : tBCD; Inline;
  2945. begin
  2946. z := IntegerToBCD ( myInttype ( i ) );
  2947. end;
  2948. operator := ( const BCD : tBCD ) z : int64; Inline;
  2949. begin
  2950. z := BCDToInteger ( BCD );
  2951. end;
  2952. {$endif}
  2953. {$ifndef FPUNONE}
  2954. operator := ( const r : Single ) z : tBCD; Inline;
  2955. begin
  2956. z := DoubleToBCD ( myRealtype ( r ) );
  2957. end;
  2958. operator := ( const BCD : tBCD ) z : Single; Inline;
  2959. begin
  2960. z := BCDToDouble ( BCD );
  2961. end;
  2962. operator := ( const r : Double ) z : tBCD; Inline;
  2963. begin
  2964. z := DoubleToBCD ( myRealtype ( r ) );
  2965. end;
  2966. operator := ( const BCD : tBCD ) z : Double; Inline;
  2967. begin
  2968. z := BCDToDouble ( BCD );
  2969. end;
  2970. {$if sizeof ( extended ) <> sizeof ( double )}
  2971. operator := ( const r : Extended ) z : tBCD; Inline;
  2972. begin
  2973. z := DoubleToBCD ( {myRealtype (} r {)} );
  2974. end;
  2975. operator := ( const BCD : tBCD ) z : Extended; Inline;
  2976. begin
  2977. z := BCDToDouble ( BCD );
  2978. end;
  2979. {$endif}
  2980. {$endif}
  2981. operator := ( const c : currency ) z : tBCD; Inline;
  2982. begin
  2983. CurrToBCD ( c, z );
  2984. end;
  2985. operator := ( const BCD : tBCD ) z : currency; Inline;
  2986. begin
  2987. BCDToCurr ( BCD, z );
  2988. end;
  2989. {$ifdef comproutines}
  2990. {$undef makedirect}
  2991. {$ifdef makedirect}
  2992. operator := ( const c : Comp ) z : tBCD; Inline;
  2993. var
  2994. cc : int64 absolute c;
  2995. begin
  2996. z := IntegerToBCD ( cc );
  2997. end;
  2998. { $define version1} { only one of these may be defined! }
  2999. { $define version2} { version 1 produces a compiler error (with INLINE only!)}
  3000. {$define version3} { I wasn't able to reduce the problem, sorry }
  3001. {$ifdef version1}
  3002. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3003. var
  3004. zz : Comp absolute z;
  3005. begin
  3006. zz := BCDToInteger ( BCD );
  3007. end;
  3008. {$endif}
  3009. {$ifdef version2}
  3010. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3011. var
  3012. zz : int64;
  3013. zzz : Comp absolute zz;
  3014. begin
  3015. zz := BCDToInteger ( BCD );
  3016. z := zzz;
  3017. end;
  3018. {$endif}
  3019. {$ifdef version3}
  3020. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3021. var
  3022. zz : record
  3023. case Boolean of
  3024. False: ( i : int64 );
  3025. True: ( c : Comp );
  3026. end;
  3027. begin
  3028. zz.i := BCDToInteger ( BCD );
  3029. z := zz.c;
  3030. end;
  3031. {$endif}
  3032. {$else}
  3033. operator := ( const c : Comp ) z : tBCD; Inline;
  3034. begin
  3035. z := CompToBCD ( c );
  3036. end;
  3037. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3038. begin
  3039. z := BCDToComp ( BCD );
  3040. end;
  3041. {$endif}
  3042. {$endif}
  3043. operator := ( const s : string ) z : tBCD; Inline;
  3044. begin
  3045. z := StrToBCD ( s );
  3046. end;
  3047. operator := ( const BCD : tBCD ) z : string; Inline;
  3048. begin
  3049. z := BCDToStr ( BCD );
  3050. end;
  3051. operator := ( const s : AnsiString ) z : tBCD; Inline;
  3052. begin
  3053. z := StrToBCD ( s );
  3054. end;
  3055. operator := ( const BCD : tBCD ) z : AnsiString; Inline;
  3056. begin
  3057. z := BCDToStr ( BCD );
  3058. end;
  3059. {$endif}
  3060. Function VariantToBCD(const VargSrc : TVarData) : TBCD;
  3061. begin
  3062. with VargSrc do
  3063. case vType and not varTypeMask of
  3064. 0: case vType of
  3065. varEmpty : Result := 0;
  3066. varSmallInt : Result := vSmallInt;
  3067. varShortInt : Result := vShortInt;
  3068. varInteger : Result := vInteger;
  3069. varSingle : Result := vSingle;
  3070. varDouble : Result := vDouble;
  3071. varCurrency : Result := vCurrency;
  3072. varDate : Result := vDate;
  3073. varBoolean : Result := Integer(vBoolean);
  3074. varVariant : Result := VariantToBCD(PVarData(vPointer)^);
  3075. varByte : Result := vByte;
  3076. varWord : Result := vWord;
  3077. varLongWord : Result := vLongWord;
  3078. varInt64 : Result := vInt64;
  3079. varQword : Result := vQWord;
  3080. varString : Result := AnsiString(vString);
  3081. else
  3082. if vType=VarFmtBCD then
  3083. Result := TFMTBcdVarData(vPointer).BCD
  3084. else
  3085. not_implemented;
  3086. end;
  3087. varByRef: if Assigned(vPointer) then case vType and varTypeMask of
  3088. varSmallInt : Result := PSmallInt(vPointer)^;
  3089. varShortInt : Result := PShortInt(vPointer)^;
  3090. varInteger : Result := PInteger(vPointer)^;
  3091. varSingle : Result := PSingle(vPointer)^;
  3092. varDouble : Result := PDouble(vPointer)^;
  3093. varCurrency : Result := PCurrency(vPointer)^;
  3094. varDate : Result := PDate(vPointer)^;
  3095. varBoolean : Result := SmallInt(PWordBool(vPointer)^);
  3096. varVariant : Result := VariantToBCD(PVarData(vPointer)^);
  3097. varByte : Result := PByte(vPointer)^;
  3098. varWord : Result := PWord(vPointer)^;
  3099. varLongWord : Result := PLongWord(vPointer)^;
  3100. varInt64 : Result := PInt64(vPointer)^;
  3101. varQword : Result := PQWord(vPointer)^;
  3102. else { other vtype }
  3103. not_implemented;
  3104. end else { pointer is nil }
  3105. not_implemented;
  3106. else { array or something like that }
  3107. not_implemented;
  3108. end;
  3109. end;
  3110. function VarToBCD ( const aValue : Variant ) : tBCD;
  3111. begin
  3112. Result:=VariantToBCD(TVarData(aValue));
  3113. end;
  3114. constructor TFMTBcdVarData.create;
  3115. begin
  3116. inherited create;
  3117. FBcd:=NullBCD;
  3118. end;
  3119. constructor TFMTBcdVarData.create(const BCD : tBCD);
  3120. begin
  3121. inherited create;
  3122. FBcd:=BCD;
  3123. end;
  3124. function TFMTBcdFactory.GetInstance(const v : TVarData): tObject;
  3125. begin
  3126. result:=tObject(v.VPointer);
  3127. end;
  3128. procedure TFMTBcdFactory.BinaryOp(var Left: TVarData; const Right: TVarData; const Operation: TVarOp);
  3129. var l, r: TBCD;
  3130. begin
  3131. l:=VariantToBCD(Left);
  3132. r:=VariantToBCD(Right);
  3133. case Operation of
  3134. opAdd:
  3135. l:=l+r;
  3136. opSubtract:
  3137. l:=l-r;
  3138. opMultiply:
  3139. l:=l*r;
  3140. opDivide:
  3141. l:=l/r;
  3142. else
  3143. RaiseInvalidOp;
  3144. end;
  3145. if Left.vType=VarType then
  3146. TFMTBcdVarData(Left.VPointer).BCD := l
  3147. else
  3148. RaiseInvalidOp;
  3149. end;
  3150. procedure TFMTBcdFactory.Compare(const Left, Right: TVarData; var Relationship: TVarCompareResult);
  3151. var l, r: TBCD;
  3152. CmpRes: integer;
  3153. begin
  3154. l:=VariantToBCD(Left);
  3155. r:=VariantToBCD(Right);
  3156. CmpRes := BCDCompare(l,r);
  3157. if CmpRes=0 then
  3158. Relationship := crEqual
  3159. else if CmpRes<0 then
  3160. Relationship := crLessThan
  3161. else
  3162. Relationship := crGreaterThan;
  3163. end;
  3164. function TFMTBcdFactory.CompareOp(const Left, Right: TVarData; const Operation: TVarOp): Boolean;
  3165. var l, r: TBCD;
  3166. begin
  3167. l:=VariantToBCD(Left);
  3168. r:=VariantToBCD(Right);
  3169. case Operation of
  3170. opCmpEq:
  3171. Result := l=r;
  3172. opCmpNe:
  3173. Result := l<>r;
  3174. opCmpLt:
  3175. Result := l<r;
  3176. opCmpLe:
  3177. Result := l<=r;
  3178. opCmpGt:
  3179. Result := l>r;
  3180. opCmpGe:
  3181. Result := l>=r;
  3182. else
  3183. RaiseInvalidOp;
  3184. end;
  3185. end;
  3186. procedure TFMTBcdFactory.Clear(var V: TVarData);
  3187. begin
  3188. FreeAndNil(tObject(V.VPointer));
  3189. V.VType:=varEmpty;
  3190. end;
  3191. procedure TFMTBcdFactory.Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean);
  3192. begin
  3193. if Indirect then
  3194. Dest.VPointer:=Source.VPointer
  3195. else
  3196. Dest.VPointer:=TFMTBcdVarData.Create(TFMTBcdVarData(Source.VPointer).BCD);
  3197. Dest.VType:=VarType;
  3198. end;
  3199. procedure TFMTBcdFactory.Cast(var Dest: TVarData; const Source: TVarData);
  3200. begin
  3201. not_implemented;
  3202. end;
  3203. procedure TFMTBcdFactory.CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType);
  3204. var v: TVarData;
  3205. begin
  3206. if Source.vType=VarType then
  3207. begin
  3208. VarDataInit(v);
  3209. try
  3210. v.vType:=varDouble;
  3211. v.vDouble:=TFMTBcdVarData(Source.vPointer).BCD;
  3212. VarDataCastTo(Dest, v, aVarType); //now cast Double to any requested type
  3213. finally
  3214. VarDataClear(v);
  3215. end;
  3216. end
  3217. else
  3218. inherited;
  3219. end;
  3220. {$if declared ( myMinIntBCD ) }
  3221. (*
  3222. {$if sizeof ( integer ) = 2 }
  3223. {$ifdef BCDgr4 }
  3224. const
  3225. myMinIntBCDValue : packed array [ 1..3 ] of Char = #$32#$76#$80;
  3226. {$endif}
  3227. {$else}
  3228. {$if sizeof ( integer ) = 4 }
  3229. *)
  3230. {$ifdef BCDgr9 }
  3231. const
  3232. myMinIntBCDValue : packed array [ 1..10 ] of Char = #$21#$47#$48#$36#$48;
  3233. {$endif}
  3234. (*
  3235. {$else}
  3236. {$if sizeof ( integer ) = 8 }
  3237. {$ifdef BCDgr18 }
  3238. const
  3239. myMinIntBCDValue : packed array [ 1..19 ] of Char = #$92#$23#$37#$20#$36#$85#$47#$75#$80#$80;
  3240. {$endif}
  3241. {$else}
  3242. {$fatal You have an interesting integer type! Sorry, not supported}
  3243. {$endif}
  3244. {$endif}
  3245. {$endif}
  3246. *)
  3247. {$endif}
  3248. initialization
  3249. FillChar ( null_, SizeOf ( null_ ), #0 );
  3250. FillChar ( NullBCD_, SizeOf ( NullBCD_ ), #0 );
  3251. FillChar ( OneBCD_, SizeOf ( OneBCD_ ), #0 );
  3252. OneBCD_.Precision := 1;
  3253. OneBCD_.Fraction[low ( OneBCD_.Fraction )] := $10;
  3254. {$if declared ( myMinIntBCD ) }
  3255. FillChar ( myMinIntBCD, SizeOf ( myMinIntBCD ), #0 );
  3256. {$ifndef bigger_BCD}
  3257. myMinIntBCD.SignSpecialPlaces := NegBit;
  3258. {$else}
  3259. myMinIntBCD.Negativ := True;
  3260. {$endif}
  3261. {$if sizeof ( integer ) = 2 }
  3262. {$ifdef BCDgr4 }
  3263. myMinIntBCD.Precision := 5;
  3264. Move ( myMinIntBCDValue, myMinIntBCD.Fraction, SizeOf ( myMinIntBCDValue ) );
  3265. {$endif}
  3266. {$else}
  3267. {$if sizeof ( integer ) = 4 }
  3268. {$ifdef BCDgr9 }
  3269. myMinIntBCD.Precision := 10;
  3270. Move ( myMinIntBCDValue, myMinIntBCD.Fraction, SizeOf ( myMinIntBCDValue ) );
  3271. {$endif}
  3272. {$else}
  3273. {$if sizeof ( integer ) = 8 }
  3274. {$ifdef BCDgr18 }
  3275. myMinIntBCD.Precision := 19;
  3276. Move ( myMinIntBCDValue, myMinIntBCD.Fraction, SizeOf ( myMinIntBCDValue ) );
  3277. {$endif}
  3278. {$else}
  3279. {$fatal You have an interesting integer type! Sorry, not supported}
  3280. {$endif}
  3281. {$endif}
  3282. {$endif}
  3283. {$endif}
  3284. FMTBcdFactory:=TFMTBcdFactory.create;
  3285. finalization
  3286. FreeAndNil(FMTBcdFactory)
  3287. end.