12640 lines
353 KiB
ObjectPascal
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.
|
|
|