fmtbcd.pp 111 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969
  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 := False;
  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 := True
  1193. else inife := infrac;
  1194. end;
  1195. 'e',
  1196. 'E': if inife = inexp
  1197. then result := True
  1198. else inife := inexp;
  1199. '+',
  1200. '-': if ( inife = inexp ) AND ( fp[inexp] = 0 )
  1201. then pse := i
  1202. else result := True;
  1203. else begin
  1204. result := True;
  1205. errp := i;
  1206. end;
  1207. end;
  1208. end;
  1209. if result
  1210. then begin
  1211. result := False;
  1212. for i := errp TO lav do
  1213. if aValue[i] <> ' '
  1214. then result := True;
  1215. end;
  1216. if 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 NOT 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 := True;
  1233. end;
  1234. if 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 := True;
  1267. end;
  1268. if result
  1269. then EXIT;
  1270. FDig := p;
  1271. if LDig < 0
  1272. then LDig := 0;
  1273. Plac := LDig;
  1274. result := NOT 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 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. result[1] := '0';
  1424. {$else}
  1425. result := result + '0';
  1426. {$endif}
  1427. end;
  1428. if Prec > 0
  1429. then begin
  1430. pp := low ( bh.FDig ) - 1;
  1431. if Plac > 0
  1432. then pp := 1;
  1433. for i := FDig TO LDig do
  1434. begin
  1435. if i = pp
  1436. then begin
  1437. {$ifndef use_ansistring}
  1438. Inc ( l );
  1439. result[l] := dp;
  1440. {$else}
  1441. result := result + dp;
  1442. {$endif}
  1443. end;
  1444. {$ifndef use_ansistring}
  1445. Inc ( l );
  1446. result[l] := Chr ( Singles[i] + Ord ( '0' ) );
  1447. {$else}
  1448. result := result + Chr ( Singles[i] + Ord ( '0' ) );
  1449. {$endif}
  1450. end;
  1451. end;
  1452. end;
  1453. {$ifndef use_ansistring}
  1454. result[0] := Chr ( l );
  1455. {$endif}
  1456. end;
  1457. {$ifndef FPUNONE}
  1458. function BCDToDouble ( const BCD : tBCD ) : myRealtype;
  1459. var
  1460. bh : tBCD_helper;
  1461. i : {$ifopt r+} low ( bh.FDig )..high ( bh.LDig ) {$else} Integer {$endif};
  1462. r,
  1463. e : myRealtype;
  1464. begin
  1465. unpack_BCD ( BCD, bh );
  1466. WITH bh do
  1467. begin
  1468. r := 0;
  1469. e := 1;
  1470. for i := 0 DOWNTO FDig do
  1471. begin
  1472. r := r + Singles[i] * e;
  1473. e := e * 10;
  1474. end;
  1475. e := 1;
  1476. for i := 1 TO LDig do
  1477. begin
  1478. e := e / 10;
  1479. r := r + Singles[i] * e;
  1480. end;
  1481. if Neg
  1482. then BCDToDouble := -r
  1483. else BCDToDouble := +r;
  1484. end;
  1485. end;
  1486. {$endif}
  1487. function BCDToInteger ( const BCD : tBCD;
  1488. Truncate : Boolean = False ) : myInttype;
  1489. var
  1490. bh : tBCD_helper;
  1491. res : myInttype;
  1492. i : {$ifopt r+} low ( bh.FDig )..0 {$else} Integer {$endif};
  1493. {
  1494. unclear: behaviour if overflow: abort? return 0? return something?
  1495. so: checks are missing yet
  1496. }
  1497. begin
  1498. unpack_BCD ( BCD, bh );
  1499. res := 0;
  1500. WITH bh do
  1501. begin
  1502. for i := FDig TO 0 do
  1503. res := res * 10 - Singles[i];
  1504. if NOT Truncate
  1505. then
  1506. if Plac > 0
  1507. then
  1508. if Singles[1] > 4
  1509. then Dec ( res );
  1510. if Neg
  1511. then BCDToInteger := +res
  1512. else BCDToInteger := -res;
  1513. end;
  1514. end;
  1515. { From DB.pas }
  1516. function BCDToCurr ( const BCD : tBCD;
  1517. var Curr : currency ) : Boolean;
  1518. var
  1519. bh : tBCD_helper;
  1520. res : int64;
  1521. c : currency absolute res;
  1522. i : {$ifopt r+} low ( bh.FDig )..4 {$else} Integer {$endif};
  1523. {
  1524. unclear: behaviour if overflow: abort? return 0? return something?
  1525. }
  1526. begin
  1527. BCDToCurr := True;
  1528. unpack_BCD ( BCD, bh );
  1529. res := 0;
  1530. WITH bh do
  1531. begin
  1532. for i := FDig TO 4 do
  1533. res := res * 10 + Singles[i];
  1534. if Plac > 4
  1535. then
  1536. if Singles[5] > 4
  1537. then Inc ( res );
  1538. if Neg
  1539. then Curr := -c
  1540. else Curr := +c;
  1541. end;
  1542. end;
  1543. procedure BCDAdd ( const BCDin1,
  1544. BCDin2 : tBCD;
  1545. var BCDout : tBCD );
  1546. var
  1547. bhr,
  1548. bh1,
  1549. bh2 : tBCD_helper;
  1550. ue : {$ifopt r+} 0..1 {$else} Integer {$endif};
  1551. i : {$ifopt r+} low ( bh1.FDig )..high ( bh1.LDig ) {$else} Integer {$endif};
  1552. v : {$ifopt r+} 0..9 + 9 + 1 {$else} Integer {$endif};
  1553. BCD : tBCD;
  1554. negate : Boolean;
  1555. begin
  1556. negate := IsBCDNegative ( BCDin1 );
  1557. if negate <> IsBCDNegative ( BCDin2 )
  1558. then begin
  1559. if negate
  1560. then begin
  1561. BCD := BCDin1;
  1562. BCDNegate ( BCD );
  1563. BCDSubtract ( BCDin2, BCD, BCDout );
  1564. EXIT;
  1565. end;
  1566. BCD := BCDin2;
  1567. BCDNegate ( BCD );
  1568. BCDSubtract ( BCDin1, BCD, BCDout );
  1569. EXIT;
  1570. end;
  1571. bhr := null_.bh;
  1572. WITH bhr do
  1573. begin
  1574. unpack_BCD ( BCDin1, bh1 );
  1575. unpack_BCD ( BCDin2, bh2 );
  1576. if bh1.FDig < bh2.FDig
  1577. then FDig := bh1.FDig
  1578. else FDig := bh2.FDig;
  1579. if bh1.LDig > bh2.LDig
  1580. then LDig := bh1.LDig
  1581. else LDig := bh2.LDig;
  1582. Plac := LDig;
  1583. ue := 0;
  1584. for i := LDig DOWNTO FDig do
  1585. begin
  1586. v := bh1.Singles[i] + bh2.Singles[i] + ue;
  1587. ue := v DIV 10;
  1588. Singles[i] := v MOD 10;
  1589. end;
  1590. if ue <> 0
  1591. then begin
  1592. Dec ( FDig );
  1593. Singles[FDig] := ue;
  1594. end;
  1595. Neg := negate;
  1596. end;
  1597. if NOT pack_BCD ( bhr, BCDout )
  1598. then begin
  1599. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  1600. end;
  1601. end;
  1602. procedure BCDSubtract ( const BCDin1,
  1603. BCDin2 : tBCD;
  1604. var BCDout : tBCD );
  1605. var
  1606. bhr,
  1607. bh1,
  1608. bh2 : tBCD_helper;
  1609. cmp : {$ifopt r+} -1..1 {$else} Integer {$endif};
  1610. ue : {$ifopt r+} 0..1 {$else} Integer {$endif};
  1611. i : {$ifopt r+} low ( bh1.FDig )..high ( bh1.LDig ) {$else} Integer {$endif};
  1612. v : {$ifopt r+} 0 - 9 - 1..9 - 0 - 0 {$else} Integer {$endif};
  1613. negate : Boolean;
  1614. BCD : tBCD;
  1615. begin
  1616. negate := IsBCDNegative ( BCDin1 );
  1617. if negate <> IsBCDNegative ( BCDin2 )
  1618. then begin
  1619. if negate
  1620. then begin
  1621. BCD := BCDin1;
  1622. BCDNegate ( BCD );
  1623. BCDAdd ( BCDin2, BCD, BCDout );
  1624. BCDNegate ( BCDout );
  1625. EXIT;
  1626. end;
  1627. BCD := BCDin2;
  1628. BCDNegate ( BCD );
  1629. BCDAdd ( BCDin1, BCD, BCDout );
  1630. EXIT;
  1631. end;
  1632. cmp := BCDCompare ( BCDin1, BCDin2 );
  1633. if cmp = 0
  1634. then begin
  1635. BCDout := NullBCD;
  1636. EXIT;
  1637. end;
  1638. bhr := null_.bh; { n n }
  1639. WITH bhr do { > < > < }
  1640. begin { }
  1641. if ( cmp > 0 ) = negate { +123 +12 -12 -123 }
  1642. then begin { - +12 - +123 - -123 - -12 }
  1643. unpack_BCD ( BCDin1, bh2 ); { x x }
  1644. unpack_BCD ( BCDin2, bh1 ); { s s s s }
  1645. negate := NOT negate; { nn n nn n }
  1646. end
  1647. else begin
  1648. unpack_BCD ( BCDin1, bh1 );
  1649. unpack_BCD ( BCDin2, bh2 );
  1650. end;
  1651. if bh1.FDig < bh2.FDig
  1652. then FDig := bh1.FDig
  1653. else FDig := bh2.FDig;
  1654. if bh1.LDig > bh2.LDig
  1655. then LDig := bh1.LDig
  1656. else LDig := bh2.LDig;
  1657. Plac := LDig;
  1658. ue := 0;
  1659. for i := LDig DOWNTO FDig do
  1660. begin
  1661. v := Integer ( bh1.Singles[i] ) - bh2.Singles[i] - ue;
  1662. ue := 0;
  1663. if v < 0
  1664. then begin
  1665. ue := 1;
  1666. Inc ( v, 10 );
  1667. end;
  1668. Singles[i] := v;
  1669. end;
  1670. Neg := negate;
  1671. if NOT pack_BCD ( bhr, BCDout )
  1672. then begin
  1673. {should never occur!}
  1674. RAISE eBCDOverflowException.create ( 'in BCDSubtract' );
  1675. end;
  1676. end;
  1677. end;
  1678. { Returns True if successful, False if Int Digits needed to be truncated }
  1679. function NormalizeBCD ( const InBCD : tBCD;
  1680. var OutBCD : tBCD;
  1681. const Prec,
  1682. Scale : Word ) : Boolean;
  1683. var
  1684. bh : tBCD_helper;
  1685. tm : {$ifopt r+} 1..maxfmtbcdfractionsize - 1 {$else} Integer {$endif};
  1686. begin
  1687. NormalizeBCD := True;
  1688. {$ifopt r+}
  1689. if ( Prec < 0 ) OR ( Prec > MaxFmtBCDFractionSize ) then RangeError;
  1690. if ( Scale < 0 ) OR ( Prec >= MaxFmtBCDFractionSize ) then RangeError;
  1691. {$endif}
  1692. if BCDScale ( InBCD ) > Scale
  1693. then begin
  1694. unpack_BCD ( InBCD, bh );
  1695. WITH bh do
  1696. begin
  1697. tm := Plac - Scale;
  1698. Plac := Scale;
  1699. { dec ( prec, tm ); Dec/Inc error? }
  1700. Prec := Prec - tm;
  1701. { dec ( ldig, tm ); Dec/Inc error? }
  1702. LDig := LDig - tm;
  1703. NormalizeBCD := False;
  1704. end;
  1705. if NOT pack_BCD ( bh, OutBCD )
  1706. then begin
  1707. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  1708. end;
  1709. end;
  1710. end;
  1711. procedure BCDMultiply ( const BCDin1,
  1712. BCDin2 : tBCD;
  1713. var BCDout : tBCD );
  1714. var
  1715. bh1,
  1716. bh2,
  1717. bhr : tBCD_helper;
  1718. bhrr : tBCD_helper_big;
  1719. i1 : {$ifopt r+} low ( bh1.FDig )..high ( bh1.LDig ) {$else} Integer {$endif};
  1720. i2 : {$ifopt r+} low ( bh2.FDig )..high ( bh2.LDig ) {$else} Integer {$endif};
  1721. i3 : {$ifopt r+} low ( bhrr.FDig )..high ( bhrr.LDig ) {$else} Integer {$endif};
  1722. v : {$ifopt r+} low ( bhrr.Singles[0] )..high ( bhrr.Singles[0] ) {$else} Integer {$endif};
  1723. ue : {$ifopt r+} low ( bhrr.Singles[0] ) DIV 10..high ( bhrr.Singles[0] ) DIV 10 {$else} Integer {$endif};
  1724. begin
  1725. unpack_BCD ( BCDin1, bh1 );
  1726. unpack_BCD ( BCDin2, bh2 );
  1727. if ( bh1.Prec = 0 ) OR ( bh2.Prec = 0 )
  1728. then begin
  1729. BCDout := NullBCD;
  1730. EXIT;
  1731. end;
  1732. bhr := null_.bh;
  1733. bhrr := null_.bhb;
  1734. WITH bhrr do
  1735. begin
  1736. Neg := bh1.Neg XOR bh2.Neg;
  1737. {
  1738. writeln ( __lo_bhb, ' ', __hi_bhb, ' ', bh1.fdig, ' ', bh2.fdig, ' ', low ( fdig ), ' ', low ( ldig ) );
  1739. }
  1740. FDig := bh1.FDig + bh2.FDig;
  1741. LDig := bh1.LDig + bh2.LDig;
  1742. for i1 := bh1.FDig TO bh1.LDig do
  1743. for i2 := bh2.FDig TO bh2.LDig do
  1744. begin
  1745. Inc ( Singles[i1 + i2],
  1746. bh1.Singles[i1]
  1747. * bh2.Singles[i2] );
  1748. {
  1749. write ( Singles[i1 + i2], ' ', bh1.Singles[i1], ' ', bh2.Singles[i2], ' : ' );
  1750. writeln ( Singles[i1 + i2] + bh1.Singles[i1] + bh2.Singles[i2] );
  1751. }
  1752. {
  1753. Singles[i1 + i2] := Singles[i1 + i2]
  1754. + bh1.Singles[i1]
  1755. * bh2.Singles[i2];
  1756. }
  1757. end;
  1758. {
  1759. for i3 := fdig to ldig do
  1760. write ( ' ', singles[i3] );
  1761. writeln;
  1762. }
  1763. if FDig < low ( bhr.Singles )
  1764. then RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  1765. ue := 0;
  1766. for i3 := LDig DOWNTO FDig do
  1767. begin
  1768. v := Singles[i3] + ue;
  1769. ue := v DIV 10;
  1770. v := v MOD 10;
  1771. bhr.Singles[i3] := v;
  1772. end;
  1773. while ue <> 0 do
  1774. begin
  1775. Dec ( FDig );
  1776. if FDig < low ( bhr.Singles )
  1777. then RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  1778. bhr.Singles[FDig] := ue MOD 10;
  1779. ue := ue DIV 10;
  1780. end;
  1781. bhr.Plac := LDig;
  1782. bhr.FDig := FDig;
  1783. if LDig > high ( bhr.Singles )
  1784. then bhr.LDig := high ( bhr.Singles )
  1785. else bhr.LDig := LDig;
  1786. end;
  1787. if NOT pack_BCD ( bhr, BCDout )
  1788. then begin
  1789. RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  1790. end;
  1791. end;
  1792. {$ifndef FPUNONE}
  1793. procedure BCDMultiply ( const BCDIn : tBCD;
  1794. const DoubleIn : myRealtype;
  1795. var BCDout : tBCD ); Inline;
  1796. begin
  1797. BCDMultiply ( BCDIn, DoubleToBCD ( DoubleIn ), BCDout );
  1798. end;
  1799. {$endif}
  1800. procedure BCDMultiply ( const BCDIn : tBCD;
  1801. const StringIn : FmtBCDStringtype;
  1802. var BCDout : tBCD ); Inline;
  1803. begin
  1804. BCDMultiply ( BCDIn, StrToBCD ( StringIn ), BCDout );
  1805. end;
  1806. procedure BCDMultiply ( const StringIn1,
  1807. StringIn2 : FmtBCDStringtype;
  1808. var BCDout : tBCD ); Inline;
  1809. begin
  1810. BCDMultiply ( StrToBCD ( StringIn1 ), StrToBCD ( StringIn2 ), BCDout );
  1811. end;
  1812. procedure BCDDivide ( const Dividend,
  1813. Divisor : tBCD;
  1814. var BCDout : tBCD );
  1815. var
  1816. bh1 : ARRAY [ Boolean ] of tBCD_helper;
  1817. bh2,
  1818. bh : tBCD_helper;
  1819. p : {$ifopt r+} low ( bh.FDig ) - high ( bh.FDig )..high ( bh.FDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1820. v1 : {$ifopt r+} low ( bh.Singles[0] )..high ( bh.Singles[0] ) {$else} Integer {$endif};
  1821. v2 : {$ifopt r+} low ( bh.Singles[0] )..high ( bh.Singles[0] ) {$else} Integer {$endif};
  1822. lFDig : {$ifopt r+} low ( bh.FDig )..high ( bh.FDig ) {$else} Integer {$endif};
  1823. d1 : {$ifopt r+} low ( bh.LDig ) - high ( bh.FDig )..high ( bh.LDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1824. d2 : {$ifopt r+} low ( bh.LDig ) - high ( bh.FDig )..high ( bh.LDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1825. d : {$ifopt r+} low ( bh.LDig ) - high ( bh.FDig )..high ( bh.LDig ) - low ( bh.FDig ) {$else} Integer {$endif};
  1826. lLdig : {$ifopt r+} low ( lFDig ) + low ( d )..high ( lFDig ) + high ( d ) {$else} Integer {$endif};
  1827. tm : {$ifopt r+} low ( lLdig ) - high ( bh2.Singles )..high ( lLdig ) - high ( bh2.Singles ) {$else} Integer {$endif};
  1828. i2 : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1829. i3 : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1830. ie : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1831. i4 : {$ifopt r+} low ( lFDig )..high ( lLdig ) {$else} Integer {$endif};
  1832. nFDig : {$ifopt r+} low ( i2 )..high ( i2 ) {$else} Integer {$endif};
  1833. nLDig : {$ifopt r+} low ( i2 )..high ( i2 ) {$else} Integer {$endif};
  1834. dd : {$ifopt r+} 0..9 {$else} Integer {$endif};
  1835. Add : {$ifopt r+} 0..99 {$else} Integer {$endif};
  1836. ue : {$ifopt r+} 0..99 {$else} Integer {$endif};
  1837. 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};
  1838. v4 : {$ifopt r+} low ( bh.Singles[0] ) + low ( add )..high ( bh.Singles[0] ) + high ( add ) {$else} Integer {$endif};
  1839. FlipFlop,
  1840. nz,
  1841. sf,
  1842. sh,
  1843. fdset : Boolean;
  1844. {
  1845. bh1p : ARRAY [ Boolean ] of ^ tBCD_helper;
  1846. }
  1847. begin
  1848. { test:
  1849. bh1p[false] := @ bh1[false];
  1850. bh1p[true] := @ bh1[true];
  1851. v := bh1[false].singles[0];
  1852. v := bh1[true].singles[0];
  1853. v := bh1p[false]^.singles[0];
  1854. v := bh1p[true]^.singles[0];
  1855. v := bh1[nz].singles[0];
  1856. v := bh1p[nz]^.singles[0];
  1857. }
  1858. unpack_BCD ( Divisor, bh2 );
  1859. unpack_BCD ( Dividend, bh1[False] );
  1860. p := bh1[False].FDig - bh2.FDig;
  1861. _SELECT
  1862. _WHEN bh2.Prec = 0
  1863. _THEN RAISE eBCDException.create ( 'Division by zero' );
  1864. _WHEN bh1[False].Prec = 0
  1865. _THEN BCDout := NullBCD;
  1866. _WHEN p < low ( bh2.Singles )
  1867. _THEN RAISE eBCDOverflowException.create ( 'in BCDDivide' );
  1868. _WHENOTHER
  1869. bh := null_.bh;
  1870. bh.Neg := bh1[False].Neg XOR bh2.Neg;
  1871. if p <= high ( bh.Singles )
  1872. then begin
  1873. bh1[True] := null_.bh;
  1874. FlipFlop := False;
  1875. fdset := p > 0;
  1876. if fdset
  1877. then bh.FDig := 0;
  1878. add := 0;
  1879. nz := True;
  1880. while nz do
  1881. WITH bh1[FlipFlop] do
  1882. begin
  1883. {
  1884. WriteLn('#####');
  1885. dumpbh ( bh1[flipflop] );
  1886. dumpbh ( bh2 );
  1887. dumpbh ( bh );
  1888. }
  1889. if ( Singles[FDig] + bh2.Singles[bh2.FDig] ) = 0
  1890. then begin
  1891. if ( FDig >= LDig )
  1892. OR ( bh2.FDig >= bh2.LDig )
  1893. then nz := False
  1894. else begin
  1895. Inc ( FDig );
  1896. Inc ( bh2.FDig );
  1897. end;
  1898. end
  1899. else begin
  1900. v1 := Singles[FDig];
  1901. v2 := bh2.Singles[bh2.FDig];
  1902. sh := v1 < v2;
  1903. if ( v1 = v2 )
  1904. then begin
  1905. nz := False;
  1906. i3 := Succ ( FDig );
  1907. ie := LDig;
  1908. while ( i3 <= ie ) AND ( NOT nz ) AND ( NOT sh ) do
  1909. begin
  1910. v1 := Singles[i3];
  1911. v2 := bh2.Singles[i3 - p];
  1912. if v1 <> v2
  1913. then begin
  1914. nz := True;
  1915. if v1 < v2
  1916. then sh := True;
  1917. end;
  1918. Inc ( i3 );
  1919. end;
  1920. end;
  1921. if NOT nz
  1922. then Add := 1
  1923. else begin
  1924. if sh
  1925. then begin
  1926. Inc ( p );
  1927. {
  1928. if p > 3 then halt;
  1929. }
  1930. if p > high ( bh.Singles )
  1931. then nz := False
  1932. else Dec ( bh2.FDig );
  1933. end
  1934. else begin
  1935. lFDig := FDig;
  1936. d1 := LDig - FDig;
  1937. d2 := bh2.LDig - bh2.FDig;
  1938. if d1 > d2
  1939. then d := d1
  1940. else d := d2;
  1941. lLdig := lFDig + d;
  1942. if lLdig > high ( bh2.Singles )
  1943. then begin
  1944. tm := ( lLdig ) - high ( bh2.Singles );
  1945. d := d - tm;
  1946. lLdig := lLdig - tm;
  1947. {runden?}
  1948. end;
  1949. sf := True;
  1950. Add := 0;
  1951. nFDig := 0;
  1952. nLDig := 0;
  1953. ue := 0;
  1954. dd := Singles[lFDig] DIV ( bh2.Singles[lFDig - p] + 1 );
  1955. {
  1956. dd := 1;
  1957. }
  1958. if dd < 1
  1959. then dd := 1;
  1960. {
  1961. writeln ( 'p=', p, ' dd=', dd, ' lFdig=', lfdig, ' lldig=', lldig );
  1962. }
  1963. for i2 := lLdig DOWNTO lFDig do
  1964. begin
  1965. v3 := Singles[i2] - bh2.Singles[i2 - p] * dd - ue;
  1966. ue := 0;
  1967. while v3 < 0 do
  1968. begin
  1969. Inc ( ue );;
  1970. v3 := v3 + 10;
  1971. end;
  1972. {
  1973. if v3 <> 0
  1974. then begin
  1975. }
  1976. bh1[NOT FlipFlop].Singles[i2] := v3;
  1977. {
  1978. nFDig := i2;
  1979. if sf
  1980. then begin
  1981. nLDig := i2;
  1982. sf := False;
  1983. end;
  1984. end;
  1985. }
  1986. end;
  1987. sf := False;
  1988. nfdig := lfdig;
  1989. nldig := lldig;
  1990. Inc ( Add, dd );
  1991. if NOT fdset
  1992. then begin
  1993. bh.FDig := p;
  1994. fdset := True;
  1995. end;
  1996. if bh.LDig < p
  1997. then begin
  1998. bh.LDig := p;
  1999. if ( bh.LDig - bh.FDig ) > Succ ( MaxFmtBCDFractionSize )
  2000. then nz := False;
  2001. end;
  2002. if sf
  2003. then nz := False
  2004. else begin
  2005. FillChar ( bh1[FlipFlop], SizeOf ( bh1[FlipFlop] ), #0 );
  2006. FlipFlop := NOT FlipFlop;
  2007. WITH bh1[FlipFlop] do
  2008. begin
  2009. FDig := nFDig;
  2010. LDig := nLDig;
  2011. end;
  2012. end;
  2013. end;
  2014. end;
  2015. if Add <> 0
  2016. then begin
  2017. i4 := p;
  2018. while ( Add <> 0 ) AND ( i4 >= bh.FDig ) do
  2019. begin
  2020. {
  2021. writeln ( '> ', i4, ' ', bh.Singles[i4], ' ', Add );
  2022. }
  2023. v4 := bh.Singles[i4] + Add;
  2024. Add := v4 DIV 10;
  2025. bh.Singles[i4] := v4 MOD 10;
  2026. Dec ( i4 );
  2027. end;
  2028. if Add <> 0
  2029. then begin
  2030. Dec ( bh.FDig );
  2031. bh.Singles[bh.FDig] := Add;
  2032. Add := 0;
  2033. end;
  2034. end;
  2035. end;
  2036. end;
  2037. end;
  2038. WITH bh do
  2039. begin
  2040. if LDig < 0
  2041. then LDig := 0;
  2042. if LDig > 0
  2043. then Plac := LDig
  2044. else Plac := 0;
  2045. end;
  2046. if NOT pack_BCD ( bh, BCDout )
  2047. then begin
  2048. RAISE eBCDOverflowException.create ( 'in BCDDivide' );
  2049. end;
  2050. _endSELECT
  2051. end;
  2052. procedure BCDDivide ( const Dividend,
  2053. Divisor : FmtBCDStringtype;
  2054. var BCDout : tBCD ); Inline;
  2055. begin
  2056. BCDDivide ( StrToBCD ( Dividend ), StrToBCD ( Divisor ), BCDout );
  2057. end;
  2058. {$ifndef FPUNONE}
  2059. procedure BCDDivide ( const Dividend : tBCD;
  2060. const Divisor : myRealtype;
  2061. var BCDout : tBCD ); Inline;
  2062. begin
  2063. BCDDivide ( Dividend, DoubleToBCD ( Divisor ), BCDout );
  2064. end;
  2065. {$endif}
  2066. procedure BCDDivide ( const Dividend : tBCD;
  2067. const Divisor : FmtBCDStringtype;
  2068. var BCDout : tBCD ); Inline;
  2069. begin
  2070. BCDDivide ( Dividend, StrToBCD ( Divisor ), BCDout );
  2071. end;
  2072. { TBCD variant creation utils }
  2073. procedure VarFmtBCDCreate ( var aDest : Variant;
  2074. const aBCD : tBCD );
  2075. begin
  2076. VarClear(aDest);
  2077. TVarData(aDest).Vtype:=FMTBcdFactory.Vartype;
  2078. TVarData(aDest).VPointer:=TFMTBcdVarData.create(aBCD);
  2079. end;
  2080. function VarFmtBCDCreate : Variant;
  2081. begin
  2082. VarFmtBCDCreate ( result, NullBCD );
  2083. end;
  2084. function VarFmtBCDCreate ( const aValue : FmtBCDStringtype;
  2085. Precision,
  2086. Scale : Word ) : Variant;
  2087. begin
  2088. VarFmtBCDCreate ( result, StrToBCD ( aValue ) );
  2089. end;
  2090. {$ifndef FPUNONE}
  2091. function VarFmtBCDCreate ( const aValue : myRealtype;
  2092. Precision : Word = 18;
  2093. Scale : Word = 4 ) : Variant;
  2094. begin
  2095. VarFmtBCDCreate ( result, DoubleToBCD ( aValue ) );
  2096. end;
  2097. {$endif}
  2098. function VarFmtBCDCreate ( const aBCD : tBCD ) : Variant;
  2099. begin
  2100. VarFmtBCDCreate ( result, aBCD );
  2101. end;
  2102. function VarIsFmtBCD ( const aValue : Variant ) : Boolean;
  2103. begin
  2104. Result:=TVarData(aValue).VType=FMTBcdFactory.VarType;
  2105. end;
  2106. function VarFmtBCD : TVartype;
  2107. begin
  2108. Result:=FMTBcdFactory.VarType;
  2109. end;
  2110. { Formatting BCD as string }
  2111. function BCDToStrF ( const BCD : tBCD;
  2112. Format : TFloatFormat;
  2113. const Precision,
  2114. Digits : Integer ) : FmtBCDStringtype;
  2115. begin
  2116. not_implemented;
  2117. result:='';
  2118. end;
  2119. function FormatBCD ( const Format : string;
  2120. BCD : tBCD ) : FmtBCDStringtype;
  2121. begin
  2122. not_implemented;
  2123. result:='';
  2124. end;
  2125. {$ifdef additional_routines}
  2126. function CurrToBCD ( const Curr : currency ) : tBCD; Inline;
  2127. begin
  2128. CurrToBCD ( Curr, result );
  2129. end;
  2130. procedure BCDAdd ( const BCDIn : tBCD;
  2131. const IntIn : myInttype;
  2132. var BCDout : tBCD );
  2133. var
  2134. BCD : tBCD;
  2135. bhr : tBCD_helper;
  2136. p : {$ifopt r+} low ( bhr.FDig ) - 1..0 {$else} Integer {$endif};
  2137. ue : {$ifopt r+} 0..high ( IntIn ) - 9 {$else} Integer {$endif};
  2138. v : {$ifopt r+} 0..{high ( ue ) + 9} high ( IntIn ) {$else} Integer {$endif};
  2139. nz : Boolean;
  2140. begin
  2141. if IntIn = 0
  2142. then begin
  2143. BCDout := BCDIn;
  2144. EXIT;
  2145. end;
  2146. if IntIn = low ( myInttype )
  2147. then begin
  2148. {$if declared ( myMinIntBCD ) }
  2149. BCDAdd ( BCDIn, myMinIntBCD, BCDout );
  2150. EXIT;
  2151. {$else}
  2152. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  2153. {$endif}
  2154. end;
  2155. if IsBCDNegative ( BCDIn )
  2156. then begin
  2157. BCD := BCDIn;
  2158. BCDNegate ( BCD );
  2159. if IntIn < 0
  2160. then BCDAdd ( BCD, -IntIn, BCDout )
  2161. else BCDSubtract ( BCD, IntIn, BCDout );
  2162. BCDNegate ( BCDout );
  2163. EXIT;
  2164. end;
  2165. if IntIn < 0
  2166. then begin
  2167. BCDSubtract ( BCDIn, -IntIn, BCDout );
  2168. EXIT;
  2169. end;
  2170. if IntIn > ( high ( IntIn ) - 9 )
  2171. then begin
  2172. BCDAdd ( BCDIn, IntegerToBCD ( IntIn ), BCDout );
  2173. EXIT;
  2174. end;
  2175. unpack_BCD ( BCDIn, bhr );
  2176. p := 0;
  2177. nz := True;
  2178. ue := IntIn;
  2179. while nz do
  2180. begin
  2181. v := bhr.Singles[p] + ue;
  2182. bhr.Singles[p] := v MOD 10;
  2183. ue := v DIV 10;
  2184. if ue = 0
  2185. then nz := False
  2186. else Dec ( p );
  2187. end;
  2188. if p < bhr.FDig
  2189. then begin
  2190. bhr.FDig := p;
  2191. bhr.Prec := bhr.Prec + ( bhr.FDig - p );
  2192. end;
  2193. if NOT pack_BCD ( bhr, BCDout )
  2194. then begin
  2195. RAISE eBCDOverflowException.create ( 'in BCDAdd' );
  2196. end;
  2197. end;
  2198. procedure BCDSubtract ( const BCDIn : tBCD;
  2199. const IntIn : myInttype;
  2200. var BCDout : tBCD );
  2201. {}
  2202. var
  2203. BCD : tBCD;
  2204. bhr : tBCD_helper;
  2205. p : {$ifopt r+} low ( bhr.FDig ) - 1..0 {$else} Integer {$endif};
  2206. ue : {$ifopt r+} 0..pred ( 100000000 ) {$else} Integer {$endif};
  2207. v : {$ifopt r+} -9..9 {$else} Integer {$endif};
  2208. direct : Boolean;
  2209. {}
  2210. begin
  2211. if IntIn = 0
  2212. then begin
  2213. BCDout := BCDIn;
  2214. EXIT;
  2215. end;
  2216. if IntIn = low ( myInttype )
  2217. then begin
  2218. {$if declared ( myMinIntBCD ) }
  2219. BCDSubtract ( BCDIn, myMinIntBCD, BCDout );
  2220. EXIT;
  2221. {$else}
  2222. RAISE eBCDOverflowException.create ( 'in BCDSubtract' );
  2223. {$endif}
  2224. end;
  2225. if IsBCDNegative ( BCDIn )
  2226. then begin
  2227. BCD := BCDIn;
  2228. BCDNegate ( BCD );
  2229. if IntIn < 0
  2230. then BCDSubtract ( BCD, -IntIn, BCDout )
  2231. else BCDAdd ( BCD, IntIn, BCDout );
  2232. BCDNegate ( BCDout );
  2233. EXIT;
  2234. end;
  2235. if IntIn < 0
  2236. then begin
  2237. BCDAdd ( BCDIn, -IntIn, BCDout );
  2238. EXIT;
  2239. end;
  2240. direct := False;
  2241. case BCDIn.Precision
  2242. -
  2243. {$ifndef bigger_BCD}
  2244. ( BCDIn.SignSpecialPlaces AND PlacesMask )
  2245. {$else}
  2246. BCDIn.Places
  2247. {$endif}
  2248. of
  2249. 2: direct := IntIn < 10;
  2250. 3: direct := IntIn < 100;
  2251. 4: direct := IntIn < 1000;
  2252. 5: direct := IntIn < 10000;
  2253. 6: direct := IntIn < 100000;
  2254. 7: direct := IntIn < 1000000;
  2255. 8: direct := IntIn < 10000000;
  2256. 9: direct := IntIn < 100000000;
  2257. end;
  2258. {
  2259. write(direct);dumpbcd(bcdin);write('[',intin,']');
  2260. }
  2261. if direct
  2262. then begin
  2263. unpack_BCD ( BCDIn, bhr );
  2264. WITH bhr do
  2265. begin
  2266. p := 0;
  2267. ue := IntIn;
  2268. while p >= FDig do
  2269. begin
  2270. v := Singles[p] - ue MOD 10;
  2271. ue := ue DIV 10;
  2272. if v < 0
  2273. then begin
  2274. v := v + 10;
  2275. ue := ue + 1;
  2276. end;
  2277. Singles[p] := v;
  2278. Dec ( p );
  2279. end;
  2280. end;
  2281. if NOT pack_BCD ( bhr, BCDout )
  2282. then begin
  2283. RAISE eBCDOverflowException.create ( 'in BCDSubtract' );
  2284. end;
  2285. end
  2286. else
  2287. {}
  2288. BCDSubtract ( BCDIn, IntegerToBCD ( IntIn ), BCDout );
  2289. end;
  2290. procedure BCDAdd ( const IntIn : myInttype;
  2291. const BCDIn : tBCD;
  2292. var BCDout : tBCD ); Inline;
  2293. begin
  2294. BCDAdd ( BCDIn, IntIn, BCDout );
  2295. end;
  2296. {$ifndef FPUNONE}
  2297. procedure BCDAdd ( const BCDIn : tBCD;
  2298. const DoubleIn : myRealtype;
  2299. var BCDout : tBCD ); Inline;
  2300. begin
  2301. BCDAdd ( BCDIn, DoubleToBCD ( DoubleIn ), BCDout );
  2302. end;
  2303. procedure BCDAdd ( const DoubleIn : myRealtype;
  2304. const BCDIn : tBCD;
  2305. var BCDout : tBCD ); Inline;
  2306. begin
  2307. BCDAdd ( DoubleToBCD ( DoubleIn ), BCDIn, BCDout );
  2308. end;
  2309. {$endif}
  2310. procedure BCDAdd ( const BCDIn : tBCD;
  2311. const Currin : currency;
  2312. var BCDout : tBCD ); Inline;
  2313. begin
  2314. BCDAdd ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2315. end;
  2316. procedure BCDAdd ( const Currin : currency;
  2317. const BCDIn : tBCD;
  2318. var BCDout : tBCD ); Inline;
  2319. begin
  2320. BCDAdd ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2321. end;
  2322. {$ifdef comproutines}
  2323. procedure BCDAdd ( const BCDIn : tBCD;
  2324. const Compin : Comp;
  2325. var BCDout : tBCD ); Inline;
  2326. begin
  2327. BCDAdd ( BCDIn, CompToBCD ( Compin ), BCDout );
  2328. end;
  2329. procedure BCDAdd ( const Compin : Comp;
  2330. const BCDIn : tBCD;
  2331. var BCDout : tBCD ); Inline;
  2332. begin
  2333. BCDAdd ( CompToBCD ( Compin ), BCDIn, BCDout );
  2334. end;
  2335. {$endif}
  2336. procedure BCDAdd ( const BCDIn : tBCD;
  2337. const StringIn : FmtBCDStringtype;
  2338. var BCDout : tBCD ); Inline;
  2339. begin
  2340. BCDAdd ( BCDIn, StrToBCD ( StringIn ), BCDout );
  2341. end;
  2342. procedure BCDAdd ( const StringIn : FmtBCDStringtype;
  2343. const BCDIn : tBCD;
  2344. var BCDout : tBCD ); Inline;
  2345. begin
  2346. BCDAdd ( StrToBCD ( StringIn ), BCDIn, BCDout );
  2347. end;
  2348. procedure BCDAdd ( const StringIn1,
  2349. StringIn2 : FmtBCDStringtype;
  2350. var BCDout : tBCD ); Inline;
  2351. begin
  2352. BCDAdd ( StrToBCD ( StringIn1 ), StrToBCD ( StringIn2 ), BCDout );
  2353. end;
  2354. procedure BCDSubtract ( const IntIn : myInttype;
  2355. const BCDIn : tBCD;
  2356. var BCDout : tBCD ); Inline;
  2357. begin
  2358. BCDSubtract ( BCDIn, IntIn, BCDout );
  2359. BCDNegate ( BCDout );
  2360. end;
  2361. {$ifndef FPUNONE}
  2362. procedure BCDSubtract ( const BCDIn : tBCD;
  2363. const DoubleIn : myRealtype;
  2364. var BCDout : tBCD ); Inline;
  2365. begin
  2366. BCDSubtract ( BCDIn, DoubleToBCD ( DoubleIn ), BCDout );
  2367. end;
  2368. procedure BCDSubtract ( const DoubleIn : myRealtype;
  2369. const BCDIn : tBCD;
  2370. var BCDout : tBCD ); Inline;
  2371. begin
  2372. BCDSubtract ( DoubleToBCD ( DoubleIn ), BCDIn, BCDout );
  2373. end;
  2374. {$endif}
  2375. procedure BCDSubtract ( const BCDIn : tBCD;
  2376. const Currin : currency;
  2377. var BCDout : tBCD ); Inline;
  2378. begin
  2379. BCDSubtract ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2380. end;
  2381. procedure BCDSubtract ( const Currin : currency;
  2382. const BCDIn : tBCD;
  2383. var BCDout : tBCD ); Inline;
  2384. begin
  2385. BCDSubtract ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2386. end;
  2387. {$ifdef comproutines}
  2388. procedure BCDSubtract ( const BCDIn : tBCD;
  2389. const Compin : Comp;
  2390. var BCDout : tBCD ); Inline;
  2391. begin
  2392. BCDSubtract ( BCDIn, CompToBCD ( Compin ), BCDout );
  2393. end;
  2394. procedure BCDSubtract ( const Compin : Comp;
  2395. const BCDIn : tBCD;
  2396. var BCDout : tBCD ); Inline;
  2397. begin
  2398. BCDSubtract ( CompToBCD ( Compin ), BCDIn, BCDout );
  2399. end;
  2400. {$endif}
  2401. procedure BCDSubtract ( const BCDIn : tBCD;
  2402. const StringIn : FmtBCDStringtype;
  2403. var BCDout : tBCD ); Inline;
  2404. begin
  2405. BCDSubtract ( BCDIn, StrToBCD ( StringIn ), BCDout );
  2406. end;
  2407. procedure BCDSubtract ( const StringIn : FmtBCDStringtype;
  2408. const BCDIn : tBCD;
  2409. var BCDout : tBCD ); Inline;
  2410. begin
  2411. BCDSubtract ( StrToBCD ( StringIn ), BCDIn, BCDout );
  2412. end;
  2413. procedure BCDSubtract ( const StringIn1,
  2414. StringIn2 : FmtBCDStringtype;
  2415. var BCDout : tBCD ); Inline;
  2416. begin
  2417. BCDSubtract ( StrToBCD ( StringIn1 ), StrToBCD ( StringIn2 ), BCDout );
  2418. end;
  2419. procedure BCDMultiply ( const BCDIn : tBCD;
  2420. const IntIn : myInttype;
  2421. var BCDout : tBCD );
  2422. var
  2423. bh : tBCD_helper;
  2424. bhr : tBCD_helper;
  2425. bhrr : tBCD_helper_big;
  2426. int : {$ifopt r+} 0..high ( bhrr.Singles[0] ) DIV 10 {$else} Integer {$endif};
  2427. i1 : {$ifopt r+} low ( bh.Singles )..high ( bh.Singles ) {$else} Integer {$endif};
  2428. i3 : {$ifopt r+} low ( bhr.Singles )..high ( bhr.Singles ) {$else} Integer {$endif};
  2429. 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};
  2430. ue : {$ifopt r+} 1 * ( low ( bhrr.Singles[0] ) + low ( bhrr.Singles[0] ) DIV 10 ) DIV 10
  2431. ..( high ( bhrr.Singles[0] ) + high ( bhrr.Singles[0] ) DIV 10 ) DIV 10 {$else} Integer {$endif};
  2432. begin
  2433. if IntIn = 0
  2434. then begin
  2435. BCDout := NullBCD;
  2436. EXIT;
  2437. end;
  2438. if IntIn = 1
  2439. then begin
  2440. BCDout := BCDIn;
  2441. EXIT;
  2442. end;
  2443. if IntIn = -1
  2444. then begin
  2445. BCDout := BCDIn;
  2446. BCDNegate ( BCDout );
  2447. EXIT;
  2448. end;
  2449. if IntIn = low ( myInttype )
  2450. then begin
  2451. {$if declared ( myMinIntBCD ) }
  2452. BCDMultiply ( BCDIn, myMinIntBCD, BCDout );
  2453. EXIT;
  2454. {$else}
  2455. RAISE eBCDOverflowException.create ( 'in BCDmultiply' );
  2456. {$endif}
  2457. end;
  2458. if Abs ( IntIn ) > low ( bhrr.Singles[0] ) DIV 10
  2459. then begin
  2460. BCDMultiply ( BCDIn, IntegerToBCD ( IntIn ), BCDout );
  2461. EXIT;
  2462. end;
  2463. unpack_BCD ( BCDIn, bh );
  2464. if bh.Prec = 0
  2465. then begin
  2466. BCDout := NullBCD;
  2467. EXIT;
  2468. end;
  2469. bhr := null_.bh;
  2470. bhrr := null_.bhb;
  2471. int := Abs ( IntIn );
  2472. WITH bhrr do
  2473. begin
  2474. Neg := bh.Neg XOR ( IntIn < 0 );
  2475. FDig := bh.FDig;
  2476. LDig := bh.LDig;
  2477. for i1 := bh.FDig TO bh.LDig do
  2478. Singles[i1] := bh.Singles[i1] * int;
  2479. {
  2480. for i3 := fdig to ldig do
  2481. write ( ' ', singles[i3] );
  2482. writeln;
  2483. }
  2484. ue := 0;
  2485. for i3 := LDig DOWNTO FDig do
  2486. begin
  2487. v := Singles[i3] + ue;
  2488. ue := v DIV 10;
  2489. v := v MOD 10;
  2490. bhr.Singles[i3] := v;
  2491. end;
  2492. while ue <> 0 do
  2493. begin
  2494. Dec ( FDig );
  2495. if FDig < low ( bhr.Singles )
  2496. then RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  2497. bhr.Singles[FDig] := ue MOD 10;
  2498. ue := ue DIV 10;
  2499. end;
  2500. bhr.Plac := LDig;
  2501. bhr.FDig := FDig;
  2502. if LDig > high ( bhr.Singles )
  2503. then bhr.LDig := high ( bhr.Singles )
  2504. else bhr.LDig := LDig;
  2505. end;
  2506. if NOT pack_BCD ( bhr, BCDout )
  2507. then begin
  2508. RAISE eBCDOverflowException.create ( 'in BCDMultiply' );
  2509. end;
  2510. end;
  2511. procedure BCDMultiply ( const IntIn : myInttype;
  2512. const BCDIn : tBCD;
  2513. var BCDout : tBCD ); Inline;
  2514. begin
  2515. BCDMultiply ( BCDIn, IntIn, BCDout );
  2516. end;
  2517. {$ifndef FPUNONE}
  2518. procedure BCDMultiply ( const DoubleIn : myRealtype;
  2519. const BCDIn : tBCD;
  2520. var BCDout : tBCD ); Inline;
  2521. begin
  2522. BCDMultiply ( DoubleToBCD ( DoubleIn ), BCDIn, BCDout );
  2523. end;
  2524. {$endif}
  2525. procedure BCDMultiply ( const BCDIn : tBCD;
  2526. const Currin : currency;
  2527. var BCDout : tBCD ); Inline;
  2528. begin
  2529. BCDMultiply ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2530. end;
  2531. procedure BCDMultiply ( const Currin : currency;
  2532. const BCDIn : tBCD;
  2533. var BCDout : tBCD ); Inline;
  2534. begin
  2535. BCDMultiply ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2536. end;
  2537. {$ifdef comproutines}
  2538. procedure BCDMultiply ( const BCDIn : tBCD;
  2539. const Compin : Comp;
  2540. var BCDout : tBCD ); Inline;
  2541. begin
  2542. BCDMultiply ( BCDIn, CompToBCD ( Compin ), BCDout );
  2543. end;
  2544. procedure BCDMultiply ( const Compin : Comp;
  2545. const BCDIn : tBCD;
  2546. var BCDout : tBCD ); Inline;
  2547. begin
  2548. BCDMultiply ( CompToBCD ( Compin ), BCDIn, BCDout );
  2549. end;
  2550. {$endif}
  2551. procedure BCDMultiply ( const StringIn : FmtBCDStringtype;
  2552. const BCDIn : tBCD;
  2553. var BCDout : tBCD ); Inline;
  2554. begin
  2555. BCDMultiply ( StrToBCD ( StringIn ), BCDIn, BCDout );
  2556. end;
  2557. procedure BCDDivide ( const Dividend : tBCD;
  2558. const Divisor : myInttype;
  2559. var BCDout : tBCD ); Inline;
  2560. begin
  2561. BCDDivide ( Dividend, IntegerToBCD ( Divisor ), BCDout );
  2562. end;
  2563. procedure BCDDivide ( const Dividend : myInttype;
  2564. const Divisor : tBCD;
  2565. var BCDout : tBCD ); Inline;
  2566. begin
  2567. BCDDivide ( IntegerToBCD ( Dividend ), Divisor, BCDout );
  2568. end;
  2569. {$ifndef FPUNONE}
  2570. procedure BCDDivide ( const Dividend : myRealtype;
  2571. const Divisor : tBCD;
  2572. var BCDout : tBCD ); Inline;
  2573. begin
  2574. BCDDivide ( DoubleToBCD ( Dividend ), Divisor, BCDout );
  2575. end;
  2576. {$endif}
  2577. procedure BCDDivide ( const BCDIn : tBCD;
  2578. const Currin : currency;
  2579. var BCDout : tBCD ); Inline;
  2580. begin
  2581. BCDDivide ( BCDIn, CurrToBCD ( Currin ), BCDout );
  2582. end;
  2583. procedure BCDDivide ( const Currin : currency;
  2584. const BCDIn : tBCD;
  2585. var BCDout : tBCD ); Inline;
  2586. begin
  2587. BCDDivide ( CurrToBCD ( Currin ), BCDIn, BCDout );
  2588. end;
  2589. {$ifdef comproutines}
  2590. procedure BCDDivide ( const BCDIn : tBCD;
  2591. const Compin : Comp;
  2592. var BCDout : tBCD ); Inline;
  2593. begin
  2594. BCDDivide ( BCDIn, CompToBCD ( Compin ), BCDout );
  2595. end;
  2596. procedure BCDDivide ( const Compin : Comp;
  2597. const BCDIn : tBCD;
  2598. var BCDout : tBCD ); Inline;
  2599. begin
  2600. BCDDivide ( CompToBCD ( Compin ), BCDIn, BCDout );
  2601. end;
  2602. {$endif}
  2603. procedure BCDDivide ( const Dividend : FmtBCDStringtype;
  2604. const Divisor : tBCD;
  2605. var BCDout : tBCD ); Inline;
  2606. begin
  2607. BCDDivide ( StrToBCD ( Dividend ), Divisor, BCDout );
  2608. end;
  2609. operator = ( const BCD1,
  2610. BCD2 : tBCD ) z : Boolean; Inline;
  2611. begin
  2612. z := BCDCompare ( BCD1, BCD2 ) = 0;
  2613. end;
  2614. operator < ( const BCD1,
  2615. BCD2 : tBCD ) z : Boolean; Inline;
  2616. begin
  2617. z := BCDCompare ( BCD1, BCD2 ) < 0;
  2618. end;
  2619. operator > ( const BCD1,
  2620. BCD2 : tBCD ) z : Boolean; Inline;
  2621. begin
  2622. z := BCDCompare ( BCD1, BCD2 ) > 0;
  2623. end;
  2624. operator <= ( const BCD1,
  2625. BCD2 : tBCD ) z : Boolean; Inline;
  2626. begin
  2627. z := BCDCompare ( BCD1, BCD2 ) <= 0;
  2628. end;
  2629. operator >= ( const BCD1,
  2630. BCD2 : tBCD ) z : Boolean; Inline;
  2631. begin
  2632. z := BCDCompare ( BCD1, BCD2 ) >= 0;
  2633. end;
  2634. (* ######################## not allowed: why?
  2635. operator + ( const BCD : tBCD ) z : tBCD; Inline;
  2636. begin
  2637. z := bcd;
  2638. end;
  2639. ##################################################### *)
  2640. operator - ( const BCD : tBCD ) z : tBCD; Inline;
  2641. begin
  2642. z := BCD;
  2643. BCDNegate ( z );
  2644. end;
  2645. operator + ( const BCD1,
  2646. BCD2 : tBCD ) z : tBCD; Inline;
  2647. begin
  2648. BCDAdd ( BCD1, BCD2, z );
  2649. end;
  2650. operator + ( const BCD : tBCD;
  2651. const i : myInttype ) z : tBCD; Inline;
  2652. begin
  2653. BCDAdd ( BCD, i, z );
  2654. end;
  2655. operator + ( const i : myInttype;
  2656. const BCD : tBCD ) z : tBCD; Inline;
  2657. begin
  2658. BCDAdd ( i, BCD, z );
  2659. end;
  2660. {$ifndef FPUNONE}
  2661. operator + ( const BCD : tBCD;
  2662. const r : myRealtype ) z : tBCD; Inline;
  2663. begin
  2664. BCDAdd ( BCD, DoubleToBCD ( r ), z );
  2665. end;
  2666. operator + ( const r : myRealtype;
  2667. const BCD : tBCD ) z : tBCD; Inline;
  2668. begin
  2669. BCDAdd ( DoubleToBCD ( r ), BCD, z );
  2670. end;
  2671. {$endif}
  2672. operator + ( const BCD : tBCD;
  2673. const c : currency ) z : tBCD; Inline;
  2674. begin
  2675. BCDAdd ( BCD, CurrToBCD ( c ), z );
  2676. end;
  2677. operator + ( const c : currency;
  2678. const BCD : tBCD ) z : tBCD; Inline;
  2679. begin
  2680. BCDAdd ( CurrToBCD ( c ), BCD, z );
  2681. end;
  2682. {$ifdef comproutines}
  2683. operator + ( const BCD : tBCD;
  2684. const c : Comp ) z : tBCD; Inline;
  2685. begin
  2686. BCDAdd ( BCD, CompToBCD ( c ), z );
  2687. end;
  2688. operator + ( const c : Comp;
  2689. const BCD : tBCD ) z : tBCD; Inline;
  2690. begin
  2691. BCDAdd ( CompToBCD ( c ), BCD, z );
  2692. end;
  2693. {$endif}
  2694. operator + ( const BCD : tBCD;
  2695. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2696. begin
  2697. BCDAdd ( BCD, StrToBCD ( s ), z );
  2698. end;
  2699. operator + ( const s : FmtBCDStringtype;
  2700. const BCD : tBCD ) z : tBCD; Inline;
  2701. begin
  2702. BCDAdd ( StrToBCD ( s ), BCD, z );
  2703. end;
  2704. operator - ( const BCD1,
  2705. BCD2 : tBCD ) z : tBCD; Inline;
  2706. begin
  2707. BCDSubtract ( BCD1, BCD2, z );
  2708. end;
  2709. operator - ( const BCD : tBCD;
  2710. const i : myInttype ) z : tBCD; Inline;
  2711. begin
  2712. BCDSubtract ( BCD, i, z );
  2713. end;
  2714. operator - ( const i : myInttype;
  2715. const BCD : tBCD ) z : tBCD; Inline;
  2716. begin
  2717. BCDSubtract ( BCD, i, z );
  2718. BCDNegate ( z );
  2719. end;
  2720. {$ifndef FPUNONE}
  2721. operator - ( const BCD : tBCD;
  2722. const r : myRealtype ) z : tBCD; Inline;
  2723. begin
  2724. BCDSubtract ( BCD, DoubleToBCD ( r ), z );
  2725. end;
  2726. operator - ( const r : myRealtype;
  2727. const BCD : tBCD ) z : tBCD; Inline;
  2728. begin
  2729. BCDSubtract ( DoubleToBCD ( r ), BCD, z );
  2730. end;
  2731. {$endif}
  2732. operator - ( const BCD : tBCD;
  2733. const c : currency ) z : tBCD; Inline;
  2734. begin
  2735. BCDSubtract ( BCD, CurrToBCD ( c ), z );
  2736. end;
  2737. operator - ( const c : currency;
  2738. const BCD : tBCD ) z : tBCD; Inline;
  2739. begin
  2740. BCDSubtract ( CurrToBCD ( c ), BCD, z );
  2741. end;
  2742. {$ifdef comproutines}
  2743. operator - ( const BCD : tBCD;
  2744. const c : Comp ) z : tBCD; Inline;
  2745. begin
  2746. BCDSubtract ( BCD, CompToBCD ( c ), z );
  2747. end;
  2748. operator - ( const c : Comp;
  2749. const BCD : tBCD ) z : tBCD; Inline;
  2750. begin
  2751. BCDSubtract ( CompToBCD ( c ), BCD, z );
  2752. end;
  2753. {$endif}
  2754. operator - ( const BCD : tBCD;
  2755. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2756. begin
  2757. BCDSubtract ( BCD, StrToBCD ( s ), z );
  2758. end;
  2759. operator - ( const s : FmtBCDStringtype;
  2760. const BCD : tBCD ) z : tBCD; Inline;
  2761. begin
  2762. BCDSubtract ( StrToBCD ( s ), BCD, z );
  2763. end;
  2764. operator * ( const BCD1,
  2765. BCD2 : tBCD ) z : tBCD; Inline;
  2766. begin
  2767. BCDMultiply ( BCD1, BCD2, z );
  2768. end;
  2769. operator * ( const BCD : tBCD;
  2770. const i : myInttype ) z : tBCD; Inline;
  2771. begin
  2772. BCDMultiply ( BCD, i, z );
  2773. end;
  2774. operator * ( const i : myInttype;
  2775. const BCD : tBCD ) z : tBCD; Inline;
  2776. begin
  2777. BCDMultiply ( BCD, i, z );
  2778. end;
  2779. {$ifndef FPUNONE}
  2780. operator * ( const BCD : tBCD;
  2781. const r : myRealtype ) z : tBCD; Inline;
  2782. begin
  2783. BCDMultiply ( BCD, DoubleToBCD ( r ), z );
  2784. end;
  2785. operator * ( const r : myRealtype;
  2786. const BCD : tBCD ) z : tBCD; Inline;
  2787. begin
  2788. BCDMultiply ( DoubleToBCD ( r ), BCD, z );
  2789. end;
  2790. {$endif}
  2791. operator * ( const BCD : tBCD;
  2792. const c : currency ) z : tBCD; Inline;
  2793. begin
  2794. BCDMultiply ( BCD, CurrToBCD ( c ), z );
  2795. end;
  2796. operator * ( const c : currency;
  2797. const BCD : tBCD ) z : tBCD; Inline;
  2798. begin
  2799. BCDMultiply ( CurrToBCD ( c ), BCD, z );
  2800. end;
  2801. {$ifdef comproutines}
  2802. operator * ( const BCD : tBCD;
  2803. const c : Comp ) z : tBCD; Inline;
  2804. begin
  2805. BCDMultiply ( BCD, CompToBCD ( c ), z );
  2806. end;
  2807. operator * ( const c : Comp;
  2808. const BCD : tBCD ) z : tBCD; Inline;
  2809. begin
  2810. BCDMultiply ( CompToBCD ( c ), BCD, z );
  2811. end;
  2812. {$endif}
  2813. operator * ( const BCD : tBCD;
  2814. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2815. begin
  2816. BCDMultiply ( BCD, StrToBCD ( s ), z );
  2817. end;
  2818. operator * ( const s : FmtBCDStringtype;
  2819. const BCD : tBCD ) z : tBCD; Inline;
  2820. begin
  2821. BCDMultiply ( StrToBCD ( s ), BCD, z );
  2822. end;
  2823. operator / ( const BCD1,
  2824. BCD2 : tBCD ) z : tBCD; Inline;
  2825. begin
  2826. BCDDivide ( BCD1, BCD2, z );
  2827. end;
  2828. operator / ( const BCD : tBCD;
  2829. const i : myInttype ) z : tBCD; Inline;
  2830. begin
  2831. BCDDivide ( BCD, i, z );
  2832. end;
  2833. operator / ( const i : myInttype;
  2834. const BCD : tBCD ) z : tBCD; Inline;
  2835. begin
  2836. BCDDivide ( IntegerToBCD ( i ), BCD, z );
  2837. end;
  2838. {$ifndef FPUNONE}
  2839. operator / ( const BCD : tBCD;
  2840. const r : myRealtype ) z : tBCD; Inline;
  2841. begin
  2842. BCDDivide ( BCD, DoubleToBCD ( r ), z );
  2843. end;
  2844. operator / ( const r : myRealtype;
  2845. const BCD : tBCD ) z : tBCD; Inline;
  2846. begin
  2847. BCDDivide ( DoubleToBCD ( r ), BCD, z );
  2848. end;
  2849. {$endif}
  2850. operator / ( const BCD : tBCD;
  2851. const c : currency ) z : tBCD; Inline;
  2852. begin
  2853. BCDDivide ( BCD, CurrToBCD ( c ), z );
  2854. end;
  2855. operator / ( const c : currency;
  2856. const BCD : tBCD ) z : tBCD; Inline;
  2857. begin
  2858. BCDDivide ( CurrToBCD ( c ), BCD, z );
  2859. end;
  2860. {$ifdef comproutines}
  2861. operator / ( const BCD : tBCD;
  2862. const c : Comp ) z : tBCD; Inline;
  2863. begin
  2864. BCDDivide ( BCD, CompToBCD ( c ), z );
  2865. end;
  2866. operator / ( const c : Comp;
  2867. const BCD : tBCD ) z : tBCD; Inline;
  2868. begin
  2869. BCDDivide ( CompToBCD ( c ), BCD, z );
  2870. end;
  2871. {$endif}
  2872. operator / ( const BCD : tBCD;
  2873. const s : FmtBCDStringtype ) z : tBCD; Inline;
  2874. begin
  2875. BCDDivide ( BCD, StrToBCD ( s ), z );
  2876. end;
  2877. operator / ( const s : FmtBCDStringtype;
  2878. const BCD : tBCD ) z : tBCD; Inline;
  2879. begin
  2880. BCDDivide ( StrToBCD ( s ), BCD, z );
  2881. end;
  2882. operator := ( const i : Byte ) z : tBCD; Inline;
  2883. begin
  2884. z := IntegerToBCD ( myInttype ( i ) );
  2885. end;
  2886. operator := ( const BCD : tBCD ) z : Byte; Inline;
  2887. begin
  2888. z := BCDToInteger ( BCD );
  2889. end;
  2890. operator := ( const i : Word ) z : tBCD; Inline;
  2891. begin
  2892. z := IntegerToBCD ( myInttype ( i ) );
  2893. end;
  2894. operator := ( const BCD : tBCD ) z : Word; Inline;
  2895. begin
  2896. z := BCDToInteger ( BCD );
  2897. end;
  2898. operator := ( const i : longword ) z : tBCD; Inline;
  2899. begin
  2900. z := IntegerToBCD ( myInttype ( i ) );
  2901. end;
  2902. operator := ( const BCD : tBCD ) z : longword; Inline;
  2903. begin
  2904. z := BCDToInteger ( BCD );
  2905. end;
  2906. {$if declared ( qword ) }
  2907. operator := ( const i : qword ) z : tBCD; Inline;
  2908. begin
  2909. z := IntegerToBCD ( myInttype ( i ) );
  2910. end;
  2911. operator := ( const BCD : tBCD ) z : qword; Inline;
  2912. begin
  2913. z := BCDToInteger ( BCD );
  2914. end;
  2915. {$endif}
  2916. operator := ( const i : ShortInt ) z : tBCD; Inline;
  2917. begin
  2918. z := IntegerToBCD ( myInttype ( i ) );
  2919. end;
  2920. operator := ( const BCD : tBCD ) z : ShortInt; Inline;
  2921. begin
  2922. z := BCDToInteger ( BCD );
  2923. end;
  2924. operator := ( const i : smallint ) z : tBCD; Inline;
  2925. begin
  2926. z := IntegerToBCD ( myInttype ( i ) );
  2927. end;
  2928. operator := ( const BCD : tBCD ) z : smallint; Inline;
  2929. begin
  2930. z := BCDToInteger ( BCD );
  2931. end;
  2932. operator := ( const i : LongInt ) z : tBCD; Inline;
  2933. begin
  2934. z := IntegerToBCD ( myInttype ( i ) );
  2935. end;
  2936. operator := ( const BCD : tBCD ) z : LongInt; Inline;
  2937. begin
  2938. z := BCDToInteger ( BCD );
  2939. end;
  2940. {$if declared ( int64 ) }
  2941. operator := ( const i : int64 ) z : tBCD; Inline;
  2942. begin
  2943. z := IntegerToBCD ( myInttype ( i ) );
  2944. end;
  2945. operator := ( const BCD : tBCD ) z : int64; Inline;
  2946. begin
  2947. z := BCDToInteger ( BCD );
  2948. end;
  2949. {$endif}
  2950. {$ifndef FPUNONE}
  2951. operator := ( const r : Single ) z : tBCD; Inline;
  2952. begin
  2953. z := DoubleToBCD ( myRealtype ( r ) );
  2954. end;
  2955. operator := ( const BCD : tBCD ) z : Single; Inline;
  2956. begin
  2957. z := BCDToDouble ( BCD );
  2958. end;
  2959. operator := ( const r : Double ) z : tBCD; Inline;
  2960. begin
  2961. z := DoubleToBCD ( myRealtype ( r ) );
  2962. end;
  2963. operator := ( const BCD : tBCD ) z : Double; Inline;
  2964. begin
  2965. z := BCDToDouble ( BCD );
  2966. end;
  2967. {$if sizeof ( extended ) <> sizeof ( double )}
  2968. operator := ( const r : Extended ) z : tBCD; Inline;
  2969. begin
  2970. z := DoubleToBCD ( {myRealtype (} r {)} );
  2971. end;
  2972. operator := ( const BCD : tBCD ) z : Extended; Inline;
  2973. begin
  2974. z := BCDToDouble ( BCD );
  2975. end;
  2976. {$endif}
  2977. {$endif}
  2978. operator := ( const c : currency ) z : tBCD; Inline;
  2979. begin
  2980. CurrToBCD ( c, z );
  2981. end;
  2982. operator := ( const BCD : tBCD ) z : currency; Inline;
  2983. begin
  2984. BCDToCurr ( BCD, z );
  2985. end;
  2986. {$ifdef comproutines}
  2987. {$undef makedirect}
  2988. {$ifdef makedirect}
  2989. operator := ( const c : Comp ) z : tBCD; Inline;
  2990. var
  2991. cc : int64 absolute c;
  2992. begin
  2993. z := IntegerToBCD ( cc );
  2994. end;
  2995. { $define version1} { only one of these may be defined! }
  2996. { $define version2} { version 1 produces a compiler error (with INLINE only!)}
  2997. {$define version3} { I wasn't able to reduce the problem, sorry }
  2998. {$ifdef version1}
  2999. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3000. var
  3001. zz : Comp absolute z;
  3002. begin
  3003. zz := BCDToInteger ( BCD );
  3004. end;
  3005. {$endif}
  3006. {$ifdef version2}
  3007. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3008. var
  3009. zz : int64;
  3010. zzz : Comp absolute zz;
  3011. begin
  3012. zz := BCDToInteger ( BCD );
  3013. z := zzz;
  3014. end;
  3015. {$endif}
  3016. {$ifdef version3}
  3017. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3018. var
  3019. zz : record
  3020. case Boolean of
  3021. False: ( i : int64 );
  3022. True: ( c : Comp );
  3023. end;
  3024. begin
  3025. zz.i := BCDToInteger ( BCD );
  3026. z := zz.c;
  3027. end;
  3028. {$endif}
  3029. {$else}
  3030. operator := ( const c : Comp ) z : tBCD; Inline;
  3031. begin
  3032. z := CompToBCD ( c );
  3033. end;
  3034. operator := ( const BCD : tBCD ) z : Comp; Inline;
  3035. begin
  3036. z := BCDToComp ( BCD );
  3037. end;
  3038. {$endif}
  3039. {$endif}
  3040. operator := ( const s : string ) z : tBCD; Inline;
  3041. begin
  3042. z := StrToBCD ( s );
  3043. end;
  3044. operator := ( const BCD : tBCD ) z : string; Inline;
  3045. begin
  3046. z := BCDToStr ( BCD );
  3047. end;
  3048. operator := ( const s : AnsiString ) z : tBCD; Inline;
  3049. begin
  3050. z := StrToBCD ( s );
  3051. end;
  3052. operator := ( const BCD : tBCD ) z : AnsiString; Inline;
  3053. begin
  3054. z := BCDToStr ( BCD );
  3055. end;
  3056. {$endif}
  3057. Function VariantToBCD(const VargSrc : TVarData) : TBCD;
  3058. begin
  3059. with VargSrc do
  3060. case vType and not varTypeMask of
  3061. 0: case vType of
  3062. varEmpty : Result := 0;
  3063. varSmallInt : Result := vSmallInt;
  3064. varShortInt : Result := vShortInt;
  3065. varInteger : Result := vInteger;
  3066. varSingle : Result := vSingle;
  3067. varDouble : Result := vDouble;
  3068. varCurrency : Result := vCurrency;
  3069. varDate : Result := vDate;
  3070. varBoolean : Result := Integer(vBoolean);
  3071. varVariant : Result := VariantToBCD(PVarData(vPointer)^);
  3072. varByte : Result := vByte;
  3073. varWord : Result := vWord;
  3074. varLongWord : Result := vLongWord;
  3075. varInt64 : Result := vInt64;
  3076. varQword : Result := vQWord;
  3077. varString : Result := AnsiString(vString);
  3078. else
  3079. if vType=VarFmtBCD then
  3080. Result := TFMTBcdVarData(vPointer).BCD
  3081. else
  3082. not_implemented;
  3083. end;
  3084. varByRef: if Assigned(vPointer) then case vType and varTypeMask of
  3085. varSmallInt : Result := PSmallInt(vPointer)^;
  3086. varShortInt : Result := PShortInt(vPointer)^;
  3087. varInteger : Result := PInteger(vPointer)^;
  3088. varSingle : Result := PSingle(vPointer)^;
  3089. varDouble : Result := PDouble(vPointer)^;
  3090. varCurrency : Result := PCurrency(vPointer)^;
  3091. varDate : Result := PDate(vPointer)^;
  3092. varBoolean : Result := SmallInt(PWordBool(vPointer)^);
  3093. varVariant : Result := VariantToBCD(PVarData(vPointer)^);
  3094. varByte : Result := PByte(vPointer)^;
  3095. varWord : Result := PWord(vPointer)^;
  3096. varLongWord : Result := PLongWord(vPointer)^;
  3097. varInt64 : Result := PInt64(vPointer)^;
  3098. varQword : Result := PQWord(vPointer)^;
  3099. else { other vtype }
  3100. not_implemented;
  3101. end else { pointer is nil }
  3102. not_implemented;
  3103. else { array or something like that }
  3104. not_implemented;
  3105. end;
  3106. end;
  3107. function VarToBCD ( const aValue : Variant ) : tBCD;
  3108. begin
  3109. Result:=VariantToBCD(TVarData(aValue));
  3110. end;
  3111. constructor TFMTBcdVarData.create;
  3112. begin
  3113. inherited create;
  3114. FBcd:=NullBCD;
  3115. end;
  3116. constructor TFMTBcdVarData.create(const BCD : tBCD);
  3117. begin
  3118. inherited create;
  3119. FBcd:=BCD;
  3120. end;
  3121. function TFMTBcdFactory.GetInstance(const v : TVarData): tObject;
  3122. begin
  3123. result:=tObject(v.VPointer);
  3124. end;
  3125. procedure TFMTBcdFactory.BinaryOp(var Left: TVarData; const Right: TVarData; const Operation: TVarOp);
  3126. var l, r: TBCD;
  3127. begin
  3128. l:=VariantToBCD(Left);
  3129. r:=VariantToBCD(Right);
  3130. case Operation of
  3131. opAdd:
  3132. l:=l+r;
  3133. opSubtract:
  3134. l:=l-r;
  3135. opMultiply:
  3136. l:=l*r;
  3137. opDivide:
  3138. l:=l/r;
  3139. else
  3140. RaiseInvalidOp;
  3141. end;
  3142. if Left.vType=VarType then
  3143. TFMTBcdVarData(Left.VPointer).BCD := l
  3144. else
  3145. RaiseInvalidOp;
  3146. end;
  3147. procedure TFMTBcdFactory.Compare(const Left, Right: TVarData; var Relationship: TVarCompareResult);
  3148. var l, r: TBCD;
  3149. CmpRes: integer;
  3150. begin
  3151. l:=VariantToBCD(Left);
  3152. r:=VariantToBCD(Right);
  3153. CmpRes := BCDCompare(l,r);
  3154. if CmpRes=0 then
  3155. Relationship := crEqual
  3156. else if CmpRes<0 then
  3157. Relationship := crLessThan
  3158. else
  3159. Relationship := crGreaterThan;
  3160. end;
  3161. function TFMTBcdFactory.CompareOp(const Left, Right: TVarData; const Operation: TVarOp): Boolean;
  3162. var l, r: TBCD;
  3163. begin
  3164. l:=VariantToBCD(Left);
  3165. r:=VariantToBCD(Right);
  3166. case Operation of
  3167. opCmpEq:
  3168. Result := l=r;
  3169. opCmpNe:
  3170. Result := l<>r;
  3171. opCmpLt:
  3172. Result := l<r;
  3173. opCmpLe:
  3174. Result := l<=r;
  3175. opCmpGt:
  3176. Result := l>r;
  3177. opCmpGe:
  3178. Result := l>=r;
  3179. else
  3180. RaiseInvalidOp;
  3181. end;
  3182. end;
  3183. procedure TFMTBcdFactory.Clear(var V: TVarData);
  3184. begin
  3185. FreeAndNil(tObject(V.VPointer));
  3186. V.VType:=varEmpty;
  3187. end;
  3188. procedure TFMTBcdFactory.Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean);
  3189. begin
  3190. if Indirect then
  3191. Dest.VPointer:=Source.VPointer
  3192. else
  3193. Dest.VPointer:=TFMTBcdVarData.Create(TFMTBcdVarData(Source.VPointer).BCD);
  3194. Dest.VType:=VarType;
  3195. end;
  3196. procedure TFMTBcdFactory.Cast(var Dest: TVarData; const Source: TVarData);
  3197. begin
  3198. not_implemented;
  3199. end;
  3200. procedure TFMTBcdFactory.CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType);
  3201. var v: TVarData;
  3202. begin
  3203. if Source.vType=VarType then
  3204. begin
  3205. VarDataInit(v);
  3206. try
  3207. v.vType:=varDouble;
  3208. v.vDouble:=TFMTBcdVarData(Source.vPointer).BCD;
  3209. VarDataCastTo(Dest, v, aVarType); //now cast Double to any requested type
  3210. finally
  3211. VarDataClear(v);
  3212. end;
  3213. end
  3214. else
  3215. inherited;
  3216. end;
  3217. {$if declared ( myMinIntBCD ) }
  3218. (*
  3219. {$if sizeof ( integer ) = 2 }
  3220. {$ifdef BCDgr4 }
  3221. const
  3222. myMinIntBCDValue : packed array [ 1..3 ] of Char = #$32#$76#$80;
  3223. {$endif}
  3224. {$else}
  3225. {$if sizeof ( integer ) = 4 }
  3226. *)
  3227. {$ifdef BCDgr9 }
  3228. const
  3229. myMinIntBCDValue : packed array [ 1..10 ] of Char = #$21#$47#$48#$36#$48;
  3230. {$endif}
  3231. (*
  3232. {$else}
  3233. {$if sizeof ( integer ) = 8 }
  3234. {$ifdef BCDgr18 }
  3235. const
  3236. myMinIntBCDValue : packed array [ 1..19 ] of Char = #$92#$23#$37#$20#$36#$85#$47#$75#$80#$80;
  3237. {$endif}
  3238. {$else}
  3239. {$fatal You have an interesting integer type! Sorry, not supported}
  3240. {$endif}
  3241. {$endif}
  3242. {$endif}
  3243. *)
  3244. {$endif}
  3245. initialization
  3246. FillChar ( null_, SizeOf ( null_ ), #0 );
  3247. FillChar ( NullBCD_, SizeOf ( NullBCD_ ), #0 );
  3248. FillChar ( OneBCD_, SizeOf ( OneBCD_ ), #0 );
  3249. OneBCD_.Precision := 1;
  3250. OneBCD_.Fraction[low ( OneBCD_.Fraction )] := $10;
  3251. {$if declared ( myMinIntBCD ) }
  3252. FillChar ( myMinIntBCD, SizeOf ( myMinIntBCD ), #0 );
  3253. {$ifndef bigger_BCD}
  3254. myMinIntBCD.SignSpecialPlaces := NegBit;
  3255. {$else}
  3256. myMinIntBCD.Negativ := True;
  3257. {$endif}
  3258. {$if sizeof ( integer ) = 2 }
  3259. {$ifdef BCDgr4 }
  3260. myMinIntBCD.Precision := 5;
  3261. Move ( myMinIntBCDValue, myMinIntBCD.Fraction, SizeOf ( myMinIntBCDValue ) );
  3262. {$endif}
  3263. {$else}
  3264. {$if sizeof ( integer ) = 4 }
  3265. {$ifdef BCDgr9 }
  3266. myMinIntBCD.Precision := 10;
  3267. Move ( myMinIntBCDValue, myMinIntBCD.Fraction, SizeOf ( myMinIntBCDValue ) );
  3268. {$endif}
  3269. {$else}
  3270. {$if sizeof ( integer ) = 8 }
  3271. {$ifdef BCDgr18 }
  3272. myMinIntBCD.Precision := 19;
  3273. Move ( myMinIntBCDValue, myMinIntBCD.Fraction, SizeOf ( myMinIntBCDValue ) );
  3274. {$endif}
  3275. {$else}
  3276. {$fatal You have an interesting integer type! Sorry, not supported}
  3277. {$endif}
  3278. {$endif}
  3279. {$endif}
  3280. {$endif}
  3281. FMTBcdFactory:=TFMTBcdFactory.create;
  3282. finalization
  3283. FreeAndNil(FMTBcdFactory)
  3284. end.