xtool/contrib/fundamentals/Utils/flcDecimal.pas

12640 lines
353 KiB
ObjectPascal

{******************************************************************************}
{ }
{ File name: flcDecimal.pas }
{ File version: 5.12 }
{ Description: Decimal number functions }
{ }
{ Copyright: Copyright (c) 2014-2020, David J Butler }
{ All rights reserved. }
{ Redistribution and use in source and binary forms, with }
{ or without modification, are permitted provided that }
{ the following conditions are met: }
{ Redistributions of source code must retain the above }
{ copyright notice, this list of conditions and the }
{ following disclaimer. }
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
{ POSSIBILITY OF SUCH DAMAGE. }
{ }
{ Github: https://github.com/fundamentalslib }
{ E-mail: fundamentals.library at gmail.com }
{ }
{ Revision history: }
{ }
{ 2014/10/19 0.01 Decimal32, Decimal64, Decimal128. }
{ 2014/10/20 0.02 SDecimal32, SDecimal64, SDecimal128. }
{ 2014/11/10 0.03 HugeDecimal. }
{ 2014/11/21 0.04 SHugeDecimal. }
{ 2015/05/05 0.05 RawByteString changes. }
{ 2015/05/06 4.06 Revised for Fundamentals 4. }
{ 2016/01/09 5.07 Revised for Fundamentals 5. }
{ 2016/01/10 5.08 Make rounding same under 32/64-bit compilers. }
{ 2018/07/17 5.09 Word32/Int32 changes. }
{ 2018/08/12 5.10 String type changes. }
{ 2019/02/22 5.11 Compilable with Delphi 7. }
{ 2020/03/10 5.12 Modify for changes to flcInteger. }
{ }
{ Supported compilers: }
{ }
{ Delphi 2010-10.4 Win32/Win64 5.12 2020/06/02 }
{ Delphi 10.2-10.4 Linux64 5.12 2020/06/02 }
{ FreePascal 3.0.4 Win64 5.12 2020/06/02 }
{ }
{******************************************************************************}
{$INCLUDE ..\flcInclude.inc}
{$IFDEF DEBUG}
{$IFDEF TEST}
{$DEFINE DECIMAL_TEST}
{$ENDIF}
{$ENDIF}
unit flcDecimal;
interface
uses
{ System }
SysUtils,
{ Fundamentals }
flcStdTypes,
flcInteger;
{ Error }
type
EDecimalError = class(Exception);
TDecimalConvertErrorType = (dceNoError, dceConvertError, dceOverflowError);
{ }
{ Structures }
{ }
type
// 5.4 digits
// encoded as Word32 scaled 10^4
// limited to 99999.9999
Decimal32 = packed record
Value32 : Word32;
end;
PDecimal32 = ^Decimal32;
// 10.9 digits
// encoded as Word64 scaled 10^9
// limited to 9999999999.999999999
Decimal64 = packed record
Value64 : Word64Rec;
end;
PDecimal64 = ^Decimal64;
// 19.19 digits
// encoded as Word128 scaled 10^19
// limited to 9999999999999999999.9999999999999999999
Decimal128 = packed record
Value128 : Word128;
end;
PDecimal128 = ^Decimal128;
// arbitrary number of digits
// internally represented as array of bytes and a count of
// the number of decimal digits to the right of the decimal point
HugeDecimal = packed record
Precision : Integer;
Digits : array of Byte;
end;
PHugeDecimal = ^HugeDecimal;
// signed Decimal32
SDecimal32 = packed record
Sign : Int8;
Value : Decimal32;
end;
PSDecimal32 = ^SDecimal32;
// signed Decimal64
SDecimal64 = packed record
Sign : Int8;
Value : Decimal64;
end;
PSDecimal64 = ^SDecimal64;
// signed Decimal128
SDecimal128 = packed record
Sign : Int8;
Value : Decimal128;
end;
PSDecimal128 = ^SDecimal128;
// signed HugeDecimal
SHugeDecimal = packed record
Sign : Int8;
Value : HugeDecimal;
end;
PSHugeDecimal = ^SHugeDecimal;
{ }
{ Decimal32 }
{ }
const
Decimal32Digits = 9;
Decimal32Precision = 4;
Decimal32Scale = 10000;
Decimal32MaxInt = 99999;
Decimal32MaxValue = 999999999;
Decimal32RoundTerm = Decimal32Scale div 2; // 5000
Decimal32MinFloat = -1.0 / Decimal32Scale / 2.0; // -0.00005
Decimal32MinFloatD : Double = Decimal32MinFloat;
Decimal32MaxFloatLim = (1 + Decimal32MaxValue) div Decimal32Scale + Decimal32MinFloat; // 99999.99995
Decimal32MaxFloatLimD : Double = Decimal32MaxFloatLim;
procedure Decimal32InitZero(var A: Decimal32); {$IFDEF UseInline}inline;{$ENDIF}
procedure Decimal32InitOne(var A: Decimal32);
procedure Decimal32InitMax(var A: Decimal32);
function Decimal32IsZero(const A: Decimal32): Boolean; {$IFDEF UseInline}inline;{$ENDIF}
function Decimal32IsOne(const A: Decimal32): Boolean;
function Decimal32IsMaximum(const A: Decimal32): Boolean;
function Decimal32IsOverflow(const A: Decimal32): Boolean;
function Word32IsDecimal32Range(const A: Word32): Boolean;
function Int16IsDecimal32Range(const A: SmallInt): Boolean;
function Int32IsDecimal32Range(const A: Int32): Boolean;
function FloatIsDecimal32Range(const A: Double): Boolean;
procedure Decimal32InitWord8(var A: Decimal32; const B: Byte);
procedure Decimal32InitWord16(var A: Decimal32; const B: Word);
procedure Decimal32InitWord32(var A: Decimal32; const B: Word32);
procedure Decimal32InitInt32(var A: Decimal32; const B: Int32);
procedure Decimal32InitDecimal32(var A: Decimal32; const B: Decimal32);
procedure Decimal32InitFloat(var A: Decimal32; const B: Double);
function Decimal32ToWord8(const A: Decimal32): Byte;
function Decimal32ToWord16(const A: Decimal32): Word;
function Decimal32ToWord32(const A: Decimal32): Word32;
function Decimal32ToInt32(const A: Decimal32): Int32;
function Decimal32ToFloat(const A: Decimal32): Double;
function Decimal32Trunc(const A: Decimal32): Word32;
function Decimal32Round(const A: Decimal32): Word32;
function Decimal32FracWord(const A: Decimal32): Word;
function Decimal32EqualsWord8(const A: Decimal32; const B: Byte): Boolean;
function Decimal32EqualsWord16(const A: Decimal32; const B: Word): Boolean;
function Decimal32EqualsWord32(const A: Decimal32; const B: Word32): Boolean;
function Decimal32EqualsInt32(const A: Decimal32; const B: Int32): Boolean;
function Decimal32EqualsDecimal32(const A: Decimal32; const B: Decimal32): Boolean;
function Decimal32EqualsFloat(const A: Decimal32; const B: Double): Boolean;
function Decimal32CompareWord8(const A: Decimal32; const B: Byte): Integer;
function Decimal32CompareWord16(const A: Decimal32; const B: Word): Integer;
function Decimal32CompareWord32(const A: Decimal32; const B: Word32): Integer;
function Decimal32CompareInt32(const A: Decimal32; const B: Int32): Integer;
function Decimal32CompareDecimal32(const A: Decimal32; const B: Decimal32): Integer;
function Decimal32CompareFloat(const A: Decimal32; const B: Double): Integer;
procedure Decimal32AddWord8(var A: Decimal32; const B: Byte);
procedure Decimal32AddWord16(var A: Decimal32; const B: Word);
procedure Decimal32AddWord32(var A: Decimal32; const B: Word32);
procedure Decimal32AddDecimal32(var A: Decimal32; const B: Decimal32);
procedure Decimal32SubtractWord8(var A: Decimal32; const B: Byte);
procedure Decimal32SubtractWord16(var A: Decimal32; const B: Word);
procedure Decimal32SubtractWord32(var A: Decimal32; const B: Word32);
procedure Decimal32SubtractDecimal32(var A: Decimal32; const B: Decimal32);
procedure Decimal32MultiplyWord8(var A: Decimal32; const B: Byte);
procedure Decimal32MultiplyWord16(var A: Decimal32; const B: Word);
procedure Decimal32MultiplyWord32(var A: Decimal32; const B: Word32);
procedure Decimal32MultiplyDecimal32(var A: Decimal32; const B: Decimal32);
procedure Decimal32Sqr(var A: Decimal32);
procedure Decimal32DivideWord8(var A: Decimal32; const B: Byte);
procedure Decimal32DivideWord16(var A: Decimal32; const B: Word);
procedure Decimal32DivideWord32(var A: Decimal32; const B: Word32);
procedure Decimal32DivideDecimal32(var A: Decimal32; const B: Decimal32);
function Decimal32ToStr(const A: Decimal32): String;
function Decimal32ToStrB(const A: Decimal32): RawByteString;
function Decimal32ToStrU(const A: Decimal32): UnicodeString;
function TryStrToDecimal32(const A: String; out B: Decimal32): TDecimalConvertErrorType;
function TryStrToDecimal32B(const A: RawByteString; out B: Decimal32): TDecimalConvertErrorType;
function StrToDecimal32(const A: String): Decimal32;
function StrToDecimal32B(const A: RawByteString): Decimal32;
{ }
{ Decimal64 }
{ }
const
Decimal64Digits = 19;
Decimal64Precision = 9;
Decimal64Scale = 1000000000;
Decimal64MaxInt = 9999999999; // 10 9's
{$IFNDEF DELPHI7_DOWN}
Decimal64MaxValue = 9999999999999999999; // 19 9's
{$ENDIF}
Decimal64MaxValueW64 : Word64Rec = (Word32s:($89E7FFFF, $8AC72304)); // 9999999999999999999
Decimal64RoundTerm = Decimal64Scale div 2; // 500000000
Decimal64MinFloat = -1.0 / Decimal64Scale / 2.0; // -0.0000000005
Decimal64MinFloatD : Double = Decimal64MinFloat;
{$IFDEF DELPHI7_DOWN}
Decimal64MaxFloatLim : Double = 999999999999999.9999999995;
Decimal64MaxFloatLimD : Double = 999999999999999.9999999995;
{$ELSE}
Decimal64MaxFloatLim = ((1 + Decimal64MaxValue) div Decimal64Scale) + Decimal64MinFloat; // 999999999999999.9999999995
Decimal64MaxFloatLimD : Double = Decimal64MaxFloatLim;
{$ENDIF}
procedure Decimal64InitZero(var A: Decimal64);
procedure Decimal64InitOne(var A: Decimal64);
procedure Decimal64InitMax(var A: Decimal64);
function Decimal64IsZero(const A: Decimal64): Boolean;
function Decimal64IsOne(const A: Decimal64): Boolean;
function Decimal64IsMaximum(const A: Decimal64): Boolean;
function Decimal64IsOverflow(const A: Decimal64): Boolean;
function Word64IsDecimal64Range(const A: Word64Rec): Boolean;
function Int32IsDecimal64Range(const A: Int32): Boolean;
function Int64IsDecimal64Range(const A: Int64): Boolean;
function FloatIsDecimal64Range(const A: Double): Boolean;
procedure Decimal64InitWord8(var A: Decimal64; const B: Byte);
procedure Decimal64InitWord16(var A: Decimal64; const B: Word);
procedure Decimal64InitWord32(var A: Decimal64; const B: Word32);
procedure Decimal64InitWord64(var A: Decimal64; const B: Word64Rec);
procedure Decimal64InitInt32(var A: Decimal64; const B: Int32);
procedure Decimal64InitInt64(var A: Decimal64; const B: Int64);
procedure Decimal64InitDecimal32(var A: Decimal64; const B: Decimal32);
procedure Decimal64InitDecimal64(var A: Decimal64; const B: Decimal64);
procedure Decimal64InitFloat(var A: Decimal64; const B: Double);
function Decimal64ToWord8(const A: Decimal64): Byte;
function Decimal64ToWord16(const A: Decimal64): Word;
function Decimal64ToWord32(const A: Decimal64): Word32;
function Decimal64ToWord64(const A: Decimal64): Word64Rec;
function Decimal64ToInt32(const A: Decimal64): Int32;
function Decimal64ToInt64(const A: Decimal64): Int64;
function Decimal64ToDecimal32(const A: Decimal64): Decimal32;
function Decimal64ToFloat(const A: Decimal64): Double;
function Decimal64Trunc(const A: Decimal64): Int64;
function Decimal64Round(const A: Decimal64): Int64;
function Decimal64FracWord(const A: Decimal64): Word32;
function Decimal64EqualsWord8(const A: Decimal64; const B: Byte): Boolean;
function Decimal64EqualsWord16(const A: Decimal64; const B: Word): Boolean;
function Decimal64EqualsWord32(const A: Decimal64; const B: Word32): Boolean;
function Decimal64EqualsInt32(const A: Decimal64; const B: Int32): Boolean;
function Decimal64EqualsInt64(const A: Decimal64; const B: Int64): Boolean;
function Decimal64EqualsDecimal64(const A: Decimal64; const B: Decimal64): Boolean;
function Decimal64EqualsFloat(const A: Decimal64; const B: Double): Boolean;
function Decimal64CompareWord8(const A: Decimal64; const B: Byte): Integer;
function Decimal64CompareWord16(const A: Decimal64; const B: Word): Integer;
function Decimal64CompareWord32(const A: Decimal64; const B: Word32): Integer;
function Decimal64CompareInt32(const A: Decimal64; const B: Int32): Integer;
function Decimal64CompareInt64(const A: Decimal64; const B: Int64): Integer;
function Decimal64CompareDecimal64(const A: Decimal64; const B: Decimal64): Integer;
function Decimal64CompareFloat(const A: Decimal64; const B: Double): Integer;
procedure Decimal64AddWord8(var A: Decimal64; const B: Byte);
procedure Decimal64AddWord16(var A: Decimal64; const B: Word);
procedure Decimal64AddWord32(var A: Decimal64; const B: Word32);
procedure Decimal64AddDecimal64(var A: Decimal64; const B: Decimal64);
procedure Decimal64SubtractWord8(var A: Decimal64; const B: Byte);
procedure Decimal64SubtractWord16(var A: Decimal64; const B: Word);
procedure Decimal64SubtractWord32(var A: Decimal64; const B: Word32);
procedure Decimal64SubtractDecimal64(var A: Decimal64; const B: Decimal64);
procedure Decimal64MultiplyWord8(var A: Decimal64; const B: Byte);
procedure Decimal64MultiplyWord16(var A: Decimal64; const B: Word);
procedure Decimal64MultiplyWord32(var A: Decimal64; const B: Word32);
procedure Decimal64MultiplyDecimal64(var A: Decimal64; const B: Decimal64);
procedure Decimal64Sqr(var A: Decimal64);
procedure Decimal64DivideWord8(var A: Decimal64; const B: Byte);
procedure Decimal64DivideWord16(var A: Decimal64; const B: Word);
procedure Decimal64DivideWord32(var A: Decimal64; const B: Word32);
procedure Decimal64DivideDecimal64(var A: Decimal64; const B: Decimal64);
function Decimal64ToStr(const A: Decimal64): String;
function Decimal64ToStrB(const A: Decimal64): RawByteString;
function Decimal64ToStrU(const A: Decimal64): UnicodeString;
function TryStrToDecimal64(const A: String; out B: Decimal64): TDecimalConvertErrorType;
function TryStrToDecimal64B(const A: RawByteString; out B: Decimal64): TDecimalConvertErrorType;
function StrToDecimal64(const A: String): Decimal64;
function StrToDecimal64B(const A: RawByteString): Decimal64;
{ }
{ Decimal128 }
{ }
const
Decimal128Digits = 38;
Decimal128Precision = 19;
Decimal128Scale : Word64Rec = (Word32s:($89E80000, $8AC72304)); // 10000000000000000000
Decimal128ScaleW128 : Word128 = (Word32s:($89E80000, $8AC72304, 0, 0)); // 10000000000000000000
Decimal128ScaleF : Double = 10000000000000000000.0;
Decimal128MaxInt : Word64Rec = (Word32s:($89E7FFFF, $8AC72304)); // 9999999999999999999 (19 9's)
Decimal128MaxValue : Word128 = (Word32s:($FFFFFFFF, $98A223F, $5A86C47A, $4B3B4CA8)); // 99999999999999999999999999999999999999 (38 9's)
Decimal128RoundTerm : Word64Rec = (Word32s:($44F40000, $45639182)); // Decimal128Scale div 2 = 5000000000000000000
Decimal128MinFloat = -0.00000000000000000005;
Decimal128MinFloatD : Double = Decimal128MinFloat;
Decimal128MaxFloatLim = 9999999999999999999.9999999999999999999;
Decimal128MaxFloatLimD : Double = Decimal128MaxFloatLim;
procedure Decimal128InitZero(var A: Decimal128);
procedure Decimal128InitOne(var A: Decimal128);
procedure Decimal128InitMax(var A: Decimal128);
function Decimal128IsZero(const A: Decimal128): Boolean;
function Decimal128IsOne(const A: Decimal128): Boolean;
function Decimal128IsMaximum(const A: Decimal128): Boolean;
function Decimal128IsOverflow(const A: Decimal128): Boolean;
function Word64IsDecimal128Range(const A: Word64Rec): Boolean;
function Word128IsDecimal128Range(const A: Word128): Boolean;
function Int64IsDecimal128Range(const A: Int64): Boolean;
function Int128IsDecimal128Range(const A: Int128): Boolean;
function FloatIsDecimal128Range(const A: Double): Boolean;
procedure Decimal128InitWord8(var A: Decimal128; const B: Byte);
procedure Decimal128InitWord16(var A: Decimal128; const B: Word);
procedure Decimal128InitWord32(var A: Decimal128; const B: Word32);
procedure Decimal128InitWord64(var A: Decimal128; const B: Word64Rec);
procedure Decimal128InitInt32(var A: Decimal128; const B: Int32);
procedure Decimal128InitInt64(var A: Decimal128; const B: Int64);
procedure Decimal128InitDecimal64(var A: Decimal128; const B: Decimal64);
procedure Decimal128InitDecimal128(var A: Decimal128; const B: Decimal128);
procedure Decimal128InitFloat(var A: Decimal128; const B: Double);
function Decimal128ToWord8(const A: Decimal128): Byte;
function Decimal128ToWord16(const A: Decimal128): Word;
function Decimal128ToWord32(const A: Decimal128): Word32;
function Decimal128ToWord64(const A: Decimal128): Word64Rec;
function Decimal128ToInt32(const A: Decimal128): Int32;
function Decimal128ToInt64(const A: Decimal128): Int64;
function Decimal128ToFloat(const A: Decimal128): Double;
function Decimal128Trunc(const A: Decimal128): Word64Rec;
function Decimal128Round(const A: Decimal128): Word64Rec;
function Decimal128FracWord(const A: Decimal128): Word64Rec;
function Decimal128EqualsWord8(const A: Decimal128; const B: Byte): Boolean;
function Decimal128EqualsWord16(const A: Decimal128; const B: Word): Boolean;
function Decimal128EqualsWord32(const A: Decimal128; const B: Word32): Boolean;
function Decimal128EqualsWord64(const A: Decimal128; const B: Word64Rec): Boolean;
function Decimal128EqualsInt32(const A: Decimal128; const B: Int32): Boolean;
function Decimal128EqualsInt64(const A: Decimal128; const B: Int64): Boolean;
function Decimal128EqualsDecimal128(const A: Decimal128; const B: Decimal128): Boolean;
function Decimal128EqualsFloat(const A: Decimal128; const B: Double): Boolean;
function Decimal128CompareWord8(const A: Decimal128; const B: Byte): Integer;
function Decimal128CompareWord16(const A: Decimal128; const B: Word): Integer;
function Decimal128CompareWord32(const A: Decimal128; const B: Word32): Integer;
function Decimal128CompareWord64(const A: Decimal128; const B: Word64Rec): Integer;
function Decimal128CompareDecimal128(const A: Decimal128; const B: Decimal128): Integer;
function Decimal128CompareFloat(const A: Decimal128; const B: Double): Integer;
procedure Decimal128AddWord8(var A: Decimal128; const B: Byte);
procedure Decimal128AddWord16(var A: Decimal128; const B: Word);
procedure Decimal128AddWord32(var A: Decimal128; const B: Word32);
procedure Decimal128AddWord64(var A: Decimal128; const B: Word64Rec);
procedure Decimal128AddDecimal128(var A: Decimal128; const B: Decimal128);
procedure Decimal128SubtractWord8(var A: Decimal128; const B: Byte);
procedure Decimal128SubtractWord16(var A: Decimal128; const B: Word);
procedure Decimal128SubtractWord32(var A: Decimal128; const B: Word32);
procedure Decimal128SubtractWord64(var A: Decimal128; const B: Word64Rec);
procedure Decimal128SubtractDecimal128(var A: Decimal128; const B: Decimal128);
procedure Decimal128MultiplyWord8(var A: Decimal128; const B: Byte);
procedure Decimal128MultiplyWord16(var A: Decimal128; const B: Word);
procedure Decimal128MultiplyWord32(var A: Decimal128; const B: Word32);
procedure Decimal128MultiplyWord64(var A: Decimal128; const B: Word64Rec);
procedure Decimal128MultiplyDecimal128(var A: Decimal128; const B: Decimal128);
procedure Decimal128Sqr(var A: Decimal128);
procedure Decimal128DivideWord8(var A: Decimal128; const B: Byte);
procedure Decimal128DivideWord16(var A: Decimal128; const B: Word);
procedure Decimal128DivideWord32(var A: Decimal128; const B: Word32);
procedure Decimal128DivideDecimal128(var A: Decimal128; const B: Decimal128);
function Decimal128ToStr(const A: Decimal128): String;
function Decimal128ToStrB(const A: Decimal128): RawByteString;
function Decimal128ToStrU(const A: Decimal128): UnicodeString;
function TryStrToDecimal128(const A: String; out B: Decimal128): TDecimalConvertErrorType;
function TryStrToDecimal128B(const A: RawByteString; out B: Decimal128): TDecimalConvertErrorType;
function StrToDecimal128(const A: String): Decimal128;
function StrToDecimal128B(const A: RawByteString): Decimal128;
{ }
{ HugeDecimal }
{ }
procedure HugeDecimalInit(out A: HugeDecimal);
procedure HugeDecimalFinalise(var A: HugeDecimal);
procedure HugeDecimalInitZero(out A: HugeDecimal);
procedure HugeDecimalInitOne(out A: HugeDecimal);
procedure HugeDecimalInitWord8(out A: HugeDecimal; const B: Byte);
procedure HugeDecimalInitWord32(out A: HugeDecimal; const B: Word32);
procedure HugeDecimalInitWord64(out A: HugeDecimal; const B: Word64Rec);
procedure HugeDecimalInitWord128(out A: HugeDecimal; const B: Word128);
procedure HugeDecimalInitDecimal32(out A: HugeDecimal; const B: Decimal32);
procedure HugeDecimalInitDecimal64(out A: HugeDecimal; const B: Decimal64);
procedure HugeDecimalInitDecimal128(out A: HugeDecimal; const B: Decimal128);
procedure HugeDecimalInitHugeDecimal(out A: HugeDecimal; const B: HugeDecimal);
procedure HugeDecimalAssignZero(var A: HugeDecimal);
procedure HugeDecimalAssignOne(var A: HugeDecimal);
procedure HugeDecimalAssignWord8(var A: HugeDecimal; const B: Byte);
procedure HugeDecimalAssignWord32(var A: HugeDecimal; const B: Word32);
procedure HugeDecimalAssignWord64(var A: HugeDecimal; const B: Word64Rec);
procedure HugeDecimalAssignWord128(var A: HugeDecimal; const B: Word128);
procedure HugeDecimalAssignDecimal32(var A: HugeDecimal; const B: Decimal32);
procedure HugeDecimalAssignDecimal64(var A: HugeDecimal; const B: Decimal64);
procedure HugeDecimalAssignDecimal128(var A: HugeDecimal; const B: Decimal128);
procedure HugeDecimalAssignHugeDecimal(var A: HugeDecimal; const B: HugeDecimal);
function HugeDecimalIsZero(const A: HugeDecimal): Boolean; {$IFDEF UseInline}inline;{$ENDIF}
function HugeDecimalIsOne(const A: HugeDecimal): Boolean;
function HugeDecimalIsOdd(const A: HugeDecimal): Boolean;
function HugeDecimalIsEven(const A: HugeDecimal): Boolean;
function HugeDecimalIsInteger(const A: HugeDecimal): Boolean;
function HugeDecimalIsLessThanOne(const A: HugeDecimal): Boolean;
function HugeDecimalIsOneOrGreater(const A: HugeDecimal): Boolean;
function HugeDecimalIsWord8Range(const A: HugeDecimal): Boolean;
function HugeDecimalDigits(const A: HugeDecimal): Integer;
function HugeDecimalIntegerDigits(const A: HugeDecimal): Integer;
function HugeDecimalDecimalDigits(const A: HugeDecimal): Integer;
function HugeDecimalGetDigit(const A: HugeDecimal; const DigitIdx: Integer): Byte;
procedure HugeDecimalSetDigit(var A: HugeDecimal; const DigitIdx: Integer; const DigitValue: Byte);
function HugeDecimalToWord8(const A: HugeDecimal): Byte;
function HugeDecimalToWord32(const A: HugeDecimal): Word32;
function HugeDecimalToWord64(const A: HugeDecimal): Word64Rec;
function HugeDecimalToWord128(const A: HugeDecimal): Word128;
function HugeDecimalToDecimal32(const A: HugeDecimal): Decimal32;
function HugeDecimalToDecimal64(const A: HugeDecimal): Decimal64;
function HugeDecimalToDecimal128(const A: HugeDecimal): Decimal128;
procedure HugeDecimalMul10(var A: HugeDecimal);
procedure HugeDecimalDiv10(var A: HugeDecimal);
procedure HugeDecimalInc(var A: HugeDecimal; const N: Byte = 1);
procedure HugeDecimalDec(var A: HugeDecimal; const N: Byte = 1);
procedure HugeDecimalTrunc(var A: HugeDecimal);
function HugeDecimalFracCompareHalf(var A: HugeDecimal): Integer;
procedure HugeDecimalRound(var A: HugeDecimal);
function HugeDecimalEqualsWord8(const A: HugeDecimal; const B: Byte): Boolean;
function HugeDecimalEqualsHugeDecimal(const A, B: HugeDecimal): Boolean;
function HugeDecimalCompareWord8(const A: HugeDecimal; const B: Byte): Integer;
function HugeDecimalCompareHugeDecimal(const A, B: HugeDecimal): Integer;
procedure HugeDecimalAddHugeDecimal(var A: HugeDecimal; const B: HugeDecimal);
procedure HugeDecimalSubtractHugeDecimal(var A: HugeDecimal; const B: HugeDecimal);
function TryStrToHugeDecimal(const S: String; var R: HugeDecimal): TDecimalConvertErrorType;
procedure StrToHugeDecimal(const S: String; var R: HugeDecimal);
function HugeDecimalToStr(const A: HugeDecimal): String;
{ }
{ SDecimal32 }
{ }
const
SDecimal32MinInt = -99999;
SDecimal32MaxInt = 99999;
SDecimal32MinFloatLim = -Decimal32MaxFloatLim;
SDecimal32MinFloatLimD : Double = SDecimal32MinFloatLim;
SDecimal32MaxFloatLim = Decimal32MaxFloatLim;
SDecimal32MaxFloatLimD : Double = SDecimal32MaxFloatLim;
procedure SDecimal32InitZero(var A: SDecimal32);
procedure SDecimal32InitOne(var A: SDecimal32);
procedure SDecimal32InitMinusOne(var A: SDecimal32);
procedure SDecimal32InitMin(var A: SDecimal32);
procedure SDecimal32InitMax(var A: SDecimal32);
function SDecimal32IsZero(const A: SDecimal32): Boolean; {$IFDEF UseInline}inline;{$ENDIF}
function SDecimal32IsOne(const A: SDecimal32): Boolean;
function SDecimal32IsMinusOne(const A: SDecimal32): Boolean;
function SDecimal32IsMinimum(const A: SDecimal32): Boolean;
function SDecimal32IsMaximum(const A: SDecimal32): Boolean;
function SDecimal32IsOverflow(const A: SDecimal32): Boolean;
function Word32IsSDecimal32Range(const A: Word32): Boolean;
function Int32IsSDecimal32Range(const A: Int32): Boolean;
function FloatIsSDecimal32Range(const A: Double): Boolean;
function SDecimal32Sign(const A: SDecimal32): Integer; {$IFDEF UseInline}inline;{$ENDIF}
procedure SDecimal32Negate(var A: SDecimal32);
procedure SDecimal32AbsInPlace(var A: SDecimal32);
procedure SDecimal32InitWord8(var A: SDecimal32; const B: Byte);
procedure SDecimal32InitWord16(var A: SDecimal32; const B: Word);
procedure SDecimal32InitWord32(var A: SDecimal32; const B: Word32);
procedure SDecimal32InitInt32(var A: SDecimal32; const B: Int32);
procedure SDecimal32InitSDecimal32(var A: SDecimal32; const B: SDecimal32);
procedure SDecimal32InitFloat(var A: SDecimal32; const B: Double);
function SDecimal32ToWord8(const A: SDecimal32): Byte;
function SDecimal32ToWord16(const A: SDecimal32): Word;
function SDecimal32ToWord32(const A: SDecimal32): Word32;
function SDecimal32ToInt32(const A: SDecimal32): Int32;
function SDecimal32ToFloat(const A: SDecimal32): Double;
function SDecimal32Trunc(const A: SDecimal32): Int32;
function SDecimal32Round(const A: SDecimal32): Int32;
function SDecimal32FracWord(const A: SDecimal32): Word;
function SDecimal32EqualsWord8(const A: SDecimal32; const B: Byte): Boolean;
function SDecimal32EqualsWord16(const A: SDecimal32; const B: Word): Boolean;
function SDecimal32EqualsWord32(const A: SDecimal32; const B: Word32): Boolean;
function SDecimal32EqualsInt32(const A: SDecimal32; const B: Int32): Boolean;
function SDecimal32EqualsSDecimal32(const A: SDecimal32; const B: SDecimal32): Boolean;
function SDecimal32EqualsFloat(const A: SDecimal32; const B: Double): Boolean;
function SDecimal32CompareWord8(const A: SDecimal32; const B: Byte): Integer;
function SDecimal32CompareWord16(const A: SDecimal32; const B: Word): Integer;
function SDecimal32CompareWord32(const A: SDecimal32; const B: Word32): Integer;
function SDecimal32CompareInt32(const A: SDecimal32; const B: Int32): Integer;
function SDecimal32CompareSDecimal32(const A: SDecimal32; const B: SDecimal32): Integer;
function SDecimal32CompareFloat(const A: SDecimal32; const B: Double): Integer;
procedure SDecimal32AddWord8(var A: SDecimal32; const B: Byte);
procedure SDecimal32AddWord16(var A: SDecimal32; const B: Word);
procedure SDecimal32AddWord32(var A: SDecimal32; const B: Word32);
procedure SDecimal32AddSDecimal32(var A: SDecimal32; const B: SDecimal32);
procedure SDecimal32SubtractWord8(var A: SDecimal32; const B: Byte);
procedure SDecimal32SubtractWord16(var A: SDecimal32; const B: Word);
procedure SDecimal32SubtractWord32(var A: SDecimal32; const B: Word32);
procedure SDecimal32SubtractSDecimal32(var A: SDecimal32; const B: SDecimal32);
procedure SDecimal32MultiplyWord8(var A: SDecimal32; const B: Byte);
procedure SDecimal32MultiplyWord16(var A: SDecimal32; const B: Word);
procedure SDecimal32MultiplyWord32(var A: SDecimal32; const B: Word32);
procedure SDecimal32MultiplySDecimal32(var A: SDecimal32; const B: SDecimal32);
procedure SDecimal32DivideWord8(var A: SDecimal32; const B: Byte);
procedure SDecimal32DivideWord16(var A: SDecimal32; const B: Word);
procedure SDecimal32DivideWord32(var A: SDecimal32; const B: Word32);
procedure SDecimal32DivideSDecimal32(var A: SDecimal32; const B: SDecimal32);
function SDecimal32ToStr(const A: SDecimal32): String;
function SDecimal32ToStrB(const A: SDecimal32): RawByteString;
function SDecimal32ToStrU(const A: SDecimal32): UnicodeString;
function TryStrToSDecimal32(const A: String; out B: SDecimal32): TDecimalConvertErrorType;
function TryStrToSDecimal32B(const A: RawByteString; out B: SDecimal32): TDecimalConvertErrorType;
function StrToSDecimal32(const A: String): SDecimal32;
function StrToSDecimal32B(const A: RawByteString): SDecimal32;
{ }
{ SDecimal64 }
{ }
const
SDecimal64MinInt = -9999999999;
SDecimal64MaxInt = 9999999999;
{$IFDEF DELPHI7_DOWN}
SDecimal64MinFloatLim : Double = -999999999999999.9999999995;
SDecimal64MinFloatLimD : Double = -999999999999999.9999999995;
SDecimal64MaxFloatLim : Double = 999999999999999.9999999995;
SDecimal64MaxFloatLimD : Double = 999999999999999.9999999995;
{$ELSE}
SDecimal64MinFloatLim = -Decimal64MaxFloatLim;
SDecimal64MinFloatLimD : Double = SDecimal64MinFloatLim;
SDecimal64MaxFloatLim = Decimal64MaxFloatLim;
SDecimal64MaxFloatLimD : Double = SDecimal64MaxFloatLim;
{$ENDIF}
procedure SDecimal64InitZero(var A: SDecimal64);
procedure SDecimal64InitOne(var A: SDecimal64);
procedure SDecimal64InitMinusOne(var A: SDecimal64);
procedure SDecimal64InitMin(var A: SDecimal64);
procedure SDecimal64InitMax(var A: SDecimal64);
function SDecimal64IsZero(const A: SDecimal64): Boolean; {$IFDEF UseInline}inline;{$ENDIF}
function SDecimal64IsOne(const A: SDecimal64): Boolean;
function SDecimal64IsMinusOne(const A: SDecimal64): Boolean;
function SDecimal64IsMinimum(const A: SDecimal64): Boolean;
function SDecimal64IsMaximum(const A: SDecimal64): Boolean;
function SDecimal64IsOverflow(const A: SDecimal64): Boolean;
function Word64IsSDecimal64Range(const A: Word64Rec): Boolean;
function Int64IsSDecimal64Range(const A: Int64): Boolean;
function FloatIsSDecimal64Range(const A: Double): Boolean;
function SDecimal64Sign(const A: SDecimal64): Integer; {$IFDEF UseInline}inline;{$ENDIF}
procedure SDecimal64Negate(var A: SDecimal64);
procedure SDecimal64AbsInPlace(var A: SDecimal64);
procedure SDecimal64InitWord8(var A: SDecimal64; const B: Byte);
procedure SDecimal64InitWord16(var A: SDecimal64; const B: Word);
procedure SDecimal64InitWord32(var A: SDecimal64; const B: Word32);
procedure SDecimal64InitWord64(var A: SDecimal64; const B: Word64Rec);
procedure SDecimal64InitInt32(var A: SDecimal64; const B: Int32);
procedure SDecimal64InitInt64(var A: SDecimal64; const B: Int64);
procedure SDecimal64InitSDecimal64(var A: SDecimal64; const B: SDecimal64);
procedure SDecimal64InitFloat(var A: SDecimal64; const B: Double);
function SDecimal64ToWord8(const A: SDecimal64): Byte;
function SDecimal64ToWord16(const A: SDecimal64): Word;
function SDecimal64ToWord32(const A: SDecimal64): Word32;
function SDecimal64ToWord64(const A: SDecimal64): Word64Rec;
function SDecimal64ToInt32(const A: SDecimal64): Int32;
function SDecimal64ToInt64(const A: SDecimal64): Int64;
function SDecimal64ToSDecimal32(const A: SDecimal64): SDecimal32; // TODO
function SDecimal64ToFloat(const A: SDecimal64): Double;
function SDecimal64Trunc(const A: SDecimal64): Int64;
function SDecimal64Round(const A: SDecimal64): Int64;
function SDecimal64FracWord(const A: SDecimal64): Word32;
function SDecimal64EqualsWord8(const A: SDecimal64; const B: Byte): Boolean;
function SDecimal64EqualsWord16(const A: SDecimal64; const B: Word): Boolean;
function SDecimal64EqualsWord32(const A: SDecimal64; const B: Word32): Boolean;
function SDecimal64EqualsInt32(const A: SDecimal64; const B: Int32): Boolean;
function SDecimal64EqualsInt64(const A: SDecimal64; const B: Int64): Boolean;
function SDecimal64EqualsSDecimal64(const A: SDecimal64; const B: SDecimal64): Boolean;
function SDecimal64EqualsFloat(const A: SDecimal64; const B: Double): Boolean;
function SDecimal64CompareWord8(const A: SDecimal64; const B: Byte): Integer;
function SDecimal64CompareWord16(const A: SDecimal64; const B: Word): Integer;
function SDecimal64CompareWord32(const A: SDecimal64; const B: Word32): Integer;
function SDecimal64CompareInt32(const A: SDecimal64; const B: Int32): Integer;
function SDecimal64CompareInt64(const A: SDecimal64; const B: Int64): Integer;
function SDecimal64CompareSDecimal64(const A: SDecimal64; const B: SDecimal64): Integer;
function SDecimal64CompareFloat(const A: SDecimal64; const B: Double): Integer;
procedure SDecimal64AddWord8(var A: SDecimal64; const B: Byte);
procedure SDecimal64AddWord16(var A: SDecimal64; const B: Word);
procedure SDecimal64AddWord32(var A: SDecimal64; const B: Word32);
procedure SDecimal64AddSDecimal64(var A: SDecimal64; const B: SDecimal64);
procedure SDecimal64SubtractWord8(var A: SDecimal64; const B: Byte);
procedure SDecimal64SubtractWord16(var A: SDecimal64; const B: Word);
procedure SDecimal64SubtractWord32(var A: SDecimal64; const B: Word32);
procedure SDecimal64SubtractSDecimal64(var A: SDecimal64; const B: SDecimal64);
procedure SDecimal64MultiplyWord8(var A: SDecimal64; const B: Byte);
procedure SDecimal64MultiplyWord16(var A: SDecimal64; const B: Word);
procedure SDecimal64MultiplyWord32(var A: SDecimal64; const B: Word32);
procedure SDecimal64MultiplySDecimal64(var A: SDecimal64; const B: SDecimal64);
procedure SDecimal64DivideWord8(var A: SDecimal64; const B: Byte);
procedure SDecimal64DivideWord16(var A: SDecimal64; const B: Word);
procedure SDecimal64DivideWord32(var A: SDecimal64; const B: Word32);
procedure SDecimal64DivideSDecimal64(var A: SDecimal64; const B: SDecimal64);
function SDecimal64ToStr(const A: SDecimal64): String;
function SDecimal64ToStrB(const A: SDecimal64): RawByteString;
function SDecimal64ToStrU(const A: SDecimal64): UnicodeString;
function TryStrToSDecimal64(const A: String; out B: SDecimal64): TDecimalConvertErrorType;
function TryStrToSDecimal64B(const A: RawByteString; out B: SDecimal64): TDecimalConvertErrorType;
function StrToSDecimal64(const A: String): SDecimal64;
function StrToSDecimal64B(const A: RawByteString): SDecimal64;
{ }
{ SDecimal128 }
{ }
const
SDecimal128MinFloatLim = -Decimal128MaxFloatLim;
SDecimal128MinFloatLimD : Double = SDecimal128MinFloatLim;
SDecimal128MaxFloatLim = Decimal128MaxFloatLim;
SDecimal128MaxFloatLimD : Double = SDecimal128MaxFloatLim;
procedure SDecimal128InitZero(var A: SDecimal128);
procedure SDecimal128InitOne(var A: SDecimal128);
procedure SDecimal128InitMax(var A: SDecimal128);
function SDecimal128IsZero(const A: SDecimal128): Boolean; {$IFDEF UseInline}inline;{$ENDIF}
function SDecimal128IsOne(const A: SDecimal128): Boolean;
function SDecimal128IsMaximum(const A: SDecimal128): Boolean;
function SDecimal128IsOverflow(const A: SDecimal128): Boolean;
function Word64IsSDecimal128Range(const A: Word64Rec): Boolean;
function Word128IsSDecimal128Range(const A: Word128): Boolean;
function Int128IsSDecimal128Range(const A: Int128): Boolean;
function FloatIsSDecimal128Range(const A: Double): Boolean;
function SDecimal128Sign(const A: SDecimal128): Integer;
procedure SDecimal128Negate(var A: SDecimal128);
procedure SDecimal128AbsInPlace(var A: SDecimal128);
procedure SDecimal128InitWord8(var A: SDecimal128; const B: Byte);
procedure SDecimal128InitWord16(var A: SDecimal128; const B: Word);
procedure SDecimal128InitWord32(var A: SDecimal128; const B: Word32);
procedure SDecimal128InitWord64(var A: SDecimal128; const B: Word64Rec);
procedure SDecimal128InitInt32(var A: SDecimal128; const B: Int32);
procedure SDecimal128InitInt64(var A: SDecimal128; const B: Int64);
procedure SDecimal128InitSDecimal128(var A: SDecimal128; const B: SDecimal128);
procedure SDecimal128InitFloat(var A: SDecimal128; const B: Double);
function SDecimal128ToWord8(const A: SDecimal128): Byte;
function SDecimal128ToWord16(const A: SDecimal128): Word;
function SDecimal128ToWord32(const A: SDecimal128): Word32;
function SDecimal128ToWord64(const A: SDecimal128): Word64Rec;
function SDecimal128ToInt32(const A: SDecimal128): Int32;
function SDecimal128ToInt64(const A: SDecimal128): Int64;
function SDecimal128ToFloat(const A: SDecimal128): Double;
function SDecimal128Trunc(const A: SDecimal128): Int128;
function SDecimal128Round(const A: SDecimal128): Int128;
function SDecimal128FracWord(const A: SDecimal128): Word64Rec;
function SDecimal128EqualsWord8(const A: SDecimal128; const B: Byte): Boolean;
function SDecimal128EqualsWord16(const A: SDecimal128; const B: Word): Boolean;
function SDecimal128EqualsWord32(const A: SDecimal128; const B: Word32): Boolean;
function SDecimal128EqualsWord64(const A: SDecimal128; const B: Word64Rec): Boolean;
function SDecimal128EqualsSDecimal128(const A: SDecimal128; const B: SDecimal128): Boolean;
function SDecimal128EqualsFloat(const A: SDecimal128; const B: Double): Boolean;
function SDecimal128CompareWord8(const A: SDecimal128; const B: Byte): Integer;
function SDecimal128CompareWord16(const A: SDecimal128; const B: Word): Integer;
function SDecimal128CompareWord32(const A: SDecimal128; const B: Word32): Integer;
function SDecimal128CompareWord64(const A: SDecimal128; const B: Word64Rec): Integer;
function SDecimal128CompareInt32(const A: SDecimal128; const B: Int32): Integer;
function SDecimal128CompareInt64(const A: SDecimal128; const B: Int64): Integer;
function SDecimal128CompareSDecimal128(const A: SDecimal128; const B: SDecimal128): Integer;
function SDecimal128CompareFloat(const A: SDecimal128; const B: Double): Integer;
procedure SDecimal128AddWord8(var A: SDecimal128; const B: Byte);
procedure SDecimal128AddWord16(var A: SDecimal128; const B: Word);
procedure SDecimal128AddWord32(var A: SDecimal128; const B: Word32);
procedure SDecimal128AddWord64(var A: SDecimal128; const B: Word64Rec);
procedure SDecimal128AddSDecimal128(var A: SDecimal128; const B: SDecimal128);
procedure SDecimal128SubtractWord8(var A: SDecimal128; const B: Byte);
procedure SDecimal128SubtractWord16(var A: SDecimal128; const B: Word);
procedure SDecimal128SubtractWord32(var A: SDecimal128; const B: Word32);
procedure SDecimal128SubtractWord64(var A: SDecimal128; const B: Word64Rec);
procedure SDecimal128SubtractSDecimal128(var A: SDecimal128; const B: SDecimal128);
procedure SDecimal128MultiplyWord8(var A: SDecimal128; const B: Byte);
procedure SDecimal128MultiplyWord16(var A: SDecimal128; const B: Word);
procedure SDecimal128MultiplyWord32(var A: SDecimal128; const B: Word32);
procedure SDecimal128MultiplyWord64(var A: SDecimal128; const B: Word64Rec);
procedure SDecimal128MultiplySDecimal128(var A: SDecimal128; const B: SDecimal128);
procedure SDecimal128DivideWord8(var A: SDecimal128; const B: Byte);
procedure SDecimal128DivideWord16(var A: SDecimal128; const B: Word);
procedure SDecimal128DivideWord32(var A: SDecimal128; const B: Word32);
procedure SDecimal128DivideWord64(var A: SDecimal128; const B: Word64Rec);
procedure SDecimal128DivideSDecimal128(var A: SDecimal128; const B: SDecimal128);
function SDecimal128ToStr(const A: SDecimal128): String;
function SDecimal128ToStrB(const A: SDecimal128): RawByteString;
function SDecimal128ToStrU(const A: SDecimal128): UnicodeString;
function TryStrToSDecimal128(const A: String; out B: SDecimal128): TDecimalConvertErrorType;
function TryStrToSDecimal128B(const A: RawByteString; out B: SDecimal128): TDecimalConvertErrorType;
function StrToSDecimal128(const A: String): SDecimal128;
function StrToSDecimal128B(const A: RawByteString): SDecimal128;
{ }
{ SHugeDecimal }
{ }
procedure SHugeDecimalInit(out A: SHugeDecimal);
procedure SHugeDecimalInitZero(out A: SHugeDecimal);
procedure SHugeDecimalInitOne(out A: SHugeDecimal);
procedure SHugeDecimalInitMinusOne(out A: SHugeDecimal);
procedure SHugeDecimalAssignZero(var A: SHugeDecimal);
procedure SHugeDecimalAssignOne(var A: SHugeDecimal);
procedure SHugeDecimalAssignMinusOne(var A: SHugeDecimal);
procedure SHugeDecimalAssignWord8(var A: SHugeDecimal; const B: Byte);
procedure SHugeDecimalAssignWord32(var A: SHugeDecimal; const B: Word32);
procedure SHugeDecimalAssignWord64(var A: SHugeDecimal; const B: Word64Rec);
procedure SHugeDecimalAssignWord128(var A: SHugeDecimal; const B: Word128);
procedure SHugeDecimalAssignInt8(var A: SHugeDecimal; const B: ShortInt);
procedure SHugeDecimalAssignInt32(var A: SHugeDecimal; const B: Int32);
procedure SHugeDecimalAssignInt64(var A: SHugeDecimal; const B: Int64);
procedure SHugeDecimalAssignDecimal32(var A: SHugeDecimal; const B: Decimal32);
procedure SHugeDecimalAssignDecimal64(var A: SHugeDecimal; const B: Decimal64);
procedure SHugeDecimalAssignDecimal128(var A: SHugeDecimal; const B: Decimal128);
procedure SHugeDecimalAssignHugeDecimal(var A: SHugeDecimal; const B: HugeDecimal);
procedure SHugeDecimalAssignSHugeDecimal(var A: SHugeDecimal; const B: SHugeDecimal);
function SHugeDecimalIsZero(const A: SHugeDecimal): Boolean; {$IFDEF UseInline}inline;{$ENDIF}
function SHugeDecimalIsOne(const A: SHugeDecimal): Boolean;
function SHugeDecimalIsMinusOne(const A: SHugeDecimal): Boolean;
function SHugeDecimalSign(const A: SHugeDecimal): Integer; {$IFDEF UseInline}inline;{$ENDIF}
procedure SHugeDecimalNegate(var A: SHugeDecimal);
procedure SHugeDecimalAbsInPlace(var A: SHugeDecimal);
function SHugeDecimalToWord8(const A: SHugeDecimal): Byte;
function SHugeDecimalToWord32(const A: SHugeDecimal): Word32;
function SHugeDecimalToWord64(const A: SHugeDecimal): Word64Rec;
function SHugeDecimalToWord128(const A: SHugeDecimal): Word128;
function SHugeDecimalToInt8(const A: SHugeDecimal): ShortInt;
function SHugeDecimalToInt32(const A: SHugeDecimal): Int32;
function SHugeDecimalToInt64(const A: SHugeDecimal): Int64;
function SHugeDecimalToDecimal32(const A: SHugeDecimal): Decimal32;
function SHugeDecimalToDecimal64(const A: SHugeDecimal): Decimal64;
function SHugeDecimalToDecimal128(const A: SHugeDecimal): Decimal128;
procedure SHugeDecimalTrunc(var A: SHugeDecimal);
function SHugeDecimalFracCompareHalf(var A: SHugeDecimal): Integer;
procedure SHugeDecimalRound(var A: SHugeDecimal);
function SHugeDecimalEqualsWord8(const A: SHugeDecimal; const B: Byte): Boolean;
function SHugeDecimalEqualsHugeDecimal(const A: SHugeDecimal; const B: HugeDecimal): Boolean;
function SHugeDecimalEqualsSHugeDecimal(const A, B: SHugeDecimal): Boolean;
function SHugeDecimalCompareWord8(const A: SHugeDecimal; const B: Byte): Integer;
function SHugeDecimalCompareHugeDecimal(const A: SHugeDecimal; const B: HugeDecimal): Integer;
function SHugeDecimalCompareSHugeDecimal(const A, B: SHugeDecimal): Integer;
procedure SHugeDecimalAddHugeDecimal(var A: SHugeDecimal; const B: HugeDecimal);
procedure SHugeDecimalAddSHugeDecimal(var A: SHugeDecimal; const B: SHugeDecimal);
procedure SHugeDecimalSubtractSHugeDecimal(var A: SHugeDecimal; const B: SHugeDecimal);
function TryStrToSHugeDecimal(const S: String; var R: SHugeDecimal): TDecimalConvertErrorType;
procedure StrToSHugeDecimal(const S: String; var R: SHugeDecimal);
function SHugeDecimalToStr(const A: SHugeDecimal): String;
{ }
{ Test cases }
{ }
{$IFDEF DECIMAL_TEST}
procedure Test;
{$ENDIF}
implementation
uses
{ System }
Math,
{ Fundamentals }
flcUtils,
flcStrings;
{ }
{ Errors }
{ }
const
SOverflowError = 'Overflow error';
SConvertError = 'Convert error';
SDivisionByZero = 'Division by zero';
SIndexOutOfRange = 'Index out of range';
SInvalidParameter = 'Invalid parameter';
{ }
{ Decimal32 }
{ }
procedure Decimal32InitZero(var A: Decimal32);
begin
A.Value32 := 0;
end;
procedure Decimal32InitOne(var A: Decimal32);
begin
A.Value32 := Decimal32Scale;
end;
procedure Decimal32InitMax(var A: Decimal32);
begin
A.Value32 := Decimal32MaxValue;
end;
function Decimal32IsZero(const A: Decimal32): Boolean;
begin
Result := A.Value32 = 0;
end;
function Decimal32IsOne(const A: Decimal32): Boolean;
begin
Result := A.Value32 = Decimal32Scale;
end;
function Decimal32IsMaximum(const A: Decimal32): Boolean;
begin
Result := A.Value32 = Decimal32MaxValue;
end;
function Decimal32IsOverflow(const A: Decimal32): Boolean;
begin
Result := A.Value32 > Decimal32MaxValue;
end;
function Word32IsDecimal32Range(const A: Word32): Boolean;
begin
Result := A <= Decimal32MaxInt;
end;
function Int16IsDecimal32Range(const A: SmallInt): Boolean;
begin
Result := A >= 0;
end;
function Int32IsDecimal32Range(const A: Int32): Boolean;
begin
Result := (A >= 0) and (A <= Decimal32MaxInt);
end;
function FloatIsDecimal32Range(const A: Double): Boolean;
begin
Result :=
(A >= Decimal32MinFloatD) and
(A < Decimal32MaxFloatLimD);
end;
procedure Decimal32InitWord8(var A: Decimal32; const B: Byte);
begin
A.Value32 := B * Decimal32Scale;
end;
procedure Decimal32InitWord16(var A: Decimal32; const B: Word);
begin
A.Value32 := B * Decimal32Scale;
end;
procedure Decimal32InitWord32(var A: Decimal32; const B: Word32);
begin
if B > Decimal32MaxInt then
raise EDecimalError.Create(SOverflowError);
A.Value32 := B * Decimal32Scale;
end;
procedure Decimal32InitInt32(var A: Decimal32; const B: Int32);
begin
if (B < 0) or (B > Decimal32MaxInt) then
raise EDecimalError.Create(SOverflowError);
A.Value32 := B * Decimal32Scale;
end;
procedure Decimal32InitDecimal32(var A: Decimal32; const B: Decimal32);
begin
A.Value32 := B.Value32;
end;
procedure Decimal32InitFloat(var A: Decimal32; const B: Double);
var D : Double;
I : Int64;
begin
if not FloatIsDecimal32Range(B) then
raise EDecimalError.Create(SOverflowError);
D := B * Decimal32Scale;
I := Round(D);
Assert(I >= 0);
Assert(I <= Decimal32MaxValue);
A.Value32 := I;
end;
function Decimal32ToWord8(const A: Decimal32): Byte;
var I : Word32;
begin
if A.Value32 mod Decimal32Scale <> 0 then
raise EDecimalError.Create(SConvertError);
I := A.Value32 div Decimal32Scale;
if not Word32IsWord8Range(I) then
raise EDecimalError.Create(SOverflowError);
Result := I;
end;
function Decimal32ToWord16(const A: Decimal32): Word;
var I : Word32;
begin
if A.Value32 mod Decimal32Scale <> 0 then
raise EDecimalError.Create(SConvertError);
I := A.Value32 div Decimal32Scale;
if not Word32IsWord16Range(I) then
raise EDecimalError.Create(SOverflowError);
Result := I;
end;
function Decimal32ToWord32(const A: Decimal32): Word32;
begin
if A.Value32 mod Decimal32Scale <> 0 then
raise EDecimalError.Create(SConvertError);
Result := A.Value32 div Decimal32Scale;
end;
function Decimal32ToInt32(const A: Decimal32): Int32;
begin
if A.Value32 mod Decimal32Scale <> 0 then
raise EDecimalError.Create(SConvertError);
Result := A.Value32 div Decimal32Scale;
end;
function Decimal32ToFloat(const A: Decimal32): Double;
var D, E : Double;
begin
D := A.Value32;
E := Decimal32Scale;
D := D / E;
Result := D;
end;
function Decimal32Trunc(const A: Decimal32): Word32;
begin
Result := A.Value32 div Decimal32Scale;
end;
function Decimal32Round(const A: Decimal32): Word32;
var F, R : Word32;
begin
R := A.Value32 div Decimal32Scale;
F := A.Value32 mod Decimal32Scale;
if (F > Decimal32RoundTerm) or
((F = Decimal32RoundTerm) and Word32IsOdd(R)) then
Inc(R);
Result := R;
end;
function Decimal32FracWord(const A: Decimal32): Word;
begin
Result := A.Value32 mod Decimal32Scale;
end;
function Decimal32EqualsWord8(const A: Decimal32; const B: Byte): Boolean;
begin
Result := A.Value32 = B * Decimal32Scale;
end;
function Decimal32EqualsWord16(const A: Decimal32; const B: Word): Boolean;
begin
Result := A.Value32 = B * Decimal32Scale;
end;
function Decimal32EqualsWord32(const A: Decimal32; const B: Word32): Boolean;
begin
Result := Int64(A.Value32) = Int64(B) * Decimal32Scale;
end;
function Decimal32EqualsInt32(const A: Decimal32; const B: Int32): Boolean;
begin
if B < 0 then
Result := False
else
Result := Int64(A.Value32) = Int64(B) * Decimal32Scale;
end;
function Decimal32EqualsDecimal32(const A: Decimal32; const B: Decimal32): Boolean;
begin
Result := A.Value32 = B.Value32;
end;
function Decimal32EqualsFloat(const A: Decimal32; const B: Double): Boolean;
var T : Decimal32;
begin
if not FloatIsDecimal32Range(B) then
Result := False
else
begin
Decimal32InitFloat(T, B);
Result := T.Value32 = A.Value32;
end;
end;
function Decimal32CompareWord8(const A: Decimal32; const B: Byte): Integer;
var C : Word32;
begin
C := B * Decimal32Scale;
Result := Word32Compare(A.Value32, C);
end;
function Decimal32CompareWord16(const A: Decimal32; const B: Word): Integer;
var C : Word32;
begin
C := B * Decimal32Scale;
Result := Word32Compare(A.Value32, C);
end;
function Decimal32CompareWord32(const A: Decimal32; const B: Word32): Integer;
var C : Int64;
begin
C := Int64(B) * Decimal32Scale;
if A.Value32 > C then
Result := 1
else
if A.Value32 < C then
Result := -1
else
Result := 0;
end;
function Decimal32CompareInt32(const A: Decimal32; const B: Int32): Integer;
var C : Int64;
begin
if B < 0 then
Result := 1
else
begin
C := Int64(B) * Decimal32Scale;
if A.Value32 > C then
Result := 1
else
if A.Value32 < C then
Result := -1
else
Result := 0;
end;
end;
function Decimal32CompareDecimal32(const A: Decimal32; const B: Decimal32): Integer;
begin
Result := Word32Compare(A.Value32, B.Value32);
end;
function Decimal32CompareFloat(const A: Decimal32; const B: Double): Integer;
var T : Decimal32;
begin
if B < Decimal32MinFloatD then
Result := 1
else
if B >= Decimal32MaxFloatLimD then
Result := -1
else
begin
Assert(FloatIsDecimal32Range(B));
Decimal32InitFloat(T, B);
Result := Word32Compare(A.Value32, T.Value32);
end;
end;
procedure Decimal32AddWord8(var A: Decimal32; const B: Byte);
var T : Word32;
begin
T := A.Value32 + (B * Decimal32Scale);
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32AddWord16(var A: Decimal32; const B: Word);
var T : Word32;
begin
T := A.Value32 + (B * Decimal32Scale);
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32AddWord32(var A: Decimal32; const B: Word32);
var T : Word32;
begin
T := A.Value32 + (B * Decimal32Scale);
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32AddDecimal32(var A: Decimal32; const B: Decimal32);
var T : Word32;
begin
T := A.Value32 + B.Value32;
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32SubtractWord8(var A: Decimal32; const B: Byte);
var T : Int64;
begin
T := Int64(A.Value32) - (B * Decimal32Scale);
if T < 0 then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32SubtractWord16(var A: Decimal32; const B: Word);
var T : Int64;
begin
T := Int64(A.Value32) - (B * Decimal32Scale);
if T < 0 then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32SubtractWord32(var A: Decimal32; const B: Word32);
var T : Int64;
begin
T := Int64(A.Value32) - (B * Decimal32Scale);
if T < 0 then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32SubtractDecimal32(var A: Decimal32; const B: Decimal32);
var T : Int64;
begin
T := Int64(A.Value32) - B.Value32;
if T < 0 then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32MultiplyWord8(var A: Decimal32; const B: Byte);
var T : Int64;
begin
T := Int64(A.Value32) * B;
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32MultiplyWord16(var A: Decimal32; const B: Word);
var T : Int64;
begin
T := Int64(A.Value32) * B;
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32MultiplyWord32(var A: Decimal32; const B: Word32);
var T : Int64;
begin
T := Int64(A.Value32) * B;
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32MultiplyDecimal32(var A: Decimal32; const B: Decimal32);
var T : Int64;
begin
T := Int64(A.Value32) * B.Value32;
T := (T + Decimal32RoundTerm) div Decimal32Scale;
if T > Decimal32MaxValue then
raise EDecimalError.Create(SOverflowError);
A.Value32 := T;
end;
procedure Decimal32Sqr(var A: Decimal32);
begin
Decimal32MultiplyDecimal32(A, A);
end;
procedure Decimal32DivideWord8(var A: Decimal32; const B: Byte);
begin
A.Value32 := A.Value32 div B;
end;
procedure Decimal32DivideWord16(var A: Decimal32; const B: Word);
begin
A.Value32 := A.Value32 div B;
end;
procedure Decimal32DivideWord32(var A: Decimal32; const B: Word32);
begin
A.Value32 := A.Value32 div B;
end;
procedure Decimal32DivideDecimal32(var A: Decimal32; const B: Decimal32);
var T : Int64;
begin
T := Int64(A.Value32) * Decimal32Scale;
A.Value32 := T div B.Value32;
end;
function Decimal32ToStr(const A: Decimal32): String;
var
S : String;
T : Word64Rec;
L : Integer;
begin
if A.Value32 = 0 then
begin
Result := '0.0000';
exit;
end;
Word64InitWord32(T, A.Value32);
S := StrPadLeft(Word64ToStr(T), '0', Decimal32Precision + 1, False);
L := Length(S);
S :=
CopyLeft(S, L - Decimal32Precision) + '.' +
CopyRight(S, Decimal32Precision);
Result := S;
end;
function Decimal32ToStrB(const A: Decimal32): RawByteString;
var
S : RawByteString;
T : Word64Rec;
L : Integer;
begin
if A.Value32 = 0 then
begin
Result := '0.0000';
exit;
end;
Word64InitWord32(T, A.Value32);
S := StrPadLeftB(Word64ToStrB(T), '0', Decimal32Precision + 1, False);
L := Length(S);
S :=
CopyLeftB(S, L - Decimal32Precision) + '.' +
CopyRightB(S, Decimal32Precision);
Result := S;
end;
function Decimal32ToStrU(const A: Decimal32): UnicodeString;
var
S : UnicodeString;
T : Word64Rec;
L : Integer;
begin
if A.Value32 = 0 then
begin
Result := '0.0000';
exit;
end;
Word64InitWord32(T, A.Value32);
S := StrPadLeftU(Word64ToStrU(T), '0', Decimal32Precision + 1, False);
L := Length(S);
S :=
CopyLeftU(S, L - Decimal32Precision) + '.' +
CopyRightU(S, Decimal32Precision);
Result := S;
end;
function TryStrToDecimal32_1(const A: String; out B: Decimal32): TDecimalConvertErrorType;
var
ResInt : Word32;
ResFrac : Word32;
Res : Word32;
I, L : Integer;
C : Char;
Digit : Integer;
DigitFactor : Word32;
RoundingDigit : Integer;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
ResInt := 0;
while I <= L do
begin
C := A[I];
if C = '.' then
if I = 1 then
begin
Result := dceConvertError;
exit;
end
else
begin
if I = L then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
break;
end;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResInt := ResInt * 10;
Inc(ResInt, Digit);
if ResInt > Decimal32MaxInt then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
end;
// fraction part
ResFrac := 0;
DigitFactor := Decimal32Scale div 10;
while I <= L do
begin
C := A[I];
Digit := CharDigitToInt(C);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResFrac, Byte(Digit) * DigitFactor);
DigitFactor := DigitFactor div 10;
if DigitFactor = 0 then
break;
end;
// rounding
if I <= L then
begin
C := A[I];
RoundingDigit := CharDigitToInt(C);
Inc(I);
if RoundingDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if RoundingDigit = 5 then
while I <= L do
begin
C := A[I];
Digit := CharDigitToInt(C);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
if Digit > 0 then
begin
RoundingDigit := 6;
break;
end;
end;
end
else
RoundingDigit := 0;
// validate remaining digits
while I <= L do
begin
C := A[I];
Digit := CharDigitToInt(C);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
end;
// combine integer and fractional parts
Res := ResInt * Decimal32Scale + ResFrac;
// round
if (RoundingDigit > 5) or
((RoundingDigit = 5) and (Res and 1 = 1)) then
begin
Inc(Res);
if Res > Decimal32MaxValue then
begin
Result := dceOverflowError;
exit;
end;
end;
// result
B.Value32 := Res;
Result := dceNoError;
end;
function TryStrToDecimal32_2(const A: String; out B: Decimal32): TDecimalConvertErrorType;
var
ResInt : Word64Rec;
ResIntDigits : Integer;
ResFrac : Word32;
ResFracDigits : Integer;
ResFracRoundDigit : Integer;
ResExp : Integer;
ResExpSign : Integer;
Res : Word32;
I, L : Integer;
C : Char;
Digit : Integer;
DigitFactor : Word32;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
Word64InitZero(ResInt);
ResIntDigits := 0;
repeat
C := A[I];
if (C = '.') or (C = 'E') then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResIntDigits);
Word64MultiplyWord8(ResInt, 10);
Word64AddWord8(ResInt, Digit);
if Word64CompareWord32(ResInt, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
if ResIntDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction part
ResFrac := 0;
ResFracDigits := 0;
ResFracRoundDigit := 0;
if I <= L then
begin
C := A[I];
if C = '.' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
DigitFactor := Decimal32Scale div 10;
repeat
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
Inc(ResFracDigits);
Inc(ResFrac, Byte(Digit) * DigitFactor);
DigitFactor := DigitFactor div 10;
if DigitFactor = 0 then
break;
until I > L;
if ResFracDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction rounding
if (I <= L) and (A[I] <> 'E') then
begin
C := A[I];
ResFracRoundDigit := CharDigitToInt(C);
Inc(I);
if ResFracRoundDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if ResFracRoundDigit = 5 then
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
if Digit > 0 then
begin
ResFracRoundDigit := 6;
break;
end;
end;
// validate remaining fraction digits
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
end;
end;
end;
end;
// exponent
ResExp := 0;
ResExpSign := 0;
if I <= L then
begin
C := A[I];
if C = 'E' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
C := A[I];
if (C = '+') or (C = '-') then
begin
if C = '+' then
ResExpSign := 1
else
ResExpSign := -1;
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
end;
repeat
C := A[I];
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResExp := ResExp * 10 + Digit;
if ResExp > 9999 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
end;
end;
// end of string
if I <= L then
begin
Result := dceConvertError;
exit;
end;
// combine integer and fractional parts
if Word64CompareWord32(ResInt, Decimal32MaxInt) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Res := Word64ToWord32(ResInt) * Decimal32Scale + ResFrac;
// round
if (ResFracRoundDigit > 5) or
((ResFracRoundDigit = 5) and (Res and 1 = 1)) then
begin
Inc(Res);
if Res > Decimal32MaxValue then
begin
Result := dceOverflowError;
exit;
end;
end;
// exponent
if Res <> 0 then
if ResExpSign >= 0 then
while ResExp > 0 do
begin
Res := Res * 10;
if Res > Decimal32MaxValue then
begin
Result := dceOverflowError;
exit;
end;
Dec(ResExp);
end
else
while ResExp > 0 do
begin
Res := Res div 10;
if Res = 0 then
break;
Dec(ResExp);
end;
// result
B.Value32 := Res;
Result := dceNoError;
end;
function TryStrToDecimal32(const A: String; out B: Decimal32): TDecimalConvertErrorType;
var
ResInt : Word64Rec;
ResIntDigits : Integer;
ResFrac : Word32;
ResFracDigits : Integer;
ResFracRoundDigit : Integer;
ResExp : Integer;
ResExpSign : Integer;
Res : Word64Rec;
I, L : Integer;
C : Char;
Digit : Integer;
DigitFactor : Word32;
R : Byte;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
Word64InitZero(ResInt);
ResIntDigits := 0;
repeat
C := A[I];
if (C = '.') or (C = 'E') then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResIntDigits);
Word64MultiplyWord8(ResInt, 10);
Word64AddWord8(ResInt, Digit);
if Word64CompareWord32(ResInt, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
if ResIntDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction part
ResFrac := 0;
ResFracDigits := 0;
ResFracRoundDigit := 0;
if I <= L then
begin
C := A[I];
if C = '.' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
DigitFactor := Decimal32Scale div 10;
repeat
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
Inc(ResFracDigits);
Inc(ResFrac, Byte(Digit) * DigitFactor);
DigitFactor := DigitFactor div 10;
if DigitFactor = 0 then
break;
until I > L;
if ResFracDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction rounding
if (I <= L) and (A[I] <> 'E') then
begin
C := A[I];
ResFracRoundDigit := CharDigitToInt(C);
Inc(I);
if ResFracRoundDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if ResFracRoundDigit = 5 then
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
if Digit > 0 then
begin
ResFracRoundDigit := 6;
break;
end;
end;
// validate remaining fraction digits
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
end;
end;
end;
end;
// exponent
ResExp := 0;
ResExpSign := 0;
if I <= L then
begin
C := A[I];
if C = 'E' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
C := A[I];
if (C = '+') or (C = '-') then
begin
if C = '+' then
ResExpSign := 1
else
ResExpSign := -1;
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
end;
repeat
C := A[I];
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResExp := ResExp * 10 + Digit;
if ResExp > 9999 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
end;
end;
// end of string
if I <= L then
begin
Result := dceConvertError;
exit;
end;
// combine integer and fractional parts
Res := ResInt;
Word64MultiplyWord32(Res, Decimal32Scale);
Word64AddWord32(Res, ResFrac);
// round
if (ResFracRoundDigit > 5) or
((ResFracRoundDigit = 5) and Word64IsOdd(Res)) then
Word64Inc(Res);
// exponent
if not Word64IsZero(Res) then
if ResExpSign >= 0 then
while ResExp > 0 do
begin
Word64MultiplyWord8(Res, 10);
if Word64CompareWord32(Res, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Dec(ResExp);
end
else
while ResExp > 0 do
begin
Word64DivideWord8(Res, 10, Res, R);
if Word64IsZero(Res) then
break;
Dec(ResExp);
end;
// result
if Word64CompareWord32(Res, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
B.Value32 := Word64ToWord32(Res);
Result := dceNoError;
end;
function TryStrToDecimal32_Tst_Frac64(const A: String; out B: Decimal32): TDecimalConvertErrorType;
var
ResInt : Word64Rec;
ResIntDigits : Integer;
ResFrac : Word64Rec;
ResFracDigits : Integer;
ResFracRoundDigit : Integer;
ResExp : Integer;
ResExpSign : Integer;
Res : Word64Rec;
I, L, N : Integer;
C : Char;
Digit : Integer;
DigitFactor, T : Word64Rec;
R : Byte;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
Word64InitZero(ResInt);
ResIntDigits := 0;
repeat
C := A[I];
if (C = '.') or (C = 'E') then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResIntDigits);
Word64MultiplyWord8(ResInt, 10);
Word64AddWord8(ResInt, Digit);
if Word64CompareWord32(ResInt, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
if ResIntDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction part
Word64InitZero(ResFrac);
ResFracDigits := 0;
ResFracRoundDigit := 0;
if I <= L then
begin
C := A[I];
if C = '.' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
Word64InitWord32(DigitFactor, Decimal64Scale div 10);
repeat
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
Inc(ResFracDigits);
T := DigitFactor;
Word64MultiplyWord8(T, Byte(Digit));
Word64AddWord64(ResFrac, T);
Word64DivideWord8(DigitFactor, 10, DigitFactor, R);
if Word64IsZero(DigitFactor) then
break;
until I > L;
if ResFracDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction rounding
if (I <= L) and (A[I] <> 'E') then
begin
C := A[I];
ResFracRoundDigit := CharDigitToInt(C);
Inc(I);
if ResFracRoundDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if ResFracRoundDigit = 5 then
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
if Digit > 0 then
begin
ResFracRoundDigit := 6;
break;
end;
end;
// validate remaining fraction digits
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
end;
end;
end;
end;
// exponent
ResExp := 0;
ResExpSign := 0;
if I <= L then
begin
C := A[I];
if C = 'E' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
C := A[I];
if (C = '+') or (C = '-') then
begin
if C = '+' then
ResExpSign := 1
else
ResExpSign := -1;
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
end;
repeat
C := A[I];
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResExp := ResExp * 10 + Digit;
if ResExp > 9999 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
end;
end;
// end of string
if I <= L then
begin
Result := dceConvertError;
exit;
end;
// combine integer and fractional parts
Res := ResInt;
Word64MultiplyWord32(Res, Decimal64Scale);
Word64AddWord64(Res, ResFrac);
// round
if (ResFracRoundDigit > 5) or
((ResFracRoundDigit = 5) and Word64IsOdd(Res)) then
Word64Inc(Res);
// exponent
if not Word64IsZero(Res) then
if ResExpSign >= 0 then
while ResExp > 0 do
begin
Word64MultiplyWord8(Res, 10);
if Word64CompareWord64(Res, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Dec(ResExp);
end
else
while ResExp > 0 do
begin
Word64DivideWord8(Res, 10, Res, R);
if Word64IsZero(Res) then
break;
Dec(ResExp);
end;
N := Decimal64Precision - Decimal32Precision;
while N > 0 do
begin
Word64DivideWord8(Res, 10, Res, R);
if Word64IsZero(Res) then
break;
Dec(N);
end;
// result
if Word64CompareWord32(Res, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
B.Value32 := Word64ToWord32(Res);
Result := dceNoError;
end;
function TryStrToDecimal32B(const A: RawByteString; out B: Decimal32): TDecimalConvertErrorType;
var
ResInt : Word64Rec;
ResIntDigits : Integer;
ResFrac : Word32;
ResFracDigits : Integer;
ResFracRoundDigit : Integer;
ResExp : Integer;
ResExpSign : Integer;
Res : Word32;
I, L : Integer;
C : AnsiChar;
Digit : Integer;
DigitFactor : Word32;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
Word64InitZero(ResInt);
ResIntDigits := 0;
repeat
C := A[I];
if (C = '.') or (C = 'E') then
break;
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResIntDigits);
Word64MultiplyWord8(ResInt, 10);
Word64AddWord8(ResInt, Digit);
if Word64CompareWord32(ResInt, Decimal32MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
if ResIntDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction part
ResFrac := 0;
ResFracDigits := 0;
ResFracRoundDigit := 0;
if I <= L then
begin
C := A[I];
if C = '.' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
DigitFactor := Decimal32Scale div 10;
repeat
C := A[I];
if C = 'E' then
break;
Digit := ByteCharDigitToInt(C);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResFracDigits);
Inc(ResFrac, Byte(Digit) * DigitFactor);
DigitFactor := DigitFactor div 10;
if DigitFactor = 0 then
break;
until I > L;
if ResFracDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction rounding
if (I <= L) and (A[I] <> 'E') then
begin
C := A[I];
ResFracRoundDigit := ByteCharDigitToInt(C);
Inc(I);
if ResFracRoundDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if ResFracRoundDigit = 5 then
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
if Digit > 0 then
begin
ResFracRoundDigit := 6;
break;
end;
end;
// validate remaining fraction digits
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
end;
end;
end;
end;
// exponent
ResExp := 0;
ResExpSign := 0;
if I <= L then
begin
C := A[I];
if C = 'E' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
C := A[I];
if (C = '+') or (C = '-') then
begin
if C = '+' then
ResExpSign := 1
else
ResExpSign := -1;
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
end;
repeat
C := A[I];
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResExp := ResExp * 10 + Digit;
if ResExp > 9999 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
end;
end;
// end of string
if I <= L then
begin
Result := dceConvertError;
exit;
end;
// combine integer and fractional parts
if Word64CompareWord32(ResInt, Decimal32MaxInt) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Res := Word64ToWord32(ResInt) * Decimal32Scale + ResFrac;
// round
if (ResFracRoundDigit > 5) or
((ResFracRoundDigit = 5) and (Res and 1 = 1)) then
begin
Inc(Res);
if Res > Decimal32MaxValue then
begin
Result := dceOverflowError;
exit;
end;
end;
// exponent
if Res <> 0 then
if ResExpSign >= 0 then
while ResExp > 0 do
begin
Res := Res * 10;
if Res > Decimal32MaxValue then
begin
Result := dceOverflowError;
exit;
end;
Dec(ResExp);
end
else
while ResExp > 0 do
begin
Res := Res div 10;
if Res = 0 then
break;
Dec(ResExp);
end;
// result
B.Value32 := Res;
Result := dceNoError;
end;
function StrToDecimal32(const A: String): Decimal32;
begin
case TryStrToDecimal32(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function StrToDecimal32B(const A: RawByteString): Decimal32;
begin
case TryStrToDecimal32B(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
{ }
{ Decimal64 }
{ }
procedure Decimal64InitZero(var A: Decimal64);
begin
Word64InitZero(A.Value64);
end;
procedure Decimal64InitOne(var A: Decimal64);
begin
Word64InitInt64(A.Value64, Decimal64Scale);
end;
procedure Decimal64InitMax(var A: Decimal64);
begin
A.Value64 := Decimal64MaxValueW64;
end;
function Decimal64IsZero(const A: Decimal64): Boolean;
begin
Result := Word64IsZero(A.Value64);
end;
function Decimal64IsOne(const A: Decimal64): Boolean;
begin
Result := Word64EqualsWord32(A.Value64, Decimal64Scale);
end;
function Decimal64IsMaximum(const A: Decimal64): Boolean;
begin
Result := Word64EqualsWord64(A.Value64, Decimal64MaxValueW64);
end;
function Decimal64IsOverflow(const A: Decimal64): Boolean;
begin
Result := Word64CompareWord64(A.Value64, Decimal64MaxValueW64) > 0;
end;
function Word64IsDecimal64Range(const A: Word64Rec): Boolean;
begin
Result := Word64CompareInt64(A, Decimal64MaxInt) <= 0;
end;
function Int32IsDecimal64Range(const A: Int32): Boolean;
begin
Result := A >= 0;
end;
function Int64IsDecimal64Range(const A: Int64): Boolean;
begin
Result := (A >= 0) and (A <= Decimal64MaxInt);
end;
function FloatIsDecimal64Range(const A: Double): Boolean;
begin
Result :=
(A >= Decimal64MinFloatD) and
(A < Decimal64MaxFloatLimD);
end;
procedure Decimal64InitWord8(var A: Decimal64; const B: Byte);
begin
Word64InitInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
procedure Decimal64InitWord16(var A: Decimal64; const B: Word);
begin
Word64InitInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
procedure Decimal64InitWord32(var A: Decimal64; const B: Word32);
begin
Word64InitInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
procedure Decimal64InitWord64(var A: Decimal64; const B: Word64Rec);
var T, F : Word64Rec;
begin
if Word64CompareInt64(B, Decimal64MaxInt) > 0 then
raise EDecimalError.Create(SOverflowError);
T := B;
Word64InitInt64(F, Decimal64Scale);
Word64MultiplyWord64InPlace(T, F);
A.Value64 := T;
end;
procedure Decimal64InitInt32(var A: Decimal64; const B: Int32);
var T, F : Word64Rec;
begin
if (B < 0) or (B > Decimal64MaxInt) then
raise EDecimalError.Create(SOverflowError);
Word64InitInt32(T, B);
Word64InitInt64(F, Decimal64Scale);
Word64MultiplyWord64InPlace(T, F);
A.Value64 := T;
end;
procedure Decimal64InitInt64(var A: Decimal64; const B: Int64);
var T, F : Word64Rec;
begin
if (B < 0) or (B > Decimal64MaxInt) then
raise EDecimalError.Create(SOverflowError);
Word64InitInt64(T, B);
Word64InitInt64(F, Decimal64Scale);
Word64MultiplyWord64InPlace(T, F);
A.Value64 := T;
end;
procedure Decimal64InitDecimal32(var A: Decimal64; const B: Decimal32);
var T, Q : Word64Rec;
R : Word;
begin
Word64InitWord32(T, B.Value32);
Word64MultiplyWord32(T, Decimal64Scale);
Word64DivideWord16(T, Decimal32Scale, Q, R);
A.Value64 := Q;
end;
procedure Decimal64InitDecimal64(var A: Decimal64; const B: Decimal64);
begin
A.Value64 := B.Value64;
end;
procedure Decimal64InitFloat(var A: Decimal64; const B: Double);
var D : Double;
I : Int64;
begin
if not FloatIsDecimal64Range(B) then
raise EDecimalError.Create(SOverflowError);
D := B * Decimal64Scale;
I := Round(D);
Word64InitInt64(A.Value64, I);
end;
function Decimal64ToWord8(const A: Decimal64): Byte;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
if R <> 0 then
raise EDecimalError.Create(SConvertError);
if not Word64IsWord8Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word64ToWord32(Q);
end;
function Decimal64ToWord16(const A: Decimal64): Word;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
if R <> 0 then
raise EDecimalError.Create(SConvertError);
if not Word64IsWord16Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word64ToWord32(Q);
end;
function Decimal64ToWord32(const A: Decimal64): Word32;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
if R <> 0 then
raise EDecimalError.Create(SConvertError);
Result := Word64ToWord32(Q);
end;
function Decimal64ToWord64(const A: Decimal64): Word64Rec;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
if R <> 0 then
raise EDecimalError.Create(SConvertError);
Result := Q;
end;
function Decimal64ToInt32(const A: Decimal64): Int32;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
if R <> 0 then
raise EDecimalError.Create(SConvertError);
if not Word64IsInt32Range(Q) then
raise EDecimalError.Create(SConvertError);
Result := Word64ToInt32(Q);
end;
function Decimal64ToInt64(const A: Decimal64): Int64;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
if R <> 0 then
raise EDecimalError.Create(SConvertError);
Result := Word64ToInt64(Q);
end;
function Decimal64ToDecimal32(const A: Decimal64): Decimal32;
var T, Q : Word128;
R : Word32;
begin
Word128InitWord64(T, A.Value64);
Word128MultiplyWord16(T, Decimal32Scale);
Word128DivideWord32(T, Decimal64Scale, Q, R);
if Word128CompareWord32(Q, Decimal32MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
Result.Value32 := Word128ToWord32(Q);
end;
function Decimal64ToFloat(const A: Decimal64): Double;
begin
Result := Word64ToFloat(A.Value64) / Decimal64Scale;
end;
function Decimal64Trunc(const A: Decimal64): Int64;
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, Q, R);
Result := Word64ToInt64(Q);
end;
function Decimal64Round(const A: Decimal64): Int64;
var F : Word32;
R : Word64Rec;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, R, F);
if (F > Decimal64RoundTerm) or
((F = Decimal64RoundTerm) and Word64IsOdd(R)) then
Word64Inc(R);
Result := Word64ToInt64(R);
end;
function Decimal64FracWord(const A: Decimal64): Word32;
var R : Word64Rec;
F : Word32;
begin
Word64DivideWord32(A.Value64, Decimal64Scale, R, F);
Result := F;
end;
function Decimal64EqualsWord8(const A: Decimal64; const B: Byte): Boolean;
begin
Result := Word64EqualsInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
function Decimal64EqualsWord16(const A: Decimal64; const B: Word): Boolean;
begin
Result := Word64EqualsInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
function Decimal64EqualsWord32(const A: Decimal64; const B: Word32): Boolean;
begin
Result := Word64EqualsInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
function Decimal64EqualsInt32(const A: Decimal64; const B: Int32): Boolean;
begin
if B < 0 then
Result := False
else
Result := Word64EqualsInt64(A.Value64, Int64(B) * Decimal64Scale);
end;
function Decimal64EqualsInt64(const A: Decimal64; const B: Int64): Boolean;
var T : Word128;
begin
if B < 0 then
Result := False
else
if B > Decimal64MaxInt then
Result := False
else
begin
Word128InitInt64(T, B);
Word128MultiplyWord32(T, Decimal64Scale);
Result := Word128EqualsWord64(T, A.Value64);
end;
end;
function Decimal64EqualsDecimal64(const A: Decimal64; const B: Decimal64): Boolean;
begin
Result := Word64EqualsWord64(A.Value64, B.Value64);
end;
function Decimal64EqualsFloat(const A: Decimal64; const B: Double): Boolean;
var T : Decimal64;
begin
if not FloatIsDecimal64Range(B) then
Result := False
else
begin
Decimal64InitFloat(T, B);
Result := Word64EqualsWord64(T.Value64, A.Value64);
end;
end;
function Decimal64CompareWord8(const A: Decimal64; const B: Byte): Integer;
var C : Int64;
begin
C := Int64(B) * Decimal64Scale;
Result := Word64CompareInt64(A.Value64, C);
end;
function Decimal64CompareWord16(const A: Decimal64; const B: Word): Integer;
var C : Int64;
begin
C := Int64(B) * Decimal64Scale;
Result := Word64CompareInt64(A.Value64, C);
end;
function Decimal64CompareWord32(const A: Decimal64; const B: Word32): Integer;
var C : Int64;
begin
C := Int64(B) * Decimal64Scale;
Result := Word64CompareInt64(A.Value64, C);
end;
function Decimal64CompareInt32(const A: Decimal64; const B: Int32): Integer;
var C : Int64;
begin
if B < 0 then
Result := 1
else
begin
C := Int64(B) * Decimal64Scale;
Result := Word64CompareInt64(A.Value64, C);
end;
end;
function Decimal64CompareInt64(const A: Decimal64; const B: Int64): Integer;
var T : Word128;
begin
if B < 0 then
Result := 1
else
begin
Word128InitInt64(T, B);
Word128MultiplyWord32(T, Decimal64Scale);
Result := -Word128CompareWord64(T, A.Value64);
end;
end;
function Decimal64CompareDecimal64(const A: Decimal64; const B: Decimal64): Integer;
begin
Result := Word64CompareWord64(A.Value64, B.Value64);
end;
function Decimal64CompareFloat(const A: Decimal64; const B: Double): Integer;
var T : Decimal64;
begin
if B < Decimal64MinFloatD then
Result := 1
else
if B >= Decimal64MaxFloatLimD then
Result := -1
else
begin
Assert(FloatIsDecimal64Range(B));
Decimal64InitFloat(T, B);
Result := Word64CompareWord64(A.Value64, T.Value64);
end;
end;
procedure Decimal64AddWord8(var A: Decimal64; const B: Byte);
var T, Q : Word64Rec;
begin
T := A.Value64;
Word64InitWord32(Q, B);
Word64MultiplyWord32(Q, Decimal64Scale);
Word64AddWord64(T, Q);
if Word64CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := T;
end;
procedure Decimal64AddWord16(var A: Decimal64; const B: Word);
var T, Q : Word64Rec;
begin
T := A.Value64;
Word64InitWord32(Q, B);
Word64MultiplyWord32(Q, Decimal64Scale);
Word64AddWord64(T, Q);
if Word64CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := T;
end;
procedure Decimal64AddWord32(var A: Decimal64; const B: Word32);
var T, Q : Word128;
begin
Word128InitWord64(T, A.Value64);
Word128InitWord32(Q, B);
Word128MultiplyWord32(Q, Decimal64Scale);
Word128AddWord128(T, Q);
if Word128CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := Word128ToWord64(T);
end;
procedure Decimal64AddDecimal64(var A: Decimal64; const B: Decimal64);
var T : Word128;
begin
Word128InitWord64(T, A.Value64);
Word128AddWord64(T, B.Value64);
if Word128CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := Word128ToWord64(T);
end;
procedure Decimal64SubtractWord8(var A: Decimal64; const B: Byte);
var T, Q : Word64Rec;
begin
T := A.Value64;
Word64InitWord32(Q, B);
Word64MultiplyWord32(Q, Decimal64Scale);
if Word64CompareWord64(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word64SubtractWord64(T, Q);
A.Value64 := T;
end;
procedure Decimal64SubtractWord16(var A: Decimal64; const B: Word);
var T, Q : Word64Rec;
begin
T := A.Value64;
Word64InitWord32(Q, B);
Word64MultiplyWord32(Q, Decimal64Scale);
if Word64CompareWord64(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word64SubtractWord64(T, Q);
A.Value64 := T;
end;
procedure Decimal64SubtractWord32(var A: Decimal64; const B: Word32);
var T, Q : Word64Rec;
begin
T := A.Value64;
Word64InitWord32(Q, B);
Word64MultiplyWord32(Q, Decimal64Scale);
if Word64CompareWord64(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word64SubtractWord64(T, Q);
A.Value64 := T;
end;
procedure Decimal64SubtractDecimal64(var A: Decimal64; const B: Decimal64);
begin
if Word64CompareWord64(A.Value64, B.Value64) < 0 then
raise EDecimalError.Create(SOverflowError);
Word64SubtractWord64(A.Value64, B.Value64);
end;
procedure Decimal64MultiplyWord8(var A: Decimal64; const B: Byte);
var T : Word128;
begin
Word128InitWord64(T, A.Value64);
Word128MultiplyWord8(T, B);
if Word128CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := Word128ToWord64(T);
end;
procedure Decimal64MultiplyWord16(var A: Decimal64; const B: Word);
var T : Word128;
begin
Word128InitWord64(T, A.Value64);
Word128MultiplyWord16(T, B);
if Word128CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := Word128ToWord64(T);
end;
procedure Decimal64MultiplyWord32(var A: Decimal64; const B: Word32);
var T : Word128;
begin
Word128InitWord64(T, A.Value64);
Word128MultiplyWord32(T, B);
if Word128CompareWord64(T, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := Word128ToWord64(T);
end;
procedure Decimal64MultiplyDecimal64(var A: Decimal64; const B: Decimal64);
var T, Q : Word128;
R : Word32;
begin
Word128InitWord64(T, A.Value64);
Word128MultiplyWord64(T, B.Value64);
Word128AddWord32(T, Decimal64RoundTerm);
Word128DivideWord32(T, Decimal64Scale, Q, R);
if Word128CompareWord64(Q, Decimal64MaxValueW64) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value64 := Word128ToWord64(Q);
end;
procedure Decimal64Sqr(var A: Decimal64);
begin
Decimal64MultiplyDecimal64(A, A);
end;
procedure Decimal64DivideWord8(var A: Decimal64; const B: Byte);
var Q : Word64Rec;
R : Byte;
begin
Word64DivideWord8(A.Value64, B, Q, R);
A.Value64 := Q;
end;
procedure Decimal64DivideWord16(var A: Decimal64; const B: Word);
var Q : Word64Rec;
R : Word;
begin
Word64DivideWord16(A.Value64, B, Q, R);
A.Value64 := Q;
end;
procedure Decimal64DivideWord32(var A: Decimal64; const B: Word32);
var Q : Word64Rec;
R : Word32;
begin
Word64DivideWord32(A.Value64, B, Q, R);
A.Value64 := Q;
end;
procedure Decimal64DivideDecimal64(var A: Decimal64; const B: Decimal64);
var T : Word128;
Q : Word64Rec;
F : Word128;
G : Word64Rec;
begin
Word128InitWord64(T, A.Value64);
Word64InitInt64(Q, Decimal64Scale);
Word128MultiplyWord64(T, Q);
Word128DivideWord64(T, B.Value64, F, G);
A.Value64 := Word128ToWord64(F);
end;
function Decimal64ToStr(const A: Decimal64): String;
var
S : String;
L : Integer;
begin
if Word64IsZero(A.Value64) then
begin
Result := '0.000000000';
exit;
end;
S := StrPadLeft(Word64ToStr(A.Value64), '0', Decimal64Precision + 1, False);
L := Length(S);
Result :=
CopyLeft(S, L - Decimal64Precision) + '.' +
CopyRight(S, Decimal64Precision);
end;
function Decimal64ToStrB(const A: Decimal64): RawByteString;
var
S : RawByteString;
L : Integer;
begin
if Word64IsZero(A.Value64) then
begin
Result := '0.000000000';
exit;
end;
S := StrPadLeftB(Word64ToStrB(A.Value64), '0', Decimal64Precision + 1, False);
L := Length(S);
Result :=
CopyLeftB(S, L - Decimal64Precision) + '.' +
CopyRightB(S, Decimal64Precision);
end;
function Decimal64ToStrU(const A: Decimal64): UnicodeString;
var
S : UnicodeString;
L : Integer;
begin
if Word64IsZero(A.Value64) then
begin
Result := '0.000000000';
exit;
end;
S := StrPadLeftU(Word64ToStrU(A.Value64), '0', Decimal64Precision + 1, False);
L := Length(S);
Result :=
CopyLeftU(S, L - Decimal64Precision) + '.' +
CopyRightU(S, Decimal64Precision);
end;
function TryStrToDecimal64(const A: String; out B: Decimal64): TDecimalConvertErrorType;
var
ResInt : Word128;
ResIntDigits : Integer;
ResFrac : Word64Rec;
ResFracDigits : Integer;
ResFracRoundDigit : Integer;
ResExp : Integer;
ResExpSign : Integer;
Res : Word64Rec;
R : Byte;
I, L : Integer;
C : Char;
Digit : Integer;
DigitFactor : Word64Rec;
T : Word64Rec;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
Word128InitZero(ResInt);
ResIntDigits := 0;
repeat
C := A[I];
if (C = '.') or (C = 'E') then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResIntDigits);
Word128MultiplyWord8(ResInt, 10);
Word128AddWord8(ResInt, Digit);
if Word128CompareWord64(ResInt, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
if ResIntDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction part
Word64InitZero(ResFrac);
ResFracDigits := 0;
ResFracRoundDigit := 0;
if I <= L then
begin
C := A[I];
if C = '.' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
Word64InitWord32(DigitFactor, Decimal64Scale);
Word64DivideWord8(DigitFactor, 10, DigitFactor, R);
repeat
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResFracDigits);
T := DigitFactor;
Word64MultiplyWord8(T, Byte(Digit));
Word64AddWord64(ResFrac, T);
Word64DivideWord8(DigitFactor, 10, DigitFactor, R);
if Word64IsZero(DigitFactor) then
break;
until I > L;
if ResFracDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction rounding
if (I <= L) and (A[I] <> 'E') then
begin
C := A[I];
ResFracRoundDigit := CharDigitToInt(C);
Inc(I);
if ResFracRoundDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if ResFracRoundDigit = 5 then
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
if Digit > 0 then
begin
ResFracRoundDigit := 6;
break;
end;
end;
// validate remaining fraction digits
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
end;
end;
end;
end;
// exponent
ResExp := 0;
ResExpSign := 0;
if I <= L then
begin
C := A[I];
if C = 'E' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
C := A[I];
if (C = '+') or (C = '-') then
begin
if C = '+' then
ResExpSign := 1
else
ResExpSign := -1;
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
end;
repeat
C := A[I];
Digit := CharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResExp := ResExp * 10 + Digit;
if ResExp > 9999 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
end;
end;
// end of string
if I <= L then
begin
Result := dceConvertError;
exit;
end;
// combine integer and fractional parts
if Word128CompareInt64(ResInt, Decimal64MaxInt) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Res := Word128ToWord64(ResInt);
Word64MultiplyWord32(Res, Decimal64Scale);
Word64AddWord64(Res, ResFrac);
// round
if (ResFracRoundDigit > 5) or
((ResFracRoundDigit = 5) and Word64IsOdd(Res)) then
begin
Word64Inc(Res);
if Word64CompareWord64(Res, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
end;
// exponent
if not Word64IsZero(Res) then
if ResExpSign >= 0 then
while ResExp > 0 do
begin
Word64MultiplyWord8(Res, 10);
if Word64CompareWord64(Res, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Dec(ResExp);
end
else
while ResExp > 0 do
begin
Word64DivideWord8(Res, 10, Res, R);
if Word64IsZero(Res) then
break;
Dec(ResExp);
end;
// result
B.Value64 := Res;
Result := dceNoError;
end;
function TryStrToDecimal64B(const A: RawByteString; out B: Decimal64): TDecimalConvertErrorType;
var
ResInt : Word128;
ResIntDigits : Integer;
ResFrac : Word64Rec;
ResFracDigits : Integer;
ResFracRoundDigit : Integer;
ResExp : Integer;
ResExpSign : Integer;
Res : Word64Rec;
R : Byte;
I, L : Integer;
C : AnsiChar;
Digit : Integer;
DigitFactor : Word64Rec;
T : Word64Rec;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
I := 1;
// integer part
Word128InitZero(ResInt);
ResIntDigits := 0;
repeat
C := A[I];
if (C = '.') or (C = 'E') then
break;
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResIntDigits);
Word128MultiplyWord8(ResInt, 10);
Word128AddWord8(ResInt, Digit);
if Word128CompareWord64(ResInt, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
if ResIntDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction part
Word64InitZero(ResFrac);
ResFracDigits := 0;
ResFracRoundDigit := 0;
if I <= L then
begin
C := A[I];
if C = '.' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
Word64InitWord32(DigitFactor, Decimal64Scale);
Word64DivideWord8(DigitFactor, 10, DigitFactor, R);
repeat
C := A[I];
if C = 'E' then
break;
Digit := ByteCharDigitToInt(C);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(ResFracDigits);
T := DigitFactor;
Word64MultiplyWord8(T, Byte(Digit));
Word64AddWord64(ResFrac, T);
Word64DivideWord8(DigitFactor, 10, DigitFactor, R);
if Word64IsZero(DigitFactor) then
break;
until I > L;
if ResFracDigits = 0 then
begin
Result := dceConvertError;
exit;
end;
// fraction rounding
if (I <= L) and (A[I] <> 'E') then
begin
C := A[I];
ResFracRoundDigit := ByteCharDigitToInt(C);
Inc(I);
if ResFracRoundDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if ResFracRoundDigit = 5 then
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
if Digit > 0 then
begin
ResFracRoundDigit := 6;
break;
end;
end;
// validate remaining fraction digits
while I <= L do
begin
C := A[I];
if C = 'E' then
break;
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
end;
end;
end;
end;
// exponent
ResExp := 0;
ResExpSign := 0;
if I <= L then
begin
C := A[I];
if C = 'E' then
begin
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
C := A[I];
if (C = '+') or (C = '-') then
begin
if C = '+' then
ResExpSign := 1
else
ResExpSign := -1;
Inc(I);
if I > L then
begin
Result := dceConvertError;
exit;
end;
end;
repeat
C := A[I];
Digit := ByteCharDigitToInt(C);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
ResExp := ResExp * 10 + Digit;
if ResExp > 9999 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
until I > L;
end;
end;
// end of string
if I <= L then
begin
Result := dceConvertError;
exit;
end;
// combine integer and fractional parts
if Word128CompareInt64(ResInt, Decimal64MaxInt) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Res := Word128ToWord64(ResInt);
Word64MultiplyWord32(Res, Decimal64Scale);
Word64AddWord64(Res, ResFrac);
// round
if (ResFracRoundDigit > 5) or
((ResFracRoundDigit = 5) and Word64IsOdd(Res)) then
begin
Word64Inc(Res);
if Word64CompareWord64(Res, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
end;
// exponent
if not Word64IsZero(Res) then
if ResExpSign >= 0 then
while ResExp > 0 do
begin
Word64MultiplyWord8(Res, 10);
if Word64CompareWord64(Res, Decimal64MaxValueW64) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Dec(ResExp);
end
else
while ResExp > 0 do
begin
Word64DivideWord8(Res, 10, Res, R);
if Word64IsZero(Res) then
break;
Dec(ResExp);
end;
// result
B.Value64 := Res;
Result := dceNoError;
end;
function StrToDecimal64(const A: String): Decimal64;
begin
case TryStrToDecimal64(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function StrToDecimal64B(const A: RawByteString): Decimal64;
begin
case TryStrToDecimal64B(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
{ }
{ Decimal128 }
{ }
procedure Decimal128InitZero(var A: Decimal128);
begin
Word128InitZero(A.Value128);
end;
procedure Decimal128InitOne(var A: Decimal128);
begin
Word128InitWord64(A.Value128, Decimal128Scale);
end;
procedure Decimal128InitMax(var A: Decimal128);
begin
A.Value128 := Decimal128MaxValue;
end;
function Decimal128IsZero(const A: Decimal128): Boolean;
begin
Result := Word128IsZero(A.Value128);
end;
function Decimal128IsOne(const A: Decimal128): Boolean;
begin
Result := Word128EqualsWord64(A.Value128, Decimal128Scale);
end;
function Decimal128IsMaximum(const A: Decimal128): Boolean;
begin
Result := Word128EqualsWord128(A.Value128, Decimal128MaxValue);
end;
function Decimal128IsOverflow(const A: Decimal128): Boolean;
begin
Result := Word128CompareWord128(A.Value128, Decimal128MaxValue) > 0;
end;
function Word64IsDecimal128Range(const A: Word64Rec): Boolean;
begin
Result := Word64CompareWord64(A, Decimal128MaxInt) <= 0;
end;
function Word128IsDecimal128Range(const A: Word128): Boolean;
begin
Result := Word128CompareWord64(A, Decimal128MaxInt) <= 0;
end;
function Int64IsDecimal128Range(const A: Int64): Boolean;
begin
Result := A >= 0;
end;
function Int128IsDecimal128Range(const A: Int128): Boolean;
begin
Result :=
not Int128IsNegative(A) and
(Int128CompareWord64(A, Decimal128MaxInt) <= 0);
end;
function FloatIsDecimal128Range(const A: Double): Boolean;
begin
Result :=
(A >= Decimal128MinFloatD) and
(A < Decimal128MaxFloatLimD);
end;
procedure Decimal128InitWord8(var A: Decimal128; const B: Byte);
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord8(T, B);
A.Value128 := T;
end;
procedure Decimal128InitWord16(var A: Decimal128; const B: Word);
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord16(T, B);
A.Value128 := T;
end;
procedure Decimal128InitWord32(var A: Decimal128; const B: Word32);
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord32(T, B);
A.Value128 := T;
end;
procedure Decimal128InitWord64(var A: Decimal128; const B: Word64Rec);
var T : Word128;
begin
if Word64CompareWord64(B, Decimal128MaxInt) > 0 then
raise EDecimalError.Create(SOverflowError);
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord64(T, B);
A.Value128 := T;
end;
procedure Decimal128InitInt32(var A: Decimal128; const B: Int32);
var T : Word128;
begin
if B < 0 then
raise EDecimalError.Create(SOverflowError);
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord32(T, B);
A.Value128 := T;
end;
procedure Decimal128InitInt64(var A: Decimal128; const B: Int64);
var T : Word128;
Q : Word64Rec;
begin
if B < 0 then
raise EDecimalError.Create(SOverflowError);
Word128InitWord64(T, Decimal128Scale);
Word64InitInt64(Q, B);
Word128MultiplyWord64(T, Q);
A.Value128 := T;
end;
procedure Decimal128InitDecimal64(var A: Decimal128; const B: Decimal64);
var T, Q : Word128;
R : Word32;
begin
Word128InitWord64(T, B.Value64);
Word128MultiplyWord64(T, Decimal128Scale);
Word128DivideWord32(T, Decimal64Scale, Q, R);
A.Value128 := Q;
end;
procedure Decimal128InitDecimal128(var A: Decimal128; const B: Decimal128);
begin
A.Value128 := B.Value128;
end;
procedure Decimal128InitFloat(var A: Decimal128; const B: Double);
var C, I, F : Double;
L : Int64;
begin
if not FloatIsDecimal128Range(B) then
raise EDecimalError.Create(SOverflowError);
C := B * Decimal128ScaleF;
I := Int(C);
F := Frac(C);
L := Round(I - (Int(I / 10) * 10));
if (F > 0.5) or
((F = 0.5) and (L and 1 = 1)) then
I := I + 1.0;
Word128InitFloat(A.Value128, I);
end;
function Decimal128ToWord8(const A: Decimal128): Byte;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
if not Word64IsZero(R) then
raise EDecimalError.Create(SConvertError);
if not Word128IsWord8Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word128ToWord32(Q);
end;
function Decimal128ToWord16(const A: Decimal128): Word;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
if not Word64IsZero(R) then
raise EDecimalError.Create(SConvertError);
if not Word128IsWord16Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word128ToWord32(Q);
end;
function Decimal128ToWord32(const A: Decimal128): Word32;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
if not Word64IsZero(R) then
raise EDecimalError.Create(SConvertError);
if not Word128IsWord32Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word128ToWord32(Q);
end;
function Decimal128ToWord64(const A: Decimal128): Word64Rec;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
if not Word64IsZero(R) then
raise EDecimalError.Create(SConvertError);
if not Word128IsWord64Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word128ToWord64(Q);
end;
function Decimal128ToInt32(const A: Decimal128): Int32;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
if not Word64IsZero(R) then
raise EDecimalError.Create(SConvertError);
if not Word128IsInt32Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word128ToInt32(Q);
end;
function Decimal128ToInt64(const A: Decimal128): Int64;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
if not Word64IsZero(R) then
raise EDecimalError.Create(SConvertError);
if not Word128IsInt64Range(Q) then
raise EDecimalError.Create(SOverflowError);
Result := Word128ToInt64(Q);
end;
function Decimal128ToFloat(const A: Decimal128): Double;
begin
Result := Word128ToFloat(A.Value128) / Decimal128ScaleF;
end;
function Decimal128Trunc(const A: Decimal128): Word64Rec;
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, Q, R);
Result := Word128ToWord64(Q);
end;
function Decimal128Round(const A: Decimal128): Word64Rec;
var F : Word64Rec;
R : Word128;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, R, F);
if (Word64CompareWord64(F, Decimal128RoundTerm) > 0) or
(Word64EqualsWord64(F, Decimal128RoundTerm) and Word128IsOdd(R)) then
Word128Inc(R);
Result := Word128ToWord64(R);
end;
function Decimal128FracWord(const A: Decimal128): Word64Rec;
var R : Word128;
F : Word64Rec;
begin
Word128DivideWord64(A.Value128, Decimal128Scale, R, F);
Result := F;
end;
function Decimal128EqualsWord8(const A: Decimal128; const B: Byte): Boolean;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord8(T, B);
Result := Word128EqualsWord128(A.Value128, T);
end;
function Decimal128EqualsWord16(const A: Decimal128; const B: Word): Boolean;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord16(T, B);
Result := Word128EqualsWord128(A.Value128, T);
end;
function Decimal128EqualsWord32(const A: Decimal128; const B: Word32): Boolean;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord32(T, B);
Result := Word128EqualsWord128(A.Value128, T);
end;
function Decimal128EqualsWord64(const A: Decimal128; const B: Word64Rec): Boolean;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord64(T, B);
Result := Word128EqualsWord128(A.Value128, T);
end;
function Decimal128EqualsInt32(const A: Decimal128; const B: Int32): Boolean;
begin
if B < 0 then
Result := False
else
Result := Decimal128EqualsWord32(A, B);
end;
function Decimal128EqualsInt64(const A: Decimal128; const B: Int64): Boolean;
var T : Word64Rec;
begin
if B < 0 then
Result := False
else
begin
Word64InitInt64(T, B);
Result := Decimal128EqualsWord64(A, T);
end;
end;
function Decimal128EqualsDecimal128(const A: Decimal128; const B: Decimal128): Boolean;
begin
Result := Word128EqualsWord128(A.Value128, B.Value128);
end;
function Decimal128EqualsFloat(const A: Decimal128; const B: Double): Boolean;
var T : Decimal128;
begin
if not FloatIsDecimal128Range(B) then
Result := False
else
begin
Decimal128InitFloat(T, B);
Result := Word128EqualsWord128(T.Value128, A.Value128);
end;
end;
function Decimal128CompareWord8(const A: Decimal128; const B: Byte): Integer;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord8(T, B);
Result := Word128CompareWord128(A.Value128, T);
end;
function Decimal128CompareWord16(const A: Decimal128; const B: Word): Integer;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord16(T, B);
Result := Word128CompareWord128(A.Value128, T);
end;
function Decimal128CompareWord32(const A: Decimal128; const B: Word32): Integer;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord32(T, B);
Result := Word128CompareWord128(A.Value128, T);
end;
function Decimal128CompareWord64(const A: Decimal128; const B: Word64Rec): Integer;
var T : Word128;
begin
Word128InitWord64(T, Decimal128Scale);
Word128MultiplyWord64(T, B);
Result := Word128CompareWord128(A.Value128, T);
end;
function Decimal128CompareDecimal128(const A: Decimal128; const B: Decimal128): Integer;
begin
Result := Word128CompareWord128(A.Value128, B.Value128);
end;
function Decimal128CompareFloat(const A: Decimal128; const B: Double): Integer;
var T : Decimal128;
begin
if B < Decimal128MinFloatD then
Result := 1
else
if B >= Decimal128MaxFloatLimD then
Result := -1
else
begin
Assert(FloatIsDecimal128Range(B));
Decimal128InitFloat(T, B);
Result := Word128CompareWord128(A.Value128, T.Value128);
end;
end;
procedure Decimal128AddWord8(var A: Decimal128; const B: Byte);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord32(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
Word128AddWord128(T, Q);
if Word128CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := T;
end;
procedure Decimal128AddWord16(var A: Decimal128; const B: Word);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord32(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
Word128AddWord128(T, Q);
if Word128CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := T;
end;
procedure Decimal128AddWord32(var A: Decimal128; const B: Word32);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord32(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
Word128AddWord128(T, Q);
if Word128CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := T;
end;
procedure Decimal128AddWord64(var A: Decimal128; const B: Word64Rec);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord64(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
Word128AddWord128(T, Q);
if Word128CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := T;
end;
procedure Decimal128AddDecimal128(var A: Decimal128; const B: Decimal128);
var T : Word256;
begin
Word256InitWord128(T, A.Value128);
Word256AddWord128(T, B.Value128);
if Word256CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := Word256ToWord128(T);
end;
procedure Decimal128SubtractWord8(var A: Decimal128; const B: Byte);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord32(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
if Word128CompareWord128(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word128SubtractWord128(T, Q);
A.Value128 := T;
end;
procedure Decimal128SubtractWord16(var A: Decimal128; const B: Word);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord32(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
if Word128CompareWord128(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word128SubtractWord128(T, Q);
A.Value128 := T;
end;
procedure Decimal128SubtractWord32(var A: Decimal128; const B: Word32);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord32(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
if Word128CompareWord128(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word128SubtractWord128(T, Q);
A.Value128 := T;
end;
procedure Decimal128SubtractWord64(var A: Decimal128; const B: Word64Rec);
var T, Q : Word128;
begin
T := A.Value128;
Word128InitWord64(Q, B);
Word128MultiplyWord64(Q, Decimal128Scale);
if Word128CompareWord128(T, Q) < 0 then
raise EDecimalError.Create(SOverflowError);
Word128SubtractWord128(T, Q);
A.Value128 := T;
end;
procedure Decimal128SubtractDecimal128(var A: Decimal128; const B: Decimal128);
begin
if Word128CompareWord128(A.Value128, B.Value128) < 0 then
raise EDecimalError.Create(SOverflowError);
Word128SubtractWord128(A.Value128, B.Value128);
end;
procedure Decimal128MultiplyWord8(var A: Decimal128; const B: Byte);
var T : Word256;
begin
Word256InitWord128(T, A.Value128);
Word256MultiplyWord8(T, B);
if Word256CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := Word256ToWord128(T);
end;
procedure Decimal128MultiplyWord16(var A: Decimal128; const B: Word);
var T : Word256;
begin
Word256InitWord128(T, A.Value128);
Word256MultiplyWord16(T, B);
if Word256CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := Word256ToWord128(T);
end;
procedure Decimal128MultiplyWord32(var A: Decimal128; const B: Word32);
var T : Word256;
begin
Word256InitWord128(T, A.Value128);
Word256MultiplyWord32(T, B);
if Word256CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := Word256ToWord128(T);
end;
procedure Decimal128MultiplyWord64(var A: Decimal128; const B: Word64Rec);
var T : Word256;
begin
Word256InitWord128(T, A.Value128);
Word256MultiplyWord64(T, B);
if Word256CompareWord128(T, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := Word256ToWord128(T);
end;
procedure Decimal128MultiplyDecimal128(var A: Decimal128; const B: Decimal128);
var T, Q : Word256;
R : Word128;
begin
Word256InitWord128(T, A.Value128);
Word256MultiplyWord128(T, B.Value128);
Word256AddWord64(T, Decimal128RoundTerm);
Word256DivideWord128(T, Decimal128ScaleW128, Q, R);
if Word256CompareWord128(Q, Decimal128MaxValue) > 0 then
raise EDecimalError.Create(SOverflowError);
A.Value128 := Word256ToWord128(Q);
end;
procedure Decimal128Sqr(var A: Decimal128);
begin
Decimal128MultiplyDecimal128(A, A);
end;
procedure Decimal128DivideWord8(var A: Decimal128; const B: Byte);
var Q : Word128;
R : Byte;
begin
Word128DivideWord8(A.Value128, B, Q, R);
A.Value128 := Q;
end;
procedure Decimal128DivideWord16(var A: Decimal128; const B: Word);
var Q : Word128;
R : Word;
begin
Word128DivideWord16(A.Value128, B, Q, R);
A.Value128 := Q;
end;
procedure Decimal128DivideWord32(var A: Decimal128; const B: Word32);
var Q : Word128;
R : Word32;
begin
Word128DivideWord32(A.Value128, B, Q, R);
A.Value128 := Q;
end;
procedure Decimal128DivideWord64(var A: Decimal128; const B: Word64Rec);
var Q : Word128;
R : Word64Rec;
begin
Word128DivideWord64(A.Value128, B, Q, R);
A.Value128 := Q;
end;
procedure Decimal128DivideDecimal128(var A: Decimal128; const B: Decimal128);
var T : Word256;
Q : Word128;
F : Word256;
G : Word128;
begin
Word256InitWord128(T, A.Value128);
Word128InitWord64(Q, Decimal128Scale);
Word256MultiplyWord128(T, Q);
Word256DivideWord128(T, B.Value128, F, G);
A.Value128 := Word256ToWord128(F);
end;
function Decimal128ToStr(const A: Decimal128): String;
var
S : String;
L : Integer;
begin
if Word128IsZero(A.Value128) then
begin
Result := '0.0000000000000000000';
exit;
end;
S := StrPadLeft(Word128ToStr(A.Value128), '0', Decimal128Precision + 1, False);
L := Length(S);
Result :=
CopyLeft(S, L - Decimal128Precision) + '.' +
CopyRight(S, Decimal128Precision);
end;
function Decimal128ToStrB(const A: Decimal128): RawByteString;
var
S : RawByteString;
L : Integer;
begin
if Word128IsZero(A.Value128) then
begin
Result := '0.0000000000000000000';
exit;
end;
S := StrPadLeftB(Word128ToStrB(A.Value128), '0', Decimal128Precision + 1, False);
L := Length(S);
Result :=
CopyLeftB(S, L - Decimal128Precision) + '.' +
CopyRightB(S, Decimal128Precision);
end;
function Decimal128ToStrU(const A: Decimal128): UnicodeString;
var
S : UnicodeString;
L : Integer;
begin
if Word128IsZero(A.Value128) then
begin
Result := '0.0000000000000000000';
exit;
end;
S := StrPadLeftU(Word128ToStrU(A.Value128), '0', Decimal128Precision + 1, False);
L := Length(S);
Result :=
CopyLeftU(S, L - Decimal128Precision) + '.' +
CopyRightU(S, Decimal128Precision);
end;
function TryStrToDecimal128(const A: String; out B: Decimal128): TDecimalConvertErrorType;
var
ResInt : Word128;
ResFrac : Word128;
Res : Word128;
I, L : Integer;
Ch : Char;
Digit : Integer;
C, D : Word64Rec;
E : Byte;
T : Word128;
RoundingDigit : Integer;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
// integer part
Word128InitZero(ResInt);
I := 1;
while I <= L do
begin
Ch := A[I];
if Ch = '.' then
if I = 1 then
begin
Result := dceConvertError;
exit;
end
else
begin
if I = L then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
break;
end;
Digit := CharDigitToInt(Ch);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Word128MultiplyWord8(ResInt, 10);
Word128AddWord8(ResInt, Digit);
if Word128CompareWord64(ResInt, Decimal128MaxInt) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
end;
// fraction part
Word128InitZero(ResFrac);
Word64DivideWord8(Decimal128Scale, 10, C, E);
while I <= L do
begin
Digit := CharDigitToInt(A[I]);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Word128InitWord64(T, C);
Word128MultiplyWord8(T, Byte(Digit));
Word128AddWord128(ResFrac, T);
Word64DivideWord8(C, 10, D, E);
C := D;
if Word64IsZero(C) then
break;
end;
// rounding
if I <= L then
begin
RoundingDigit := CharDigitToInt(A[I]);
Inc(I);
if RoundingDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if RoundingDigit = 5 then
while I <= L do
begin
Digit := CharDigitToInt(A[I]);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
if Digit > 0 then
begin
RoundingDigit := 6;
break;
end;
end;
end
else
RoundingDigit := 0;
// validate remaining digits
while I <= L do
begin
Digit := CharDigitToInt(A[I]);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
end;
// combine integer and fractional parts
Res := ResInt;
Word128MultiplyWord64(Res, Decimal128Scale);
Word128AddWord128(Res, ResFrac);
// round
if (RoundingDigit > 5) or
((RoundingDigit = 5) and Word128IsOdd(Res)) then
begin
Word128Inc(Res);
if Word128CompareWord128(Res, Decimal128MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
end;
// result
B.Value128 := Res;
Result := dceNoError;
end;
function TryStrToDecimal128B(const A: RawByteString; out B: Decimal128): TDecimalConvertErrorType;
var
ResInt : Word128;
ResFrac : Word128;
Res : Word128;
I, L : Integer;
Ch : AnsiChar;
Digit : Integer;
C, D : Word64Rec;
E : Byte;
T : Word128;
RoundingDigit : Integer;
begin
L := Length(A);
if L = 0 then
begin
Result := dceConvertError;
exit;
end;
// integer part
Word128InitZero(ResInt);
I := 1;
while I <= L do
begin
Ch := A[I];
if Ch = '.' then
if I = 1 then
begin
Result := dceConvertError;
exit;
end
else
begin
if I = L then
begin
Result := dceConvertError;
exit;
end;
Inc(I);
break;
end;
Digit := ByteCharDigitToInt(Ch);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Word128MultiplyWord8(ResInt, 10);
Word128AddWord8(ResInt, Digit);
if Word128CompareWord64(ResInt, Decimal128MaxInt) > 0 then
begin
Result := dceOverflowError;
exit;
end;
Inc(I);
end;
// fraction part
Word128InitZero(ResFrac);
Word64DivideWord8(Decimal128Scale, 10, C, E);
while I <= L do
begin
Digit := ByteCharDigitToInt(A[I]);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
Word128InitWord64(T, C);
Word128MultiplyWord8(T, Byte(Digit));
Word128AddWord128(ResFrac, T);
Word64DivideWord8(C, 10, D, E);
C := D;
if Word64IsZero(C) then
break;
end;
// rounding
if I <= L then
begin
RoundingDigit := ByteCharDigitToInt(A[I]);
Inc(I);
if RoundingDigit < 0 then
begin
Result := dceConvertError;
exit;
end;
if RoundingDigit = 5 then
while I <= L do
begin
Digit := ByteCharDigitToInt(A[I]);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
if Digit > 0 then
begin
RoundingDigit := 6;
break;
end;
end;
end
else
RoundingDigit := 0;
// validate remaining digits
while I <= L do
begin
Digit := ByteCharDigitToInt(A[I]);
Inc(I);
if Digit < 0 then
begin
Result := dceConvertError;
exit;
end;
end;
// combine integer and fractional parts
Res := ResInt;
Word128MultiplyWord64(Res, Decimal128Scale);
Word128AddWord128(Res, ResFrac);
// round
if (RoundingDigit > 5) or
((RoundingDigit = 5) and Word128IsOdd(Res)) then
begin
Word128Inc(Res);
if Word128CompareWord128(Res, Decimal128MaxValue) > 0 then
begin
Result := dceOverflowError;
exit;
end;
end;
// result
B.Value128 := Res;
Result := dceNoError;
end;
function StrToDecimal128(const A: String): Decimal128;
begin
case TryStrToDecimal128(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function StrToDecimal128B(const A: RawByteString): Decimal128;
begin
case TryStrToDecimal128B(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
{ }
{ HugeDecimal }
{ }
// Returns number of bytes required to encode value B
function HugeDecimalEncLength32(const B: Word32): Integer;
var
L : Word32;
C : Integer;
begin
if B = 0 then
Result := 0
else
begin
L := B;
C := 0;
repeat
L := L div 10;
Inc(C);
until L = 0;
Result := C;
end;
end;
// Returns number of bytes required to encode value B
function HugeDecimalEncLength64(const B: Word64Rec): Integer;
var
L : Word64Rec;
R : Byte;
C : Integer;
begin
if Word64IsZero(B) then
Result := 0
else
begin
L := B;
C := 0;
repeat
Word64DivideWord8(L, 10, L, R);
Inc(C);
until Word64IsZero(L);
Result := C;
end;
end;
// Returns number of bytes required to encode value B
function HugeDecimalEncLength128(const B: Word128): Integer;
var
L : Word128;
R : Byte;
C : Integer;
begin
if Word128IsZero(B) then
Result := 0
else
begin
L := B;
C := 0;
repeat
Word128DivideWord8(L, 10, L, R);
Inc(C);
until Word128IsZero(L);
Result := C;
end;
end;
// Pre: A not initialised
// Post: A = 0
procedure HugeDecimalInit(out A: HugeDecimal);
begin
FillChar(A, SizeOf(HugeDecimal), 0);
end;
// Pre: A initialised
procedure HugeDecimalFinalise(var A: HugeDecimal);
begin
A.Digits := nil;
end;
// Pre: A not initialised
// Post: A = 0
procedure HugeDecimalInitZero(out A: HugeDecimal);
begin
HugeDecimalInit(A);
end;
// Pre: A not initialised
// Post: A = 1
procedure HugeDecimalInitOne(out A: HugeDecimal);
begin
HugeDecimalInit(A);
HugeDecimalAssignOne(A);
end;
// Pre: A not initialised
procedure HugeDecimalInitWord8(out A: HugeDecimal; const B: Byte);
begin
HugeDecimalInit(A);
HugeDecimalAssignWord8(A, B);
end;
// Pre: A not initialised
procedure HugeDecimalInitWord32(out A: HugeDecimal; const B: Word32);
begin
HugeDecimalInit(A);
HugeDecimalAssignWord32(A, B);
end;
// Pre: A not initialised
procedure HugeDecimalInitWord64(out A: HugeDecimal; const B: Word64Rec);
begin
HugeDecimalInit(A);
HugeDecimalAssignWord64(A, B);
end;
// Pre: A not initialised
procedure HugeDecimalInitWord128(out A: HugeDecimal; const B: Word128);
begin
HugeDecimalInit(A);
HugeDecimalAssignWord128(A, B);
end;
// Pre: A not initialised
procedure HugeDecimalInitDecimal32(out A: HugeDecimal; const B: Decimal32);
begin
HugeDecimalInit(A);
HugeDecimalAssignDecimal32(A, B);
end;
// Pre: A not initialised
procedure HugeDecimalInitDecimal64(out A: HugeDecimal; const B: Decimal64);
begin
HugeDecimalInit(A);
HugeDecimalAssignDecimal64(A, B);
end;
// Pre: A not initialised
procedure HugeDecimalInitDecimal128(out A: HugeDecimal; const B: Decimal128);
begin
HugeDecimalInit(A);
HugeDecimalAssignDecimal128(A, B);
end;
// Pre: A not initialised
// B initialised
procedure HugeDecimalInitHugeDecimal(out A: HugeDecimal; const B: HugeDecimal);
begin
HugeDecimalInit(A);
HugeDecimalAssignHugeDecimal(A, B);
end;
// Pre: A initialised
// Post: A normalised
// A = 0
procedure HugeDecimalAssignZero(var A: HugeDecimal);
begin
A.Precision := 0;
SetLength(A.Digits, 0);
end;
// Pre: A initialised
// Post: A normalised
// A = 1
procedure HugeDecimalAssignOne(var A: HugeDecimal);
begin
A.Precision := 0;
SetLength(A.Digits, 1);
A.Digits[0] := 1;
end;
// Pre: A initialised
// Post: A normalised
procedure HugeDecimalAssignWord8(var A: HugeDecimal; const B: Byte);
begin
A.Precision := 0;
if B = 0 then
SetLength(A.Digits, 0)
else
if B < 10 then
begin
SetLength(A.Digits, 1);
A.Digits[0] := B;
end
else
if B < 100 then
begin
SetLength(A.Digits, 2);
A.Digits[0] := B mod 10;
A.Digits[1] := B div 10;
end
else
begin
SetLength(A.Digits, 3);
A.Digits[0] := B mod 10;
A.Digits[1] := (B div 10) mod 10;
A.Digits[2] := B div 100;
end;
end;
// Pre: A initialised
// Post: A normalised
procedure HugeDecimalAssignWord32(var A: HugeDecimal; const B: Word32);
var
L : Word32;
I : Integer;
begin
A.Precision := 0;
if B = 0 then
SetLength(A.Digits, 0)
else
begin
SetLength(A.Digits, HugeDecimalEncLength32(B));
L := B;
I := 0;
repeat
A.Digits[I] := L mod 10;
L := L div 10;
Inc(I);
until L = 0;
end;
end;
// Pre: A initialised
// Post: A normalised
procedure HugeDecimalAssignWord64(var A: HugeDecimal; const B: Word64Rec);
var
L : Word64Rec;
R : Byte;
I : Integer;
begin
A.Precision := 0;
if Word64IsZero(B) then
SetLength(A.Digits, 0)
else
begin
SetLength(A.Digits, HugeDecimalEncLength64(B));
L := B;
I := 0;
repeat
Word64DivideWord8(L, 10, L, R);
A.Digits[I] := R;
Inc(I);
until Word64IsZero(L);
end;
end;
// Pre: A initialised
// Post: A normalised
procedure HugeDecimalAssignWord128(var A: HugeDecimal; const B: Word128);
var
L : Word128;
R : Byte;
I : Integer;
begin
A.Precision := 0;
if Word128IsZero(B) then
SetLength(A.Digits, 0)
else
begin
SetLength(A.Digits, HugeDecimalEncLength128(B));
L := B;
I := 0;
repeat
Word128DivideWord8(L, 10, L, R);
A.Digits[I] := R;
Inc(I);
until Word128IsZero(L);
end;
end;
// Post: A normalised
procedure HugeDecimalAssignDecimal32(var A: HugeDecimal; const B: Decimal32);
var
Val32 : Word32;
DigitCnt, DigitIdx : Integer;
Digit : Byte;
const
MaxDigits = Decimal32Digits;
Precision = Decimal32Precision;
begin
A.Precision := 0;
Val32 := B.Value32;
if Val32 = 0 then
begin
SetLength(A.Digits, 0);
exit;
end;
SetLength(A.Digits, MaxDigits);
DigitIdx := 0;
// skip trailing decimal zeros
Digit := Val32 mod 10;
Val32 := Val32 div 10;
DigitCnt := 1;
while Digit = 0 do
begin
Digit := Val32 mod 10;
Val32 := Val32 div 10;
Inc(DigitCnt);
if DigitCnt > Precision then
break;
end;
// store significant decimal digits
while DigitCnt <= Precision do
begin
Inc(A.Precision);
A.Digits[DigitIdx] := Digit;
Inc(DigitIdx);
Digit := Val32 mod 10;
Val32 := Val32 div 10;
Inc(DigitCnt);
end;
// store interger digits
while (Digit > 0) or (Val32 > 0) do
begin
A.Digits[DigitIdx] := Digit;
Inc(DigitIdx);
Digit := Val32 mod 10;
Val32 := Val32 div 10;
end;
// set length
SetLength(A.Digits, DigitIdx);
end;
// Post: A normalised
procedure HugeDecimalAssignDecimal64(var A: HugeDecimal; const B: Decimal64);
var
Val64 : Word64Rec;
DigitCnt, DigitIdx : Integer;
Digit : Byte;
const
MaxDigits = Decimal64Digits;
Precision = Decimal64Precision;
begin
A.Precision := 0;
Val64 := B.Value64;
if Word64IsZero(Val64) then
begin
SetLength(A.Digits, 0);
exit;
end;
SetLength(A.Digits, MaxDigits);
DigitIdx := 0;
// skip trailing decimal zeros
Word64DivideWord8(Val64, 10, Val64, Digit);
DigitCnt := 1;
while Digit = 0 do
begin
Word64DivideWord8(Val64, 10, Val64, Digit);
Inc(DigitCnt);
if DigitCnt > Precision then
break;
end;
// store significant decimal digits
while DigitCnt <= Precision do
begin
Inc(A.Precision);
A.Digits[DigitIdx] := Digit;
Inc(DigitIdx);
Word64DivideWord8(Val64, 10, Val64, Digit);
Inc(DigitCnt);
end;
// store interger digits
while (Digit > 0) or not Word64IsZero(Val64) do
begin
A.Digits[DigitIdx] := Digit;
Inc(DigitIdx);
Word64DivideWord8(Val64, 10, Val64, Digit);
end;
// set length
SetLength(A.Digits, DigitIdx);
end;
// Post: A normalised
procedure HugeDecimalAssignDecimal128(var A: HugeDecimal; const B: Decimal128);
var
Val128 : Word128;
DigitCnt, DigitIdx : Integer;
Digit : Byte;
const
MaxDigits = Decimal128Digits;
Precision = Decimal128Precision;
begin
A.Precision := 0;
Val128 := B.Value128;
if Word128IsZero(Val128) then
begin
SetLength(A.Digits, 0);
exit;
end;
SetLength(A.Digits, MaxDigits);
DigitIdx := 0;
// skip trailing decimal zeros
Word128DivideWord8(Val128, 10, Val128, Digit);
DigitCnt := 1;
while Digit = 0 do
begin
Word128DivideWord8(Val128, 10, Val128, Digit);
Inc(DigitCnt);
if DigitCnt > Precision then
break;
end;
// store significant decimal digits
while DigitCnt <= Precision do
begin
Inc(A.Precision);
A.Digits[DigitIdx] := Digit;
Inc(DigitIdx);
Word128DivideWord8(Val128, 10, Val128, Digit);
Inc(DigitCnt);
end;
// store interger digits
while (Digit > 0) or not Word128IsZero(Val128) do
begin
A.Digits[DigitIdx] := Digit;
Inc(DigitIdx);
Word128DivideWord8(Val128, 10, Val128, Digit);
end;
// set length
SetLength(A.Digits, DigitIdx);
end;
// Pre: A is initialised
procedure HugeDecimalAssignHugeDecimal(var A: HugeDecimal; const B: HugeDecimal);
begin
A.Precision := B.Precision;
A.Digits := Copy(B.Digits);
end;
// Pre: A is normalised
function HugeDecimalIsZero(const A: HugeDecimal): Boolean;
begin
Result := Length(A.Digits) = 0;
end;
// Pre: A is normalised
function HugeDecimalIsOne(const A: HugeDecimal): Boolean;
begin
Result :=
(Length(A.Digits) = 1) and
(A.Precision = 0) and
(A.Digits[0] = 1);
end;
// Pre: A is normalised
function HugeDecimalIsOdd(const A: HugeDecimal): Boolean;
begin
Result :=
(Length(A.Digits) > 0) and
(A.Precision = 0) and
(A.Digits[0] and 1 = 1);
end;
// Pre: A is normalised
function HugeDecimalIsEven(const A: HugeDecimal): Boolean;
var L : Integer;
begin
L := Length(A.Digits);
if L = 0 then
Result := True
else
Result :=
(A.Precision = 0) and
(A.Digits[0] and 1 = 0);
end;
// Pre: A is normalised
function HugeDecimalIsInteger(const A: HugeDecimal): Boolean;
begin
Result := A.Precision = 0;
end;
// Pre: A is normalised
function HugeDecimalIsLessThanOne(const A: HugeDecimal): Boolean;
begin
Result := A.Precision = Length(A.Digits);
end;
// Pre: A is normalised
function HugeDecimalIsOneOrGreater(const A: HugeDecimal): Boolean;
begin
Result := A.Precision < Length(A.Digits);
end;
// Pre: A is normalised
function HugeDecimalIsWord8Range(const A: HugeDecimal): Boolean;
var
DigitsLen : Integer;
T : Word16;
begin
if A.Precision > 0 then
Result := False
else
begin
DigitsLen := Length(A.Digits);
if DigitsLen < 3 then
Result := True
else
if DigitsLen > 3 then
Result := False
else
begin
T := A.Digits[0] +
A.Digits[1] * 10 +
A.Digits[2] * 100;
Result := T <= $00FF;
end;
end;
end;
// Pre: A is normalised
function HugeDecimalDigits(const A: HugeDecimal): Integer;
var
L : Integer;
begin
L := Length(A.Digits);
if L = 0 then
Result := 1
else
Result := L;
end;
// Pre: A is normalised
function HugeDecimalIntegerDigits(const A: HugeDecimal): Integer;
begin
Result := HugeDecimalDigits(A) - A.Precision;
end;
// Pre: A is normalised
function HugeDecimalDecimalDigits(const A: HugeDecimal): Integer;
begin
Result := A.Precision;
end;
// Pre: A is normalised
function HugeDecimalGetDigit(const A: HugeDecimal; const DigitIdx: Integer): Byte;
var
DigitsLen, DigitIdxRev : Integer;
Digit : Byte;
begin
if DigitIdx < 0 then
raise EDecimalError.Create(SIndexOutOfRange);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
Result := 0;
exit;
end;
if DigitIdx >= DigitsLen then
raise EDecimalError.Create(SIndexOutOfRange);
DigitIdxRev := DigitsLen - DigitIdx - 1;
Digit := A.Digits[DigitIdxRev];
Result := Digit;
end;
// Post: A not normalised
procedure HugeDecimalSetDigit(var A: HugeDecimal; const DigitIdx: Integer; const DigitValue: Byte);
var
TotDigits, DigitsLen, DigitIdxRev : Integer;
begin
if DigitValue > 9 then
raise EDecimalError.Create(SInvalidParameter);
if DigitIdx < 0 then
raise EDecimalError.Create(SIndexOutOfRange);
TotDigits := HugeDecimalDigits(A);
if DigitIdx >= TotDigits then
raise EDecimalError.Create(SIndexOutOfRange);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
if DigitValue = 0 then
exit;
SetLength(A.Digits, 1);
A.Digits[0] := DigitValue;
exit;
end;
DigitIdxRev := TotDigits - DigitIdx - 1;
A.Digits[DigitIdxRev] := DigitValue;
end;
// Pre: A is normalised
function HugeDecimalToWord8(const A: HugeDecimal): Byte;
var
TotDigits : Integer;
T : Word;
begin
if A.Precision > 0 then
raise EDecimalError.Create(SConvertError);
TotDigits := Length(A.Digits);
if TotDigits = 0 then
Result := 0
else
if TotDigits = 1 then
Result := A.Digits[0]
else
if TotDigits = 2 then
Result := A.Digits[0] + A.Digits[1] * 10
else
if TotDigits = 3 then
begin
T := A.Digits[0] +
A.Digits[1] * 10 +
A.Digits[2] * 100;
if T > 255 then
raise EDecimalError.Create(SOverflowError);
Result := T;
end
else
raise EDecimalError.Create(SOverflowError);
end;
// Pre: A is normalised
function HugeDecimalToWord32(const A: HugeDecimal): Word32;
var
DigitsLen, DigIdx : Integer;
T : Word64Rec;
Digit : Byte;
begin
if A.Precision > 0 then
raise EDecimalError.Create(SConvertError);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
Result := 0
else
begin
Word64InitZero(T);
for DigIdx := 0 to DigitsLen - 1 do
begin
if DigIdx > 0 then
Word64MultiplyWord8(T, 10);
Digit := A.Digits[DigitsLen - DigIdx - 1];
Word64AddWord8(T, Digit);
if Word64CompareWord32(T, $FFFFFFFF) > 0 then
raise EDecimalError.Create(SOverflowError);
end;
Result := Word64ToWord32(T);
end;
end;
// Pre: A is normalised
function HugeDecimalToWord64(const A: HugeDecimal): Word64Rec;
var
DigitsLen, DigIdx : Integer;
T : Word128;
Digit : Byte;
begin
if A.Precision > 0 then
raise EDecimalError.Create(SConvertError);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
Word64InitZero(Result)
else
begin
Word128InitZero(T);
for DigIdx := 0 to DigitsLen - 1 do
begin
if DigIdx > 0 then
Word128MultiplyWord8(T, 10);
Digit := A.Digits[DigitsLen - DigIdx - 1];
Word128AddWord8(T, Digit);
if Word128CompareWord64(T, Word64ConstMaximum) > 0 then
raise EDecimalError.Create(SOverflowError);
end;
Result := Word128ToWord64(T);
end;
end;
// Pre: A is normalised
function HugeDecimalToWord128(const A: HugeDecimal): Word128;
var
DigitsLen, DigIdx : Integer;
T : Word256;
Digit : Byte;
begin
if A.Precision > 0 then
raise EDecimalError.Create(SConvertError);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
Word128InitZero(Result)
else
begin
Word256InitZero(T);
for DigIdx := 0 to DigitsLen - 1 do
begin
if DigIdx > 0 then
Word256MultiplyWord8(T, 10);
Digit := A.Digits[DigitsLen - DigIdx - 1];
Word256AddWord32(T, Digit);
if Word256CompareWord128(T, Word128ConstMaximum) > 0 then
raise EDecimalError.Create(SOverflowError);
end;
Result := Word256ToWord128(T);
end;
end;
// Pre: A is normalised
function HugeDecimalToDecimal32(const A: HugeDecimal): Decimal32;
var
Digit : Byte;
DigitIdx, DigitsLen, IntDigits : Integer;
Val32 : Word32;
begin
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
Decimal32InitZero(Result);
exit;
end;
IntDigits := DigitsLen - A.Precision;
if IntDigits > Decimal32Digits - Decimal32Precision then
raise EDecimalError.Create(SOverflowError);
Val32 := 0;
DigitIdx := 0;
while DigitIdx < DigitsLen do
begin
Digit := A.Digits[DigitsLen - DigitIdx - 1];
Inc(DigitIdx);
Val32 := Val32 * 10 + Digit;
if DigitIdx = DigitsLen then
break;
if DigitIdx = IntDigits + Decimal32Precision then
break;
end;
while DigitIdx < IntDigits + Decimal32Precision do
begin
Val32 := Val32 * 10;
Inc(DigitIdx);
end;
Result.Value32 := Val32;
end;
// Pre: A is normalised
function HugeDecimalToDecimal64(const A: HugeDecimal): Decimal64;
var
Digit : Byte;
DigitIdx, DigitsLen, IntDigits : Integer;
Val64 : Word64Rec;
begin
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
Decimal64InitZero(Result);
exit;
end;
IntDigits := DigitsLen - A.Precision;
if IntDigits > Decimal64Digits - Decimal64Precision then
raise EDecimalError.Create(SOverflowError);
Word64InitZero(Val64);
DigitIdx := 0;
while DigitIdx < DigitsLen do
begin
Digit := A.Digits[DigitsLen - DigitIdx - 1];
Inc(DigitIdx);
Word64MultiplyWord8(Val64, 10);
Word64AddWord8(Val64, Digit);
if DigitIdx = DigitsLen then
break;
if DigitIdx = IntDigits + Decimal64Precision then
break;
end;
while DigitIdx < IntDigits + Decimal64Precision do
begin
Word64MultiplyWord8(Val64, 10);
Inc(DigitIdx);
end;
Result.Value64 := Val64;
end;
// Pre: A is normalised
function HugeDecimalToDecimal128(const A: HugeDecimal): Decimal128;
var
Digit : Byte;
DigitIdx, DigitsLen, IntDigits : Integer;
Val128 : Word128;
begin
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
Decimal128InitZero(Result);
exit;
end;
IntDigits := DigitsLen - A.Precision;
if IntDigits > Decimal128Digits - Decimal128Precision then
raise EDecimalError.Create(SOverflowError);
Word128InitZero(Val128);
DigitIdx := 0;
while DigitIdx < DigitsLen do
begin
Digit := A.Digits[DigitsLen - DigitIdx - 1];
Inc(DigitIdx);
Word128MultiplyWord8(Val128, 10);
Word128AddWord8(Val128, Digit);
if DigitIdx = DigitsLen then
break;
if DigitIdx = IntDigits + Decimal128Precision then
break;
end;
while DigitIdx < IntDigits + Decimal128Precision do
begin
Word128MultiplyWord8(Val128, 10);
Inc(DigitIdx);
end;
Result.Value128 := Val128;
end;
// Pre: A is normalised
// Post: A is normalised
procedure HugeDecimalMul10(var A: HugeDecimal);
var
DigitsLen, DecPrecision, DigitIdx : Integer;
begin
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
exit;
DecPrecision := A.Precision;
if DecPrecision > 0 then
begin
A.Precision := DecPrecision - 1;
if A.Digits[DigitsLen - 1] = 0 then
SetLength(A.Digits, DigitsLen - 1);
end
else
begin
Inc(DigitsLen);
SetLength(A.Digits, DigitsLen);
for DigitIdx := DigitsLen - 1 downto 1 do
A.Digits[DigitIdx] := A.Digits[DigitIdx - 1];
A.Digits[0] := 0;
end;
end;
// Pre: A is normalised
// Post: A is normalised
procedure HugeDecimalDiv10(var A: HugeDecimal);
var
DigitsLen, DecPrecision, DigitIdx : Integer;
begin
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
exit;
DecPrecision := A.Precision;
if DecPrecision > 0 then
begin
Inc(DecPrecision);
A.Precision := DecPrecision;
if DecPrecision > DigitsLen then
begin
Inc(DigitsLen);
SetLength(A.Digits, DigitsLen);
A.Digits[DigitsLen - 1] := 0;
end;
end
else
if A.Digits[0] = 0 then
begin
for DigitIdx := 0 to DigitsLen - 2 do
A.Digits[DigitIdx] := A.Digits[DigitIdx + 1];
Dec(DigitsLen);
SetLength(A.Digits, DigitsLen);
end
else
begin
Inc(DecPrecision);
A.Precision := DecPrecision;
end;
end;
// Post: A normalised
procedure HugeDecimalInternalNormalise(var A: HugeDecimal);
var
DigitsLen, ZeroCnt, DigitIdx : Integer;
begin
DigitsLen := Length(A.Digits);
// trim zeros preceding integer
ZeroCnt := 0;
while ZeroCnt < DigitsLen - A.Precision do
begin
if A.Digits[DigitsLen - ZeroCnt - 1] <> 0 then
break;
Inc(ZeroCnt);
end;
if ZeroCnt > 0 then
begin
Dec(DigitsLen, ZeroCnt);
SetLength(A.Digits, DigitsLen);
end;
// trim zeros trailing fraction
ZeroCnt := 0;
while ZeroCnt < A.Precision do
begin
if A.Digits[ZeroCnt] <> 0 then
break;
Inc(ZeroCnt);
end;
if ZeroCnt > 0 then
begin
for DigitIdx := 0 to DigitsLen - ZeroCnt - 1 do
A.Digits[DigitIdx] := A.Digits[DigitIdx + ZeroCnt];
Dec(DigitsLen, ZeroCnt);
SetLength(A.Digits, DigitsLen);
Dec(A.Precision, ZeroCnt);
end;
end;
procedure HugeDecimalInternalAddDigit(var A: HugeDecimal; const StartDigitIdx: Integer;
const DigitValue: Byte);
var
DigitsLen, DigitIdx : Integer;
Digit, AddValue : Byte;
begin
Assert(StartDigitIdx >= 0);
Assert(StartDigitIdx < Length(A.Digits));
Assert(DigitValue <= 9);
if DigitValue = 0 then
exit;
DigitsLen := Length(A.Digits);
DigitIdx := StartDigitIdx;
AddValue := DigitValue;
while DigitIdx < DigitsLen do
begin
Digit := A.Digits[DigitIdx];
Inc(Digit, AddValue);
A.Digits[DigitIdx] := Digit mod 10;
AddValue := Digit div 10;
if AddValue = 0 then
exit;
Inc(DigitIdx);
end;
Assert((AddValue > 0) and (AddValue <= 9));
SetLength(A.Digits, DigitsLen + 1);
A.Digits[DigitsLen] := AddValue;
end;
procedure HugeDecimalInternalSubtractDigit(var A: HugeDecimal; const StartDigitIdx: Integer;
const DigitValue: Byte);
var
DigitsLen, DigitIdx : Integer;
Digit : Byte;
SDigit, SubValue : ShortInt;
Borrow : Boolean;
begin
Assert(StartDigitIdx >= 0);
Assert(StartDigitIdx < Length(A.Digits));
Assert(DigitValue <= 9);
if DigitValue = 0 then
exit;
DigitsLen := Length(A.Digits);
DigitIdx := StartDigitIdx;
SubValue := DigitValue;
Borrow := False;
while DigitIdx < DigitsLen do
begin
Digit := A.Digits[DigitIdx];
Assert(Digit <= 9);
SDigit := Digit - SubValue;
if SDigit < 0 then
begin
Borrow := True;
Inc(SDigit, 10);
SubValue := 1;
end
else
Borrow := False;
A.Digits[DigitIdx] := SDigit;
if not Borrow then
begin
if (SDigit = 0) and (DigitIdx = DigitsLen - 1) then
SetLength(A.Digits, DigitsLen - 1);
exit;
end;
Inc(DigitIdx);
end;
Assert(Borrow);
raise EDecimalError.Create(SOverflowError);
end;
// Pre: A is normalised, N <= 9
// Post: A is normalised
procedure HugeDecimalInc(var A: HugeDecimal; const N: Byte);
var
DigitsLen, IntDigits : Integer;
begin
if N = 0 then
exit;
if N > 9 then
raise EConvertError.Create(SInvalidParameter);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
SetLength(A.Digits, 1);
A.Digits[0] := N;
exit;
end;
IntDigits := DigitsLen - A.Precision;
if IntDigits = 0 then
begin
SetLength(A.Digits, DigitsLen + 1);
A.Digits[DigitsLen] := N;
exit;
end;
HugeDecimalInternalAddDigit(A, A.Precision, N);
end;
// Pre: A is normalised, N <= 9
// Post: A is normalised
procedure HugeDecimalDec(var A: HugeDecimal; const N: Byte);
var
DigitsLen, IntDigits : Integer;
begin
if N = 0 then
exit;
if N > 9 then
raise EConvertError.Create(SInvalidParameter);
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
raise EDecimalError.Create(SOverflowError);
IntDigits := DigitsLen - A.Precision;
if IntDigits = 0 then
raise EDecimalError.Create(SOverflowError);
HugeDecimalInternalSubtractDigit(A, A.Precision, N);
end;
// Pre: A is normalised
// Post: A is normalised
procedure HugeDecimalTrunc(var A: HugeDecimal);
var
DigitsLen, IntDigits, DecDigits, DigitIdx : Integer;
begin
DecDigits := A.Precision;
if DecDigits = 0 then
exit;
DigitsLen := Length(A.Digits);
IntDigits := DigitsLen - DecDigits;
if IntDigits = 0 then
begin
HugeDecimalInitZero(A);
exit;
end;
for DigitIdx := 0 to IntDigits - 1 do
A.Digits[DigitIdx] := A.Digits[DigitIdx + DecDigits];
SetLength(A.Digits, IntDigits);
A.Precision := 0;
end;
// Pre: A is normalised
function HugeDecimalFracCompareHalf(var A: HugeDecimal): Integer;
var
TotDigits, IntDigits, DigitIdx, Digit1 : Integer;
begin
if A.Precision = 0 then
begin
Result := -1;
exit;
end;
TotDigits := HugeDecimalDigits(A);
IntDigits := TotDigits - A.Precision;
Digit1 := HugeDecimalGetDigit(A, IntDigits);
if Digit1 < 5 then
begin
Result := -1;
exit;
end;
if Digit1 > 5 then
begin
Result := 1;
exit;
end;
for DigitIdx := IntDigits + 1 to TotDigits - 1 do
begin
Digit1 := HugeDecimalGetDigit(A, IntDigits);
if Digit1 > 0 then
begin
Result := 1;
exit;
end;
end;
Result := 0;
end;
procedure HugeDecimalRound(var A: HugeDecimal);
var
F : Integer;
begin
if A.Precision = 0 then
exit;
F := HugeDecimalFracCompareHalf(A);
HugeDecimalTrunc(A);
if (F > 0) or
((F = 0) and HugeDecimalIsOdd(A)) then
HugeDecimalInc(A);
end;
function HugeDecimalEqualsWord8(const A: HugeDecimal; const B: Byte): Boolean;
var
DigitsLen : Integer;
begin
if A.Precision > 0 then
Result := False
else
if B = 0 then
Result := HugeDecimalIsZero(A)
else
begin
DigitsLen := Length(A.Digits);
if B < 10 then
begin
if DigitsLen <> 1 then
Result := False
else
Result := A.Digits[0] = B;
end
else
if B < 100 then
begin
if DigitsLen <> 2 then
Result := False
else
Result := (A.Digits[0] + A.Digits[1] * 10) = B;
end
else
begin
if DigitsLen <> 3 then
Result := False
else
Result := (A.Digits[0] + A.Digits[1] * 10 + A.Digits[2] * 100) = B;
end;
end;
end;
// Pre: A and B normalised
function HugeDecimalEqualsHugeDecimal(const A, B: HugeDecimal): Boolean;
var
DigitsLen, DigitsIdx : Integer;
begin
if A.Precision <> B.Precision then
begin
Result := False;
exit;
end;
DigitsLen := Length(A.Digits);
if DigitsLen <> Length(B.Digits) then
begin
Result := False;
exit;
end;
for DigitsIdx := 0 to DigitsLen - 1 do
if A.Digits[DigitsIdx] <> B.Digits[DigitsIdx] then
begin
Result := False;
exit;
end;
Result := True;
end;
// Pre: A normalised
function HugeDecimalCompareWord8(const A: HugeDecimal; const B: Byte): Integer;
var
DigitsLen, IntDigits, Precision, Cmp : Integer;
begin
DigitsLen := Length(A.Digits);
Precision := A.Precision;
IntDigits := DigitsLen - Precision;
if B = 0 then
begin
if DigitsLen = 0 then
Result := 0
else
Result := 1;
end
else
if B < 10 then
begin
if IntDigits < 1 then
Result := -1
else
if IntDigits > 1 then
Result := 1
else
begin
Cmp := Word8Compare(A.Digits[Precision], B);
if (Cmp = 0) and (Precision > 0) then
Cmp := 1;
Result := Cmp;
end;
end
else
if B < 100 then
begin
if IntDigits < 2 then
Result := -1
else
if IntDigits > 2 then
Result := 1
else
begin
Cmp := Word8Compare(
A.Digits[Precision] +
A.Digits[Precision + 1] * 10, B);
if (Cmp = 0) and (Precision > 0) then
Cmp := 1;
Result := Cmp;
end;
end
else
begin
if IntDigits < 3 then
Result := -1
else
if IntDigits > 3 then
Result := 1
else
begin
Cmp := Word16Compare(
A.Digits[Precision] +
A.Digits[Precision + 1] * 10 +
A.Digits[Precision + 2] * 100, B);
if (Cmp = 0) and (Precision > 0) then
Cmp := 1;
Result := Cmp;
end;
end;
end;
// Pre: A and B normalised
function HugeDecimalCompareHugeDecimal(const A, B: HugeDecimal): Integer;
var
ADigitsLen, BDigitsLen : Integer;
AIntDigits, BIntDigits : Integer;
DigitIdx, MinPrecision : Integer;
Digit1, Digit2 : Byte;
begin
ADigitsLen := Length(A.Digits);
BDigitsLen := Length(B.Digits);
if ADigitsLen = 0 then
begin
if BDigitsLen = 0 then
Result := 0 // A = B = 0
else
Result := -1; // A = 0, B > 0 ... A < B
exit;
end;
// compare integer digits
AIntDigits := ADigitsLen - A.Precision;
BIntDigits := BDigitsLen - B.Precision;
if AIntDigits < BIntDigits then
begin
Result := -1;
exit;
end
else
if AIntDigits > BIntDigits then
begin
Result := 1;
exit;
end;
for DigitIdx := 0 to AIntDigits - 1 do
begin
Digit1 := A.Digits[ADigitsLen - DigitIdx - 1];
Digit2 := B.Digits[BDigitsLen - DigitIdx - 1];
if Digit1 < Digit2 then
begin
Result := -1;
exit;
end
else
if Digit1 > Digit2 then
begin
Result := 1;
exit;
end;
end;
// compare fractional part
if A.Precision < B.Precision then
MinPrecision := A.Precision
else
MinPrecision := B.Precision;
for DigitIdx := 0 to MinPrecision - 1 do
begin
Digit1 := A.Digits[ADigitsLen - AIntDigits - DigitIdx - 1];
Digit2 := B.Digits[BDigitsLen - BIntDigits - DigitIdx - 1];
if Digit1 < Digit2 then
begin
Result := -1;
exit;
end
else
if Digit1 > Digit2 then
begin
Result := 1;
exit;
end;
end;
// check if digits remain
if A.Precision = B.Precision then
Result := 0
else
if A.Precision > B.Precision then
Result := 1
else
Result := -1;
end;
// Pre: A and B normalised
// Post: A contains result normalised
procedure HugeDecimalAddHugeDecimal(var A: HugeDecimal; const B: HugeDecimal);
var
Res : HugeDecimal;
DigitsLenA, DigitsLenB : Integer;
PrecisionA, PrecisionB, Precision : Integer;
IntDigitsA, IntDigitsB, IntDigits : Integer;
Idx, T : Integer;
Digit : Byte;
begin
DigitsLenB := Length(B.Digits);
if DigitsLenB = 0 then
exit;
DigitsLenA := Length(A.Digits);
if DigitsLenA = 0 then
begin
HugeDecimalAssignHugeDecimal(A, B);
exit;
end;
PrecisionA := A.Precision;
PrecisionB := B.Precision;
if PrecisionA > PrecisionB then
Precision := PrecisionA
else
Precision := PrecisionB;
IntDigitsA := DigitsLenA - PrecisionA;
IntDigitsB := DigitsLenB - PrecisionB;
if IntDigitsA > IntDigitsB then
IntDigits := IntDigitsA
else
IntDigits := IntDigitsB;
HugeDecimalInit(Res);
Res.Precision := Precision;
SetLength(Res.Digits, Precision + IntDigits);
Digit := 0;
for Idx := 0 to Precision - 1 do
begin
T := Precision - Idx;
if PrecisionA >= T then
Inc(Digit, A.Digits[PrecisionA - T]);
if PrecisionB >= T then
Inc(Digit, B.Digits[PrecisionB - T]);
Res.Digits[Idx] := Digit mod 10;
Digit := Digit div 10;
end;
for Idx := 0 to IntDigits - 1 do
begin
if Idx < IntDigitsA then
Inc(Digit, A.Digits[PrecisionA + Idx]);
if Idx < IntDigitsB then
Inc(Digit, B.Digits[PrecisionB + Idx]);
Res.Digits[Precision + Idx] := Digit mod 10;
Digit := Digit div 10;
end;
if Digit > 0 then
begin
SetLength(Res.Digits, Precision + IntDigits + 1);
Res.Digits[Precision + IntDigits] := Digit;
end;
HugeDecimalInternalNormalise(Res);
HugeDecimalAssignHugeDecimal(A, Res);
end;
// Pre: A and B normalised
// Post: A contains result normalised
procedure HugeDecimalSubtractHugeDecimal(var A: HugeDecimal; const B: HugeDecimal);
var
Res : HugeDecimal;
DigitsLenA, DigitsLenB, DigitsLen : Integer;
Cmp : Integer;
PrecisionA, PrecisionB, Precision : Integer;
IntDigitsA, IntDigitsB, IntDigits : Integer;
J, I : Integer;
Digit, DigitB : Byte;
SDigit : ShortInt;
Borrow : Boolean;
begin
DigitsLenB := Length(B.Digits);
if DigitsLenB = 0 then
exit;
Cmp := HugeDecimalCompareHugeDecimal(A, B);
if Cmp = 0 then
begin
HugeDecimalAssignZero(A);
exit;
end;
if Cmp < 0 then
raise EDecimalError.Create(SOverflowError);
DigitsLenA := Length(A.Digits);
PrecisionA := A.Precision;
PrecisionB := B.Precision;
if PrecisionA > PrecisionB then
Precision := PrecisionA
else
Precision := PrecisionB;
IntDigitsA := DigitsLenA - PrecisionA;
IntDigitsB := DigitsLenB - PrecisionB;
Assert(IntDigitsA >= IntDigitsB);
IntDigits := IntDigitsA;
HugeDecimalInit(Res);
Res.Precision := Precision;
DigitsLen := Precision + IntDigits;
SetLength(Res.Digits, DigitsLen);
J := 0;
while J < PrecisionB - PrecisionA do
begin
Res.Digits[J] := 0;
Inc(J);
end;
for I := 0 to DigitsLenA - 1 do
Res.Digits[J + I] := A.Digits[I];
if PrecisionB < PrecisionA then
J := PrecisionA - PrecisionB
else
J := 0;
Borrow := False;
for I := 0 to DigitsLen - 1 do
begin
Digit := Res.Digits[I];
if I < J then
DigitB := 0
else
if I - J < DigitsLenB then
DigitB := B.Digits[I - J]
else
begin
DigitB := 0;
if not Borrow then
break;
end;
SDigit := Digit - DigitB;
if Borrow then
Dec(SDigit);
if SDigit < 0 then
begin
Inc(SDigit, 10);
Borrow := True;
end
else
Borrow := False;
Res.Digits[I] := SDigit;
end;
HugeDecimalInternalNormalise(Res);
HugeDecimalAssignHugeDecimal(A, Res);
end;
// Post: R normalised if result is dceNoError
function TryStrToHugeDecimal(const S: String; var R: HugeDecimal): TDecimalConvertErrorType;
var
LenS, IdxS, IdxZ, Precision, DigitI : Integer;
DigitC : Char;
NonZero : Boolean;
begin
LenS := Length(S);
if LenS = 0 then
begin
Result := dceConvertError;
exit;
end;
HugeDecimalAssignZero(R);
IdxS := 1;
// skip preceding zeros
while IdxS <= LenS do
begin
DigitC := S[IdxS];
if DigitC <> '0' then
break;
Inc(IdxS);
end;
// parse integer part
while IdxS <= LenS do
begin
DigitC := S[IdxS];
if DigitC = '.' then
if IdxS = 1 then
begin
Result := dceConvertError;
exit;
end
else
break;
DigitI := CharDigitToInt(DigitC);
if DigitI < 0 then
begin
Result := dceConvertError;
exit;
end;
HugeDecimalMul10(R);
HugeDecimalInc(R, DigitI);
Inc(IdxS);
end;
// parse decimal part
if (IdxS <= LenS) and (S[IdxS] = '.') then
begin
Inc(IdxS);
if IdxS > LenS then
begin
Result := dceConvertError;
exit;
end;
Precision := 0;
while IdxS <= LenS do
begin
DigitC := S[IdxS];
DigitI := CharDigitToInt(DigitC);
if DigitI < 0 then
begin
Result := dceConvertError;
exit;
end;
if DigitI = 0 then
begin
// check if all traling digits are zero
NonZero := False;
for IdxZ := IdxS + 1 to LenS do
if S[IdxZ] <> '0' then
begin
NonZero := True;
break;
end;
if not NonZero then
break;
end;
HugeDecimalMul10(R);
HugeDecimalInc(R, DigitI);
Inc(Precision);
Inc(IdxS);
end;
R.Precision := Precision;
end;
// success
Result := dceNoError;
end;
// Post: R normalised if no exception
procedure StrToHugeDecimal(const S: String; var R: HugeDecimal);
begin
case TryStrToHugeDecimal(S, R) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
end;
end;
// Pre: A normalised
function HugeDecimalToStr(const A: HugeDecimal): String;
var
DigitsLen, Digits, StrLen, DigitIdx, ResPos, DecimalPos : Integer;
ResStr : String;
Digit : Byte;
ZeroIntDigits : Boolean;
begin
DigitsLen := Length(A.Digits);
if DigitsLen = 0 then
begin
Result := '0';
exit;
end;
Digits := HugeDecimalDigits(A);
StrLen := Digits;
if A.Precision > 0 then
Inc(StrLen);
ZeroIntDigits := A.Precision = Digits;
if A.Precision > 0 then
begin
if ZeroIntDigits then
DecimalPos := -1
else
DecimalPos := Digits - A.Precision + 1;
end
else
DecimalPos := -1;
if ZeroIntDigits then
Inc(StrLen);
SetLength(ResStr, StrLen);
ResPos := 1;
if ZeroIntDigits then
begin
ResStr[ResPos] := '0';
Inc(ResPos);
ResStr[ResPos] := '.';
Inc(ResPos);
end;
for DigitIdx := 0 to DigitsLen - 1 do
begin
Digit := A.Digits[DigitsLen - DigitIdx - 1];
ResStr[ResPos] := IntToCharDigit(Digit);
Inc(ResPos);
if ResPos = DecimalPos then
begin
ResStr[ResPos] := '.';
Inc(ResPos);
end;
end;
Result := ResStr;
end;
{ }
{ SDecimal32 }
{ }
procedure SDecimal32InitZero(var A: SDecimal32);
begin
A.Sign := 0;
Decimal32InitZero(A.Value);
end;
procedure SDecimal32InitOne(var A: SDecimal32);
begin
A.Sign := 1;
Decimal32InitOne(A.Value);
end;
procedure SDecimal32InitMinusOne(var A: SDecimal32);
begin
A.Sign := -1;
Decimal32InitOne(A.Value);
end;
procedure SDecimal32InitMin(var A: SDecimal32);
begin
A.Sign := -1;
Decimal32InitMax(A.Value);
end;
procedure SDecimal32InitMax(var A: SDecimal32);
begin
A.Sign := 1;
Decimal32InitMax(A.Value);
end;
function SDecimal32IsZero(const A: SDecimal32): Boolean;
begin
Result := A.Sign = 0;
end;
function SDecimal32IsOne(const A: SDecimal32): Boolean;
begin
Result := (A.Sign > 0) and Decimal32IsOne(A.Value);
end;
function SDecimal32IsMinusOne(const A: SDecimal32): Boolean;
begin
Result := (A.Sign < 0) and Decimal32IsOne(A.Value);
end;
function SDecimal32IsMinimum(const A: SDecimal32): Boolean;
begin
Result := (A.Sign < 0) and Decimal32IsMaximum(A.Value);
end;
function SDecimal32IsMaximum(const A: SDecimal32): Boolean;
begin
Result := (A.Sign > 0) and Decimal32IsMaximum(A.Value);
end;
function SDecimal32IsOverflow(const A: SDecimal32): Boolean;
begin
Result := Decimal32IsOverflow(A.Value);
end;
function Word32IsSDecimal32Range(const A: Word32): Boolean;
begin
Result := A <= SDecimal32MaxInt;
end;
function Int32IsSDecimal32Range(const A: Int32): Boolean;
begin
Result := (A >= SDecimal32MinInt) and (A <= SDecimal32MaxInt);
end;
function FloatIsSDecimal32Range(const A: Double): Boolean;
begin
Result :=
(A > SDecimal32MinFloatLimD) and
(A < SDecimal32MaxFloatLimD);
end;
function SDecimal32Sign(const A: SDecimal32): Integer;
begin
Result := A.Sign;
end;
procedure SDecimal32Negate(var A: SDecimal32);
begin
A.Sign := -A.Sign;
end;
procedure SDecimal32AbsInPlace(var A: SDecimal32);
begin
if A.Sign < 0 then
A.Sign := 1;
end;
procedure SDecimal32InitWord8(var A: SDecimal32; const B: Byte);
begin
if B = 0 then
SDecimal32InitZero(A)
else
begin
A.Sign := 1;
Decimal32InitWord8(A.Value, B);
end;
end;
procedure SDecimal32InitWord16(var A: SDecimal32; const B: Word);
begin
if B = 0 then
SDecimal32InitZero(A)
else
begin
A.Sign := 1;
Decimal32InitWord16(A.Value, B);
end;
end;
procedure SDecimal32InitWord32(var A: SDecimal32; const B: Word32);
begin
if B = 0 then
SDecimal32InitZero(A)
else
begin
A.Sign := 1;
Decimal32InitWord32(A.Value, B);
end;
end;
procedure SDecimal32InitInt32(var A: SDecimal32; const B: Int32);
begin
if B = 0 then
SDecimal32InitZero(A)
else
if B < 0 then
begin
A.Sign := -1;
Decimal32InitWord32(A.Value, -B);
end
else
begin
A.Sign := 1;
Decimal32InitWord32(A.Value, B);
end;
end;
procedure SDecimal32InitSDecimal32(var A: SDecimal32; const B: SDecimal32);
begin
A.Sign := B.Sign;
A.Value := B.Value;
end;
procedure SDecimal32InitFloat(var A: SDecimal32; const B: Double);
begin
if B < Decimal32MinFloatD then
begin
A.Sign := -1;
Decimal32InitFloat(A.Value, -B);
end
else
if B > -Decimal32MinFloatD then
begin
A.Sign := 1;
Decimal32InitFloat(A.Value, B);
end
else
SDecimal32InitZero(A);
end;
function SDecimal32ToWord8(const A: SDecimal32): Byte;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal32ToWord8(A.Value);
end;
function SDecimal32ToWord16(const A: SDecimal32): Word;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal32ToWord16(A.Value);
end;
function SDecimal32ToWord32(const A: SDecimal32): Word32;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal32ToWord32(A.Value);
end;
function SDecimal32ToInt32(const A: SDecimal32): Int32;
var T : Int32;
begin
T := Decimal32ToInt32(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal32ToFloat(const A: SDecimal32): Double;
var T : Double;
begin
T := Decimal32ToFloat(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal32Trunc(const A: SDecimal32): Int32;
var T : Int32;
begin
T := Decimal32Trunc(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal32Round(const A: SDecimal32): Int32;
var T : Int32;
begin
T := Decimal32Round(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal32FracWord(const A: SDecimal32): Word;
begin
Result := Decimal32FracWord(A.Value);
end;
function SDecimal32EqualsWord8(const A: SDecimal32; const B: Byte): Boolean;
begin
Result := (A.Sign >= 0) and Decimal32EqualsWord8(A.Value, B);
end;
function SDecimal32EqualsWord16(const A: SDecimal32; const B: Word): Boolean;
begin
Result := (A.Sign >= 0) and Decimal32EqualsWord16(A.Value, B);
end;
function SDecimal32EqualsWord32(const A: SDecimal32; const B: Word32): Boolean;
begin
Result := (A.Sign >= 0) and Decimal32EqualsWord32(A.Value, B);
end;
function SDecimal32EqualsInt32(const A: SDecimal32; const B: Int32): Boolean;
begin
if A.Sign = 0 then
Result := (B = 0)
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := False
else
Result := Decimal32EqualsWord32(A.Value, B);
end
else
begin
if B >= 0 then
Result := False
else
Result := Decimal32EqualsWord32(A.Value, -B);
end;
end;
function SDecimal32EqualsSDecimal32(const A: SDecimal32; const B: SDecimal32): Boolean;
begin
Result :=
(A.Sign = B.Sign) and
Decimal32EqualsDecimal32(A.Value, B.Value);
end;
function SDecimal32EqualsFloat(const A: SDecimal32; const B: Double): Boolean;
begin
if A.Sign >= 0 then
Result := Decimal32EqualsFloat(A.Value, B)
else
Result := Decimal32EqualsFloat(A.Value, -B);
end;
function SDecimal32CompareWord8(const A: SDecimal32; const B: Byte): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal32CompareWord8(A.Value, B)
else
Result := -1;
end;
function SDecimal32CompareWord16(const A: SDecimal32; const B: Word): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal32CompareWord16(A.Value, B)
else
Result := -1;
end;
function SDecimal32CompareWord32(const A: SDecimal32; const B: Word32): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal32CompareWord32(A.Value, B)
else
Result := -1;
end;
function SDecimal32CompareInt32(const A: SDecimal32; const B: Int32): Integer;
begin
if A.Sign = 0 then
begin
if B < 0 then
Result := 1
else
if B > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := 1
else
Result := Decimal32CompareWord32(A.Value, B);
end
else
begin
if B >= 0 then
Result := -1
else
Result := -Decimal32CompareWord32(A.Value, -B);
end;
end;
function SDecimal32CompareSDecimal32(const A: SDecimal32; const B: SDecimal32): Integer;
begin
if A.Sign = 0 then
begin
if B.Sign < 0 then
Result := 1
else
if B.Sign > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B.Sign <= 0 then
Result := 1
else
Result := Decimal32CompareDecimal32(A.Value, B.Value);
end
else
begin
if B.Sign >= 0 then
Result := -1
else
Result := -Decimal32CompareDecimal32(A.Value, B.Value);
end;
end;
function SDecimal32CompareFloat(const A: SDecimal32; const B: Double): Integer;
begin
if A.Sign >= 0 then
Result := Decimal32CompareFloat(A.Value, B)
else
Result := -Decimal32CompareFloat(A.Value, -B);
end;
procedure SDecimal32AddWord8(var A: SDecimal32; const B: Byte);
var S : Int8;
T : Decimal32;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal32InitWord8(A.Value, B);
end
else
if A.Sign > 0 then
Decimal32AddWord8(A.Value, B)
else
begin
S := Decimal32CompareWord8(A.Value, B);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractWord8(A.Value, B)
else
begin
A.Sign := 1;
Decimal32InitWord8(T, B);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32AddWord16(var A: SDecimal32; const B: Word);
var S : Int8;
T : Decimal32;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal32InitWord16(A.Value, B);
end
else
if A.Sign > 0 then
Decimal32AddWord16(A.Value, B)
else
begin
S := Decimal32CompareWord16(A.Value, B);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractWord16(A.Value, B)
else
begin
A.Sign := 1;
Decimal32InitWord16(T, B);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32AddWord32(var A: SDecimal32; const B: Word32);
var S : Int8;
T : Decimal32;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal32InitWord32(A.Value, B);
end
else
if A.Sign > 0 then
Decimal32AddWord32(A.Value, B)
else
begin
S := Decimal32CompareWord32(A.Value, B);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractWord32(A.Value, B)
else
begin
A.Sign := 1;
Decimal32InitWord32(T, B);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32AddSDecimal32(var A: SDecimal32; const B: SDecimal32);
var S : Int8;
T : Decimal32;
begin
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal32InitDecimal32(A.Value, B.Value);
end
else
if (A.Sign = B.Sign) then
Decimal32AddDecimal32(A.Value, B.Value)
else
begin
S := Decimal32CompareDecimal32(A.Value, B.Value);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractDecimal32(A.Value, B.Value)
else
begin
A.Sign := -A.Sign;
Decimal32InitDecimal32(T, B.Value);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32SubtractWord8(var A: SDecimal32; const B: Byte);
var S : Int8;
T : Decimal32;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal32InitWord8(A.Value, B);
end
else
if A.Sign < 0 then
Decimal32AddWord8(A.Value, B)
else
begin
S := Decimal32CompareWord8(A.Value, B);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractWord8(A.Value, B)
else
begin
A.Sign := -1;
Decimal32InitWord8(T, B);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32SubtractWord16(var A: SDecimal32; const B: Word);
var S : Int8;
T : Decimal32;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal32InitWord16(A.Value, B);
end
else
if A.Sign < 0 then
Decimal32AddWord8(A.Value, B)
else
begin
S := Decimal32CompareWord16(A.Value, B);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractWord16(A.Value, B)
else
begin
A.Sign := -1;
Decimal32InitWord16(T, B);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32SubtractWord32(var A: SDecimal32; const B: Word32);
var S : Int8;
T : Decimal32;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal32InitWord32(A.Value, B);
end
else
if A.Sign < 0 then
Decimal32AddWord32(A.Value, B)
else
begin
S := Decimal32CompareWord32(A.Value, B);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractWord32(A.Value, B)
else
begin
A.Sign := -1;
Decimal32InitWord32(T, B);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32SubtractSDecimal32(var A: SDecimal32; const B: SDecimal32);
var S : Int8;
T : Decimal32;
begin
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal32InitDecimal32(A.Value, B.Value);
end
else
if A.Sign <> B.Sign then
Decimal32AddDecimal32(A.Value, B.Value)
else
begin
S := Decimal32CompareDecimal32(A.Value, B.Value);
if S = 0 then
SDecimal32InitZero(A)
else
if S > 0 then
Decimal32SubtractDecimal32(A.Value, B.Value)
else
begin
A.Sign := -A.Sign;
Decimal32InitDecimal32(T, B.Value);
Decimal32SubtractDecimal32(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal32MultiplyWord8(var A: SDecimal32; const B: Byte);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal32InitZero(A);
exit;
end;
Decimal32MultiplyWord8(A.Value, B);
end;
procedure SDecimal32MultiplyWord16(var A: SDecimal32; const B: Word);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal32InitZero(A);
exit;
end;
Decimal32MultiplyWord16(A.Value, B);
end;
procedure SDecimal32MultiplyWord32(var A: SDecimal32; const B: Word32);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal32InitZero(A);
exit;
end;
Decimal32MultiplyWord32(A.Value, B);
end;
procedure SDecimal32MultiplySDecimal32(var A: SDecimal32; const B: SDecimal32);
begin
if A.Sign = 0 then
exit;
if B.Sign = 0 then
begin
SDecimal32InitZero(A);
exit;
end;
Decimal32MultiplyDecimal32(A.Value, B.Value);
if A.Sign = B.Sign then
A.Sign := 1
else
A.Sign := -1;
end;
procedure SDecimal32DivideWord8(var A: SDecimal32; const B: Byte);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal32DivideWord8(A.Value, B);
end;
procedure SDecimal32DivideWord16(var A: SDecimal32; const B: Word);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal32DivideWord16(A.Value, B);
end;
procedure SDecimal32DivideWord32(var A: SDecimal32; const B: Word32);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal32DivideWord32(A.Value, B);
end;
procedure SDecimal32DivideSDecimal32(var A: SDecimal32; const B: SDecimal32);
begin
if B.Sign = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal32DivideDecimal32(A.Value, B.Value);
if A.Sign = B.Sign then
A.Sign := 1
else
A.Sign := -1;
end;
function SDecimal32ToStr(const A: SDecimal32): String;
var S : String;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal32ToStr(A.Value);
Result := S;
end;
function SDecimal32ToStrB(const A: SDecimal32): RawByteString;
var S : RawByteString;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal32ToStrB(A.Value);
Result := S;
end;
function SDecimal32ToStrU(const A: SDecimal32): UnicodeString;
var S : UnicodeString;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal32ToStrU(A.Value);
Result := S;
end;
function TryStrToSDecimal32(const A: String; out B: SDecimal32): TDecimalConvertErrorType;
var C : Char;
T : String;
R : TDecimalConvertErrorType;
begin
if A = '' then
raise EDecimalError.Create(SConvertError);
C := A[1];
if (C = '+') or (C = '-') then
T := CopyFrom(A, 2)
else
begin
C := '+';
T := A;
end;
R := TryStrToDecimal32(T, B.Value);
if R = dceNoError then
begin
if Decimal32IsZero(B.Value) then
B.Sign := 0
else
if C = '+' then
B.Sign := 1
else
B.Sign := -1;
end;
Result := R;
end;
function TryStrToSDecimal32B(const A: RawByteString; out B: SDecimal32): TDecimalConvertErrorType;
var C : AnsiChar;
T : RawByteString;
R : TDecimalConvertErrorType;
begin
if A = '' then
raise EDecimalError.Create(SConvertError);
C := A[1];
if (C = '+') or (C = '-') then
T := CopyFromB(A, 2)
else
begin
C := '+';
T := A;
end;
R := TryStrToDecimal32B(T, B.Value);
if R = dceNoError then
begin
if Decimal32IsZero(B.Value) then
B.Sign := 0
else
if C = '+' then
B.Sign := 1
else
B.Sign := -1;
end;
Result := R;
end;
function StrToSDecimal32(const A: String): SDecimal32;
begin
case TryStrToSDecimal32(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function StrToSDecimal32B(const A: RawByteString): SDecimal32;
begin
case TryStrToSDecimal32B(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
{ }
{ SDecimal64 }
{ }
procedure SDecimal64InitZero(var A: SDecimal64);
begin
A.Sign := 0;
Decimal64InitZero(A.Value);
end;
procedure SDecimal64InitOne(var A: SDecimal64);
begin
A.Sign := 1;
Decimal64InitOne(A.Value);
end;
procedure SDecimal64InitMinusOne(var A: SDecimal64);
begin
A.Sign := -1;
Decimal64InitOne(A.Value);
end;
procedure SDecimal64InitMin(var A: SDecimal64);
begin
A.Sign := -1;
Decimal64InitMax(A.Value);
end;
procedure SDecimal64InitMax(var A: SDecimal64);
begin
A.Sign := 1;
Decimal64InitMax(A.Value);
end;
function SDecimal64IsZero(const A: SDecimal64): Boolean;
begin
Result := A.Sign = 0;
end;
function SDecimal64IsOne(const A: SDecimal64): Boolean;
begin
Result := (A.Sign > 0) and Decimal64IsOne(A.Value);
end;
function SDecimal64IsMinusOne(const A: SDecimal64): Boolean;
begin
Result := (A.Sign < 0) and Decimal64IsOne(A.Value);
end;
function SDecimal64IsMinimum(const A: SDecimal64): Boolean;
begin
Result := (A.Sign < 0) and Decimal64IsMaximum(A.Value);
end;
function SDecimal64IsMaximum(const A: SDecimal64): Boolean;
begin
Result := (A.Sign > 0) and Decimal64IsMaximum(A.Value);
end;
function SDecimal64IsOverflow(const A: SDecimal64): Boolean;
begin
Result := Decimal64IsOverflow(A.Value);
end;
function Word64IsSDecimal64Range(const A: Word64Rec): Boolean;
begin
Result := Word64CompareInt64(A, Decimal64MaxInt) <= 0;
end;
function Int64IsSDecimal64Range(const A: Int64): Boolean;
begin
Result := (A >= SDecimal64MinInt) and (A <= SDecimal64MaxInt);
end;
function FloatIsSDecimal64Range(const A: Double): Boolean;
begin
Result :=
(A > SDecimal64MinFloatLimD) and
(A < SDecimal64MaxFloatLimD);
end;
function SDecimal64Sign(const A: SDecimal64): Integer;
begin
Result := A.Sign;
end;
procedure SDecimal64Negate(var A: SDecimal64);
begin
A.Sign := -A.Sign;
end;
procedure SDecimal64AbsInPlace(var A: SDecimal64);
begin
if A.Sign < 0 then
A.Sign := 1;
end;
procedure SDecimal64InitWord8(var A: SDecimal64; const B: Byte);
begin
if B = 0 then
SDecimal64InitZero(A)
else
begin
A.Sign := 1;
Decimal64InitWord8(A.Value, B);
end;
end;
procedure SDecimal64InitWord16(var A: SDecimal64; const B: Word);
begin
if B = 0 then
SDecimal64InitZero(A)
else
begin
A.Sign := 1;
Decimal64InitWord16(A.Value, B);
end;
end;
procedure SDecimal64InitWord32(var A: SDecimal64; const B: Word32);
begin
if B = 0 then
SDecimal64InitZero(A)
else
begin
A.Sign := 1;
Decimal64InitWord32(A.Value, B);
end;
end;
procedure SDecimal64InitWord64(var A: SDecimal64; const B: Word64Rec);
begin
if Word64IsZero(B) then
SDecimal64InitZero(A)
else
begin
A.Sign := 1;
Decimal64InitWord64(A.Value, B);
end;
end;
procedure SDecimal64InitInt32(var A: SDecimal64; const B: Int32);
begin
if B = 0 then
SDecimal64InitZero(A)
else
if B < 0 then
begin
A.Sign := -1;
Decimal64InitWord32(A.Value, -B);
end
else
begin
A.Sign := 1;
Decimal64InitWord32(A.Value, B);
end;
end;
procedure SDecimal64InitInt64(var A: SDecimal64; const B: Int64);
begin
if B = 0 then
SDecimal64InitZero(A)
else
if B < 0 then
begin
A.Sign := -1;
Decimal64InitInt64(A.Value, -B);
end
else
begin
A.Sign := 1;
Decimal64InitInt64(A.Value, B);
end;
end;
procedure SDecimal64InitSDecimal64(var A: SDecimal64; const B: SDecimal64);
begin
A.Sign := B.Sign;
A.Value := B.Value;
end;
procedure SDecimal64InitFloat(var A: SDecimal64; const B: Double);
begin
if B < Decimal64MinFloatD then
begin
A.Sign := -1;
Decimal64InitFloat(A.Value, -B);
end
else
if B > -Decimal64MinFloatD then
begin
A.Sign := 1;
Decimal64InitFloat(A.Value, B);
end
else
SDecimal64InitZero(A);
end;
function SDecimal64ToWord8(const A: SDecimal64): Byte;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal64ToWord8(A.Value);
end;
function SDecimal64ToWord16(const A: SDecimal64): Word;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal64ToWord16(A.Value);
end;
function SDecimal64ToWord32(const A: SDecimal64): Word32;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal64ToWord32(A.Value);
end;
function SDecimal64ToWord64(const A: SDecimal64): Word64Rec;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal64ToWord64(A.Value);
end;
function SDecimal64ToInt32(const A: SDecimal64): Int32;
var T : Int32;
begin
T := Decimal64ToInt32(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal64ToInt64(const A: SDecimal64): Int64;
var T : Int64;
begin
T := Decimal64ToInt64(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal64ToSDecimal32(const A: SDecimal64): SDecimal32;
begin
// TODO
end;
function SDecimal64ToFloat(const A: SDecimal64): Double;
var T : Double;
begin
T := Decimal64ToFloat(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal64Trunc(const A: SDecimal64): Int64;
var T : Int64;
begin
T := Decimal64Trunc(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal64Round(const A: SDecimal64): Int64;
var T : Int64;
begin
T := Decimal64Round(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal64FracWord(const A: SDecimal64): Word32;
begin
Result := Decimal64FracWord(A.Value);
end;
function SDecimal64EqualsWord8(const A: SDecimal64; const B: Byte): Boolean;
begin
Result := (A.Sign >= 0) and Decimal64EqualsWord8(A.Value, B);
end;
function SDecimal64EqualsWord16(const A: SDecimal64; const B: Word): Boolean;
begin
Result := (A.Sign >= 0) and Decimal64EqualsWord16(A.Value, B);
end;
function SDecimal64EqualsWord32(const A: SDecimal64; const B: Word32): Boolean;
begin
Result := (A.Sign >= 0) and Decimal64EqualsWord32(A.Value, B);
end;
function SDecimal64EqualsInt32(const A: SDecimal64; const B: Int32): Boolean;
begin
if A.Sign = 0 then
Result := (B = 0)
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := False
else
Result := Decimal64EqualsWord32(A.Value, B);
end
else
begin
if B >= 0 then
Result := False
else
Result := Decimal64EqualsWord32(A.Value, -B);
end;
end;
function SDecimal64EqualsInt64(const A: SDecimal64; const B: Int64): Boolean;
begin
if A.Sign = 0 then
Result := (B = 0)
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := False
else
Result := Decimal64EqualsInt64(A.Value, B);
end
else
begin
if B >= 0 then
Result := False
else
Result := Decimal64EqualsInt64(A.Value, -B);
end;
end;
function SDecimal64EqualsSDecimal64(const A: SDecimal64; const B: SDecimal64): Boolean;
begin
Result :=
(A.Sign = B.Sign) and
Decimal64EqualSDecimal64(A.Value, B.Value);
end;
function SDecimal64EqualsFloat(const A: SDecimal64; const B: Double): Boolean;
begin
if A.Sign >= 0 then
Result := Decimal64EqualsFloat(A.Value, B)
else
Result := Decimal64EqualsFloat(A.Value, -B);
end;
function SDecimal64CompareWord8(const A: SDecimal64; const B: Byte): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal64CompareWord8(A.Value, B)
else
Result := -1;
end;
function SDecimal64CompareWord16(const A: SDecimal64; const B: Word): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal64CompareWord16(A.Value, B)
else
Result := -1;
end;
function SDecimal64CompareWord32(const A: SDecimal64; const B: Word32): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal64CompareWord32(A.Value, B)
else
Result := -1;
end;
function SDecimal64CompareInt32(const A: SDecimal64; const B: Int32): Integer;
begin
if A.Sign = 0 then
begin
if B < 0 then
Result := 1
else
if B > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := 1
else
Result := Decimal64CompareWord32(A.Value, B);
end
else
begin
if B >= 0 then
Result := -1
else
Result := -Decimal64CompareWord32(A.Value, -B);
end;
end;
function SDecimal64CompareInt64(const A: SDecimal64; const B: Int64): Integer;
begin
if A.Sign = 0 then
begin
if B < 0 then
Result := 1
else
if B > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := 1
else
Result := Decimal64CompareInt64(A.Value, B);
end
else
begin
if B >= 0 then
Result := -1
else
Result := -Decimal64CompareInt64(A.Value, -B);
end;
end;
function SDecimal64CompareSDecimal64(const A: SDecimal64; const B: SDecimal64): Integer;
begin
if A.Sign = 0 then
begin
if B.Sign < 0 then
Result := 1
else
if B.Sign > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B.Sign <= 0 then
Result := 1
else
Result := Decimal64CompareDecimal64(A.Value, B.Value);
end
else
begin
if B.Sign >= 0 then
Result := -1
else
Result := -Decimal64CompareDecimal64(A.Value, B.Value);
end;
end;
function SDecimal64CompareFloat(const A: SDecimal64; const B: Double): Integer;
begin
if A.Sign >= 0 then
Result := Decimal64CompareFloat(A.Value, B)
else
Result := -Decimal64CompareFloat(A.Value, -B);
end;
procedure SDecimal64AddWord8(var A: SDecimal64; const B: Byte);
var S : Int8;
T : Decimal64;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal64InitWord8(A.Value, B);
end
else
if A.Sign > 0 then
Decimal64AddWord8(A.Value, B)
else
begin
S := Decimal64CompareWord8(A.Value, B);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractWord8(A.Value, B)
else
begin
A.Sign := 1;
Decimal64InitWord8(T, B);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64AddWord16(var A: SDecimal64; const B: Word);
var S : Int8;
T : Decimal64;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal64InitWord16(A.Value, B);
end
else
if A.Sign > 0 then
Decimal64AddWord16(A.Value, B)
else
begin
S := Decimal64CompareWord16(A.Value, B);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractWord16(A.Value, B)
else
begin
A.Sign := 1;
Decimal64InitWord16(T, B);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64AddWord32(var A: SDecimal64; const B: Word32);
var S : Int8;
T : Decimal64;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal64InitWord32(A.Value, B);
end
else
if A.Sign > 0 then
Decimal64AddWord32(A.Value, B)
else
begin
S := Decimal64CompareWord32(A.Value, B);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractWord32(A.Value, B)
else
begin
A.Sign := 1;
Decimal64InitWord32(T, B);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64AddSDecimal64(var A: SDecimal64; const B: SDecimal64);
var S : Int8;
T : Decimal64;
begin
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal64InitDecimal64(A.Value, B.Value);
end
else
if A.Sign = B.Sign then
Decimal64AddDecimal64(A.Value, B.Value)
else
begin
S := Decimal64CompareDecimal64(A.Value, B.Value);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractDecimal64(A.Value, B.Value)
else
begin
A.Sign := -A.Sign;
Decimal64InitDecimal64(T, B.Value);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64SubtractWord8(var A: SDecimal64; const B: Byte);
var S : Int8;
T : Decimal64;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal64InitWord8(A.Value, B);
end
else
if A.Sign < 0 then
Decimal64AddWord8(A.Value, B)
else
begin
S := Decimal64CompareWord8(A.Value, B);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractWord8(A.Value, B)
else
begin
A.Sign := -1;
Decimal64InitWord8(T, B);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64SubtractWord16(var A: SDecimal64; const B: Word);
var S : Int8;
T : Decimal64;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal64InitWord16(A.Value, B);
end
else
if A.Sign < 0 then
Decimal64AddWord8(A.Value, B)
else
begin
S := Decimal64CompareWord16(A.Value, B);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractWord16(A.Value, B)
else
begin
A.Sign := -1;
Decimal64InitWord16(T, B);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64SubtractWord32(var A: SDecimal64; const B: Word32);
var S : Int8;
T : Decimal64;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal64InitWord32(A.Value, B);
end
else
if A.Sign < 0 then
Decimal64AddWord32(A.Value, B)
else
begin
S := Decimal64CompareWord32(A.Value, B);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractWord32(A.Value, B)
else
begin
A.Sign := -1;
Decimal64InitWord32(T, B);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64SubtractSDecimal64(var A: SDecimal64; const B: SDecimal64);
var S : Int8;
T : Decimal64;
begin
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal64InitDecimal64(A.Value, B.Value);
end
else
if A.Sign <> B.Sign then
Decimal64AddDecimal64(A.Value, B.Value)
else
begin
S := Decimal64CompareDecimal64(A.Value, B.Value);
if S = 0 then
SDecimal64InitZero(A)
else
if S > 0 then
Decimal64SubtractDecimal64(A.Value, B.Value)
else
begin
A.Sign := -A.Sign;
Decimal64InitDecimal64(T, B.Value);
Decimal64SubtractDecimal64(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal64MultiplyWord8(var A: SDecimal64; const B: Byte);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal64InitZero(A);
exit;
end;
Decimal64MultiplyWord8(A.Value, B);
end;
procedure SDecimal64MultiplyWord16(var A: SDecimal64; const B: Word);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal64InitZero(A);
exit;
end;
Decimal64MultiplyWord16(A.Value, B);
end;
procedure SDecimal64MultiplyWord32(var A: SDecimal64; const B: Word32);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal64InitZero(A);
exit;
end;
Decimal64MultiplyWord32(A.Value, B);
end;
procedure SDecimal64MultiplySDecimal64(var A: SDecimal64; const B: SDecimal64);
begin
if A.Sign = 0 then
exit;
if B.Sign = 0 then
begin
SDecimal64InitZero(A);
exit;
end;
Decimal64MultiplyDecimal64(A.Value, B.Value);
if A.Sign = B.Sign then
A.Sign := 1
else
A.Sign := -1;
end;
procedure SDecimal64DivideWord8(var A: SDecimal64; const B: Byte);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal64DivideWord8(A.Value, B);
end;
procedure SDecimal64DivideWord16(var A: SDecimal64; const B: Word);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal64DivideWord16(A.Value, B);
end;
procedure SDecimal64DivideWord32(var A: SDecimal64; const B: Word32);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal64DivideWord32(A.Value, B);
end;
procedure SDecimal64DivideSDecimal64(var A: SDecimal64; const B: SDecimal64);
begin
if B.Sign = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal64DivideDecimal64(A.Value, B.Value);
if A.Sign = B.Sign then
A.Sign := 1
else
A.Sign := -1;
end;
function SDecimal64ToStr(const A: SDecimal64): String;
var S : String;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal64ToStr(A.Value);
Result := S;
end;
function SDecimal64ToStrB(const A: SDecimal64): RawByteString;
var S : RawByteString;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal64ToStrB(A.Value);
Result := S;
end;
function SDecimal64ToStrU(const A: SDecimal64): UnicodeString;
var S : UnicodeString;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal64ToStrU(A.Value);
Result := S;
end;
function TryStrToSDecimal64(const A: String; out B: SDecimal64): TDecimalConvertErrorType;
var C : Char;
T : String;
R : TDecimalConvertErrorType;
begin
if A = '' then
raise EDecimalError.Create(SConvertError);
C := A[1];
if (C = '+') or (C = '-') then
T := CopyFrom(A, 2)
else
begin
C := '+';
T := A;
end;
R := TryStrToDecimal64(T, B.Value);
if R = dceNoError then
begin
if Decimal64IsZero(B.Value) then
B.Sign := 0
else
if C = '+' then
B.Sign := 1
else
B.Sign := -1;
end;
Result := R;
end;
function TryStrToSDecimal64B(const A: RawByteString; out B: SDecimal64): TDecimalConvertErrorType;
var C : AnsiChar;
T : RawByteString;
R : TDecimalConvertErrorType;
begin
if A = '' then
raise EDecimalError.Create(SConvertError);
C := A[1];
if (C = '+') or (C = '-') then
T := CopyFromB(A, 2)
else
begin
C := '+';
T := A;
end;
R := TryStrToDecimal64B(T, B.Value);
if R = dceNoError then
begin
if Decimal64IsZero(B.Value) then
B.Sign := 0
else
if C = '+' then
B.Sign := 1
else
B.Sign := -1;
end;
Result := R;
end;
function StrToSDecimal64(const A: String): SDecimal64;
begin
case TryStrToSDecimal64(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function StrToSDecimal64B(const A: RawByteString): SDecimal64;
begin
case TryStrToSDecimal64B(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
{ }
{ SDecimal128 }
{ }
procedure SDecimal128InitZero(var A: SDecimal128);
begin
A.Sign := 0;
Decimal128InitZero(A.Value);
end;
procedure SDecimal128InitOne(var A: SDecimal128);
begin
A.Sign := 1;
Decimal128InitOne(A.Value);
end;
procedure SDecimal128InitMinusOne(var A: SDecimal128);
begin
A.Sign := -1;
Decimal128InitOne(A.Value);
end;
procedure SDecimal128InitMin(var A: SDecimal128);
begin
A.Sign := -1;
Decimal128InitMax(A.Value);
end;
procedure SDecimal128InitMax(var A: SDecimal128);
begin
A.Sign := 1;
Decimal128InitMax(A.Value);
end;
function SDecimal128IsZero(const A: SDecimal128): Boolean;
begin
Result := A.Sign = 0;
end;
function SDecimal128IsOne(const A: SDecimal128): Boolean;
begin
Result := (A.Sign > 0) and Decimal128IsOne(A.Value);
end;
function SDecimal128IsMinusOne(const A: SDecimal128): Boolean;
begin
Result := (A.Sign < 0) and Decimal128IsOne(A.Value);
end;
function SDecimal128IsMinimum(const A: SDecimal128): Boolean;
begin
Result := (A.Sign < 0) and Decimal128IsMaximum(A.Value);
end;
function SDecimal128IsMaximum(const A: SDecimal128): Boolean;
begin
Result := (A.Sign > 0) and Decimal128IsMaximum(A.Value);
end;
function SDecimal128IsOverflow(const A: SDecimal128): Boolean;
begin
Result := Decimal128IsOverflow(A.Value);
end;
function Word64IsSDecimal128Range(const A: Word64Rec): Boolean;
begin
Result := Word64CompareWord64(A, Decimal128MaxInt) <= 0;
end;
function Word128IsSDecimal128Range(const A: Word128): Boolean;
begin
Result := Word128CompareWord64(A, Decimal128MaxInt) <= 0;
end;
function Int128IsSDecimal128Range(const A: Int128): Boolean;
var T : Int128;
begin
T := A;
Int128AbsInPlace(T);
Result := Int128CompareWord64(T, Decimal128MaxInt) <= 0;
end;
function FloatIsSDecimal128Range(const A: Double): Boolean;
begin
Result :=
(A > SDecimal128MinFloatLimD) and
(A < SDecimal128MaxFloatLimD);
end;
procedure SDecimal128InitWord8(var A: SDecimal128; const B: Byte);
begin
if B = 0 then
SDecimal128InitZero(A)
else
begin
A.Sign := 1;
Decimal128InitWord8(A.Value, B);
end;
end;
function SDecimal128Sign(const A: SDecimal128): Integer;
begin
Result := A.Sign;
end;
procedure SDecimal128Negate(var A: SDecimal128);
begin
A.Sign := -A.Sign;
end;
procedure SDecimal128AbsInPlace(var A: SDecimal128);
begin
if A.Sign < 0 then
A.Sign := 1;
end;
procedure SDecimal128InitWord16(var A: SDecimal128; const B: Word);
begin
if B = 0 then
SDecimal128InitZero(A)
else
begin
A.Sign := 1;
Decimal128InitWord16(A.Value, B);
end;
end;
procedure SDecimal128InitWord32(var A: SDecimal128; const B: Word32);
begin
if B = 0 then
SDecimal128InitZero(A)
else
begin
A.Sign := 1;
Decimal128InitWord32(A.Value, B);
end;
end;
procedure SDecimal128InitWord64(var A: SDecimal128; const B: Word64Rec);
begin
if Word64IsZero(B) then
SDecimal128InitZero(A)
else
begin
A.Sign := 1;
Decimal128InitWord64(A.Value, B);
end;
end;
procedure SDecimal128InitInt32(var A: SDecimal128; const B: Int32);
begin
if B = 0 then
SDecimal128InitZero(A)
else
if B < 0 then
begin
A.Sign := -1;
Decimal128InitWord32(A.Value, -B);
end
else
begin
A.Sign := 1;
Decimal128InitWord32(A.Value, B);
end;
end;
procedure SDecimal128InitInt64(var A: SDecimal128; const B: Int64);
begin
if B = 0 then
SDecimal128InitZero(A)
else
if B < 0 then
begin
A.Sign := -1;
Decimal128InitInt64(A.Value, -B);
end
else
begin
A.Sign := 1;
Decimal128InitInt64(A.Value, B);
end;
end;
procedure SDecimal128InitSDecimal128(var A: SDecimal128; const B: SDecimal128);
begin
A.Sign := B.Sign;
A.Value := B.Value;
end;
procedure SDecimal128InitFloat(var A: SDecimal128; const B: Double);
begin
if B < Decimal128MinFloatD then
begin
A.Sign := -1;
Decimal128InitFloat(A.Value, -B);
end
else
if B > -Decimal128MinFloatD then
begin
A.Sign := 1;
Decimal128InitFloat(A.Value, B);
end
else
SDecimal128InitZero(A);
end;
function SDecimal128ToWord8(const A: SDecimal128): Byte;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal128ToWord8(A.Value);
end;
function SDecimal128ToWord16(const A: SDecimal128): Word;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal128ToWord16(A.Value);
end;
function SDecimal128ToWord32(const A: SDecimal128): Word32;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal128ToWord32(A.Value);
end;
function SDecimal128ToWord64(const A: SDecimal128): Word64Rec;
begin
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError);
Result := Decimal128ToWord64(A.Value);
end;
function SDecimal128ToInt32(const A: SDecimal128): Int32;
var T : Int32;
begin
T := Decimal128ToInt32(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal128ToInt64(const A: SDecimal128): Int64;
var T : Int64;
begin
T := Decimal128ToInt64(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal128ToFloat(const A: SDecimal128): Double;
var T : Double;
begin
T := Decimal128ToFloat(A.Value);
if A.Sign < 0 then
T := -T;
Result := T;
end;
function SDecimal128Trunc(const A: SDecimal128): Int128;
var T : Word64Rec;
Q : Int128;
begin
T := Decimal128Trunc(A.Value);
Int128InitWord64(Q, T);
if A.Sign < 0 then
Int128Negate(Q);
Result := Q;
end;
function SDecimal128Round(const A: SDecimal128): Int128;
var T : Word64Rec;
Q : Int128;
begin
T := Decimal128Round(A.Value);
Int128InitWord64(Q, T);
if A.Sign < 0 then
Int128Negate(Q);
Result := Q;
end;
function SDecimal128FracWord(const A: SDecimal128): Word64Rec;
begin
Result := Decimal128FracWord(A.Value);
end;
function SDecimal128EqualsWord8(const A: SDecimal128; const B: Byte): Boolean;
begin
Result := (A.Sign >= 0) and Decimal128EqualsWord8(A.Value, B);
end;
function SDecimal128EqualsWord16(const A: SDecimal128; const B: Word): Boolean;
begin
Result := (A.Sign >= 0) and Decimal128EqualsWord16(A.Value, B);
end;
function SDecimal128EqualsWord32(const A: SDecimal128; const B: Word32): Boolean;
begin
Result := (A.Sign >= 0) and Decimal128EqualsWord32(A.Value, B);
end;
function SDecimal128EqualsWord64(const A: SDecimal128; const B: Word64Rec): Boolean;
begin
Result := (A.Sign >= 0) and Decimal128EqualsWord64(A.Value, B);
end;
function SDecimal128EqualsInt32(const A: SDecimal128; const B: Int32): Boolean;
begin
if A.Sign = 0 then
Result := (B = 0)
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := False
else
Result := Decimal128EqualsWord32(A.Value, B);
end
else
begin
if B >= 0 then
Result := False
else
Result := Decimal128EqualsWord32(A.Value, -B);
end;
end;
function SDecimal128EqualsInt64(const A: SDecimal128; const B: Int64): Boolean;
begin
if A.Sign = 0 then
Result := (B = 0)
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := False
else
Result := Decimal128EqualsInt64(A.Value, B);
end
else
begin
if B >= 0 then
Result := False
else
Result := Decimal128EqualsInt64(A.Value, -B);
end;
end;
function SDecimal128EqualsSDecimal128(const A: SDecimal128; const B: SDecimal128): Boolean;
begin
Result :=
(A.Sign = B.Sign) and
Decimal128EqualSDecimal128(A.Value, B.Value);
end;
function SDecimal128EqualsFloat(const A: SDecimal128; const B: Double): Boolean;
begin
if A.Sign >= 0 then
Result := Decimal128EqualsFloat(A.Value, B)
else
Result := Decimal128EqualsFloat(A.Value, -B);
end;
function SDecimal128CompareWord8(const A: SDecimal128; const B: Byte): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal128CompareWord8(A.Value, B)
else
Result := -1;
end;
function SDecimal128CompareWord16(const A: SDecimal128; const B: Word): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal128CompareWord16(A.Value, B)
else
Result := -1;
end;
function SDecimal128CompareWord32(const A: SDecimal128; const B: Word32): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal128CompareWord32(A.Value, B)
else
Result := -1;
end;
function SDecimal128CompareWord64(const A: SDecimal128; const B: Word64Rec): Integer;
begin
if A.Sign = 0 then
if Word64IsZero(B) then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := Decimal128CompareWord64(A.Value, B)
else
Result := -1;
end;
function SDecimal128CompareInt32(const A: SDecimal128; const B: Int32): Integer;
begin
if A.Sign = 0 then
begin
if B < 0 then
Result := 1
else
if B > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := 1
else
Result := Decimal128CompareWord32(A.Value, B);
end
else
begin
if B >= 0 then
Result := -1
else
Result := -Decimal128CompareWord32(A.Value, -B);
end;
end;
function SDecimal128CompareInt64(const A: SDecimal128; const B: Int64): Integer;
var T : Word64Rec;
begin
if A.Sign = 0 then
begin
if B < 0 then
Result := 1
else
if B > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B <= 0 then
Result := 1
else
begin
Word64InitInt64(T, B);
Result := Decimal128CompareWord64(A.Value, T);
end;
end
else
begin
if B >= 0 then
Result := -1
else
begin
Word64InitInt64(T, -B);
Result := -Decimal128CompareWord64(A.Value, T);
end;
end;
end;
function SDecimal128CompareSDecimal128(const A: SDecimal128; const B: SDecimal128): Integer;
begin
if A.Sign = 0 then
begin
if B.Sign < 0 then
Result := 1
else
if B.Sign > 0 then
Result := -1
else
Result := 0;
end
else
if A.Sign > 0 then
begin
if B.Sign <= 0 then
Result := 1
else
Result := Decimal128CompareDecimal128(A.Value, B.Value);
end
else
begin
if B.Sign >= 0 then
Result := -1
else
Result := -Decimal128CompareDecimal128(A.Value, B.Value);
end;
end;
function SDecimal128CompareFloat(const A: SDecimal128; const B: Double): Integer;
begin
if A.Sign >= 0 then
Result := Decimal128CompareFloat(A.Value, B)
else
Result := -Decimal128CompareFloat(A.Value, -B);
end;
procedure SDecimal128AddWord8(var A: SDecimal128; const B: Byte);
var S : Int8;
T : Decimal128;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal128InitWord8(A.Value, B);
end
else
if A.Sign > 0 then
Decimal128AddWord8(A.Value, B)
else
begin
S := Decimal128CompareWord8(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord8(A.Value, B)
else
begin
A.Sign := 1;
Decimal128InitWord8(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128AddWord16(var A: SDecimal128; const B: Word);
var S : Int8;
T : Decimal128;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal128InitWord16(A.Value, B);
end
else
if A.Sign > 0 then
Decimal128AddWord16(A.Value, B)
else
begin
S := Decimal128CompareWord16(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord16(A.Value, B)
else
begin
A.Sign := 1;
Decimal128InitWord16(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128AddWord32(var A: SDecimal128; const B: Word32);
var S : Int8;
T : Decimal128;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal128InitWord32(A.Value, B);
end
else
if A.Sign > 0 then
Decimal128AddWord32(A.Value, B)
else
begin
S := Decimal128CompareWord32(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord32(A.Value, B)
else
begin
A.Sign := 1;
Decimal128InitWord32(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128AddWord64(var A: SDecimal128; const B: Word64Rec);
var S : Int8;
T : Decimal128;
begin
if Word64IsZero(B) then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal128InitWord64(A.Value, B);
end
else
if A.Sign > 0 then
Decimal128AddWord64(A.Value, B)
else
begin
S := Decimal128CompareWord64(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord64(A.Value, B)
else
begin
A.Sign := 1;
Decimal128InitWord64(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128AddSDecimal128(var A: SDecimal128; const B: SDecimal128);
var S : Int8;
T : Decimal128;
begin
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := 1;
Decimal128InitDecimal128(A.Value, B.Value);
end
else
if A.Sign = B.Sign then
Decimal128AddDecimal128(A.Value, B.Value)
else
begin
S := Decimal128CompareDecimal128(A.Value, B.Value);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractDecimal128(A.Value, B.Value)
else
begin
A.Sign := -A.Sign;
Decimal128InitDecimal128(T, B.Value);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128SubtractWord8(var A: SDecimal128; const B: Byte);
var S : Int8;
T : Decimal128;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal128InitWord8(A.Value, B);
end
else
if A.Sign < 0 then
Decimal128AddWord8(A.Value, B)
else
begin
S := Decimal128CompareWord8(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord8(A.Value, B)
else
begin
A.Sign := -1;
Decimal128InitWord8(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128SubtractWord16(var A: SDecimal128; const B: Word);
var S : Int8;
T : Decimal128;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal128InitWord16(A.Value, B);
end
else
if A.Sign < 0 then
Decimal128AddWord8(A.Value, B)
else
begin
S := Decimal128CompareWord16(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord16(A.Value, B)
else
begin
A.Sign := -1;
Decimal128InitWord16(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128SubtractWord32(var A: SDecimal128; const B: Word32);
var S : Int8;
T : Decimal128;
begin
if B = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal128InitWord32(A.Value, B);
end
else
if A.Sign < 0 then
Decimal128AddWord32(A.Value, B)
else
begin
S := Decimal128CompareWord32(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord32(A.Value, B)
else
begin
A.Sign := -1;
Decimal128InitWord32(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128SubtractWord64(var A: SDecimal128; const B: Word64Rec);
var S : Int8;
T : Decimal128;
begin
if Word64IsZero(B) then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal128InitWord64(A.Value, B);
end
else
if A.Sign < 0 then
Decimal128AddWord64(A.Value, B)
else
begin
S := Decimal128CompareWord64(A.Value, B);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractWord64(A.Value, B)
else
begin
A.Sign := -1;
Decimal128InitWord64(T, B);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128SubtractSDecimal128(var A: SDecimal128; const B: SDecimal128);
var S : Int8;
T : Decimal128;
begin
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
A.Sign := -1;
Decimal128InitDecimal128(A.Value, B.Value);
end
else
if A.Sign <> B.Sign then
Decimal128AddDecimal128(A.Value, B.Value)
else
begin
S := Decimal128CompareDecimal128(A.Value, B.Value);
if S = 0 then
SDecimal128InitZero(A)
else
if S > 0 then
Decimal128SubtractDecimal128(A.Value, B.Value)
else
begin
A.Sign := -A.Sign;
Decimal128InitDecimal128(T, B.Value);
Decimal128SubtractDecimal128(T, A.Value);
A.Value := T;
end;
end;
end;
procedure SDecimal128MultiplyWord8(var A: SDecimal128; const B: Byte);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal128InitZero(A);
exit;
end;
Decimal128MultiplyWord8(A.Value, B);
end;
procedure SDecimal128MultiplyWord16(var A: SDecimal128; const B: Word);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal128InitZero(A);
exit;
end;
Decimal128MultiplyWord16(A.Value, B);
end;
procedure SDecimal128MultiplyWord32(var A: SDecimal128; const B: Word32);
begin
if A.Sign = 0 then
exit;
if B = 0 then
begin
SDecimal128InitZero(A);
exit;
end;
Decimal128MultiplyWord32(A.Value, B);
end;
procedure SDecimal128MultiplyWord64(var A: SDecimal128; const B: Word64Rec);
begin
if A.Sign = 0 then
exit;
if Word64IsZero(B) then
begin
SDecimal128InitZero(A);
exit;
end;
Decimal128MultiplyWord64(A.Value, B);
end;
procedure SDecimal128MultiplySDecimal128(var A: SDecimal128; const B: SDecimal128);
begin
if A.Sign = 0 then
exit;
if B.Sign = 0 then
begin
SDecimal128InitZero(A);
exit;
end;
Decimal128MultiplyDecimal128(A.Value, B.Value);
if A.Sign = B.Sign then
A.Sign := 1
else
A.Sign := -1;
end;
procedure SDecimal128DivideWord8(var A: SDecimal128; const B: Byte);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal128DivideWord8(A.Value, B);
end;
procedure SDecimal128DivideWord16(var A: SDecimal128; const B: Word);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal128DivideWord16(A.Value, B);
end;
procedure SDecimal128DivideWord32(var A: SDecimal128; const B: Word32);
begin
if B = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal128DivideWord32(A.Value, B);
end;
procedure SDecimal128DivideWord64(var A: SDecimal128; const B: Word64Rec);
begin
if Word64IsZero(B) then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal128DivideWord64(A.Value, B);
end;
procedure SDecimal128DivideSDecimal128(var A: SDecimal128; const B: SDecimal128);
begin
if B.Sign = 0 then
raise EDecimalError.Create(SDivisionByZero);
if A.Sign = 0 then
exit;
Decimal128DivideDecimal128(A.Value, B.Value);
if A.Sign = B.Sign then
A.Sign := 1
else
A.Sign := -1;
end;
function SDecimal128ToStr(const A: SDecimal128): String;
var S : String;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal128ToStr(A.Value);
Result := S;
end;
function SDecimal128ToStrB(const A: SDecimal128): RawByteString;
var S : RawByteString;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal128ToStrB(A.Value);
Result := S;
end;
function SDecimal128ToStrU(const A: SDecimal128): UnicodeString;
var S : UnicodeString;
begin
if A.Sign < 0 then
S := '-'
else
S := '';
S := S + Decimal128ToStrU(A.Value);
Result := S;
end;
function TryStrToSDecimal128(const A: String; out B: SDecimal128): TDecimalConvertErrorType;
var C : Char;
T : String;
R : TDecimalConvertErrorType;
begin
if A = '' then
raise EDecimalError.Create(SConvertError);
C := A[1];
if (C = '+') or (C = '-') then
T := CopyFrom(A, 2)
else
begin
C := '+';
T := A;
end;
R := TryStrToDecimal128(T, B.Value);
if R = dceNoError then
begin
if Decimal128IsZero(B.Value) then
B.Sign := 0
else
if C = '+' then
B.Sign := 1
else
B.Sign := -1;
end;
Result := R;
end;
function TryStrToSDecimal128B(const A: RawByteString; out B: SDecimal128): TDecimalConvertErrorType;
var C : AnsiChar;
T : RawByteString;
R : TDecimalConvertErrorType;
begin
if A = '' then
raise EDecimalError.Create(SConvertError);
C := A[1];
if (C = '+') or (C = '-') then
T := CopyFromB(A, 2)
else
begin
C := '+';
T := A;
end;
R := TryStrToDecimal128B(T, B.Value);
if R = dceNoError then
begin
if Decimal128IsZero(B.Value) then
B.Sign := 0
else
if C = '+' then
B.Sign := 1
else
B.Sign := -1;
end;
Result := R;
end;
function StrToSDecimal128(const A: String): SDecimal128;
begin
case TryStrToSDecimal128(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function StrToSDecimal128B(const A: RawByteString): SDecimal128;
begin
case TryStrToSDecimal128B(A, Result) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
{ }
{ SHugeDecimal }
{ }
procedure SHugeDecimalInit(out A: SHugeDecimal);
begin
A.Sign := 0;
HugeDecimalInit(A.Value);
end;
procedure SHugeDecimalInitZero(out A: SHugeDecimal);
begin
SHugeDecimalInit(A);
SHugeDecimalAssignZero(A);
end;
procedure SHugeDecimalInitOne(out A: SHugeDecimal);
begin
SHugeDecimalInit(A);
SHugeDecimalAssignOne(A);
end;
procedure SHugeDecimalInitMinusOne(out A: SHugeDecimal);
begin
SHugeDecimalInit(A);
SHugeDecimalAssignMinusOne(A);
end;
procedure SHugeDecimalAssignZero(var A: SHugeDecimal);
begin
A.Sign := 0;
HugeDecimalAssignZero(A.Value);
end;
procedure SHugeDecimalAssignOne(var A: SHugeDecimal);
begin
A.Sign := 1;
HugeDecimalAssignOne(A.Value);
end;
procedure SHugeDecimalAssignMinusOne(var A: SHugeDecimal);
begin
A.Sign := -1;
HugeDecimalAssignOne(A.Value);
end;
procedure SHugeDecimalAssignWord8(var A: SHugeDecimal; const B: Byte);
begin
if B = 0 then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignWord8(A.Value, B);
end;
end;
procedure SHugeDecimalAssignWord32(var A: SHugeDecimal; const B: Word32);
begin
if B = 0 then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignWord32(A.Value, B);
end;
end;
procedure SHugeDecimalAssignWord64(var A: SHugeDecimal; const B: Word64Rec);
begin
if Word64IsZero(B) then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignWord64(A.Value, B);
end;
end;
procedure SHugeDecimalAssignWord128(var A: SHugeDecimal; const B: Word128);
begin
if Word128IsZero(B) then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignWord128(A.Value, B);
end;
end;
procedure SHugeDecimalAssignInt8(var A: SHugeDecimal; const B: ShortInt);
begin
if B = 0 then
SHugeDecimalAssignZero(A)
else
begin
if B < 0 then
A.Sign := -1
else
A.Sign := 1;
HugeDecimalAssignWord8(A.Value, Abs(Int32(B)));
end;
end;
procedure SHugeDecimalAssignInt32(var A: SHugeDecimal; const B: Int32);
begin
if B = 0 then
SHugeDecimalAssignZero(A)
else
begin
if B < 0 then
A.Sign := -1
else
A.Sign := 1;
HugeDecimalAssignWord32(A.Value, Abs(Int64(B)));
end;
end;
procedure SHugeDecimalAssignInt64(var A: SHugeDecimal; const B: Int64);
var
R : Int128;
begin
if B = 0 then
SHugeDecimalAssignZero(A)
else
begin
if B < 0 then
A.Sign := -1
else
A.Sign := 1;
Int128InitInt64(R, B);
Int128AbsInPlace(R);
HugeDecimalAssignWord64(A.Value, Int128ToWord64(R));
end;
end;
procedure SHugeDecimalAssignDecimal32(var A: SHugeDecimal; const B: Decimal32);
begin
if Decimal32IsZero(B) then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignDecimal32(A.Value, B);
end;
end;
procedure SHugeDecimalAssignDecimal64(var A: SHugeDecimal; const B: Decimal64);
begin
if Decimal64IsZero(B) then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignDecimal64(A.Value, B);
end;
end;
procedure SHugeDecimalAssignDecimal128(var A: SHugeDecimal; const B: Decimal128);
begin
if Decimal128IsZero(B) then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignDecimal128(A.Value, B);
end;
end;
procedure SHugeDecimalAssignHugeDecimal(var A: SHugeDecimal; const B: HugeDecimal);
begin
if HugeDecimalIsZero(B) then
SHugeDecimalAssignZero(A)
else
begin
A.Sign := 1;
HugeDecimalAssignHugeDecimal(A.Value, B);
end;
end;
procedure SHugeDecimalAssignSHugeDecimal(var A: SHugeDecimal; const B: SHugeDecimal);
begin
A.Sign := B.Sign;
HugeDecimalAssignHugeDecimal(A.Value, B.Value);
end;
function SHugeDecimalIsZero(const A: SHugeDecimal): Boolean;
begin
Result := A.Sign = 0;
end;
function SHugeDecimalIsOne(const A: SHugeDecimal): Boolean;
begin
Result := (A.Sign = 1) and HugeDecimalIsOne(A.Value);
end;
function SHugeDecimalIsMinusOne(const A: SHugeDecimal): Boolean;
begin
Result := (A.Sign = -1) and HugeDecimalIsOne(A.Value);
end;
function SHugeDecimalSign(const A: SHugeDecimal): Integer;
begin
Result := A.Sign;
end;
procedure SHugeDecimalNegate(var A: SHugeDecimal);
begin
if A.Sign <> 0 then
A.Sign := -A.Sign;
end;
procedure SHugeDecimalAbsInPlace(var A: SHugeDecimal);
begin
if A.Sign < 0 then
A.Sign := 1;
end;
function SHugeDecimalToWord8(const A: SHugeDecimal): Byte;
begin
if A.Sign = 0 then
Result := 0
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToWord8(A.Value);
end;
function SHugeDecimalToWord32(const A: SHugeDecimal): Word32;
begin
if A.Sign = 0 then
Result := 0
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToWord32(A.Value);
end;
function SHugeDecimalToWord64(const A: SHugeDecimal): Word64Rec;
begin
if A.Sign = 0 then
Word64InitZero(Result)
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToWord64(A.Value);
end;
function SHugeDecimalToWord128(const A: SHugeDecimal): Word128;
begin
if A.Sign = 0 then
Word128InitZero(Result)
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToWord128(A.Value);
end;
function SHugeDecimalToInt8(const A: SHugeDecimal): ShortInt;
var
T : Int16;
begin
if A.Sign = 0 then
Result := 0
else
begin
T := HugeDecimalToWord8(A.Value);
if A.Sign < 0 then
T := -T;
if not Int16IsInt8Range(T) then
raise EDecimalError.Create(SOverflowError);
Result := T;
end;
end;
function SHugeDecimalToInt32(const A: SHugeDecimal): Int32;
var
T : Int64;
begin
if A.Sign = 0 then
Result := 0
else
begin
T := HugeDecimalToWord32(A.Value);
if A.Sign < 0 then
T := -T;
if not Int64IsInt32Range(T) then
raise EDecimalError.Create(SOverflowError);
Result := T;
end;
end;
function SHugeDecimalToInt64(const A: SHugeDecimal): Int64;
var
T : Int128;
begin
if A.Sign = 0 then
Result := 0
else
begin
Int128InitWord64(T, HugeDecimalToWord64(A.Value));
if A.Sign < 0 then
Int128Negate(T);
if not Int128IsInt64Range(T) then
raise EDecimalError.Create(SOverflowError);
Result := Int128ToInt64(T);
end;
end;
function SHugeDecimalToDecimal32(const A: SHugeDecimal): Decimal32;
begin
if A.Sign = 0 then
Decimal32InitZero(Result)
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToDecimal32(A.Value);
end;
function SHugeDecimalToDecimal64(const A: SHugeDecimal): Decimal64;
begin
if A.Sign = 0 then
Decimal64InitZero(Result)
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToDecimal64(A.Value);
end;
function SHugeDecimalToDecimal128(const A: SHugeDecimal): Decimal128;
begin
if A.Sign = 0 then
Decimal128InitZero(Result)
else
if A.Sign < 0 then
raise EDecimalError.Create(SOverflowError)
else
Result := HugeDecimalToDecimal128(A.Value);
end;
procedure SHugeDecimalTrunc(var A: SHugeDecimal);
begin
if A.Sign = 0 then
exit;
HugeDecimalTrunc(A.Value);
end;
function SHugeDecimalFracCompareHalf(var A: SHugeDecimal): Integer;
begin
if A.Sign = 0 then
Result := -1
else
Result := HugeDecimalFracCompareHalf(A.Value);
end;
procedure SHugeDecimalRound(var A: SHugeDecimal);
begin
if A.Sign = 0 then
exit;
HugeDecimalRound(A.Value);
end;
function SHugeDecimalEqualsWord8(const A: SHugeDecimal; const B: Byte): Boolean;
begin
if A.Sign = 0 then
Result := (B = 0)
else
if A.Sign > 0 then
Result := HugeDecimalEqualsWord8(A.Value, B)
else
Result := False;
end;
function SHugeDecimalEqualsHugeDecimal(const A: SHugeDecimal; const B: HugeDecimal): Boolean;
begin
if A.Sign = 0 then
Result := HugeDecimalIsZero(B)
else
if A.Sign > 0 then
Result := HugeDecimalEqualsHugeDecimal(A.Value, B)
else
Result := False;
end;
function SHugeDecimalEqualsSHugeDecimal(const A, B: SHugeDecimal): Boolean;
begin
if A.Sign <> B.Sign then
Result := False
else
Result := HugeDecimalEqualsHugeDecimal(A.Value, B.Value);
end;
function SHugeDecimalCompareWord8(const A: SHugeDecimal; const B: Byte): Integer;
begin
if A.Sign = 0 then
if B = 0 then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := HugeDecimalCompareWord8(A.Value, B)
else
Result := -1;
end;
function SHugeDecimalCompareHugeDecimal(const A: SHugeDecimal; const B: HugeDecimal): Integer;
begin
if A.Sign = 0 then
if HugeDecimalIsZero(B) then
Result := 0
else
Result := -1
else
if A.Sign > 0 then
Result := HugeDecimalCompareHugeDecimal(A.Value, B)
else
Result := -1;
end;
function SHugeDecimalCompareSHugeDecimal(const A, B: SHugeDecimal): Integer;
begin
if A.Sign = 0 then
if B.Sign = 0 then
Result := 0
else
if B.Sign < 0 then
Result := 1
else
Result := -1
else
if A.Sign > 0 then
if B.Sign <= 0 then
Result := 1
else
Result := HugeDecimalCompareHugeDecimal(A.Value, B.Value)
else
if B.Sign >= 0 then
Result := -1
else
Result := HugeDecimalCompareHugeDecimal(B.Value, A.Value);
end;
procedure SHugeDecimalAddHugeDecimal(var A: SHugeDecimal; const B: HugeDecimal);
var
C : Integer;
R : HugeDecimal;
begin
// Handle B = 0 or A = 0
if HugeDecimalIsZero(B) then
exit;
if A.Sign = 0 then
begin
HugeDecimalAssignHugeDecimal(A.Value, B);
A.Sign := 1;
exit;
end;
// A <> 0 and B <> 0
// Handle A > 0
if A.Sign > 0 then
begin
HugeDecimalAddHugeDecimal(A.Value, B);
exit;
end;
// A < 0
// Compare absolute values
C := HugeDecimalCompareHugeDecimal(A.Value, B);
// Handle Abs(A) = B
if C = 0 then
begin
SHugeDecimalAssignZero(A);
exit;
end;
// Abs(A) <> B
// Calculate result value = Abs(A - B)
if C < 0 then
begin
HugeDecimalInitHugeDecimal(R, B);
HugeDecimalSubtractHugeDecimal(R, A.Value);
HugeDecimalAssignHugeDecimal(A.Value, R);
end
else
HugeDecimalSubtractHugeDecimal(A.Value, B);
// Set result sign
if ((A.Sign > 0) and (C > 0)) or
((A.Sign < 0) and (C < 0)) then
A.Sign := 1
else
A.Sign := -1;
end;
procedure SHugeDecimalAddSHugeDecimal(var A: SHugeDecimal; const B: SHugeDecimal);
var
C : Integer;
R : HugeDecimal;
begin
// Handle B = 0 or A = 0
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
SHugeDecimalAssignSHugeDecimal(A, B);
exit;
end;
// A <> 0 and B <> 0
// Handle Sign(A) = Sign(B)
if A.Sign = B.Sign then
begin
HugeDecimalAddHugeDecimal(A.Value, B.Value);
exit;
end;
// Sign(A) <> Sign(B)
// Compare absolute values
C := HugeDecimalCompareHugeDecimal(A.Value, B.Value);
// Handle Abs(A) = Abs(B)
if C = 0 then
begin
SHugeDecimalAssignZero(A);
exit;
end;
// Abs(A) <> Abs(B)
// Calculate result value = Abs(A - B)
if C < 0 then
begin
HugeDecimalInitHugeDecimal(R, B.Value);
HugeDecimalSubtractHugeDecimal(R, A.Value);
HugeDecimalAssignHugeDecimal(A.Value, R);
end
else
HugeDecimalSubtractHugeDecimal(A.Value, B.Value);
// Set result sign
if ((A.Sign > 0) and (C > 0)) or
((A.Sign < 0) and (C < 0)) then
A.Sign := 1
else
A.Sign := -1;
end;
procedure SHugeDecimalSubtractSHugeDecimal(var A: SHugeDecimal; const B: SHugeDecimal);
var
C : Integer;
R : HugeDecimal;
begin
// Handle B = 0 or A = 0
if B.Sign = 0 then
exit;
if A.Sign = 0 then
begin
HugeDecimalAssignHugeDecimal(A.Value, B.Value);
A.Sign := -B.Sign;
exit;
end;
// A <> 0 and B <> 0
// Handle Sign(A) <> Sign(B)
if A.Sign <> B.Sign then
begin
HugeDecimalAddHugeDecimal(A.Value, B.Value);
exit;
end;
// Sign(A) = Sign(B)
// Compare absolute values
C := HugeDecimalCompareHugeDecimal(A.Value, B.Value);
// Handle Abs(A) = Abs(B)
if C = 0 then
begin
SHugeDecimalAssignZero(A);
exit;
end;
// Abs(A) <> Abs(B)
// Calculate result value = Abs(A - B)
if C < 0 then
begin
HugeDecimalInitHugeDecimal(R, B.Value);
HugeDecimalSubtractHugeDecimal(R, A.Value);
HugeDecimalAssignHugeDecimal(A.Value, R);
end
else
HugeDecimalSubtractHugeDecimal(A.Value, B.Value);
// Set result sign
if ((A.Sign > 0) and (C > 0)) or
((A.Sign < 0) and (C < 0)) then
A.Sign := 1
else
A.Sign := -1;
end;
function TryStrToSHugeDecimal(const S: String; var R: SHugeDecimal): TDecimalConvertErrorType;
var
LenS : Integer;
SignCh : Char;
T : String;
ValA : HugeDecimal;
ConvErr : TDecimalConvertErrorType;
begin
LenS := Length(S);
if LenS = 0 then
begin
Result := dceConvertError;
exit;
end;
SignCh := S[1];
if (SignCh = '+') or (SignCh = '-') then
T := Copy(S, 2, LenS - 1)
else
T := S;
ConvErr := TryStrToHugeDecimal(T, ValA);
if ConvErr <> dceNoError then
begin
Result := ConvErr;
exit;
end;
if HugeDecimalIsZero(ValA) then
begin
SHugeDecimalAssignZero(R);
Result := dceNoError;
exit;
end;
HugeDecimalAssignHugeDecimal(R.Value, ValA);
if SignCh = '-' then
R.Sign := -1
else
R.Sign := 1;
Result := dceNoError;
end;
procedure StrToSHugeDecimal(const S: String; var R: SHugeDecimal);
begin
case TryStrToSHugeDecimal(S, R) of
dceNoError : ;
dceConvertError : raise EDecimalError.Create(SConvertError);
dceOverflowError : raise EDecimalError.Create(SOverflowError);
end;
end;
function SHugeDecimalToStr(const A: SHugeDecimal): String;
var
R : String;
begin
if A.Sign = 0 then
Result := '0'
else
begin
R := HugeDecimalToStr(A.Value);
if A.Sign < 0 then
R := '-' + R;
Result := R;
end;
end;
{ }
{ Test cases }
{ }
{$IFDEF DECIMAL_TEST}
{$ASSERTIONS ON}
procedure Test_Decimal32;
var A, B : Decimal32;
begin
// Zero
Decimal32InitZero(A);
Assert(Decimal32IsZero(A));
Assert(not Decimal32IsOne(A));
Assert(not Decimal32IsMaximum(A));
Assert(not Decimal32IsOverflow(A));
Assert(Decimal32ToWord8(A) = 0);
Assert(Decimal32ToStr(A) = '0.0000');
Assert(Decimal32EqualsWord8(A, 0));
Assert(Decimal32CompareWord8(A, 0) = 0);
Assert(Decimal32CompareWord8(A, 1) = -1);
Assert(Decimal32Trunc(A) = 0);
Assert(Decimal32Round(A) = 0);
Assert(Decimal32FracWord(A) = 0);
Assert(Decimal32EqualsFloat(A, 0.0));
Assert(Decimal32EqualsFloat(A, 0.000049));
Assert(Decimal32EqualsFloat(A, 0.00005));
Assert(not Decimal32EqualsFloat(A, 0.000051));
Assert(Decimal32CompareFloat(A, 0.0000) = 0);
Assert(Decimal32CompareFloat(A, -0.0001) = 1);
Assert(Decimal32CompareFloat(A, 0.0001) = -1);
// One
Decimal32InitOne(A);
Assert(not Decimal32IsZero(A));
Assert(Decimal32IsOne(A));
Assert(Decimal32ToWord8(A) = 1);
Assert(Decimal32ToStr(A) = '1.0000');
Assert(Decimal32ToStrB(A) = '1.0000');
Assert(Decimal32EqualsWord8(A, 1));
Assert(Decimal32CompareWord8(A, 0) = 1);
Assert(Decimal32CompareWord8(A, 1) = 0);
Assert(Decimal32CompareWord8(A, 2) = -1);
Assert(Decimal32Trunc(A) = 1);
Assert(Decimal32Round(A) = 1);
Assert(Decimal32EqualsFloat(A, 1.0));
Assert(Decimal32EqualsFloat(A, 1.000049));
Assert(not Decimal32EqualsFloat(A, 1.000051));
// 2
Decimal32InitWord8(A, 2);
Assert(Decimal32ToWord8(A) = 2);
Assert(Decimal32EqualsWord16(A, 2));
Assert(Decimal32EqualsWord32(A, 2));
Assert(Decimal32EqualsInt32(A, 2));
Assert(not Decimal32EqualsInt32(A, -1));
Assert(not Decimal32EqualsWord32(A, 999999999));
Assert(Decimal32CompareWord16(A, 2) = 0);
Assert(Decimal32CompareWord32(A, 999999999) = -1);
Assert(Decimal32CompareInt32(A, 2) = 0);
Assert(Decimal32CompareInt32(A, -1) = 1);
Assert(Decimal32CompareInt32(A, 3) = -1);
// MaxWord16
Decimal32InitWord16(A, $FFFF);
Assert(Decimal32ToWord16(A) = $FFFF);
Assert(Decimal32ToStr(A) = '65535.0000');
Assert(FloatIsDecimal32Range(0.0000));
Assert(not FloatIsDecimal32Range(-0.0001));
Assert(FloatIsDecimal32Range(-0.00005));
Assert(not FloatIsDecimal32Range(-0.000051));
Assert(FloatIsDecimal32Range(99999.9999));
Assert(FloatIsDecimal32Range(99999.999949));
Assert(not FloatIsDecimal32Range(99999.99995));
Assert(not FloatIsDecimal32Range(100000.0000));
// 99999
Decimal32InitWord32(A, 99999);
Assert(Decimal32ToWord32(A) = 99999);
Assert(Decimal32ToStr(A) = '99999.0000');
Assert(Decimal32Trunc(A) = 99999);
// 1.2345
Decimal32InitFloat(A, 1.2345);
Assert(Abs(Decimal32ToFloat(A) - 1.2345) < 1e-9);
Assert(Decimal32ToStr(A) = '1.2345');
Assert(Decimal32Trunc(A) = 1);
Assert(Decimal32Round(A) = 1);
Assert(Decimal32EqualsFloat(A, 1.2345));
// 1.23445
Decimal32InitFloat(A, 1.23445);
Assert(Abs(Decimal32ToFloat(A) - 1.2344) < 1e-9);
Assert(Decimal32ToStr(A) = '1.2344');
// 1.23455
Decimal32InitFloat(A, 1.23455);
Assert(Abs(Decimal32ToFloat(A) - 1.2346) < 1e-9);
Assert(Decimal32ToStr(A) = '1.2346');
// MaxDecimal32
Decimal32InitFloat(A, 99999.9999);
Assert(Decimal32IsMaximum(A));
// MaxDecimal32
Decimal32InitMax(A);
Assert(Decimal32IsMaximum(A));
Assert(not Decimal32IsOverflow(A));
Assert(Decimal32ToStr(A) = '99999.9999');
Assert(Decimal32Trunc(A) = 99999);
Assert(Decimal32Round(A) = 100000);
Assert(Decimal32FracWord(A) = 9999);
Assert(Decimal32EqualsFloat(A, 99999.9999));
Assert(Decimal32EqualsFloat(A, 99999.999949));
Assert(not Decimal32EqualsFloat(A, 99999.99995));
// Trunc/Round
Decimal32InitFloat(A, 99999.4999);
Assert(Decimal32Trunc(A) = 99999);
Assert(Decimal32Round(A) = 99999);
Decimal32InitFloat(A, 99999.5000);
Assert(Decimal32Trunc(A) = 99999);
Assert(Decimal32Round(A) = 100000);
Assert(Decimal32FracWord(A) = 5000);
Decimal32InitFloat(A, 99998.5000);
Assert(Decimal32Trunc(A) = 99998);
Assert(Decimal32Round(A) = 99998);
Decimal32InitFloat(A, 99998.5001);
Assert(Decimal32Trunc(A) = 99998);
Assert(Decimal32Round(A) = 99999);
// 0.1
Decimal32InitFloat(A, 0.1);
Assert(Decimal32ToStr(A) = '0.1000');
Assert(Decimal32EqualsFloat(A, 0.1));
// 0.0001
Decimal32InitFloat(A, 0.0001);
Assert(Decimal32ToStr(A) = '0.0001');
Assert(Decimal32EqualsFloat(A, 0.0001));
// InitFloat Rounding
Decimal32InitFloat(A, 0.00005);
Assert(Decimal32ToStr(A) = '0.0000');
Decimal32InitFloat(A, 0.000051);
Assert(Decimal32ToStr(A) = '0.0001');
Decimal32InitFloat(A, 0.00025);
Assert(Decimal32ToStr(A) = '0.0002');
Decimal32InitFloat(A, 0.00055);
Assert(Decimal32ToStr(A) = '0.0006');
Decimal32InitFloat(A, -0.000049);
Assert(Decimal32ToStr(A) = '0.0000');
Decimal32InitFloat(A, -0.000050);
Assert(Decimal32ToStr(A) = '0.0000');
// Add/Subtract
Decimal32InitFloat(A, 1.9375);
Assert(Decimal32ToFloat(A) = 1.9375);
Decimal32AddWord8(A, 1);
Assert(Decimal32ToFloat(A) = 2.9375);
Decimal32AddWord16(A, 10000);
Assert(Decimal32ToFloat(A) = 10002.9375);
Decimal32AddWord32(A, 10000);
Assert(Decimal32ToFloat(A) = 20002.9375);
Assert(Decimal32ToStr(A) = '20002.9375');
Decimal32SubtractWord32(A, 10000);
Assert(Decimal32ToFloat(A) = 10002.9375);
Decimal32SubtractWord16(A, 10000);
Assert(Decimal32ToFloat(A) = 2.9375);
Decimal32SubtractWord8(A, 1);
Assert(Decimal32ToFloat(A) = 1.9375);
// Add/Subtract
Decimal32InitFloat(A, 1.9375);
Decimal32InitFloat(B, 2.5000);
Decimal32AddDecimal32(A, B);
Assert(Decimal32ToFloat(A) = 4.4375);
Decimal32SubtractDecimal32(A, B);
Assert(Decimal32ToFloat(A) = 1.9375);
// Equals/Compare
Decimal32InitFloat(A, 1.9375);
Decimal32InitFloat(B, 2.5000);
Assert(not Decimal32EqualsDecimal32(A, B));
Assert(Decimal32EqualsDecimal32(A, A));
Assert(Decimal32CompareDecimal32(A, B) = -1);
Assert(Decimal32CompareDecimal32(A, A) = 0);
Assert(Decimal32CompareDecimal32(B, A) = 1);
// Multiply/Divide
Decimal32InitFloat(A, 1.9375);
Decimal32MultiplyWord8(A, 3);
Assert(Decimal32ToFloat(A) = 5.8125);
Decimal32MultiplyWord16(A, 101);
Assert(Decimal32ToFloat(A) = 587.0625);
Decimal32MultiplyWord32(A, 13);
Assert(Decimal32ToFloat(A) = 7631.8125);
Assert(Decimal32ToStr(A) = '7631.8125');
Decimal32DivideWord32(A, 13);
Assert(Decimal32ToFloat(A) = 587.0625);
Decimal32DivideWord16(A, 101);
Assert(Decimal32ToFloat(A) = 5.8125);
Decimal32DivideWord8(A, 3);
Assert(Decimal32ToStr(A) = '1.9375');
// Multiply/Divide
Decimal32InitFloat(A, 1.9375);
Decimal32InitFloat(B, 2.5000);
Decimal32MultiplyDecimal32(A, B);
Assert(Abs(Decimal32ToFloat(A) - 4.8438) < 1e-9);
Assert(Decimal32ToStr(A) = '4.8438');
Decimal32DivideDecimal32(A, B);
Assert(Decimal32ToStr(A) = '1.9375');
// Multiply
Decimal32InitFloat(A, 1.9375);
Decimal32InitFloat(B, 3.1200);
Decimal32MultiplyDecimal32(A, B);
Assert(Decimal32ToFloat(A) - 6.045 < 1e-10);
Assert(Decimal32ToStr(A) = '6.0450');
// Multiply
Decimal32InitFloat(A, 16.9375);
Decimal32InitFloat(B, 3.1200);
Decimal32MultiplyDecimal32(A, B);
Assert(Decimal32ToFloat(A) - 52.8450 < 1e-10);
Assert(Decimal32ToStr(A) = '52.8450');
// Str
A := StrToDecimal32('0');
Assert(Decimal32ToWord8(A) = 0);
A := StrToDecimal32('0000000.0000000');
Assert(Decimal32ToWord8(A) = 0);
A := StrToDecimal32('1');
Assert(Decimal32ToWord8(A) = 1);
A := StrToDecimal32('1.0');
Assert(Decimal32ToWord8(A) = 1);
A := StrToDecimal32('00000000000001.000000000000000');
Assert(Decimal32ToWord8(A) = 1);
A := StrToDecimal32('1.0000000000000001');
Assert(Decimal32ToWord8(A) = 1);
A := StrToDecimal32('123.9385');
Assert(Decimal32ToStr(A) = '123.9385');
A := StrToDecimal32('123.93856');
Assert(Decimal32ToStr(A) = '123.9386');
A := StrToDecimal32('123.93855');
Assert(Decimal32ToStr(A) = '123.9386');
A := StrToDecimal32('123.93865');
Assert(Decimal32ToStr(A) = '123.9386');
A := StrToDecimal32('123.938650000000010');
Assert(Decimal32ToStr(A) = '123.9387');
A := StrToDecimal32('12345.99995');
Assert(Decimal32ToStr(A) = '12346.0000');
A := StrToDecimal32('99999.9999');
Assert(Decimal32ToStr(A) = '99999.9999');
// Str
Assert(TryStrToDecimal32('0', A) = dceNoError);
Assert(Decimal32ToWord32(A) = 0);
Assert(TryStrToDecimal32('99999', A) = dceNoError);
Assert(Decimal32ToWord32(A) = 99999);
Assert(TryStrToDecimal32('12345.99995', A) = dceNoError);
Assert(Decimal32ToStr(A) = '12346.0000');
Assert(TryStrToDecimal32('99999.9999', A) = dceNoError);
Assert(Decimal32ToStr(A) = '99999.9999');
// Str exponent
Assert(TryStrToDecimal32('1E0', A) = dceNoError);
Assert(Decimal32ToStr(A) = '1.0000');
Assert(TryStrToDecimal32('1E+1', A) = dceNoError);
Assert(Decimal32ToStr(A) = '10.0000');
Assert(TryStrToDecimal32('1E-1', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.1000');
Assert(TryStrToDecimal32('1.23E0', A) = dceNoError);
Assert(Decimal32ToStr(A) = '1.2300');
Assert(TryStrToDecimal32('1.23E1', A) = dceNoError);
Assert(Decimal32ToStr(A) = '12.3000');
Assert(TryStrToDecimal32('1.23E+2', A) = dceNoError);
Assert(Decimal32ToStr(A) = '123.0000');
Assert(TryStrToDecimal32('1.23E+3', A) = dceNoError);
Assert(Decimal32ToStr(A) = '1230.0000');
Assert(TryStrToDecimal32('1.23E+4', A) = dceNoError);
Assert(Decimal32ToStr(A) = '12300.0000');
Assert(TryStrToDecimal32('1.23E-1', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.1230');
Assert(TryStrToDecimal32('1.23E-2', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.0123');
Assert(TryStrToDecimal32('1.23E-3', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.0012');
Assert(TryStrToDecimal32('1.23E-4', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.0001');
Assert(TryStrToDecimal32('1.23E-5', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.0000');
Assert(TryStrToDecimal32('1.23E-100', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.0000');
Assert(TryStrToDecimal32('0.1234E+0', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.1234');
Assert(TryStrToDecimal32('0.1234E+1', A) = dceNoError);
Assert(Decimal32ToStr(A) = '1.2340');
Assert(TryStrToDecimal32('0.1234E+2', A) = dceNoError);
Assert(Decimal32ToStr(A) = '12.3400');
Assert(TryStrToDecimal32('0.1234E-1', A) = dceNoError);
Assert(Decimal32ToStr(A) = '0.0123');
Assert(TryStrToDecimal32('1234321E-4', A) = dceNoError);
Assert(Decimal32ToStr(A) = '123.4321');
// Assert(TryStrToDecimal32('0.1234321E+3', A) = dceNoError); // TODO FIX
// Assert(Decimal32ToStr(A) = '123.4321');
// Str overflow error
Assert(TryStrToDecimal32('100000', A) = dceOverflowError);
Assert(TryStrToDecimal32('99999.99995', A) = dceOverflowError);
// Str convert error
Assert(TryStrToDecimal32('', A) = dceConvertError);
Assert(TryStrToDecimal32('-', A) = dceConvertError);
Assert(TryStrToDecimal32('+', A) = dceConvertError);
Assert(TryStrToDecimal32(' ', A) = dceConvertError);
Assert(TryStrToDecimal32('.', A) = dceConvertError);
Assert(TryStrToDecimal32('0.', A) = dceConvertError);
Assert(TryStrToDecimal32('.0', A) = dceConvertError);
Assert(TryStrToDecimal32(' 0', A) = dceConvertError);
Assert(TryStrToDecimal32('0 ', A) = dceConvertError);
Assert(TryStrToDecimal32('E', A) = dceConvertError);
Assert(TryStrToDecimal32('E-', A) = dceConvertError);
Assert(TryStrToDecimal32('1E', A) = dceConvertError);
Assert(TryStrToDecimal32('1E+', A) = dceConvertError);
Assert(TryStrToDecimal32('E+0', A) = dceConvertError);
Assert(TryStrToDecimal32('1.E+0', A) = dceConvertError);
end;
procedure Test_Decimal64;
var A, B : Decimal64;
C : Decimal32;
begin
Decimal64InitZero(A);
Assert(Decimal64IsZero(A));
Assert(not Decimal64IsOne(A));
Assert(not Decimal64IsMaximum(A));
Assert(not Decimal64IsOverflow(A));
Assert(Decimal64ToWord8(A) = 0);
Assert(Decimal64ToStr(A) = '0.000000000');
Assert(Decimal64EqualsWord8(A, 0));
Assert(Decimal64CompareWord8(A, 0) = 0);
Assert(Decimal64CompareWord8(A, 1) = -1);
Assert(Decimal64Trunc(A) = 0);
Assert(Decimal64Round(A) = 0);
Assert(Decimal64FracWord(A) = 0);
Assert(Decimal64EqualsFloat(A, 0.0));
Assert(Decimal64EqualsFloat(A, 0.00000000049));
Assert(Decimal64EqualsFloat(A, 0.0000000005));
Assert(not Decimal64EqualsFloat(A, 0.00000000051));
Assert(Decimal64CompareFloat(A, 0.000000000) = 0);
Assert(Decimal64CompareFloat(A, -0.000000001) = 1);
Assert(Decimal64CompareFloat(A, 0.000000001) = -1);
Decimal64InitOne(A);
Assert(not Decimal64IsZero(A));
Assert(Decimal64IsOne(A));
Assert(Decimal64ToWord8(A) = 1);
Assert(Decimal64ToStr(A) = '1.000000000');
Assert(Decimal64ToStrB(A) = '1.000000000');
Assert(Decimal64EqualsWord8(A, 1));
Assert(Decimal64CompareWord8(A, 0) = 1);
Assert(Decimal64CompareWord8(A, 1) = 0);
Assert(Decimal64CompareWord8(A, 2) = -1);
Assert(Decimal64Trunc(A) = 1);
Assert(Decimal64Round(A) = 1);
Assert(Decimal64EqualsFloat(A, 1.0));
Assert(Decimal64EqualsFloat(A, 1.00000000049));
Assert(not Decimal64EqualsFloat(A, 1.00000000051));
Decimal64InitWord8(A, 2);
Assert(Decimal64ToWord8(A) = 2);
Assert(Decimal64EqualsWord16(A, 2));
Assert(Decimal64EqualsWord32(A, 2));
Assert(not Decimal64EqualsWord32(A, 999999999));
Assert(Decimal64CompareWord16(A, 2) = 0);
Assert(Decimal64CompareWord32(A, 999999999) = -1);
Assert(Decimal64EqualsInt32(A, 2));
Assert(not Decimal64EqualsInt32(A, -1));
Assert(not Decimal64EqualsInt64(A, MaxInt64));
Assert(Decimal64CompareInt32(A, 2) = 0);
Assert(Decimal64CompareInt32(A, -1) = 1);
Assert(Decimal64CompareInt32(A, MaxInt32) = -1);
Assert(Decimal64CompareInt64(A, -1) = 1);
Assert(Decimal64CompareInt64(A, 2) = 0);
Assert(Decimal64CompareInt64(A, MaxInt64) = -1);
Decimal64InitWord16(A, $FFFF);
Assert(Decimal64ToWord16(A) = $FFFF);
Assert(Decimal64ToStr(A) = '65535.000000000');
Decimal64InitWord32(A, $FFFFFFFF);
Assert(Decimal64ToWord32(A) = $FFFFFFFF);
Assert(Decimal64ToStr(A) = '4294967295.000000000');
Assert(FloatIsDecimal64Range(0.000000000));
Assert(not FloatIsDecimal64Range(-0.000000001));
Assert(FloatIsDecimal64Range(-0.0000000005));
Assert(not FloatIsDecimal64Range(-0.00000000051));
{$IFNDEF DELPHI7_DOWN}
Assert(not FloatIsDecimal64Range(9999999999.999999999));
Assert(not FloatIsDecimal64Range(10000000000.000000000));
{$ENDIF}
Decimal64InitInt64(A, Decimal64MaxInt);
Assert(Decimal64ToInt64(A) = 9999999999);
Assert(Decimal64ToStr(A) = '9999999999.000000000');
Assert(Decimal64Trunc(A) = 9999999999);
Decimal64InitFloat(A, 1.234567890);
Assert(Abs(Decimal64ToFloat(A) - 1.234567890) < 1e-12);
Assert(Decimal64ToStr(A) = '1.234567890');
Assert(Decimal64Trunc(A) = 1);
Assert(Decimal64Round(A) = 1);
Assert(Decimal64EqualsFloat(A, 1.234567890));
Decimal64InitFloat(A, 1.2345111115);
Assert(Abs(Decimal64ToFloat(A) - 1.234511112) < 1e-12);
Assert(Decimal64ToStr(A) = '1.234511112');
Decimal64InitFloat(A, 1.2345111125);
Assert(Abs(Decimal64ToFloat(A) - 1.234511112) < 1e-12);
Assert(Decimal64ToStr(A) = '1.234511112');
Decimal64InitFloat(A, 1.23451111251);
Assert(Abs(Decimal64ToFloat(A) - 1.234511113) < 1e-12);
Assert(Decimal64ToStr(A) = '1.234511113');
A := StrToDecimal64('9999999999.999999999');
Assert(Decimal64IsMaximum(A));
Decimal64InitMax(A);
Assert(Decimal64IsMaximum(A));
Assert(not Decimal64IsOverflow(A));
Assert(Decimal64ToStr(A) = '9999999999.999999999');
Assert(Decimal64Trunc(A) = 9999999999);
Assert(Decimal64Round(A) = 10000000000);
Assert(Decimal64FracWord(A) = 999999999);
A := StrToDecimal64('9999999999.499999999');
Assert(Decimal64Trunc(A) = 9999999999);
Assert(Decimal64Round(A) = 9999999999);
A := StrToDecimal64('9999999999.500000000');
Assert(Decimal64Trunc(A) = 9999999999);
Assert(Decimal64Round(A) = 10000000000);
Assert(Decimal64FracWord(A) = 500000000);
A := StrToDecimal64('9999999998.500000000');
Assert(Decimal64Trunc(A) = 9999999998);
Assert(Decimal64Round(A) = 9999999998);
A := StrToDecimal64('9999999998.500000001');
Assert(Decimal64Trunc(A) = 9999999998);
Assert(Decimal64Round(A) = 9999999999);
Decimal64InitFloat(A, 0.1);
Assert(Decimal64ToStr(A) = '0.100000000');
Assert(Decimal64EqualsFloat(A, 0.1));
Decimal64InitFloat(A, 0.000000001);
Assert(Decimal64ToStr(A) = '0.000000001');
Assert(Decimal64EqualsFloat(A, 0.000000001));
Decimal64InitFloat(A, 0.0000000005);
Assert(Decimal64ToStr(A) = '0.000000000');
Decimal64InitFloat(A, 0.00000000051);
Assert(Decimal64ToStr(A) = '0.000000001');
Decimal64InitFloat(A, 0.0000000025);
Assert(Decimal64ToStr(A) = '0.000000002');
Decimal64InitFloat(A, 0.0000000055);
Assert(Decimal64ToStr(A) = '0.000000006');
Decimal64InitFloat(A, -0.00000000049);
Assert(Decimal64ToStr(A) = '0.000000000');
Decimal64InitFloat(A, -0.00000000050);
Assert(Decimal64ToStr(A) = '0.000000000');
Decimal64InitFloat(A, 1.9375);
Assert(Decimal64ToFloat(A) = 1.9375);
Decimal64AddWord8(A, 1);
Assert(Decimal64ToFloat(A) = 2.9375);
Decimal64AddWord16(A, 10000);
Assert(Decimal64ToFloat(A) = 10002.9375);
Decimal64AddWord32(A, 10000);
Assert(Decimal64ToFloat(A) = 20002.9375);
Assert(Decimal64ToStr(A) = '20002.937500000');
Decimal64SubtractWord32(A, 10000);
Assert(Decimal64ToFloat(A) = 10002.9375);
Decimal64SubtractWord16(A, 10000);
Assert(Decimal64ToFloat(A) = 2.9375);
Decimal64SubtractWord8(A, 1);
Assert(Decimal64ToFloat(A) = 1.9375);
Decimal64InitFloat(A, 1.9375);
Decimal64InitFloat(B, 2.5000);
Decimal64AddDecimal64(A, B);
Assert(Decimal64ToFloat(A) = 4.4375);
Decimal64SubtractDecimal64(A, B);
Assert(Decimal64ToFloat(A) = 1.9375);
Decimal64InitFloat(A, 1.9375);
Decimal64InitFloat(B, 2.5000);
Assert(not Decimal64EqualsDecimal64(A, B));
Assert(Decimal64EqualsDecimal64(A, A));
Assert(Decimal64CompareDecimal64(A, B) = -1);
Assert(Decimal64CompareDecimal64(A, A) = 0);
Assert(Decimal64CompareDecimal64(B, A) = 1);
Decimal64InitFloat(A, 1.9375);
Decimal64MultiplyWord8(A, 3);
Assert(Decimal64ToFloat(A) = 5.8125);
Decimal64MultiplyWord16(A, 101);
Assert(Decimal64ToFloat(A) = 587.0625);
Decimal64MultiplyWord32(A, 13);
Assert(Decimal64ToFloat(A) = 7631.8125);
Assert(Decimal64ToStr(A) = '7631.812500000');
Decimal64DivideWord32(A, 13);
Assert(Decimal64ToFloat(A) = 587.0625);
Decimal64DivideWord16(A, 101);
Assert(Decimal64ToFloat(A) = 5.8125);
Decimal64DivideWord8(A, 3);
Assert(Decimal64ToStr(A) = '1.937500000');
Decimal64InitFloat(A, 1.9375);
Decimal64InitFloat(B, 2.5000);
Decimal64MultiplyDecimal64(A, B);
Assert(Decimal64ToFloat(A) = 4.84375);
Assert(Decimal64ToStr(A) = '4.843750000');
Decimal64DivideDecimal64(A, B);
Assert(Decimal64ToStr(A) = '1.937500000');
Decimal64InitFloat(A, 12.937512);
Decimal64InitFloat(B, 3.123433);
Decimal64MultiplyDecimal64(A, B);
Assert(Decimal64ToFloat(A) - 40.409451919 < 1e-10);
Assert(Decimal64ToStr(A) = '40.409451919');
Decimal32InitFloat(C, 1.9375);
Decimal64InitDecimal32(A, C);
Assert(Decimal64ToStr(A) = '1.937500000');
Assert(Decimal32ToStr(Decimal64ToDecimal32(A)) = '1.9375');
A := StrToDecimal64('0');
Assert(Decimal64ToWord8(A) = 0);
A := StrToDecimal64('000000000000.000000000000');
Assert(Decimal64ToWord8(A) = 0);
A := StrToDecimal64('1');
Assert(Decimal64ToWord8(A) = 1);
A := StrToDecimal64('1.0');
Assert(Decimal64ToWord8(A) = 1);
A := StrToDecimal64('0000000000000000001.00000000000000000000');
Assert(Decimal64ToWord8(A) = 1);
A := StrToDecimal64('1.0000000000000001');
Assert(Decimal64ToWord8(A) = 1);
A := StrToDecimal64('123.938500000');
Assert(Decimal64ToStr(A) = '123.938500000');
A := StrToDecimal64('123.9385000005');
Assert(Decimal64ToStr(A) = '123.938500000');
A := StrToDecimal64('123.9385000015');
Assert(Decimal64ToStr(A) = '123.938500002');
A := StrToDecimal64('123.9386000025');
Assert(Decimal64ToStr(A) = '123.938600002');
A := StrToDecimal64('123.93860000251');
Assert(Decimal64ToStr(A) = '123.938600003');
A := StrToDecimal64('9999999999.999999999');
Assert(Decimal64ToStr(A) = '9999999999.999999999');
Assert(TryStrToDecimal64('0', A) = dceNoError);
Assert(Decimal64ToWord32(A) = 0);
Assert(TryStrToDecimal64('9999999999', A) = dceNoError);
Assert(Decimal64ToInt64(A) = 9999999999);
Assert(TryStrToDecimal64('10000000000', A) = dceOverflowError);
Assert(TryStrToDecimal64('9999999999.9999999995', A) = dceOverflowError);
Assert(TryStrToDecimal64('', A) = dceConvertError);
Assert(TryStrToDecimal64('-', A) = dceConvertError);
Assert(TryStrToDecimal64('+', A) = dceConvertError);
Assert(TryStrToDecimal64(' ', A) = dceConvertError);
Assert(TryStrToDecimal64('.', A) = dceConvertError);
Assert(TryStrToDecimal64('0.', A) = dceConvertError);
Assert(TryStrToDecimal64('.0', A) = dceConvertError);
Assert(TryStrToDecimal64(' 0', A) = dceConvertError);
Assert(TryStrToDecimal64('0 ', A) = dceConvertError);
end;
procedure Test_Decimal128;
var A, B : Decimal128;
C : Decimal64;
begin
Decimal128InitZero(A);
Assert(Decimal128IsZero(A));
Assert(not Decimal128IsOne(A));
Assert(not Decimal128IsMaximum(A));
Assert(not Decimal128IsOverflow(A));
Assert(Decimal128ToWord8(A) = 0);
Assert(Decimal128ToStr(A) = '0.0000000000000000000');
Assert(Decimal128EqualsWord8(A, 0));
Assert(Decimal128CompareWord8(A, 0) = 0);
Assert(Decimal128CompareWord8(A, 1) = -1);
Assert(Word64ToStr(Decimal128Trunc(A)) = '0');
Assert(Word64ToStr(Decimal128Round(A)) = '0');
Assert(Word64ToStr(Decimal128FracWord(A)) = '0');
Assert(Decimal128EqualsFloat(A, 0.0));
Assert(Decimal128EqualsFloat(A, 0.000000000000000000049));
Assert(Decimal128EqualsFloat(A, 0.00000000000000000005));
Assert(not Decimal128EqualsFloat(A, 0.000000000000000000051));
Assert(Decimal128CompareFloat(A, 0.0000000000000000000) = 0);
Assert(Decimal128CompareFloat(A, -0.0000000000000000001) = 1);
Assert(Decimal128CompareFloat(A, 0.0000000000000000001) = -1);
Decimal128InitOne(A);
Assert(not Decimal128IsZero(A));
Assert(Decimal128IsOne(A));
Assert(Decimal128ToWord8(A) = 1);
Assert(Decimal128ToStr(A) = '1.0000000000000000000');
Assert(Decimal128ToStrB(A) = '1.0000000000000000000');
Assert(Decimal128EqualsWord8(A, 1));
Assert(Decimal128CompareWord8(A, 0) = 1);
Assert(Decimal128CompareWord8(A, 1) = 0);
Assert(Decimal128CompareWord8(A, 2) = -1);
Assert(Word64ToStr(Decimal128Trunc(A)) = '1');
Assert(Word64ToStr(Decimal128Round(A)) = '1');
Assert(Decimal128EqualsFloat(A, 1.0));
Assert(Decimal128EqualsFloat(A, 1.000000000000000000049));
Assert(Decimal128EqualsFloat(A, 1.000000000000000000051));
Decimal128InitWord8(A, 2);
Assert(Decimal128ToWord8(A) = 2);
Assert(Decimal128EqualsWord16(A, 2));
Assert(Decimal128EqualsWord32(A, 2));
Assert(not Decimal128EqualsWord32(A, 999999999));
Assert(Decimal128CompareWord16(A, 2) = 0);
Assert(Decimal128CompareWord32(A, 999999999) = -1);
Decimal128InitWord16(A, $FFFF);
Assert(Decimal128ToWord16(A) = $FFFF);
Assert(Decimal128ToStr(A) = '65535.0000000000000000000');
Decimal128InitWord32(A, $FFFFFFFF);
Assert(Decimal128ToWord32(A) = $FFFFFFFF);
Assert(Decimal128ToStr(A) = '4294967295.0000000000000000000');
Assert(FloatIsDecimal128Range(0.000000000));
Assert(not FloatIsDecimal128Range(-0.0000000000000000001));
Assert(FloatIsDecimal128Range(-0.00000000000000000005));
Assert(not FloatIsDecimal128Range(-0.00000000051));
Assert(not FloatIsDecimal128Range(9999999999999999999.999999999));
Assert(not FloatIsDecimal128Range(10000000000000000000.000000000));
Decimal128InitWord64(A, Decimal128MaxInt);
Assert(Word64ToStr(Decimal128ToWord64(A)) = '9999999999999999999');
Assert(Decimal128ToStr(A) = '9999999999999999999.0000000000000000000');
Assert(Word64ToStr(Decimal128Trunc(A)) = '9999999999999999999');
Decimal128InitFloat(A, 1.234567890123456789);
Assert(Abs(Decimal128ToFloat(A) - 1.23456789012346) < 1e-10);
Assert(CopyLeft(Decimal128ToStr(A), 16) = '1.23456789012345');
Assert(Word64ToStr(Decimal128Trunc(A)) = '1');
Assert(Word64ToStr(Decimal128Round(A)) = '1');
Assert(Decimal128EqualsFloat(A, 1.234567890123456789));
Decimal128InitFloat(A, 1.2345111115);
Assert(Abs(Decimal128ToFloat(A) - 1.2345111115) < 1e-12);
Assert(CopyLeft(Decimal128ToStr(A), 16) = '1.23451111150000');
A := StrToDecimal128('9999999999999999999.9999999999999999999');
Assert(Decimal128IsMaximum(A));
A := StrToDecimal128B('9999999999999999999.9999999999999999999');
Assert(Decimal128IsMaximum(A));
Decimal128InitMax(A);
Assert(Decimal128IsMaximum(A));
Assert(not Decimal128IsOverflow(A));
Assert(Decimal128ToStr(A) = '9999999999999999999.9999999999999999999');
Assert(Word64ToStr(Decimal128Trunc(A)) = '9999999999999999999');
Assert(Word64ToStr(Decimal128Round(A)) = '10000000000000000000');
Assert(Word64ToStr(Decimal128FracWord(A)) = '9999999999999999999');
A := StrToDecimal128('9999999999999999999.4999999999999999999');
Assert(Word64ToStr(Decimal128Trunc(A)) = '9999999999999999999');
Assert(Word64ToStr(Decimal128Round(A)) = '9999999999999999999');
Assert(Word64ToStr(Decimal128FracWord(A)) = '4999999999999999999');
A := StrToDecimal128('9999999999999999999.500000000');
Assert(Word64ToStr(Decimal128Trunc(A)) = '9999999999999999999');
Assert(Word64ToStr(Decimal128Round(A)) = '10000000000000000000');
Assert(Word64ToStr(Decimal128FracWord(A)) = '5000000000000000000');
A := StrToDecimal128('9999999999999999998.500000000');
Assert(Word64ToStr(Decimal128Trunc(A)) = '9999999999999999998');
Assert(Word64ToStr(Decimal128Round(A)) = '9999999999999999998');
Assert(Word64ToStr(Decimal128FracWord(A)) = '5000000000000000000');
A := StrToDecimal128('9999999999999999998.5000000000000000001');
Assert(Word64ToStr(Decimal128Trunc(A)) = '9999999999999999998');
Assert(Word64ToStr(Decimal128Round(A)) = '9999999999999999999');
Assert(Word64ToStr(Decimal128FracWord(A)) = '5000000000000000001');
Decimal128InitFloat(A, 0.1);
Assert(CopyLeft(Decimal128ToStr(A), 16) = '0.10000000000000');
Assert(Decimal128EqualsFloat(A, 0.1));
Decimal128InitFloat(A, 1.9375);
Assert(Decimal128ToFloat(A) = 1.9375);
Decimal128AddWord8(A, 1);
Assert(Decimal128ToFloat(A) = 2.9375);
Decimal128AddWord16(A, 10000);
Assert(Decimal128ToFloat(A) = 10002.9375);
Decimal128AddWord32(A, 10000);
Assert(Decimal128ToFloat(A) = 20002.9375);
Assert(Decimal128ToStr(A) = '20002.9375000000000000000');
Decimal128SubtractWord32(A, 10000);
Assert(Decimal128ToFloat(A) = 10002.9375);
Decimal128SubtractWord16(A, 10000);
Assert(Decimal128ToFloat(A) = 2.9375);
Decimal128SubtractWord8(A, 1);
Assert(Decimal128ToFloat(A) = 1.9375);
Decimal128InitFloat(A, 1.9375);
Decimal128InitFloat(B, 2.5000);
Decimal128AddDecimal128(A, B);
Assert(Decimal128ToFloat(A) = 4.4375);
Decimal128SubtractDecimal128(A, B);
Assert(Decimal128ToFloat(A) = 1.9375);
Decimal128InitFloat(A, 1.9375);
Decimal128InitFloat(B, 2.5000);
Assert(not Decimal128EqualsDecimal128(A, B));
Assert(Decimal128EqualsDecimal128(A, A));
Assert(Decimal128CompareDecimal128(A, B) = -1);
Assert(Decimal128CompareDecimal128(A, A) = 0);
Assert(Decimal128CompareDecimal128(B, A) = 1);
Decimal128InitFloat(A, 1.9375);
Decimal128MultiplyWord8(A, 3);
Assert(Decimal128ToFloat(A) = 5.8125);
Decimal128MultiplyWord16(A, 101);
Assert(Decimal128ToFloat(A) = 587.0625);
Decimal128MultiplyWord32(A, 13);
Assert(Abs(Decimal128ToFloat(A) - 7631.8125) < 1e-10);
Assert(Decimal128ToStr(A) = '7631.8125000000000000000');
Decimal128DivideWord32(A, 13);
Assert(Decimal128ToFloat(A) = 587.0625);
Decimal128DivideWord16(A, 101);
Assert(Decimal128ToFloat(A) = 5.8125);
Decimal128DivideWord8(A, 3);
Assert(Decimal128ToStr(A) = '1.9375000000000000000');
Decimal128InitFloat(A, 1.9375);
Decimal128InitFloat(B, 2.5000);
Decimal128MultiplyDecimal128(A, B);
Assert(Decimal128ToFloat(A) = 4.84375);
Assert(Decimal128ToStr(A) = '4.8437500000000000000');
Decimal128DivideDecimal128(A, B);
Assert(Decimal128ToStr(A) = '1.9375000000000000000');
Decimal128InitFloat(A, 12.937512);
Decimal128InitFloat(B, 3.123433);
Decimal128MultiplyDecimal128(A, B);
Assert(Decimal128ToFloat(A) - 40.409451919 < 1e-10);
Assert(Decimal128ToStr(A) = '40.4094519186960000000');
Decimal64InitFloat(C, 1.9375);
Decimal128InitDecimal64(A, C);
Assert(Decimal128ToStr(A) = '1.9375000000000000000');
A := StrToDecimal128('12.3456789');
Decimal128Sqr(A);
Assert(Decimal128ToStr(A) = '152.4157875019052100000');
A := StrToDecimal128('0');
Assert(Decimal128ToWord8(A) = 0);
A := StrToDecimal128('000000000000000000000.000000000000000000000');
Assert(Decimal128ToWord8(A) = 0);
A := StrToDecimal128('1');
Assert(Decimal128ToWord8(A) = 1);
A := StrToDecimal128('1.0');
Assert(Decimal128ToWord8(A) = 1);
A := StrToDecimal128('0000000000000000000000000001.00000000000000000000000000000');
Assert(Decimal128ToWord8(A) = 1);
A := StrToDecimal128('1.00000000000000000000000001');
Assert(Decimal128ToWord8(A) = 1);
A := StrToDecimal128('123.938500000');
Assert(Decimal128ToStr(A) = '123.9385000000000000000');
A := StrToDecimal128('123.93850000000000000005');
Assert(Decimal128ToStr(A) = '123.9385000000000000000');
A := StrToDecimal128('123.93850000000000000015');
Assert(Decimal128ToStr(A) = '123.9385000000000000002');
A := StrToDecimal128('123.93860000000000000025');
Assert(Decimal128ToStr(A) = '123.9386000000000000002');
A := StrToDecimal128('123.938600000000000000251');
Assert(Decimal128ToStr(A) = '123.9386000000000000003');
A := StrToDecimal128('9999999999999999999.9999999999999999999');
Assert(Decimal128ToStr(A) = '9999999999999999999.9999999999999999999');
Assert(TryStrToDecimal128('0', A) = dceNoError);
Assert(Decimal128ToWord32(A) = 0);
Assert(TryStrToDecimal128('9999999999999999999', A) = dceNoError);
Assert(Word64ToStr(Decimal128ToWord64(A)) = '9999999999999999999');
Assert(TryStrToDecimal128('10000000000000000000', A) = dceOverflowError);
Assert(TryStrToDecimal128('9999999999999999999.99999999999999999995', A) = dceOverflowError);
Assert(TryStrToDecimal128('', A) = dceConvertError);
Assert(TryStrToDecimal128('-', A) = dceConvertError);
Assert(TryStrToDecimal128('+', A) = dceConvertError);
Assert(TryStrToDecimal128(' ', A) = dceConvertError);
Assert(TryStrToDecimal128('.', A) = dceConvertError);
Assert(TryStrToDecimal128('0.', A) = dceConvertError);
Assert(TryStrToDecimal128('.0', A) = dceConvertError);
Assert(TryStrToDecimal128(' 0', A) = dceConvertError);
Assert(TryStrToDecimal128('0 ', A) = dceConvertError);
end;
procedure Test_HugeDecimal;
var
A, B : HugeDecimal;
F : Word64Rec;
G : Word128;
begin
HugeDecimalInit(A);
HugeDecimalInit(B);
// Zero
HugeDecimalAssignZero(A);
Assert(HugeDecimalIsZero(A));
Assert(not HugeDecimalIsOne(A));
Assert(HugeDecimalDigits(A) = 1);
Assert(HugeDecimalIntegerDigits(A) = 1);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalToWord8(A) = 0);
Assert(HugeDecimalToWord32(A) = 0);
Assert(Word64ToWord32(HugeDecimalToWord64(A)) = 0);
Assert(Word128ToWord32(HugeDecimalToWord128(A)) = 0);
Assert(HugeDecimalToStr(A) = '0');
Assert(HugeDecimalGetDigit(A, 0) = 0);
Assert(HugeDecimalFracCompareHalf(A) = -1);
Assert(HugeDecimalIsInteger(A));
Assert(HugeDecimalIsWord8Range(A));
Assert(HugeDecimalIsEven(A));
Assert(not HugeDecimalIsOdd(A));
Assert(HugeDecimalIsLessThanOne(A));
Assert(not HugeDecimalIsOneOrGreater(A));
Assert(HugeDecimalEqualsHugeDecimal(A, A));
Assert(HugeDecimalCompareHugeDecimal(A, A) = 0);
Assert(HugeDecimalEqualsWord8(A, 0));
Assert(not HugeDecimalEqualsWord8(A, 1));
Assert(not HugeDecimalEqualsWord8(A, 10));
Assert(not HugeDecimalEqualsWord8(A, 100));
Assert(HugeDecimalCompareWord8(A, 0) = 0);
Assert(HugeDecimalCompareWord8(A, 1) = -1);
Assert(HugeDecimalCompareWord8(A, 10) = -1);
Assert(HugeDecimalCompareWord8(A, 100) = -1);
// One
HugeDecimalAssignOne(A);
Assert(not HugeDecimalIsZero(A));
Assert(HugeDecimalIsOne(A));
Assert(HugeDecimalDigits(A) = 1);
Assert(HugeDecimalIntegerDigits(A) = 1);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalToWord8(A) = 1);
Assert(HugeDecimalToWord32(A) = 1);
Assert(Word64ToWord32(HugeDecimalToWord64(A)) = 1);
Assert(Word128ToWord32(HugeDecimalToWord128(A)) = 1);
Assert(HugeDecimalToStr(A) = '1');
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalFracCompareHalf(A) = -1);
Assert(HugeDecimalIsInteger(A));
Assert(HugeDecimalIsWord8Range(A));
Assert(not HugeDecimalIsEven(A));
Assert(HugeDecimalIsOdd(A));
Assert(not HugeDecimalIsLessThanOne(A));
Assert(HugeDecimalIsOneOrGreater(A));
Assert(HugeDecimalEqualsHugeDecimal(A, A));
Assert(HugeDecimalCompareHugeDecimal(A, A) = 0);
Assert(HugeDecimalEqualsWord8(A, 1));
Assert(not HugeDecimalEqualsWord8(A, 2));
Assert(not HugeDecimalEqualsWord8(A, 10));
Assert(not HugeDecimalEqualsWord8(A, 100));
Assert(HugeDecimalCompareWord8(A, 0) = 1);
Assert(HugeDecimalCompareWord8(A, 1) = 0);
Assert(HugeDecimalCompareWord8(A, 2) = -1);
Assert(HugeDecimalCompareWord8(A, 12) = -1);
Assert(HugeDecimalCompareWord8(A, 123) = -1);
// 10
HugeDecimalAssignWord8(A, 10);
Assert(not HugeDecimalIsZero(A));
Assert(not HugeDecimalIsOne(A));
Assert(HugeDecimalDigits(A) = 2);
Assert(HugeDecimalIntegerDigits(A) = 2);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalToWord8(A) = 10);
Assert(HugeDecimalToWord32(A) = 10);
Assert(HugeDecimalToStr(A) = '10');
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 0);
Assert(HugeDecimalIsEven(A));
Assert(not HugeDecimalIsOdd(A));
Assert(not HugeDecimalIsLessThanOne(A));
Assert(HugeDecimalIsOneOrGreater(A));
Assert(HugeDecimalEqualsHugeDecimal(A, A));
Assert(HugeDecimalCompareHugeDecimal(A, A) = 0);
Assert(HugeDecimalEqualsWord8(A, 10));
Assert(not HugeDecimalEqualsWord8(A, 1));
Assert(not HugeDecimalEqualsWord8(A, 11));
Assert(not HugeDecimalEqualsWord8(A, 100));
Assert(HugeDecimalCompareWord8(A, 0) = 1);
Assert(HugeDecimalCompareWord8(A, 9) = 1);
Assert(HugeDecimalCompareWord8(A, 10) = 0);
Assert(HugeDecimalCompareWord8(A, 11) = -1);
Assert(HugeDecimalCompareWord8(A, 123) = -1);
// 123
HugeDecimalAssignWord8(A, 123);
Assert(HugeDecimalDigits(A) = 3);
Assert(HugeDecimalIntegerDigits(A) = 3);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalToWord8(A) = 123);
Assert(HugeDecimalToWord32(A) = 123);
Assert(HugeDecimalToStr(A) = '123');
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(HugeDecimalGetDigit(A, 2) = 3);
Assert(HugeDecimalIsWord8Range(A));
Assert(HugeDecimalIsOdd(A));
Assert(HugeDecimalEqualsWord8(A, 123));
Assert(not HugeDecimalEqualsWord8(A, 1));
Assert(not HugeDecimalEqualsWord8(A, 11));
Assert(not HugeDecimalEqualsWord8(A, 255));
Assert(HugeDecimalCompareWord8(A, 0) = 1);
Assert(HugeDecimalCompareWord8(A, 1) = 1);
Assert(HugeDecimalCompareWord8(A, 12) = 1);
Assert(HugeDecimalCompareWord8(A, 122) = 1);
Assert(HugeDecimalCompareWord8(A, 123) = 0);
Assert(HugeDecimalCompareWord8(A, 124) = -1);
// 256
HugeDecimalAssignWord32(A, 256);
Assert(HugeDecimalDigits(A) = 3);
Assert(HugeDecimalIntegerDigits(A) = 3);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalToWord32(A) = 256);
Assert(not HugeDecimalIsWord8Range(A));
Assert(not HugeDecimalEqualsWord8(A, 1));
Assert(not HugeDecimalEqualsWord8(A, 11));
Assert(not HugeDecimalEqualsWord8(A, 255));
Assert(HugeDecimalCompareWord8(A, 255) = 1);
// 1234
HugeDecimalAssignWord32(A, 1234);
Assert(HugeDecimalDigits(A) = 4);
Assert(HugeDecimalToWord32(A) = 1234);
Assert(HugeDecimalToStr(A) = '1234');
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(HugeDecimalGetDigit(A, 2) = 3);
Assert(HugeDecimalGetDigit(A, 3) = 4);
Assert(not HugeDecimalIsWord8Range(A));
// 12345
HugeDecimalAssignWord32(A, 12345);
Assert(HugeDecimalDigits(A) = 5);
Assert(HugeDecimalToWord32(A) = 12345);
Assert(HugeDecimalToStr(A) = '12345');
// 123456
HugeDecimalAssignWord32(A, 123456);
Assert(HugeDecimalDigits(A) = 6);
Assert(HugeDecimalToWord32(A) = 123456);
Assert(HugeDecimalToStr(A) = '123456');
Word64InitOne(F);
HugeDecimalAssignWord64(A, F);
Assert(HugeDecimalIsOne(A));
// Word64Max
Word64InitMaximum(F);
HugeDecimalAssignWord64(A, F);
Assert(HugeDecimalToStr(A) = '18446744073709551615');
Assert(HugeDecimalDigits(A) = 20);
Assert(HugeDecimalIntegerDigits(A) = 20);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 19) = 5);
Assert(Word64ToStr(HugeDecimalToWord64(A)) = '18446744073709551615');
Assert(Word128ToStr(HugeDecimalToWord128(A)) = '18446744073709551615');
Word128InitOne(G);
HugeDecimalAssignWord128(A, G);
Assert(HugeDecimalIsOne(A));
// Word128Max
Word128InitMaximum(G);
HugeDecimalAssignWord128(A, G);
Assert(HugeDecimalToStr(A) = '340282366920938463463374607431768211455');
Assert(HugeDecimalDigits(A) = 39);
Assert(HugeDecimalIntegerDigits(A) = 39);
Assert(HugeDecimalDecimalDigits(A) = 0);
Assert(HugeDecimalGetDigit(A, 0) = 3);
Assert(HugeDecimalGetDigit(A, 36) = 4);
Assert(HugeDecimalGetDigit(A, 37) = 5);
Assert(HugeDecimalGetDigit(A, 38) = 5);
Assert(Word128ToStr(HugeDecimalToWord128(A)) = '340282366920938463463374607431768211455');
// 0.0000
HugeDecimalAssignDecimal32(A, StrToDecimal32('0'));
Assert(HugeDecimalToStr(A) = '0');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '0.0000');
Assert(HugeDecimalIsInteger(A));
// 1.0000
HugeDecimalAssignDecimal32(A, StrToDecimal32('1'));
Assert(HugeDecimalToStr(A) = '1');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '1.0000');
Assert(HugeDecimalIsInteger(A));
// 12.0000
HugeDecimalAssignDecimal32(A, StrToDecimal32('12'));
Assert(HugeDecimalToStr(A) = '12');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '12.0000');
// 123.0000
HugeDecimalAssignDecimal32(A, StrToDecimal32('123'));
Assert(HugeDecimalToStr(A) = '123');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '123.0000');
// 1234.0000
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234'));
Assert(HugeDecimalToStr(A) = '1234');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '1234.0000');
// 12345.0000
HugeDecimalAssignDecimal32(A, StrToDecimal32('12345'));
Assert(HugeDecimalToStr(A) = '12345');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '12345.0000');
// 0.1
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.1'));
Assert(HugeDecimalToStr(A) = '0.1');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '0.1000');
Assert(HugeDecimalDigits(A) = 1);
Assert(HugeDecimalIntegerDigits(A) = 0);
Assert(HugeDecimalDecimalDigits(A) = 1);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalFracCompareHalf(A) = -1);
Assert(not HugeDecimalIsInteger(A));
Assert(HugeDecimalIsLessThanOne(A));
Assert(not HugeDecimalIsOneOrGreater(A));
Assert(HugeDecimalEqualsHugeDecimal(A, A));
Assert(HugeDecimalCompareHugeDecimal(A, A) = 0);
Assert(HugeDecimalCompareWord8(A, 0) = 1);
Assert(HugeDecimalCompareWord8(A, 1) = -1);
// 0.01
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.01'));
Assert(HugeDecimalDigits(A) = 2);
Assert(HugeDecimalIntegerDigits(A) = 0);
Assert(HugeDecimalDecimalDigits(A) = 2);
Assert(HugeDecimalToStr(A) = '0.01');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '0.0100');
Assert(HugeDecimalIsLessThanOne(A));
Assert(not HugeDecimalIsOneOrGreater(A));
Assert(HugeDecimalEqualsHugeDecimal(A, A));
Assert(HugeDecimalCompareHugeDecimal(A, A) = 0);
Assert(HugeDecimalCompareWord8(A, 0) = 1);
Assert(HugeDecimalCompareWord8(A, 1) = -1);
// 20.01
HugeDecimalAssignDecimal32(A, StrToDecimal32('20.01'));
Assert(HugeDecimalDigits(A) = 4);
Assert(HugeDecimalIntegerDigits(A) = 2);
Assert(HugeDecimalDecimalDigits(A) = 2);
Assert(HugeDecimalToStr(A) = '20.01');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '20.0100');
Assert(not HugeDecimalIsLessThanOne(A));
Assert(HugeDecimalIsOneOrGreater(A));
Assert(HugeDecimalEqualsHugeDecimal(A, A));
Assert(HugeDecimalCompareHugeDecimal(A, A) = 0);
Assert(not HugeDecimalEqualsWord8(A, 20));
Assert(not HugeDecimalEqualsWord8(A, 21));
Assert(HugeDecimalCompareWord8(A, 20) = 1);
Assert(HugeDecimalCompareWord8(A, 21) = -1);
// 0.12
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.12'));
Assert(HugeDecimalToStr(A) = '0.12');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '0.1200');
Assert(HugeDecimalDigits(A) = 2);
Assert(HugeDecimalIntegerDigits(A) = 0);
Assert(HugeDecimalDecimalDigits(A) = 2);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(not HugeDecimalIsInteger(A));
Assert(HugeDecimalIsLessThanOne(A));
Assert(not HugeDecimalEqualsWord8(A, 0));
// 0.123
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.123'));
Assert(HugeDecimalToStr(A) = '0.123');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '0.1230');
Assert(HugeDecimalDigits(A) = 3);
Assert(HugeDecimalIntegerDigits(A) = 0);
Assert(HugeDecimalDecimalDigits(A) = 3);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(HugeDecimalGetDigit(A, 2) = 3);
Assert(not HugeDecimalEqualsWord8(A, 0));
// 0.1234
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.1234'));
Assert(HugeDecimalToStr(A) = '0.1234');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '0.1234');
Assert(HugeDecimalDigits(A) = 4);
Assert(HugeDecimalIntegerDigits(A) = 0);
Assert(HugeDecimalDecimalDigits(A) = 4);
// 1.2
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.2'));
Assert(HugeDecimalToStr(A) = '1.2');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '1.2000');
Assert(HugeDecimalDigits(A) = 2);
Assert(HugeDecimalIntegerDigits(A) = 1);
Assert(HugeDecimalDecimalDigits(A) = 1);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(not HugeDecimalIsLessThanOne(A));
// 1.23
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.23'));
Assert(HugeDecimalToStr(A) = '1.23');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '1.2300');
Assert(HugeDecimalDigits(A) = 3);
Assert(HugeDecimalIntegerDigits(A) = 1);
Assert(HugeDecimalDecimalDigits(A) = 2);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(HugeDecimalGetDigit(A, 2) = 3);
Assert(not HugeDecimalEqualsWord8(A, 1));
Assert(HugeDecimalCompareWord8(A, 0) = 1);
Assert(HugeDecimalCompareWord8(A, 1) = 1);
Assert(HugeDecimalCompareWord8(A, 2) = -1);
// 1.234
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.234'));
Assert(HugeDecimalToStr(A) = '1.234');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '1.2340');
Assert(HugeDecimalDigits(A) = 4);
Assert(HugeDecimalIntegerDigits(A) = 1);
Assert(HugeDecimalDecimalDigits(A) = 3);
Assert(HugeDecimalGetDigit(A, 0) = 1);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(HugeDecimalGetDigit(A, 2) = 3);
Assert(HugeDecimalGetDigit(A, 3) = 4);
// 1.2345
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.2345'));
Assert(HugeDecimalToStr(A) = '1.2345');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '1.2345');
Assert(HugeDecimalDigits(A) = 5);
Assert(HugeDecimalIntegerDigits(A) = 1);
Assert(HugeDecimalDecimalDigits(A) = 4);
// 21.2345
HugeDecimalAssignDecimal32(A, StrToDecimal32('21.2345'));
Assert(HugeDecimalToStr(A) = '21.2345');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '21.2345');
Assert(HugeDecimalDigits(A) = 6);
Assert(HugeDecimalIntegerDigits(A) = 2);
Assert(HugeDecimalDecimalDigits(A) = 4);
Assert(HugeDecimalGetDigit(A, 0) = 2);
Assert(HugeDecimalGetDigit(A, 1) = 1);
Assert(HugeDecimalGetDigit(A, 2) = 2);
Assert(HugeDecimalGetDigit(A, 3) = 3);
Assert(HugeDecimalGetDigit(A, 4) = 4);
Assert(HugeDecimalGetDigit(A, 5) = 5);
Assert(HugeDecimalCompareWord8(A, 1) = 1);
Assert(HugeDecimalCompareWord8(A, 21) = 1);
Assert(HugeDecimalCompareWord8(A, 22) = -1);
Assert(HugeDecimalCompareWord8(A, 123) = -1);
// 321.2345
HugeDecimalAssignDecimal32(A, StrToDecimal32('321.2345'));
Assert(HugeDecimalToStr(A) = '321.2345');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '321.2345');
Assert(HugeDecimalDigits(A) = 7);
Assert(HugeDecimalIntegerDigits(A) = 3);
Assert(HugeDecimalDecimalDigits(A) = 4);
Assert(HugeDecimalGetDigit(A, 0) = 3);
Assert(HugeDecimalGetDigit(A, 1) = 2);
Assert(HugeDecimalGetDigit(A, 2) = 1);
Assert(HugeDecimalGetDigit(A, 3) = 2);
Assert(HugeDecimalGetDigit(A, 4) = 3);
Assert(HugeDecimalGetDigit(A, 5) = 4);
Assert(HugeDecimalGetDigit(A, 6) = 5);
Assert(HugeDecimalCompareWord8(A, 1) = 1);
Assert(HugeDecimalCompareWord8(A, 21) = 1);
Assert(HugeDecimalCompareWord8(A, 255) = 1);
// 4321.2345
HugeDecimalAssignDecimal32(A, StrToDecimal32('4321.2345'));
Assert(HugeDecimalToStr(A) = '4321.2345');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '4321.2345');
// 54321.2345
HugeDecimalAssignDecimal32(A, StrToDecimal32('54321.2345'));
Assert(HugeDecimalToStr(A) = '54321.2345');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '54321.2345');
// 54321.234
HugeDecimalAssignDecimal32(A, StrToDecimal32('54321.234'));
Assert(HugeDecimalToStr(A) = '54321.234');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '54321.2340');
// 54321.23
HugeDecimalAssignDecimal32(A, StrToDecimal32('54321.23'));
Assert(HugeDecimalToStr(A) = '54321.23');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '54321.2300');
// 54321.2
HugeDecimalAssignDecimal32(A, StrToDecimal32('54321.2'));
Assert(HugeDecimalToStr(A) = '54321.2');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '54321.2000');
// 54321
HugeDecimalAssignDecimal32(A, StrToDecimal32('54321'));
Assert(HugeDecimalToStr(A) = '54321');
Assert(Decimal32ToStr(HugeDecimalToDecimal32(A)) = '54321.0000');
// 0.000000000
HugeDecimalAssignDecimal64(A, StrToDecimal64('0'));
Assert(HugeDecimalToStr(A) = '0');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.000000000');
// 0.01
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.01'));
Assert(HugeDecimalToStr(A) = '0.01');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.010000000');
// 0.00102
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.00102'));
Assert(HugeDecimalToStr(A) = '0.00102');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.001020000');
// 0.1
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.1'));
Assert(HugeDecimalToStr(A) = '0.1');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.100000000');
// 0.12
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.12'));
Assert(HugeDecimalToStr(A) = '0.12');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.120000000');
// 0.123
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.123'));
Assert(HugeDecimalToStr(A) = '0.123');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.123000000');
// 0.12345678
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.12345678'));
Assert(HugeDecimalToStr(A) = '0.12345678');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.123456780');
// 0.123456789
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.123456789'));
Assert(HugeDecimalToStr(A) = '0.123456789');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '0.123456789');
// 1.2
HugeDecimalAssignDecimal64(A, StrToDecimal64('1.2'));
Assert(HugeDecimalToStr(A) = '1.2');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '1.200000000');
// 1.23
HugeDecimalAssignDecimal64(A, StrToDecimal64('1.23'));
Assert(HugeDecimalToStr(A) = '1.23');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '1.230000000');
// 1.234
HugeDecimalAssignDecimal64(A, StrToDecimal64('1.234'));
Assert(HugeDecimalToStr(A) = '1.234');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '1.234000000');
// 123456789.123456789
HugeDecimalAssignDecimal64(A, StrToDecimal64('123456789.123456789'));
Assert(HugeDecimalToStr(A) = '123456789.123456789');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '123456789.123456789');
Assert(HugeDecimalDigits(A) = 18);
Assert(HugeDecimalIntegerDigits(A) = 9);
Assert(HugeDecimalDecimalDigits(A) = 9);
// 1234567890.123456789
HugeDecimalAssignDecimal64(A, StrToDecimal64('1234567890.123456789'));
Assert(HugeDecimalToStr(A) = '1234567890.123456789');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '1234567890.123456789');
Assert(HugeDecimalDigits(A) = 19);
Assert(HugeDecimalIntegerDigits(A) = 10);
Assert(HugeDecimalDecimalDigits(A) = 9);
// 9999999999.999999999
HugeDecimalAssignDecimal64(A, StrToDecimal64('9999999999.999999999'));
Assert(HugeDecimalToStr(A) = '9999999999.999999999');
Assert(Decimal64ToStr(HugeDecimalToDecimal64(A)) = '9999999999.999999999');
Assert(HugeDecimalDigits(A) = 19);
Assert(HugeDecimalIntegerDigits(A) = 10);
Assert(HugeDecimalDecimalDigits(A) = 9);
// 0.0000000000000000000
HugeDecimalAssignDecimal128(A, StrToDecimal128('0.0'));
Assert(Decimal128ToStr(HugeDecimalToDecimal128(A)) = '0.0000000000000000000');
// 0.1234567890123456789
HugeDecimalAssignDecimal128(A, StrToDecimal128('0.1234567890123456789'));
Assert(Decimal128ToStr(HugeDecimalToDecimal128(A)) = '0.1234567890123456789');
// Trunc
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.0'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.1'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.0'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.2'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.23'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.234'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.2345'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('12.0'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalAssignDecimal32(A, StrToDecimal32('12.3'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalAssignDecimal32(A, StrToDecimal32('12.34'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalAssignDecimal32(A, StrToDecimal32('12.345'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalAssignDecimal32(A, StrToDecimal32('12.3456'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.0'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '123');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.4'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '123');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.45'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '123');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.456'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '123');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.4567'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '123');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234.0'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1234');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234.5'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1234');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234.56'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1234');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234.567'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1234');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234.5678'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1234');
HugeDecimalAssignDecimal64(A, StrToDecimal64('123456789.123456789'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '123456789');
HugeDecimalAssignDecimal64(A, StrToDecimal64('1234567890.123456789'));
HugeDecimalTrunc(A);
Assert(HugeDecimalToStr(A) = '1234567890');
// SetDigit
HugeDecimalAssignDecimal32(A, StrToDecimal32('1234.5678'));
HugeDecimalSetDigit(A, 0, 9);
Assert(HugeDecimalToStr(A) = '9234.5678');
HugeDecimalSetDigit(A, 1, 8);
Assert(HugeDecimalToStr(A) = '9834.5678');
HugeDecimalSetDigit(A, 2, 7);
Assert(HugeDecimalToStr(A) = '9874.5678');
HugeDecimalSetDigit(A, 3, 6);
Assert(HugeDecimalToStr(A) = '9876.5678');
HugeDecimalSetDigit(A, 4, 1);
Assert(HugeDecimalToStr(A) = '9876.1678');
HugeDecimalSetDigit(A, 5, 2);
Assert(HugeDecimalToStr(A) = '9876.1278');
HugeDecimalSetDigit(A, 6, 3);
Assert(HugeDecimalToStr(A) = '9876.1238');
HugeDecimalSetDigit(A, 7, 4);
Assert(HugeDecimalToStr(A) = '9876.1234');
// SetDigit
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.1'));
HugeDecimalSetDigit(A, 0, 9);
Assert(HugeDecimalToStr(A) = '0.9');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.0'));
HugeDecimalSetDigit(A, 0, 9);
Assert(HugeDecimalToStr(A) = '9');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.2'));
HugeDecimalSetDigit(A, 0, 9);
Assert(HugeDecimalToStr(A) = '9.2');
HugeDecimalSetDigit(A, 1, 8);
Assert(HugeDecimalToStr(A) = '9.8');
// FracCompareHalf
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.4999'));
Assert(HugeDecimalFracCompareHalf(A) = -1);
Assert(not HugeDecimalIsInteger(A));
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.5000'));
Assert(HugeDecimalFracCompareHalf(A) = 0);
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.5001'));
Assert(HugeDecimalFracCompareHalf(A) = 1);
// Zero Mul/Div
HugeDecimalAssignZero(A);
HugeDecimalMul10(A);
Assert(HugeDecimalIsZero(A));
HugeDecimalDiv10(A);
Assert(HugeDecimalIsZero(A));
// Mul10
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.001'));
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '0.01');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '0.1');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '10');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '100');
// Div10
HugeDecimalAssignDecimal32(A, StrToDecimal32('100'));
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '10');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.1');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.01');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.001');
// Mul10
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.0012'));
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '0.012');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '0.12');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '1.2');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '120');
// Div10
HugeDecimalAssignDecimal32(A, StrToDecimal32('120'));
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '12');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '1.2');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.12');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.012');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.0012');
// Mul10
HugeDecimalAssignDecimal64(A, StrToDecimal64('0.00102'));
Assert(HugeDecimalToStr(A) = '0.00102');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '0.0102');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '0.102');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '1.02');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '10.2');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '102');
HugeDecimalMul10(A);
Assert(HugeDecimalToStr(A) = '1020');
// Div10
HugeDecimalAssignDecimal32(A, StrToDecimal32('1020'));
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '102');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '10.2');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '1.02');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.102');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.0102');
HugeDecimalDiv10(A);
Assert(HugeDecimalToStr(A) = '0.00102');
// Compare
HugeDecimalAssignDecimal32(A, StrToDecimal32('12.34'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('12.341'));
Assert(not HugeDecimalEqualsHugeDecimal(A, B));
Assert(HugeDecimalCompareHugeDecimal(A, B) = -1);
Assert(HugeDecimalCompareHugeDecimal(B, A) = 1);
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.0012'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0.001'));
Assert(not HugeDecimalEqualsHugeDecimal(A, B));
Assert(HugeDecimalCompareHugeDecimal(A, B) = 1);
Assert(HugeDecimalCompareHugeDecimal(B, A) = -1);
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.0054'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('122.0054'));
Assert(not HugeDecimalEqualsHugeDecimal(A, B));
Assert(HugeDecimalCompareHugeDecimal(A, B) = 1);
Assert(HugeDecimalCompareHugeDecimal(B, A) = -1);
HugeDecimalAssignDecimal32(A, StrToDecimal32('1121.0052'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('122.0052'));
Assert(not HugeDecimalEqualsHugeDecimal(A, B));
Assert(HugeDecimalCompareHugeDecimal(A, B) = 1);
Assert(HugeDecimalCompareHugeDecimal(B, A) = -1);
HugeDecimalAssignDecimal32(A, StrToDecimal32('1423.0034'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1423.0034'));
Assert(HugeDecimalEqualsHugeDecimal(A, B));
Assert(HugeDecimalCompareHugeDecimal(A, B) = 0);
Assert(HugeDecimalCompareHugeDecimal(B, A) = 0);
// Inc/Dec
HugeDecimalAssignDecimal32(A, StrToDecimal32('0'));
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '2');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('9'));
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '10');
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '11');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '10');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '9');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.01'));
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '1.01');
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '2.01');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '1.01');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '0.01');
HugeDecimalAssignDecimal32(A, StrToDecimal32('9.01'));
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '10.01');
HugeDecimalInc(A);
Assert(HugeDecimalToStr(A) = '11.01');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '10.01');
HugeDecimalDec(A);
Assert(HugeDecimalToStr(A) = '9.01');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0'));
HugeDecimalInc(A, 2);
Assert(HugeDecimalToStr(A) = '2');
HugeDecimalInc(A, 9);
Assert(HugeDecimalToStr(A) = '11');
HugeDecimalDec(A, 9);
Assert(HugeDecimalToStr(A) = '2');
HugeDecimalDec(A, 2);
Assert(HugeDecimalToStr(A) = '0');
// Round
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.0'));
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.49'));
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.5'));
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.51'));
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1'));
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.4999'));
Assert(HugeDecimalToStr(A) = '1.4999');
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.5'));
HugeDecimalRound(A);
Assert(HugeDecimalToStr(A) = '2');
// StrToHugeDecimal
Assert(TryStrToHugeDecimal('', A) = dceConvertError);
Assert(TryStrToHugeDecimal(' ', A) = dceConvertError);
Assert(TryStrToHugeDecimal('x', A) = dceConvertError);
Assert(TryStrToHugeDecimal('.', A) = dceConvertError);
Assert(TryStrToHugeDecimal('0.', A) = dceConvertError);
Assert(TryStrToHugeDecimal('.0', A) = dceConvertError);
Assert(TryStrToHugeDecimal('0', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '0');
Assert(HugeDecimalIsZero(A));
Assert(TryStrToHugeDecimal('000', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '0');
Assert(HugeDecimalIsZero(A));
Assert(TryStrToHugeDecimal('1', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '1');
Assert(HugeDecimalIsOne(A));
Assert(TryStrToHugeDecimal('001', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '1');
Assert(HugeDecimalIsOne(A));
Assert(TryStrToHugeDecimal('10', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '10');
Assert(TryStrToHugeDecimal('123', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '123');
Assert(HugeDecimalToWord8(A) = 123);
Assert(TryStrToHugeDecimal('0.1', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '0.1');
Assert(TryStrToHugeDecimal('00.1', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '0.1');
Assert(TryStrToHugeDecimal('00.10', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '0.1');
Assert(TryStrToHugeDecimal('1.2', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '1.2');
Assert(TryStrToHugeDecimal('001.200', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '1.2');
Assert(TryStrToHugeDecimal('3004.2001', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '3004.2001');
Assert(TryStrToHugeDecimal('123456.7890123', A) = dceNoError);
Assert(HugeDecimalToStr(A) = '123456.7890123');
StrToHugeDecimal('010123456.7890123990', A);
Assert(HugeDecimalToStr(A) = '10123456.789012399');
// Add
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.1'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '1.1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1.1'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '1.1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '0');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.2'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('3.4'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '4.6');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.23'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('54.1'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '55.33');
HugeDecimalAssignDecimal32(A, StrToDecimal32('0.001'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('123'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '123.001');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.99'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0.01'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '124');
HugeDecimalAssignDecimal32(A, StrToDecimal32('98.99'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1.01'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '100');
HugeDecimalAssignDecimal32(A, StrToDecimal32('19'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0.001'));
HugeDecimalAddHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '19.001');
// Subtract
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.1'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '1.1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.1'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1.1'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '0');
Assert(HugeDecimalIsZero(A));
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.1'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '0.1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('1.1'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('0.1'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '1');
HugeDecimalAssignDecimal32(A, StrToDecimal32('21'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '20');
HugeDecimalAssignDecimal32(A, StrToDecimal32('12'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('3'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '9');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.456'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1.2'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '122.256');
HugeDecimalAssignDecimal32(A, StrToDecimal32('123.456'));
HugeDecimalAssignDecimal32(B, StrToDecimal32('1.4567'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '121.9993');
HugeDecimalAssignDecimal64(A, StrToDecimal64('1.00200101'));
HugeDecimalAssignDecimal64(B, StrToDecimal64('1.00100202'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '0.00099899');
HugeDecimalAssignDecimal64(A, StrToDecimal64('2.12345678'));
HugeDecimalAssignDecimal64(B, StrToDecimal64('1.23456789'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '0.88888889');
HugeDecimalAssignDecimal64(A, StrToDecimal64('111.12345678'));
HugeDecimalAssignDecimal64(B, StrToDecimal64('0.123'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '111.00045678');
HugeDecimalAssignDecimal64(A, StrToDecimal64('123.4'));
HugeDecimalAssignDecimal64(B, StrToDecimal64('0.12345678'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '123.27654322');
HugeDecimalAssignDecimal64(A, StrToDecimal64('1'));
HugeDecimalAssignDecimal64(B, StrToDecimal64('0.12345678'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '0.87654322');
HugeDecimalAssignDecimal64(A, StrToDecimal64('1.12345678'));
HugeDecimalAssignDecimal64(B, StrToDecimal64('0.12345678'));
HugeDecimalSubtractHugeDecimal(A, B);
Assert(HugeDecimalToStr(A) = '1');
Assert(HugeDecimalIsOne(A));
// Finalise
HugeDecimalFinalise(B);
HugeDecimalFinalise(A);
end;
procedure Test_SDecimal32;
var A, B : SDecimal32;
begin
SDecimal32InitZero(A);
Assert(SDecimal32IsZero(A));
Assert(not SDecimal32IsOne(A));
Assert(not SDecimal32IsMaximum(A));
Assert(not SDecimal32IsMinimum(A));
Assert(not SDecimal32IsOverflow(A));
Assert(SDecimal32ToInt32(A) = 0);
Assert(SDecimal32ToStr(A) = '0.0000');
Assert(SDecimal32EqualsInt32(A, 0));
Assert(SDecimal32CompareWord8(A, 0) = 0);
Assert(SDecimal32CompareWord8(A, 1) = -1);
Assert(SDecimal32CompareInt32(A, 0) = 0);
Assert(SDecimal32CompareInt32(A, -1) = 1);
Assert(SDecimal32CompareInt32(A, 1) = -1);
Assert(SDecimal32Trunc(A) = 0);
Assert(SDecimal32Round(A) = 0);
Assert(SDecimal32FracWord(A) = 0);
Assert(SDecimal32EqualsFloat(A, 0.0));
Assert(not SDecimal32EqualsFloat(A, 0.000051));
Assert(SDecimal32CompareFloat(A, 0.0000) = 0);
Assert(SDecimal32CompareFloat(A, -0.0001) = 1);
Assert(SDecimal32CompareFloat(A, 0.0001) = -1);
Assert(SDecimal32Sign(A) = 0);
SDecimal32InitOne(A);
Assert(not SDecimal32IsZero(A));
Assert(SDecimal32IsOne(A));
Assert(not SDecimal32IsMinusOne(A));
Assert(SDecimal32ToWord8(A) = 1);
Assert(SDecimal32ToStr(A) = '1.0000');
Assert(SDecimal32ToStrB(A) = '1.0000');
Assert(SDecimal32EqualsWord8(A, 1));
Assert(SDecimal32EqualsInt32(A, 1));
Assert(not SDecimal32EqualsInt32(A, -1));
Assert(SDecimal32CompareWord8(A, 0) = 1);
Assert(SDecimal32CompareWord8(A, 1) = 0);
Assert(SDecimal32CompareWord8(A, 2) = -1);
Assert(SDecimal32CompareInt32(A, -1) = 1);
Assert(SDecimal32CompareInt32(A, 1) = 0);
Assert(SDecimal32CompareInt32(A, 2) = -1);
Assert(SDecimal32EqualsFloat(A, 1.0));
Assert(SDecimal32EqualsFloat(A, 1.000049));
Assert(SDecimal32Sign(A) = 1);
SDecimal32InitMinusOne(A);
Assert(not SDecimal32IsZero(A));
Assert(not SDecimal32IsOne(A));
Assert(SDecimal32IsMinusOne(A));
Assert(SDecimal32ToInt32(A) = -1);
Assert(SDecimal32ToStr(A) = '-1.0000');
Assert(SDecimal32ToStrB(A) = '-1.0000');
Assert(not SDecimal32EqualsWord8(A, 1));
Assert(SDecimal32EqualsInt32(A, -1));
Assert(not SDecimal32EqualsInt32(A, 1));
Assert(SDecimal32CompareWord8(A, 0) = -1);
Assert(SDecimal32CompareWord8(A, 1) = -1);
Assert(SDecimal32CompareInt32(A, 0) = -1);
Assert(SDecimal32CompareInt32(A, 1) = -1);
Assert(SDecimal32CompareInt32(A, -1) = 0);
Assert(SDecimal32CompareInt32(A, -2) = 1);
Assert(SDecimal32EqualsFloat(A, -1.0));
Assert(SDecimal32EqualsFloat(A, -1.000049));
Assert(SDecimal32Sign(A) = -1);
Assert(FloatIsSDecimal32Range(0.0000));
Assert(FloatIsSDecimal32Range(-0.0001));
Assert(FloatIsSDecimal32Range(-0.00005));
Assert(FloatIsSDecimal32Range(+99999.9999));
Assert(FloatIsSDecimal32Range(-99999.9999));
Assert(FloatIsSDecimal32Range(+99999.999949));
Assert(FloatIsSDecimal32Range(-99999.999949));
Assert(not FloatIsSDecimal32Range(+99999.99995));
Assert(not FloatIsSDecimal32Range(-99999.99995));
Assert(not FloatIsSDecimal32Range(+100000.0000));
Assert(not FloatIsSDecimal32Range(-100000.0000));
SDecimal32InitWord32(A, 99999);
Assert(SDecimal32ToWord32(A) = 99999);
Assert(SDecimal32ToStr(A) = '99999.0000');
Assert(SDecimal32Trunc(A) = 99999);
Assert(SDecimal32Sign(A) = 1);
SDecimal32InitInt32(A, -99999);
Assert(SDecimal32ToInt32(A) = -99999);
Assert(SDecimal32ToStr(A) = '-99999.0000');
Assert(SDecimal32Trunc(A) = -99999);
Assert(SDecimal32Sign(A) = -1);
SDecimal32InitFloat(A, -1.2345);
Assert(Abs(SDecimal32ToFloat(A) - -1.2345) < 1e-9);
Assert(SDecimal32ToStr(A) = '-1.2345');
Assert(SDecimal32Trunc(A) = -1);
Assert(SDecimal32Round(A) = -1);
Assert(SDecimal32EqualsFloat(A, -1.2345));
SDecimal32InitFloat(A, -1.23445);
Assert(Abs(SDecimal32ToFloat(A) - -1.2344) < 1e-9);
Assert(SDecimal32ToStr(A) = '-1.2344');
SDecimal32InitFloat(A, -1.23455);
Assert(Abs(SDecimal32ToFloat(A) - -1.2346) < 1e-9);
Assert(SDecimal32ToStr(A) = '-1.2346');
SDecimal32InitFloat(A, 99999.9999);
Assert(SDecimal32IsMaximum(A));
Assert(not SDecimal32IsMinimum(A));
SDecimal32InitFloat(A, -99999.9999);
Assert(not SDecimal32IsMaximum(A));
Assert(SDecimal32IsMinimum(A));
SDecimal32InitMax(A);
Assert(SDecimal32IsMaximum(A));
Assert(not SDecimal32IsOverflow(A));
Assert(SDecimal32ToStr(A) = '99999.9999');
Assert(SDecimal32Trunc(A) = 99999);
Assert(SDecimal32Round(A) = 100000);
Assert(SDecimal32FracWord(A) = 9999);
Assert(SDecimal32EqualsFloat(A, 99999.9999));
Assert(SDecimal32EqualsFloat(A, 99999.999949));
Assert(not SDecimal32EqualsFloat(A, 99999.99995));
SDecimal32InitMin(A);
Assert(SDecimal32IsMinimum(A));
Assert(not SDecimal32IsOverflow(A));
Assert(SDecimal32ToStr(A) = '-99999.9999');
Assert(SDecimal32Trunc(A) = -99999);
Assert(SDecimal32Round(A) = -100000);
Assert(SDecimal32FracWord(A) = 9999);
Assert(SDecimal32EqualsFloat(A, -99999.9999));
Assert(SDecimal32EqualsFloat(A, -99999.999949));
Assert(not SDecimal32EqualsFloat(A, -99999.99995));
SDecimal32InitFloat(A, -99999.4999);
Assert(SDecimal32Trunc(A) = -99999);
Assert(SDecimal32Round(A) = -99999);
SDecimal32InitFloat(A, -99999.5000);
Assert(SDecimal32Trunc(A) = -99999);
Assert(SDecimal32Round(A) = -100000);
Assert(SDecimal32FracWord(A) = 5000);
SDecimal32InitFloat(A, -99998.5000);
Assert(SDecimal32Trunc(A) = -99998);
Assert(SDecimal32Round(A) = -99998);
SDecimal32InitFloat(A, -99998.5001);
Assert(SDecimal32Trunc(A) = -99998);
Assert(SDecimal32Round(A) = -99999);
SDecimal32InitFloat(A, -0.1);
Assert(SDecimal32ToStr(A) = '-0.1000');
Assert(SDecimal32EqualsFloat(A, -0.1));
SDecimal32InitFloat(A, -0.00005);
Assert(SDecimal32ToStr(A) = '0.0000');
SDecimal32InitFloat(A, -0.000051);
Assert(SDecimal32ToStr(A) = '-0.0001');
SDecimal32InitFloat(A, -0.00025);
Assert(SDecimal32ToStr(A) = '-0.0002');
SDecimal32InitFloat(A, -0.00055);
Assert(SDecimal32ToStr(A) = '-0.0006');
SDecimal32InitFloat(A, -0.000049);
Assert(SDecimal32ToStr(A) = '0.0000');
SDecimal32InitFloat(A, -0.000050);
Assert(SDecimal32ToStr(A) = '0.0000');
SDecimal32InitFloat(A, -1.9375);
Assert(SDecimal32ToFloat(A) = -1.9375);
SDecimal32AddWord8(A, 1);
Assert(SDecimal32ToFloat(A) = -0.9375);
SDecimal32AddWord8(A, 1);
Assert(SDecimal32ToFloat(A) = 0.0625);
SDecimal32AddWord8(A, 1);
Assert(SDecimal32ToFloat(A) = 1.0625);
SDecimal32SubtractWord8(A, 1);
Assert(SDecimal32ToFloat(A) = 0.0625);
SDecimal32SubtractWord8(A, 1);
Assert(SDecimal32ToFloat(A) = -0.9375);
SDecimal32SubtractWord8(A, 1);
Assert(SDecimal32ToFloat(A) = -1.9375);
SDecimal32InitFloat(A, -1.9375);
SDecimal32InitFloat(B, 2.5000);
SDecimal32AddSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = 0.5625);
SDecimal32AddSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = 3.0625);
SDecimal32SubtractSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = 0.5625);
SDecimal32SubtractSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = -1.9375);
SDecimal32SubtractSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = -4.4375);
SDecimal32InitFloat(A, -1.9375);
SDecimal32InitFloat(B, -2.5000);
SDecimal32AddSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = -4.4375);
SDecimal32SubtractSDecimal32(A, B);
Assert(SDecimal32ToFloat(A) = -1.9375);
SDecimal32InitFloat(A, 1.9375);
SDecimal32InitFloat(B, 2.5000);
Assert(not SDecimal32EqualsSDecimal32(A, B));
Assert(SDecimal32EqualsSDecimal32(A, A));
Assert(SDecimal32CompareSDecimal32(A, B) = -1);
Assert(SDecimal32CompareSDecimal32(A, A) = 0);
Assert(SDecimal32CompareSDecimal32(B, A) = 1);
SDecimal32InitFloat(A, -1.9375);
SDecimal32InitFloat(B, 2.5000);
Assert(not SDecimal32EqualsSDecimal32(A, B));
Assert(SDecimal32EqualsSDecimal32(A, A));
Assert(SDecimal32CompareSDecimal32(A, B) = -1);
Assert(SDecimal32CompareSDecimal32(A, A) = 0);
Assert(SDecimal32CompareSDecimal32(B, A) = 1);
SDecimal32InitFloat(A, -1.9375);
SDecimal32InitFloat(B, -2.5000);
Assert(not SDecimal32EqualsSDecimal32(A, B));
Assert(SDecimal32EqualsSDecimal32(A, A));
Assert(SDecimal32CompareSDecimal32(A, B) = 1);
Assert(SDecimal32CompareSDecimal32(A, A) = 0);
Assert(SDecimal32CompareSDecimal32(B, A) = -1);
SDecimal32InitFloat(A, -1.9375);
SDecimal32MultiplyWord8(A, 3);
Assert(SDecimal32ToFloat(A) = -5.8125);
SDecimal32InitFloat(A, 1.9375);
SDecimal32InitFloat(B, -3.1200);
SDecimal32MultiplySDecimal32(A, B);
Assert(SDecimal32ToFloat(A) + 6.045 < 1e-10);
Assert(SDecimal32ToStr(A) = '-6.0450');
SDecimal32MultiplySDecimal32(A, B);
Assert(SDecimal32ToStr(A) = '18.8604');
SDecimal32DivideSDecimal32(A, B);
Assert(SDecimal32ToStr(A) = '-6.0450');
SDecimal32DivideSDecimal32(A, B);
Assert(SDecimal32ToStr(A) = '1.9375');
SDecimal32InitFloat(A, -16.9375);
SDecimal32InitFloat(B, -3.1200);
SDecimal32MultiplySDecimal32(A, B);
Assert(SDecimal32ToFloat(A) - 52.8450 < 1e-10);
Assert(SDecimal32ToStr(A) = '52.8450');
SDecimal32DivideSDecimal32(A, B);
Assert(SDecimal32ToStr(A) = '-16.9375');
SDecimal32DivideSDecimal32(A, B);
Assert(SDecimal32ToStr(A) = '5.4286');
A := StrToSDecimal32('0');
Assert(SDecimal32ToWord8(A) = 0);
A := StrToSDecimal32('+0');
Assert(SDecimal32ToWord8(A) = 0);
A := StrToSDecimal32('-0');
Assert(SDecimal32ToWord8(A) = 0);
A := StrToSDecimal32('+1');
Assert(SDecimal32ToWord8(A) = 1);
A := StrToSDecimal32('-1.0');
Assert(SDecimal32ToInt32(A) = -1);
A := StrToSDecimal32('-1.0000000000000001');
Assert(SDecimal32ToInt32(A) = -1);
A := StrToSDecimal32('-123.9385');
Assert(SDecimal32ToStr(A) = '-123.9385');
A := StrToSDecimal32('-123.93856');
Assert(SDecimal32ToStr(A) = '-123.9386');
A := StrToSDecimal32('-123.93855');
Assert(SDecimal32ToStr(A) = '-123.9386');
A := StrToSDecimal32('-123.93865');
Assert(SDecimal32ToStr(A) = '-123.9386');
A := StrToSDecimal32('-123.938650000000010');
Assert(SDecimal32ToStr(A) = '-123.9387');
A := StrToSDecimal32('-99999.9999');
Assert(SDecimal32ToStr(A) = '-99999.9999');
Assert(TryStrToSDecimal32('0', A) = dceNoError);
Assert(SDecimal32ToInt32(A) = 0);
Assert(TryStrToSDecimal32('-99999', A) = dceNoError);
Assert(SDecimal32ToInt32(A) = -99999);
Assert(TryStrToSDecimal32('-100000', A) = dceOverflowError);
Assert(TryStrToSDecimal32('-99999.99995', A) = dceOverflowError);
end;
procedure Test_SDecimal64;
var A, B : SDecimal64;
begin
SDecimal64InitZero(A);
Assert(SDecimal64IsZero(A));
Assert(not SDecimal64IsOne(A));
Assert(not SDecimal64IsMaximum(A));
Assert(not SDecimal64IsOverflow(A));
Assert(SDecimal64ToWord8(A) = 0);
Assert(SDecimal64ToStr(A) = '0.000000000');
Assert(SDecimal64EqualsWord8(A, 0));
Assert(SDecimal64CompareWord8(A, 0) = 0);
Assert(SDecimal64CompareWord8(A, 1) = -1);
Assert(SDecimal64Trunc(A) = 0);
Assert(SDecimal64Round(A) = 0);
Assert(SDecimal64FracWord(A) = 0);
Assert(SDecimal64EqualsFloat(A, 0.0));
Assert(SDecimal64EqualsFloat(A, 0.00000000049));
Assert(SDecimal64EqualsFloat(A, 0.0000000005));
Assert(not SDecimal64EqualsFloat(A, 0.00000000051));
Assert(SDecimal64CompareFloat(A, 0.000000000) = 0);
Assert(SDecimal64CompareFloat(A, -0.000000001) = 1);
Assert(SDecimal64CompareFloat(A, 0.000000001) = -1);
Assert(SDecimal64Sign(A) = 0);
SDecimal64InitOne(A);
Assert(not SDecimal64IsZero(A));
Assert(SDecimal64IsOne(A));
Assert(not SDecimal64IsMinusOne(A));
Assert(SDecimal64ToInt32(A) = 1);
Assert(SDecimal64ToStr(A) = '1.000000000');
Assert(SDecimal64ToStrB(A) = '1.000000000');
Assert(SDecimal64EqualsWord8(A, 1));
Assert(SDecimal64CompareWord8(A, 0) = 1);
Assert(SDecimal64CompareWord8(A, 1) = 0);
Assert(SDecimal64CompareWord8(A, 2) = -1);
Assert(SDecimal64Trunc(A) = 1);
Assert(SDecimal64Round(A) = 1);
Assert(SDecimal64EqualsFloat(A, 1.0));
Assert(SDecimal64EqualsFloat(A, 1.00000000049));
Assert(not SDecimal64EqualsFloat(A, 1.00000000051));
Assert(SDecimal64Sign(A) = 1);
SDecimal64InitMinusOne(A);
Assert(not SDecimal64IsZero(A));
Assert(not SDecimal64IsOne(A));
Assert(SDecimal64IsMinusOne(A));
Assert(SDecimal64ToInt32(A) = -1);
Assert(SDecimal64ToStr(A) = '-1.000000000');
Assert(SDecimal64ToStrB(A) = '-1.000000000');
Assert(not SDecimal64EqualsWord8(A, 1));
Assert(SDecimal64EqualsInt32(A, -1));
Assert(SDecimal64CompareWord8(A, 0) = -1);
Assert(SDecimal64CompareInt32(A, -2) = 1);
Assert(SDecimal64CompareInt32(A, -1) = 0);
Assert(SDecimal64CompareInt32(A, 0) = -1);
Assert(SDecimal64Trunc(A) = -1);
Assert(SDecimal64Round(A) = -1);
Assert(SDecimal64EqualsFloat(A, -1.0));
Assert(SDecimal64EqualsFloat(A, -1.00000000049));
Assert(not SDecimal64EqualsFloat(A, -1.00000000051));
Assert(SDecimal64Sign(A) = -1);
Assert(FloatIsSDecimal64Range(0.000000000));
Assert(FloatIsSDecimal64Range(-0.000000001));
Assert(FloatIsSDecimal64Range(-0.0000000005));
{$IFNDEF DELPHI7_DOWN}
Assert(not FloatIsSDecimal64Range(9999999999.999999999));
Assert(not FloatIsSDecimal64Range(10000000000.000000000));
{$ENDIF}
SDecimal64InitInt64(A, SDecimal64MaxInt);
Assert(SDecimal64ToInt64(A) = 9999999999);
Assert(SDecimal64ToStr(A) = '9999999999.000000000');
Assert(SDecimal64Trunc(A) = 9999999999);
Assert(SDecimal64Sign(A) = 1);
SDecimal64InitInt64(A, SDecimal64MinInt);
Assert(SDecimal64ToInt64(A) = -9999999999);
Assert(SDecimal64ToStr(A) = '-9999999999.000000000');
Assert(SDecimal64Trunc(A) = -9999999999);
Assert(SDecimal64Sign(A) = -1);
SDecimal64InitFloat(A, -1.234567890);
Assert(Abs(SDecimal64ToFloat(A) - -1.234567890) < 1e-12);
Assert(SDecimal64ToStr(A) = '-1.234567890');
Assert(SDecimal64Trunc(A) = -1);
Assert(SDecimal64Round(A) = -1);
Assert(SDecimal64EqualsFloat(A, -1.234567890));
SDecimal64InitFloat(A, -1.2345111115);
Assert(Abs(SDecimal64ToFloat(A) - -1.234511112) < 1e-12);
Assert(SDecimal64ToStr(A) = '-1.234511112');
SDecimal64InitFloat(A, -1.2345111125);
Assert(Abs(SDecimal64ToFloat(A) - -1.234511112) < 1e-12);
Assert(SDecimal64ToStr(A) = '-1.234511112');
SDecimal64InitFloat(A, -1.23451111251);
Assert(Abs(SDecimal64ToFloat(A) - -1.234511113) < 1e-12);
Assert(SDecimal64ToStr(A) = '-1.234511113');
A := StrToSDecimal64('9999999999.999999999');
Assert(SDecimal64IsMaximum(A));
A := StrToSDecimal64('-9999999999.999999999');
Assert(SDecimal64IsMinimum(A));
SDecimal64InitMax(A);
Assert(SDecimal64IsMaximum(A));
Assert(not SDecimal64IsOverflow(A));
Assert(SDecimal64ToStr(A) = '9999999999.999999999');
Assert(SDecimal64Trunc(A) = 9999999999);
Assert(SDecimal64Round(A) = 10000000000);
Assert(SDecimal64FracWord(A) = 999999999);
SDecimal64InitMin(A);
Assert(SDecimal64IsMinimum(A));
Assert(not SDecimal64IsOverflow(A));
Assert(SDecimal64ToStr(A) = '-9999999999.999999999');
Assert(SDecimal64Trunc(A) = -9999999999);
Assert(SDecimal64Round(A) = -10000000000);
Assert(SDecimal64FracWord(A) = 999999999);
A := StrToSDecimal64('-9999999999.499999999');
Assert(SDecimal64Trunc(A) = -9999999999);
Assert(SDecimal64Round(A) = -9999999999);
A := StrToSDecimal64('-9999999999.500000000');
Assert(SDecimal64Trunc(A) = -9999999999);
Assert(SDecimal64Round(A) = -10000000000);
Assert(SDecimal64FracWord(A) = 500000000);
A := StrToSDecimal64('-9999999998.500000000');
Assert(SDecimal64Trunc(A) = -9999999998);
Assert(SDecimal64Round(A) = -9999999998);
A := StrToSDecimal64('-9999999998.500000001');
Assert(SDecimal64Trunc(A) = -9999999998);
Assert(SDecimal64Round(A) = -9999999999);
SDecimal64InitFloat(A, -0.1);
Assert(SDecimal64ToStr(A) = '-0.100000000');
Assert(SDecimal64EqualsFloat(A, -0.1));
SDecimal64InitFloat(A, -0.000000001);
Assert(SDecimal64ToStr(A) = '-0.000000001');
Assert(SDecimal64EqualsFloat(A, -0.000000001));
SDecimal64InitFloat(A, -0.0000000005);
Assert(SDecimal64ToStr(A) = '0.000000000');
SDecimal64InitFloat(A, -0.00000000051);
Assert(SDecimal64ToStr(A) = '-0.000000001');
SDecimal64InitFloat(A, -0.0000000025);
Assert(SDecimal64ToStr(A) = '-0.000000002');
SDecimal64InitFloat(A, -0.0000000055);
Assert(SDecimal64ToStr(A) = '-0.000000006');
SDecimal64InitFloat(A, -0.00000000049);
Assert(SDecimal64ToStr(A) = '0.000000000');
SDecimal64InitFloat(A, -0.00000000050);
Assert(SDecimal64ToStr(A) = '0.000000000');
SDecimal64InitFloat(A, -1.9375);
Assert(SDecimal64ToFloat(A) = -1.9375);
SDecimal64AddWord8(A, 1);
Assert(SDecimal64ToFloat(A) = -0.9375);
SDecimal64AddWord8(A, 1);
Assert(SDecimal64ToFloat(A) = 0.0625);
SDecimal64AddWord8(A, 1);
Assert(SDecimal64ToFloat(A) = 1.0625);
SDecimal64SubtractWord8(A, 1);
Assert(SDecimal64ToFloat(A) = 0.0625);
SDecimal64SubtractWord8(A, 1);
Assert(SDecimal64ToFloat(A) = -0.9375);
SDecimal64SubtractWord8(A, 1);
Assert(SDecimal64ToFloat(A) = -1.9375);
SDecimal64InitFloat(A, -1.9375);
SDecimal64InitFloat(B, -2.5000);
SDecimal64AddSDecimal64(A, B);
Assert(SDecimal64ToFloat(A) = -4.4375);
SDecimal64SubtractSDecimal64(A, B);
Assert(SDecimal64ToFloat(A) = -1.9375);
SDecimal64InitFloat(A, -1.9375);
SDecimal64InitFloat(B, -2.5000);
Assert(not SDecimal64EqualsSDecimal64(A, B));
Assert(SDecimal64EqualsSDecimal64(A, A));
Assert(SDecimal64CompareSDecimal64(A, B) = 1);
Assert(SDecimal64CompareSDecimal64(A, A) = 0);
Assert(SDecimal64CompareSDecimal64(B, A) = -1);
SDecimal64InitFloat(A, -1.9375);
SDecimal64MultiplyWord8(A, 3);
Assert(SDecimal64ToFloat(A) = -5.8125);
SDecimal64DivideWord8(A, 3);
Assert(SDecimal64ToStr(A) = '-1.937500000');
SDecimal64InitFloat(A, 1.9375);
SDecimal64InitFloat(B, -2.5000);
SDecimal64MultiplySDecimal64(A, B);
Assert(SDecimal64ToFloat(A) = -4.84375);
Assert(SDecimal64ToStr(A) = '-4.843750000');
SDecimal64DivideSDecimal64(A, B);
Assert(SDecimal64ToStr(A) = '1.937500000');
SDecimal64InitFloat(A, -12.937512);
SDecimal64InitFloat(B, -3.123433);
SDecimal64MultiplySDecimal64(A, B);
Assert(SDecimal64ToFloat(A) - 40.409451919 < 1e-10);
Assert(SDecimal64ToStr(A) = '40.409451919');
A := StrToSDecimal64('0');
Assert(SDecimal64ToWord8(A) = 0);
A := StrToSDecimal64('-0');
Assert(SDecimal64ToWord8(A) = 0);
A := StrToSDecimal64('+0');
Assert(SDecimal64ToWord8(A) = 0);
A := StrToSDecimal64('-0.0000');
A := StrToSDecimal64('000000000000.000000000000');
Assert(SDecimal64ToWord8(A) = 0);
A := StrToSDecimal64('-1');
Assert(SDecimal64ToInt32(A) = -1);
A := StrToSDecimal64('-1.0');
Assert(SDecimal64ToInt32(A) = -1);
A := StrToSDecimal64('-1.0000000000000001');
Assert(SDecimal64ToInt32(A) = -1);
A := StrToSDecimal64('-123.938500000');
Assert(SDecimal64ToStr(A) = '-123.938500000');
A := StrToSDecimal64('-123.9385000005');
Assert(SDecimal64ToStr(A) = '-123.938500000');
A := StrToSDecimal64('-123.9385000015');
Assert(SDecimal64ToStr(A) = '-123.938500002');
A := StrToSDecimal64('-123.9386000025');
Assert(SDecimal64ToStr(A) = '-123.938600002');
A := StrToSDecimal64('-123.93860000251');
Assert(SDecimal64ToStr(A) = '-123.938600003');
A := StrToSDecimal64('-9999999999.999999999');
Assert(SDecimal64ToStr(A) = '-9999999999.999999999');
Assert(TryStrToSDecimal64('0', A) = dceNoError);
Assert(SDecimal64ToWord32(A) = 0);
Assert(TryStrToSDecimal64('-9999999999', A) = dceNoError);
Assert(SDecimal64ToInt64(A) = -9999999999);
Assert(TryStrToSDecimal64('-10000000000', A) = dceOverflowError);
Assert(TryStrToSDecimal64('-9999999999.9999999995', A) = dceOverflowError);
end;
procedure Test_SDecimal128;
var A, B : SDecimal128;
C : Word64Rec;
begin
SDecimal128InitZero(A);
Assert(SDecimal128IsZero(A));
Assert(not SDecimal128IsOne(A));
Assert(not SDecimal128IsMaximum(A));
Assert(not SDecimal128IsOverflow(A));
Assert(SDecimal128Sign(A) = 0);
Assert(SDecimal128ToWord8(A) = 0);
Assert(SDecimal128ToInt64(A) = 0);
Assert(SDecimal128ToStr(A) = '0.0000000000000000000');
Assert(SDecimal128EqualsWord8(A, 0));
Assert(SDecimal128EqualsWord16(A, 0));
Assert(SDecimal128EqualsWord32(A, 0));
Assert(not SDecimal128EqualsWord32(A, 1));
Word64InitZero(C);
Assert(SDecimal128EqualsWord64(A, C));
Assert(SDecimal128EqualsInt64(A, 0));
Assert(not SDecimal128EqualsInt64(A, 1));
Assert(SDecimal128CompareWord8(A, 0) = 0);
Assert(SDecimal128CompareWord8(A, 1) = -1);
Assert(SDecimal128CompareWord16(A, 0) = 0);
Assert(SDecimal128CompareWord16(A, 1) = -1);
Assert(Int128ToStr(SDecimal128Trunc(A)) = '0');
Assert(Int128ToStr(SDecimal128Round(A)) = '0');
Assert(Word64ToStr(SDecimal128FracWord(A)) = '0');
Assert(SDecimal128EqualsFloat(A, 0.0));
Assert(SDecimal128Sign(A) = 0);
Assert(SDecimal128CompareFloat(A, 0.0) = 0);
Assert(SDecimal128CompareFloat(A, 0.1) = -1);
Assert(SDecimal128CompareFloat(A, -0.1) = 1);
SDecimal128Negate(A);
Assert(SDecimal128Sign(A) = 0);
Assert(SDecimal128IsZero(A));
SDecimal128AbsInPlace(A);
Assert(SDecimal128Sign(A) = 0);
SDecimal128InitOne(A);
Assert(not SDecimal128IsZero(A));
Assert(SDecimal128IsOne(A));
Assert(not SDecimal128IsMinusOne(A));
Assert(SDecimal128Sign(A) = 1);
Assert(SDecimal128ToInt32(A) = 1);
Assert(SDecimal128ToStr(A) = '1.0000000000000000000');
Assert(SDecimal128ToStrB(A) = '1.0000000000000000000');
Assert(SDecimal128ToStrU(A) = '1.0000000000000000000');
Assert(SDecimal128EqualsWord8(A, 1));
Assert(not SDecimal128EqualsWord8(A, 0));
Assert(SDecimal128EqualsWord16(A, 1));
Assert(SDecimal128EqualsWord32(A, 1));
Assert(not SDecimal128EqualsWord32(A, 0));
Word64InitOne(C);
Assert(SDecimal128EqualsWord64(A, C));
Assert(SDecimal128EqualsInt64(A, 1));
Assert(not SDecimal128EqualsInt64(A, -1));
Assert(SDecimal128CompareWord8(A, 0) = 1);
Assert(SDecimal128CompareWord8(A, 1) = 0);
Assert(SDecimal128CompareWord8(A, 2) = -1);
Assert(SDecimal128CompareWord16(A, 0) = 1);
Assert(SDecimal128CompareWord16(A, 1) = 0);
Assert(SDecimal128CompareWord16(A, 2) = -1);
Word64InitZero(C);
Assert(SDecimal128CompareWord64(A, C) = 1);
Word64InitOne(C);
Assert(SDecimal128CompareWord64(A, C) = 0);
Word64InitWord32(C, 2);
Assert(SDecimal128CompareWord64(A, C) = -1);
Assert(Int128ToStr(SDecimal128Trunc(A)) = '1');
Assert(Int128ToStr(SDecimal128Round(A)) = '1');
Assert(SDecimal128Sign(A) = 1);
Assert(SDecimal128CompareFloat(A, 1.0) = 0);
Assert(SDecimal128CompareFloat(A, 1.1) = -1);
Assert(SDecimal128CompareFloat(A, 0.9) = 1);
Assert(SDecimal128CompareFloat(A, -0.1) = 1);
SDecimal128Negate(A);
Assert(SDecimal128Sign(A) = -1);
Assert(SDecimal128IsMinusOne(A));
SDecimal128Negate(A);
Assert(SDecimal128Sign(A) = 1);
Assert(SDecimal128IsOne(A));
SDecimal128AbsInPlace(A);
Assert(SDecimal128Sign(A) = 1);
Assert(SDecimal128IsOne(A));
Assert(SDecimal128ToWord16(A) = 1);
Assert(SDecimal128ToWord32(A) = 1);
C := SDecimal128ToWord64(A);
Assert(Word64IsOne(C));
Assert(SDecimal128ToInt64(A) = 1);
SDecimal128InitWord8(A, 1);
Assert(SDecimal128IsOne(A));
SDecimal128InitWord16(A, 1);
Assert(SDecimal128IsOne(A));
SDecimal128InitWord32(A, 1);
Assert(SDecimal128IsOne(A));
Word64InitOne(C);
SDecimal128InitWord64(A, C);
Assert(SDecimal128IsOne(A));
SDecimal128InitMinusOne(A);
Assert(not SDecimal128IsZero(A));
Assert(not SDecimal128IsOne(A));
Assert(SDecimal128IsMinusOne(A));
Assert(SDecimal128Sign(A) = -1);
Assert(SDecimal128ToInt32(A) = -1);
Assert(SDecimal128ToInt64(A) = -1);
Assert(SDecimal128ToStr(A) = '-1.0000000000000000000');
Assert(SDecimal128ToStrB(A) = '-1.0000000000000000000');
Assert(not SDecimal128EqualsWord8(A, 1));
Assert(SDecimal128EqualsInt32(A, -1));
Assert(SDecimal128EqualsInt64(A, -1));
Assert(not SDecimal128EqualsInt64(A, 1));
Assert(SDecimal128CompareWord8(A, 0) = -1);
Assert(SDecimal128CompareWord16(A, 0) = -1);
Assert(SDecimal128CompareWord32(A, 0) = -1);
Word64InitZero(C);
Assert(SDecimal128CompareWord64(A, C) = -1);
Assert(SDecimal128CompareInt32(A, -2) = 1);
Assert(SDecimal128CompareInt32(A, -1) = 0);
Assert(SDecimal128CompareInt32(A, 0) = -1);
Assert(SDecimal128CompareInt64(A, -2) = 1);
Assert(SDecimal128CompareInt64(A, -1) = 0);
Assert(SDecimal128CompareInt64(A, 0) = -1);
Assert(Int128ToStr(SDecimal128Trunc(A)) = '-1');
Assert(Int128ToStr(SDecimal128Round(A)) = '-1');
Assert(SDecimal128EqualsFloat(A, -1.0));
Assert(SDecimal128Sign(A) = -1);
Assert(SDecimal128CompareFloat(A, -1.0) = 0);
Assert(SDecimal128CompareFloat(A, -1.1) = 1);
Assert(SDecimal128CompareFloat(A, -0.9) = -1);
SDecimal128AbsInPlace(A);
Assert(SDecimal128Sign(A) = 1);
Assert(SDecimal128IsOne(A));
SDecimal128Negate(A);
Assert(SDecimal128IsMinusOne(A));
SDecimal128InitInt32(A, -1);
Assert(SDecimal128IsMinusOne(A));
SDecimal128InitInt64(A, -1);
Assert(SDecimal128IsMinusOne(A));
Assert(FloatIsSDecimal128Range(9999999999999990000.0));
Assert(not FloatIsSDecimal128Range(10000000000000000000.0));
SDecimal128InitFloat(A, -1.234567890);
Assert(Abs(SDecimal128ToFloat(A) - -1.234567890) < 1e-12);
Assert(Int128ToStr(SDecimal128Trunc(A)) = '-1');
Assert(Int128ToStr(SDecimal128Round(A)) = '-1');
Assert(SDecimal128EqualsFloat(A, -1.234567890));
A := StrToSDecimal128('9999999999999999999.9999999999999999999');
Assert(SDecimal128IsMaximum(A));
Assert(SDecimal128Sign(A) = 1);
A := StrToSDecimal128('-9999999999999999999.9999999999999999999');
Assert(SDecimal128IsMinimum(A));
Assert(SDecimal128Sign(A) = -1);
SDecimal128InitMax(A);
Assert(SDecimal128IsMaximum(A));
Assert(not SDecimal128IsOverflow(A));
Assert(SDecimal128ToStr(A) = '9999999999999999999.9999999999999999999');
Assert(Int128ToStr(SDecimal128Trunc(A)) = '9999999999999999999');
Assert(Int128ToStr(SDecimal128Round(A)) = '10000000000000000000');
Assert(Word64ToStr(SDecimal128FracWord(A)) = '9999999999999999999');
SDecimal128InitMin(A);
Assert(SDecimal128IsMinimum(A));
Assert(not SDecimal128IsOverflow(A));
Assert(SDecimal128ToStr(A) = '-9999999999999999999.9999999999999999999');
Assert(Int128ToStr(SDecimal128Trunc(A)) = '-9999999999999999999');
Assert(Int128ToStr(SDecimal128Round(A)) = '-10000000000000000000');
Assert(Word64ToStr(SDecimal128FracWord(A)) = '9999999999999999999');
SDecimal128InitFloat(A, -1.9375);
Assert(SDecimal128ToFloat(A) = -1.9375);
SDecimal128AddWord8(A, 1);
Assert(SDecimal128ToFloat(A) = -0.9375);
SDecimal128AddWord8(A, 1);
Assert(SDecimal128ToFloat(A) = 0.0625);
SDecimal128AddWord8(A, 1);
Assert(SDecimal128ToFloat(A) = 1.0625);
SDecimal128SubtractWord8(A, 1);
Assert(SDecimal128ToFloat(A) = 0.0625);
SDecimal128SubtractWord8(A, 1);
Assert(SDecimal128ToFloat(A) = -0.9375);
SDecimal128SubtractWord8(A, 1);
Assert(SDecimal128ToFloat(A) = -1.9375);
SDecimal128AddWord16(A, 2);
Assert(SDecimal128ToFloat(A) = 0.0625);
SDecimal128SubtractWord16(A, 2);
Assert(SDecimal128ToFloat(A) = -1.9375);
SDecimal128AddWord32(A, 2);
Assert(SDecimal128ToFloat(A) = 0.0625);
SDecimal128AddWord16(A, 123);
Assert(SDecimal128ToStrB(A) = '123.0625000000000000000');
SDecimal128AddWord32(A, 1000000);
Assert(SDecimal128ToStrB(A) = '1000123.0625000000000000000');
Word64InitWord32(C, 10000000);
SDecimal128AddWord64(A, C);
Assert(SDecimal128ToStrB(A) = '11000123.0625000000000000000');
SDecimal128SubtractWord64(A, C);
Assert(SDecimal128ToStrB(A) = '1000123.0625000000000000000');
SDecimal128SubtractWord32(A, 1000000);
Assert(SDecimal128ToStrB(A) = '123.0625000000000000000');
SDecimal128InitFloat(A, -1.9375);
SDecimal128InitFloat(B, -2.5000);
SDecimal128AddSDecimal128(A, B);
Assert(SDecimal128ToFloat(A) = -4.4375);
SDecimal128SubtractSDecimal128(A, B);
Assert(SDecimal128ToFloat(A) = -1.9375);
SDecimal128InitFloat(A, -1.9375);
SDecimal128InitFloat(B, -2.5000);
Assert(not SDecimal128EqualsSDecimal128(A, B));
Assert(SDecimal128EqualsSDecimal128(A, A));
Assert(SDecimal128CompareSDecimal128(A, B) = 1);
Assert(SDecimal128CompareSDecimal128(A, A) = 0);
Assert(SDecimal128CompareSDecimal128(B, A) = -1);
SDecimal128InitFloat(A, -1.9375);
SDecimal128MultiplyWord8(A, 3);
Assert(SDecimal128ToFloat(A) = -5.8125);
SDecimal128DivideWord8(A, 3);
Assert(SDecimal128ToStr(A) = '-1.9375000000000000000');
SDecimal128MultiplyWord16(A, 3);
Assert(SDecimal128ToFloat(A) = -5.8125);
SDecimal128DivideWord16(A, 3);
Assert(SDecimal128ToStr(A) = '-1.9375000000000000000');
SDecimal128MultiplyWord32(A, 3);
Assert(SDecimal128ToFloat(A) = -5.8125);
SDecimal128DivideWord32(A, 3);
Assert(SDecimal128ToStr(A) = '-1.9375000000000000000');
Word64InitWord32(C, 3);
SDecimal128MultiplyWord64(A, C);
Assert(SDecimal128ToFloat(A) = -5.8125);
SDecimal128DivideWord64(A, C);
Assert(SDecimal128ToStr(A) = '-1.9375000000000000000');
SDecimal128InitFloat(A, 1.9375);
SDecimal128InitFloat(B, -2.5000);
SDecimal128MultiplySDecimal128(A, B);
Assert(SDecimal128ToFloat(A) = -4.84375);
Assert(SDecimal128ToStr(A) = '-4.8437500000000000000');
SDecimal128DivideSDecimal128(A, B);
Assert(SDecimal128ToStr(A) = '1.9375000000000000000');
SDecimal128InitFloat(A, -12.937512);
SDecimal128InitFloat(B, -3.123433);
SDecimal128MultiplySDecimal128(A, B);
Assert(SDecimal128ToFloat(A) - 40.409451919 < 1e-10);
Assert(CopyLeft(SDecimal128ToStr(A), 16) = '40.4094519186960');
A := StrToSDecimal128('0');
Assert(SDecimal128ToWord8(A) = 0);
A := StrToSDecimal128('-0');
Assert(SDecimal128ToWord8(A) = 0);
A := StrToSDecimal128('+0');
Assert(SDecimal128ToWord8(A) = 0);
A := StrToSDecimal128('-0.0000');
Assert(SDecimal128ToWord8(A) = 0);
A := StrToSDecimal128('000000000000.000000000000');
Assert(SDecimal128ToWord8(A) = 0);
A := StrToSDecimal128('-1');
Assert(SDecimal128ToInt32(A) = -1);
A := StrToSDecimal128('-1.0');
Assert(SDecimal128ToInt32(A) = -1);
A := StrToSDecimal128('-123.938500000');
Assert(SDecimal128ToStr(A) = '-123.9385000000000000000');
Assert(TryStrToSDecimal128('0', A) = dceNoError);
Assert(SDecimal128ToWord32(A) = 0);
Assert(TryStrToSDecimal128('-9999999999999999999', A) = dceNoError);
Assert(TryStrToSDecimal128('-10000000000000000000', A) = dceOverflowError);
Assert(TryStrToSDecimal128('-9999999999999999999.99999999999999999995', A) = dceOverflowError);
end;
procedure Test_SHugeDecimal;
var
A, B : SHugeDecimal;
D : HugeDecimal;
begin
SHugeDecimalInit(A);
SHugeDecimalInit(B);
HugeDecimalInit(D);
SHugeDecimalAssignZero(A);
Assert(SHugeDecimalIsZero(A));
Assert(not SHugeDecimalIsOne(A));
Assert(not SHugeDecimalIsMinusOne(A));
Assert(SHugeDecimalToStr(A) = '0');
Assert(SHugeDecimalToWord8(A) = 0);
Assert(SHugeDecimalToWord32(A) = 0);
Assert(SHugeDecimalToInt8(A) = 0);
Assert(SHugeDecimalToInt64(A) = 0);
Assert(SHugeDecimalSign(A) = 0);
Assert(SHugeDecimalFracCompareHalf(A) = -1);
Assert(SHugeDecimalEqualsWord8(A, 0));
Assert(not SHugeDecimalEqualsWord8(A, 1));
Assert(SHugeDecimalCompareWord8(A, 0) = 0);
Assert(SHugeDecimalCompareWord8(A, 1) = -1);
SHugeDecimalAssignOne(A);
Assert(not SHugeDecimalIsZero(A));
Assert(SHugeDecimalIsOne(A));
Assert(not SHugeDecimalIsMinusOne(A));
Assert(SHugeDecimalToStr(A) = '1');
Assert(SHugeDecimalToWord8(A) = 1);
Assert(SHugeDecimalToWord32(A) = 1);
Assert(SHugeDecimalToInt8(A) = 1);
Assert(SHugeDecimalToInt64(A) = 1);
Assert(SHugeDecimalSign(A) = 1);
Assert(SHugeDecimalFracCompareHalf(A) = -1);
Assert(not SHugeDecimalEqualsWord8(A, 0));
Assert(SHugeDecimalEqualsWord8(A, 1));
Assert(SHugeDecimalCompareWord8(A, 0) = 1);
Assert(SHugeDecimalCompareWord8(A, 1) = 0);
Assert(SHugeDecimalCompareWord8(A, 2) = -1);
SHugeDecimalAssignMinusOne(A);
Assert(not SHugeDecimalIsZero(A));
Assert(not SHugeDecimalIsOne(A));
Assert(SHugeDecimalIsMinusOne(A));
Assert(SHugeDecimalToStr(A) = '-1');
Assert(SHugeDecimalToInt8(A) = -1);
Assert(SHugeDecimalToInt64(A) = -1);
Assert(SHugeDecimalSign(A) = -1);
Assert(SHugeDecimalFracCompareHalf(A) = -1);
Assert(not SHugeDecimalEqualsWord8(A, 0));
Assert(not SHugeDecimalEqualsWord8(A, 1));
Assert(SHugeDecimalCompareWord8(A, 0) = -1);
Assert(SHugeDecimalCompareWord8(A, 1) = -1);
SHugeDecimalAssignInt8(A, 0);
Assert(SHugeDecimalIsZero(A));
SHugeDecimalAssignInt8(A, -1);
Assert(SHugeDecimalIsMinusOne(A));
SHugeDecimalAssignInt8(A, 1);
Assert(SHugeDecimalIsOne(A));
SHugeDecimalAssignInt8(A, MinInt8);
Assert(SHugeDecimalToStr(A) = '-128');
Assert(SHugeDecimalToInt8(A) = -128);
Assert(SHugeDecimalToInt64(A) = -128);
Assert(SHugeDecimalSign(A) = -1);
Assert(not SHugeDecimalEqualsWord8(A, 128));
Assert(SHugeDecimalCompareWord8(A, 0) = -1);
SHugeDecimalAssignInt8(A, MaxInt8);
Assert(SHugeDecimalToStr(A) = '127');
Assert(SHugeDecimalToWord8(A) = 127);
Assert(SHugeDecimalToWord32(A) = 127);
Assert(SHugeDecimalToInt8(A) = 127);
Assert(SHugeDecimalToInt64(A) = 127);
Assert(SHugeDecimalSign(A) = 1);
Assert(SHugeDecimalEqualsWord8(A, 127));
Assert(not SHugeDecimalEqualsWord8(A, 255));
Assert(SHugeDecimalCompareWord8(A, 0) = 1);
Assert(SHugeDecimalCompareWord8(A, 127) = 0);
SHugeDecimalAssignInt32(A, MinInt32);
Assert(SHugeDecimalToStr(A) = '-2147483648');
SHugeDecimalAssignInt32(A, MaxInt32);
Assert(SHugeDecimalToStr(A) = '2147483647');
Assert(SHugeDecimalToWord32(A) = 2147483647);
SHugeDecimalAssignInt64(A, MinInt64);
Assert(SHugeDecimalToStr(A) = '-9223372036854775808');
Assert(SHugeDecimalToInt64(A) = MinInt64);
SHugeDecimalAssignInt64(A, MaxInt64);
Assert(SHugeDecimalToStr(A) = '9223372036854775807');
Assert(SHugeDecimalToInt64(A) = MaxInt64);
// Negate
SHugeDecimalAssignZero(A);
SHugeDecimalNegate(A);
Assert(SHugeDecimalToWord32(A) = 0);
SHugeDecimalAssignOne(A);
SHugeDecimalNegate(A);
Assert(SHugeDecimalToInt32(A) = -1);
SHugeDecimalAssignMinusOne(A);
SHugeDecimalNegate(A);
Assert(SHugeDecimalToInt32(A) = 1);
// Abs
SHugeDecimalAssignZero(A);
SHugeDecimalAbsInPlace(A);
Assert(SHugeDecimalToInt32(A) = 0);
SHugeDecimalAssignOne(A);
SHugeDecimalAbsInPlace(A);
Assert(SHugeDecimalToInt32(A) = 1);
SHugeDecimalAssignMinusOne(A);
SHugeDecimalAbsInPlace(A);
Assert(SHugeDecimalToInt32(A) = 1);
// Trunc
SHugeDecimalAssignDecimal32(A, StrToDecimal32('0.2000'));
Assert(SHugeDecimalToStr(A) = '0.2');
SHugeDecimalTrunc(A);
Assert(SHugeDecimalToStr(A) = '0');
SHugeDecimalAssignDecimal32(A, StrToDecimal32('1.2000'));
Assert(SHugeDecimalToStr(A) = '1.2');
SHugeDecimalTrunc(A);
Assert(SHugeDecimalToStr(A) = '1');
SHugeDecimalAssignDecimal32(A, StrToDecimal32('1.9999'));
Assert(SHugeDecimalToStr(A) = '1.9999');
SHugeDecimalTrunc(A);
Assert(SHugeDecimalToStr(A) = '1');
// Round
SHugeDecimalAssignDecimal32(A, StrToDecimal32('0.9999'));
Assert(SHugeDecimalToStr(A) = '0.9999');
Assert(SHugeDecimalFracCompareHalf(A) = 1);
SHugeDecimalRound(A);
Assert(SHugeDecimalToStr(A) = '1');
SHugeDecimalAssignDecimal32(A, StrToDecimal32('0.5000'));
Assert(SHugeDecimalToStr(A) = '0.5');
Assert(SHugeDecimalFracCompareHalf(A) = 0);
SHugeDecimalRound(A);
Assert(SHugeDecimalToStr(A) = '0');
SHugeDecimalAssignDecimal32(A, StrToDecimal32('0.5001'));
Assert(SHugeDecimalToStr(A) = '0.5001');
Assert(SHugeDecimalFracCompareHalf(A) = 1);
SHugeDecimalRound(A);
Assert(SHugeDecimalToStr(A) = '1');
SHugeDecimalAssignDecimal32(A, StrToDecimal32('1.4999'));
Assert(SHugeDecimalToStr(A) = '1.4999');
Assert(SHugeDecimalFracCompareHalf(A) = -1);
SHugeDecimalRound(A);
Assert(SHugeDecimalToStr(A) = '1');
SHugeDecimalAssignDecimal32(A, StrToDecimal32('1.5000'));
Assert(SHugeDecimalToStr(A) = '1.5');
Assert(SHugeDecimalFracCompareHalf(A) = 0);
SHugeDecimalRound(A);
Assert(SHugeDecimalToStr(A) = '2');
// Compare/Equals
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, 0);
Assert(SHugeDecimalCompareSHugeDecimal(A, B) = 1);
Assert(not SHugeDecimalEqualsSHugeDecimal(A, B));
SHugeDecimalAssignInt8(A, 0);
SHugeDecimalAssignInt8(B, 10);
Assert(SHugeDecimalCompareSHugeDecimal(A, B) = -1);
Assert(not SHugeDecimalEqualsSHugeDecimal(A, B));
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, 10);
Assert(SHugeDecimalCompareSHugeDecimal(A, B) = 0);
Assert(SHugeDecimalEqualsSHugeDecimal(A, B));
SHugeDecimalAssignInt8(A, -10);
SHugeDecimalAssignInt8(B, -10);
Assert(SHugeDecimalCompareSHugeDecimal(A, B) = 0);
Assert(SHugeDecimalEqualsSHugeDecimal(A, B));
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, -10);
Assert(SHugeDecimalCompareSHugeDecimal(A, B) = 1);
Assert(not SHugeDecimalEqualsSHugeDecimal(A, B));
SHugeDecimalAssignInt8(A, -10);
SHugeDecimalAssignInt8(B, 10);
Assert(SHugeDecimalCompareSHugeDecimal(A, B) = -1);
Assert(not SHugeDecimalEqualsSHugeDecimal(A, B));
// Compare/Equals
SHugeDecimalAssignInt8(A, 10);
HugeDecimalAssignWord8(D, 0);
Assert(SHugeDecimalCompareHugeDecimal(A, D) = 1);
Assert(not SHugeDecimalEqualsHugeDecimal(A, D));
SHugeDecimalAssignInt8(A, 0);
HugeDecimalAssignWord8(D, 10);
Assert(SHugeDecimalCompareHugeDecimal(A, D) = -1);
Assert(not SHugeDecimalEqualsHugeDecimal(A, D));
SHugeDecimalAssignInt8(A, 10);
HugeDecimalAssignWord8(D, 10);
Assert(SHugeDecimalCompareHugeDecimal(A, D) = 0);
Assert(SHugeDecimalEqualsHugeDecimal(A, D));
SHugeDecimalAssignInt8(A, -10);
HugeDecimalAssignWord8(D, 10);
Assert(SHugeDecimalCompareHugeDecimal(A, D) = -1);
Assert(not SHugeDecimalEqualsHugeDecimal(A, D));
// Add
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, 0);
SHugeDecimalAddSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 10);
SHugeDecimalAssignInt8(A, 0);
SHugeDecimalAssignInt8(B, 10);
SHugeDecimalAddSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 10);
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, 10);
SHugeDecimalAddSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 20);
SHugeDecimalAssignInt8(A, -10);
SHugeDecimalAssignInt8(B, -10);
SHugeDecimalAddSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = -20);
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, -10);
SHugeDecimalAddSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 0);
SHugeDecimalAssignInt8(A, -10);
SHugeDecimalAssignInt8(B, 10);
SHugeDecimalAddSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 0);
// Add
SHugeDecimalAssignInt8(A, 10);
HugeDecimalAssignWord8(D, 0);
SHugeDecimalAddHugeDecimal(A, D);
Assert(SHugeDecimalToInt8(A) = 10);
SHugeDecimalAssignInt8(A, 0);
HugeDecimalAssignWord8(D, 10);
SHugeDecimalAddHugeDecimal(A, D);
Assert(SHugeDecimalToInt8(A) = 10);
SHugeDecimalAssignInt8(A, 10);
HugeDecimalAssignWord8(D, 10);
SHugeDecimalAddHugeDecimal(A, D);
Assert(SHugeDecimalToInt8(A) = 20);
SHugeDecimalAssignInt8(A, -10);
HugeDecimalAssignWord8(D, 10);
SHugeDecimalAddHugeDecimal(A, D);
Assert(SHugeDecimalToInt8(A) = 0);
// Subtract
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, 0);
SHugeDecimalSubtractSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 10);
SHugeDecimalAssignInt8(A, 0);
SHugeDecimalAssignInt8(B, 10);
SHugeDecimalSubtractSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = -10);
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, 10);
SHugeDecimalSubtractSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 0);
SHugeDecimalAssignInt8(A, -10);
SHugeDecimalAssignInt8(B, -10);
SHugeDecimalSubtractSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 0);
SHugeDecimalAssignInt8(A, 10);
SHugeDecimalAssignInt8(B, -10);
SHugeDecimalSubtractSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = 20);
SHugeDecimalAssignInt8(A, -10);
SHugeDecimalAssignInt8(B, 10);
SHugeDecimalSubtractSHugeDecimal(A, B);
Assert(SHugeDecimalToInt8(A) = -20);
// StrToSHugeDecimal
Assert(TryStrToSHugeDecimal('', A) = dceConvertError);
Assert(TryStrToSHugeDecimal('+', A) = dceConvertError);
Assert(TryStrToSHugeDecimal('-', A) = dceConvertError);
Assert(TryStrToSHugeDecimal('--0', A) = dceConvertError);
Assert(TryStrToSHugeDecimal('-.', A) = dceConvertError);
Assert(TryStrToSHugeDecimal(' 0', A) = dceConvertError);
Assert(TryStrToSHugeDecimal('0', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '0');
Assert(SHugeDecimalIsZero(A));
Assert(TryStrToSHugeDecimal('+0', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '0');
Assert(SHugeDecimalIsZero(A));
Assert(TryStrToSHugeDecimal('-0', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '0');
Assert(SHugeDecimalIsZero(A));
Assert(TryStrToSHugeDecimal('1', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '1');
Assert(TryStrToSHugeDecimal('-1', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '-1');
Assert(TryStrToSHugeDecimal('+1', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '1');
Assert(TryStrToSHugeDecimal('-1.23', A) = dceNoError);
Assert(SHugeDecimalToStr(A) = '-1.23');
end;
procedure Test;
begin
SetRoundMode(rmNearest);
Test_Decimal32;
Test_Decimal64;
Test_Decimal128;
Test_HugeDecimal;
Test_SDecimal32;
Test_SDecimal64;
Test_SDecimal128;
Test_SHugeDecimal;
end;
{$ENDIF}
end.