## CInt96 - 96 bit integer data type

User projects written in or related to FreeBASIC.
Josep Roca
Posts: 415
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

### CInt96 - 96 bit integer data type

This is my attempt to implement a 96-bit data type for Free Basic. It uses a DECIMAL structure with a scale of 0 to store the values. It supports up to 29 significant digits and can represent values in excess of 7.9228 x 10^28. The largest possible value is +/-79,228,162,514,264,337,593,543,950,335.

Thanks to the overloading feature of Free Basic, you can use it as the other available numeric data types, e.g.

Code: Select all

`DIM int96 AS CInt96 = 1234567890int96 = int96 + 111int96 = int96 - 111int96 = int96 * 2int96 = int96 / 2int96 += 123int96 -= 123int96 *= 2int96 /= 2`

Because the bigger numeric variable natively supported by Free Basic is a long integer, if we want to set bigger values we need to use strings, e.g.

Code: Select all

`DIM int96 AS CInt96 = "79228162514264337593543950335"`

Documentation: https://github.com/JoseRoca/WinFBX/blob ... 20Class.md

BTW my WinFBX framework implements other data types such Currency, Decimal, Variant, Safe Array and Dictionary (associative arrays), but I'm posting this one here because it doesn't need the framework.

Save the following code as CInt96.bi (or CInt96.inc or whatever you like). To use it, just use #include "CInt96.bi".

Code: Select all

`' ########################################################################################' Microsoft Windows' File: CInt.inc' Contents: 96-bit (12 bytes) integer data type.' Compiler: FreeBasic 32 & 64-bit' Written in 2018 by José Roca. Freeware. Use at your own risk.' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.' #########################################################################################pragma once#include once "windows.bi"#include once "win/ole2.bi"' ========================================================================================' CInt96 class' ========================================================================================TYPE CInt96Public:   m_int96 AS DECIMAL   ' // The underlying DECIMAL structurePublic:   DECLARE CONSTRUCTOR   DECLARE CONSTRUCTOR (BYREF cSrc AS CInt96)   DECLARE CONSTRUCTOR (BYREF decSrc AS DECIMAL)   DECLARE CONSTRUCTOR (BYVAL nInteger AS LONGINT)   DECLARE CONSTRUCTOR (BYVAL nUInteger AS ULONGINT)   DECLARE CONSTRUCTOR (BYREF wszSrc AS WSTRING)   DECLARE DESTRUCTOR   DECLARE OPERATOR LET (BYREF cSrc AS CInt96)   DECLARE OPERATOR LET (BYVAL nInteger AS LONGINT)   DECLARE OPERATOR LET (BYVAL nUInteger AS ULONGINT)   DECLARE OPERATOR LET (BYREF wszSrc AS WSTRING)   DECLARE OPERATOR += (BYREF int96 AS CInt96)   DECLARE OPERATOR += (BYVAL nValue AS LONGINT)   DECLARE OPERATOR += (BYVAL nValue AS ULONGINT)   DECLARE OPERATOR += (BYREF wszValue AS WSTRING)   DECLARE OPERATOR -= (BYREF int96 AS CInt96)   DECLARE OPERATOR -= (BYVAL nValue AS LONGINT)   DECLARE OPERATOR -= (BYVAL nValue AS ULONGINT)   DECLARE OPERATOR -= (BYREF wszValue AS WSTRING)   DECLARE OPERATOR *= (BYREF int96 AS CInt96)   DECLARE OPERATOR *= (BYVAL nValue AS LONGINT)   DECLARE OPERATOR *= (BYVAL nValue AS ULONGINT)   DECLARE OPERATOR *= (BYREF wszValue AS WSTRING)   DECLARE OPERATOR /= (BYREF cOperand AS CInt96)   DECLARE OPERATOR /= (BYVAL nValue AS LONGINT)   DECLARE OPERATOR /= (BYVAL nValue AS ULONGINT)   DECLARE OPERATOR /= (BYREF wszValue AS WSTRING)   DECLARE OPERATOR CAST () AS BYTE   DECLARE OPERATOR CAST () AS UBYTE   DECLARE OPERATOR CAST () AS SHORT   DECLARE OPERATOR CAST () AS USHORT   DECLARE OPERATOR CAST () AS LONG   DECLARE OPERATOR CAST () AS ULONG   DECLARE OPERATOR CAST () AS LONGINT   DECLARE OPERATOR CAST () AS ULONGINT   DECLARE OPERATOR CAST () AS SINGLE   DECLARE OPERATOR CAST () AS DOUBLE   DECLARE OPERATOR CAST () AS CURRENCY   DECLARE OPERATOR CAST () AS VARIANT   DECLARE OPERATOR CAST () AS STRING   DECLARE FUNCTION Abs_ () AS CInt96   DECLARE FUNCTION ToVar () AS VARIANT   DECLARE FUNCTION Sign () AS UBYTE   DECLARE FUNCTION IsSigned () AS BOOLEAN   DECLARE FUNCTION IsUnsigned () AS BOOLEANEND TYPE' ========================================================================================' ========================================================================================' CInt96 constructors' ========================================================================================PRIVATE CONSTRUCTOR CInt96END CONSTRUCTOR' ========================================================================================' ========================================================================================PRIVATE CONSTRUCTOR CInt96 (BYREF cSrc AS CInt96)   m_int96 = cSrc.m_int96END CONSTRUCTOR' ========================================================================================' ========================================================================================PRIVATE CONSTRUCTOR CInt96 (BYREF decSrc AS DECIMAL)   IF decSrc.Scale THEN SetLastError(VarDecInt(@decSrc, @m_int96)) ELSE m_int96 = decSrcEND CONSTRUCTOR' ========================================================================================' ========================================================================================PRIVATE CONSTRUCTOR CInt96 (BYVAL nInteger AS LONGINT)   SetLastError(VarDecFromI8(nInteger, @m_int96))END CONSTRUCTOR' ========================================================================================' ========================================================================================PRIVATE CONSTRUCTOR CInt96 (BYVAL nUInteger AS ULONGINT)   SetLastError(VarDecFromUI8(nuInteger, @m_int96))END CONSTRUCTOR' ========================================================================================' ========================================================================================PRIVATE CONSTRUCTOR CInt96 (BYREF wszSrc AS WSTRING)   IF INSTR(wszSrc, ".") THEN SetLastError(E_INVALIDARG) : EXIT CONSTRUCTOR   SetLastError(VarDecFromStr(@wszSrc, 0, 0, @m_int96))END CONSTRUCTOR' ========================================================================================' ========================================================================================' CInt96 destructor' ========================================================================================PRIVATE DESTRUCTOR CInt96END DESTRUCTOR' ========================================================================================' ========================================================================================' Assignment operators' ========================================================================================PRIVATE OPERATOR CInt96.LET (BYREF cSrc AS CInt96)   m_int96 = cSrc.m_int96END OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.LET (BYVAL nInteger AS LONGINT)   SetLastError(VarDecFromI8(nInteger, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.LET (BYVAL nUInteger AS ULONGINT)   SetLastError(VarDecFromUI8(nuInteger, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.LET (BYREF wszSrc AS WSTRING)   IF INSTR(wszSrc, ".") THEN SetLastError(E_INVALIDARG) : EXIT OPERATOR   SetLastError(VarDecFromStr(@wszSrc, 0, 0, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' Comparison operators.' ========================================================================================' *** Ok ***PRIVATE OPERATOR = (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS BOOLEAN   RETURN (VarDecCmp(@int961.m_int96, @int962.m_int96) = VARCMP_EQ)END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR <> (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS BOOLEAN   RETURN (VarDecCmp(@int961.m_int96, @int962.m_int96) <> VARCMP_EQ)END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR < (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS BOOLEAN   RETURN (VarDecCmp(@int961.m_int96, @int962.m_int96) = VARCMP_LT)END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR > (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS BOOLEAN   RETURN (VarDecCmp(@int961.m_int96, @int962.m_int96) = VARCMP_GT)END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR <= (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS BOOLEAN   DIM hr AS HRESULT = VarDecCmp(@int961.m_int96, @int962.m_int96)   RETURN (hr = VARCMP_LT) OR (hr = VARCMP_EQ)END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR >= (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS BOOLEAN   DIM hr AS HRESULT = VarDecCmp(@int961.m_int96, @int962.m_int96)   RETURN (hr = VARCMP_GT) OR (hr = VARCMP_EQ)END OPERATOR' ========================================================================================' ========================================================================================' Math operators.' ========================================================================================' *** Ok ***PRIVATE OPERATOR + (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM hr AS LONG = VarDecAdd(@int961.m_int96, @int962.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int961   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR + (BYREF int96Src AS CInt96, BYREF wszValue AS WSTRING) AS CInt96   DIM d AS DECIMAL   DIM dec AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : RETURN int96Src   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecAdd(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue is greater that -9223372036854775808 or it will be truncated.' For values smaller than -9223372036854775808 use a string.' ========================================================================================PRIVATE OPERATOR + (BYREF int96Src AS CInt96, BYVAL nValue AS LONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecAdd(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR + (BYVAL nValue AS LONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   hr = VarDecAdd(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue does not exceed 18446744073709551615 or it will be truncated.' For values greater than 18446744073709551615 use a string.' ========================================================================================PRIVATE OPERATOR + (BYREF int96Src AS CInt96, BYVAL nValue AS ULONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecAdd(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR + (BYVAL nValue AS ULONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   hr = VarDecAdd(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.+= (BYREF int96Src AS CInt96)    SetLastError(VarDecAdd(@m_int96, @int96Src.m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue is greater that -9223372036854775808 or it will be truncated.' For values smaller than -9223372036854775808 use a string.PRIVATE OPERATOR CInt96.+= (BYVAL nValue AS LONGINT)   DIM dec AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nValue, @dec)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecAdd(@m_int96, @dec, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue does not exceed 18446744073709551615 or it will be truncated.' For values greater than 18446744073709551615 use a string.PRIVATE OPERATOR CInt96.+= (BYVAL nValue AS ULONGINT)   DIM dec AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nValue, @dec)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecAdd(@m_int96, @dec, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.+= (BYREF wszValue AS WSTRING)   DIM d AS DECIMAL   DIM dec AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : EXIT OPERATOR   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecAdd(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR - (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM hr AS LONG = VarDecSub(@int961.m_int96, @int962.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int961   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue is greater that -9223372036854775808 or it will be truncated.' For values smaller than -9223372036854775808 use a string.PRIVATE OPERATOR - (BYREF int96Src AS CInt96, BYVAL nValue AS LONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecSub(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue does not exceed 18446744073709551615 or it will be truncated.' For values greater than 18446744073709551615 use a string.PRIVATE OPERATOR - (BYREF int96Src AS CInt96, BYVAL nValue AS ULONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecSub(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue is greater that -9223372036854775808 or it will be truncated.' For values smaller than -9223372036854775808 use a string.PRIVATE OPERATOR - (BYVAL nValue AS LONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   hr = VarDecSub(@d, @int96Src.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue does not exceed 18446744073709551615 or it will be truncated.' For values greater than 18446744073709551615 use a string.PRIVATE OPERATOR - (BYVAL nValue AS ULONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   hr = VarDecSub(@d, @int96Src.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nValue   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR - (BYREF int96Src AS CInt96, BYREF wszValue AS WSTRING) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : RETURN int96Src   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF VarDecSub(@int96Src.m_int96, @d, @dec) <> S_OK THEN RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.-= (BYREF int96Src AS CInt96)   SetLastError(VarDecSub(@m_int96, @int96Src.m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue does not exceed 18446744073709551615 or it will be truncated.' For values greater than 18446744073709551615 use a string.PRIVATE OPERATOR CInt96.-= (BYVAL nValue AS LONGINT)   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecSub(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***' Make sure that nValue does not exceed 18446744073709551615 or it will be truncated.' For values greater than 18446744073709551615 use a string.PRIVATE OPERATOR CInt96.-= (BYVAL nValue AS ULONGINT)   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nValue, @d)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecSub(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.-= (BYREF wszValue AS WSTRING)   DIM d AS DECIMAL   DIM dec AS DECIMAL   IF INSTR(wszValue, ".") THEN EXIT OPERATOR   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecSub(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR - (BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   SetLastError(VarDecNeg(@int96Src.m_int96, @dec))   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR * (BYREF int961 AS CInt96, BYREF int962 AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM hr AS LONG = VarDecMul(@int961.m_int96, @int962.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int961   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR * (BYVAL nOperand AS LONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   hr = VarDecMul(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR * (BYREF int96Src AS CInt96, BYVAL nOperand AS LONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecMul(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR * (BYREF int96Src AS CInt96, BYVAL nOperand AS ULONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr  AS LONG = VarDecFromUI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecMul(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR * (BYVAL nOperand AS ULONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   hr = VarDecMul(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR * (BYREF int96Src AS CInt96, BYREF wszValue AS WSTRING) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : RETURN int96Src   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecMul(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.*= (BYREF int96Src AS CInt96)   SetLasterror(VarDecMul(@m_int96, @int96Src.m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.*= (BYVAL nOperand AS LONGINT)   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nOperand, @d)   IF hr THEN SetLastError(hr) ELSE SetLastError(VarDecMul(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.*= (BYVAL nOperand AS ULONGINT)   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nOperand, @d)   IF hr <> S_OK THEN SetLasterror(hr) ELSE SetLastError(VarDecMul(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96.*= (BYREF wszValue AS WSTRING)   DIM d AS DECIMAL   DIM dec AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : EXIT OPERATOR   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) ELSE SetLastError(VarDecMul(@m_int96, @d, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR / (BYREF int96Src AS CInt96, BYREF cOperand AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM hr AS LONG = VarDecDiv(@int96Src.m_int96, @cOperand.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   IF dec.Scale THEN hr = VarDecInt(@dec, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR / (BYREF int96Src AS CInt96, BYVAL nOperand AS LONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nOperand, @d)   hr = VarDecDiv(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   IF dec.Scale THEN hr = VarDecInt(@dec, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR / (BYVAL nOperand AS LONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nOperand, @d)   hr = VarDecDiv(@d, @int96Src.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   IF dec.Scale THEN hr = VarDecInt(@dec, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR / (BYREF int96Src AS CInt96, BYVAL nOperand AS ULONGINT) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nOperand, @d)   hr = VarDecDiv(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   IF dec.Scale THEN hr = VarDecInt(@dec, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR / (BYVAL nOperand AS ULONGINT, BYREF int96Src AS CInt96) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   hr = VarDecDiv(@d, @int96Src.m_int96, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   IF dec.Scale THEN hr = VarDecInt(@dec, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN nOperand   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR / (BYREF int96Src AS CInt96, BYREF wszValue AS WSTRING) AS CInt96   DIM dec AS DECIMAL   DIM d AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : RETURN int96Src   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   hr = VarDecDiv(@int96Src.m_int96, @d, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   IF dec.Scale THEN hr = VarDecInt(@dec, @dec)   IF hr <> S_OK THEN SetLastError(hr) : RETURN int96Src   RETURN decEND OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96./= (BYREF cOperand AS CInt96)   DIM hr AS LONG = VarDecDiv(@m_int96, @cOperand.m_int96, @m_int96)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   IF m_int96.Scale THEN SetLastError(VarDecInt(@m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96./= (BYVAL nOperand AS LONGINT)   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   hr = VarDecDiv(@m_int96, @d, @m_int96)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   IF m_int96.Scale THEN SetLastError(VarDecInt(@m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96./= (BYVAL nOperand AS ULONGINT)   DIM d AS DECIMAL   DIM hr AS LONG = VarDecFromUI8(nOperand, @d)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   hr = VarDecDiv(@m_int96, @d, @m_int96)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   IF m_int96.Scale THEN SetLastError(VarDecInt(@m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' *** Ok ***PRIVATE OPERATOR CInt96./= (BYREF wszValue AS WSTRING)   DIM d AS DECIMAL   DIM dec AS DECIMAL   IF INSTR(wszValue, ".") THEN SetLastError(E_INVALIDARG) : EXIT OPERATOR   DIM hr AS LONG = VarDecFromStr(@wszValue, 0, 0, @d)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   hr = VarDecDiv(@m_int96, @d, @m_int96)   IF hr <> S_OK THEN SetLastError(hr) : EXIT OPERATOR   IF m_int96.Scale THEN SetLastError(VarDecInt(@m_int96, @m_int96))END OPERATOR' ========================================================================================' ========================================================================================' Cast operators.' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS BYTE   DIM nValue AS BYTE   SetLastError(VarI1FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS UBYTE   DIM nValue AS UBYTE   SetLastError(VarUI1FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS SHORT   DIM nValue AS SHORT   SetLastError(VarI2FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS USHORT   DIM nValue AS USHORT   SetLastError(VarUI2FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS LONG   DIM nValue AS LONG   SetLastError(VarI4FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS ULONG   DIM nValue AS ULONG   SetLastError(VarUI4FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS LONGINT   DIM nValue AS LONGINT   SetLastError(VarI8FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS ULONGINT   DIM nValue AS LONGINT   SetLastError(VarUI8FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS SINGLE   DIM nValue AS SINGLE   SetLastError(VarR4FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS DOUBLE   DIM nValue AS DOUBLE   SetLastError(VarR8FromDec(@m_int96, @nValue))   OPERATOR = nValueEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS CURRENCY   DIM cy AS CURRENCY   SetLastError(VarCyFromDec(@m_int96, @cy))   OPERATOR = cyEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS VARIANT   DIM v AS VARIANT   v.vt = VT_DECIMAL   v.decVal = m_int96   RETURN vEND OPERATOR' ========================================================================================' ========================================================================================PRIVATE OPERATOR CInt96.CAST () AS STRING   DIM bstrOut AS BSTR   VarBstrFromDec(@m_int96, 0, 0, @bstrOut)   DIM s AS STRING = *cast(WSTRING PTR, bstrOut)   SysFreeString(bstrOut)   OPERATOR = sEND OPERATOR' ========================================================================================' ========================================================================================' Returns the address of the underlying decimal value.' ========================================================================================PRIVATE OPERATOR * (BYREF int96 AS CInt96) AS DECIMAL PTR   OPERATOR = VARPTR(int96.m_int96)END OPERATOR' ========================================================================================' ========================================================================================' Retrieves the absolute value of a CInt96 data type.' ========================================================================================PRIVATE FUNCTION CInt96.Abs_ () AS CInt96   DIM dec AS DECIMAL   SetLastError(VarDecAbs(@m_int96, @dec))   RETURN decEND FUNCTION' ========================================================================================' ========================================================================================' Converts the currency to a VT_CY variant.' To allow to assign the decimal to a CVAR variable' DIM dec AS CInt96 = 12345.1234' DIM cv AS CVAR = dec.ToVar' ========================================================================================PRIVATE FUNCTION CInt96.ToVar () AS VARIANT   DIM v AS VARIANT   v.vt = VT_DECIMAL   v.decVal = m_int96   RETURN vEND FUNCTION' ========================================================================================' ========================================================================================' Returns the sign of this decimal number.' Returns 0 if it is not signed of &h80 (128) if it is signed.' ========================================================================================PRIVATE FUNCTION CInt96.Sign () AS UBYTE   RETURN m_int96.signEND FUNCTION' ========================================================================================' ========================================================================================' Returns true if this number is signed or false otherwise.' ========================================================================================PRIVATE FUNCTION CInt96.IsSigned () AS BOOLEAN   IF m_int96.sign THEN RETURN TRUE ELSE RETURN FALSEEND FUNCTION' ========================================================================================' ========================================================================================' Returns true if this number is unsigned or false otherwise.' ========================================================================================PRIVATE FUNCTION CInt96.IsUnsigned () AS BOOLEAN   IF m_int96.sign = 0 THEN RETURN TRUE ELSE RETURN FALSEEND FUNCTION' ========================================================================================`
Last edited by Josep Roca on Sep 18, 2018 4:45, edited 1 time in total.
Posts: 1284
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: CInt96 - 96 bit integer dta type

Why 96 bit and not 128 bit?
For scientific calculations the maximum is a bit limited. It can contain avogrado's constant, but not the mass of the sun in kg.
Josep Roca
Posts: 415
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

### Re: CInt96 - 96 bit integer dta type

Because the Windows API functions that I have used don't allow more. The DECIMAL structure uses 12 bytes to store the number, an UBYTE for the sign and another UBYTE for the scale.

Code: Select all

`type tagDEC   wReserved as USHORT   union      type         scale as UBYTE         sign as UBYTE      end type      signscale as USHORT   end union   Hi32 as ULONG   union      type         Lo32 as ULONG         Mid32 as ULONG      end type      Lo64 as ULONGLONG   end unionend typetype DECIMAL as tagDEC`
deltarho[1859]
Posts: 1739
Joined: Jan 02, 2017 0:34
Location: UK

### Re: CInt96 - 96 bit integer dta type

Very impressive.

Code: Select all

`#Include "cint.bas"Dim big as Cint96big = 9223372036854775807 ' Max Longint valuebig *= 7Print bigSleep' Gives 64563604257983430649`

José are these early days for this project? I was thinking of the bitwise operations, shr and so on.
Josep Roca
Posts: 415
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

### Re: CInt96 - 96 bit integer dta type

I have implemented all I can. If somebody is able to overload the bitwise operators to work with these big numbers it will be a very welcome addition. Arithmetic shift is no my speciality.
deltarho[1859]
Posts: 1739
Joined: Jan 02, 2017 0:34
Location: UK

### Re: CInt96 - 96 bit integer dta type

Josep Roca wrote:it will be a very welcome addition

It would indeed. Any takers?
Josep Roca
Posts: 415
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

### Re: CInt96 - 96 bit integer dta type

I will experiment to see if I can implement ^, AND, OR, XOR, EQV, IMP and MOD. I have had a crazy idea that maybe will work. SHR and SHL are beyond my knowledge.
srvaldez
Posts: 1879
Joined: Sep 25, 2005 21:54

### Re: CInt96 - 96 bit integer dta type

for anyone interested, the Decimal type is defined in wtypes.bi, for convenience I paste the definition below

Code: Select all

`type tagDEC   wReserved as USHORT   union      type         scale as UBYTE         sign as UBYTE      end type      signscale as USHORT   end union   Hi32 as ULONG   union      type         Lo32 as ULONG         Mid32 as ULONG      end type      Lo64 as ULONGLONG   end unionend typetype DECIMAL as tagDEC`

type LongLong is 64-bit or LongInt
so if you have

Code: Select all

`#Include "cint.bas"Dim big as Cint96big = 9223372036854775807 ' Max Longint valuebig *= 7Print bigprint "big.scale = ";big.m_int96.scale      ''Ubyteprint "big.sign = ";big.m_int96.sign         ''Ubyteprint "big.signscale = ";big.m_int96.signscale   ''Ushortprint "big.Hi32 = ";big.m_int96.Hi32         ''Ulongprint "big.Mid32 = ";big.m_int96.Mid32      ''Ulongprint "big.Lo64 = ";big.m_int96.Lo64         ''UlongIntSleep`

knowing how to access the Decimal components, it should be straightforward to implement the desired bit functions
deltarho[1859]
Posts: 1739
Joined: Jan 02, 2017 0:34
Location: UK

### Re: CInt96 - 96 bit integer dta type

@srvaldez

I was going to put you forward as one of the takers but thought would be a bit of a cheek. <smile>
srvaldez
Posts: 1879
Joined: Sep 25, 2005 21:54

### Re: CInt96 - 96 bit integer dta type

@deltarho[1859]
to shift a dec value by 1 should be straightforward, it would be something like this
not tested

Code: Select all

`Dim as Cint96 big, tmpDim carry as ulongcarry=bit( big.m_int96.Lo64, 63 )tmp.m_int96.Lo64 = big.m_int96.Lo64 shl 1tmp.m_int96.Hi32 = (big.m_int96.Hi32 shl 1) or carry`

I am not sure that's right but it should be something like that, it's of course more complicated if you want to shift by more than 1
to shift right, you do something like the following
not tested

Code: Select all

`Dim as Cint96 big, tmpDim carry as ulongcarry=bit( big.Hi32, 0 )tmp.Hi32 = big.m_int96.Hi32 shr 1tmp.m_int96.Lo64  = big.m_int96.Lo64  shr 1if carry then   tmp.m_int96.Lo64 or=&h8000000000000000ULLend if`
deltarho[1859]
Posts: 1739
Joined: Jan 02, 2017 0:34
Location: UK

### Re: CInt96 - 96 bit integer dta type

Hi32 is not mentioned in Cint.
Josep Roca
Posts: 415
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

### Re: CInt96 - 96 bit integer dta type

Hi32 is not a datatype but the name of a member of the DECIMAL structure and is an ULONG.

BTW my crazy idea does not work. The API functions involved overflow with these big numbers.
srvaldez
Posts: 1879
Joined: Sep 25, 2005 21:54

### Re: CInt96 - 96 bit integer dta type

with the help of stack overflow here's the shift left function, it certainly needs to be optimized but am under the weather and not up to par
the right shift function should be similar
https://stackoverflow.com/questions/599 ... bit-number

Code: Select all

`function shift_left96(byval n as CInt96, byval k as long) as CInt96   dim as ulong a, b, c   a=n.m_int96.Hi32   b=n.m_int96.Mid32   c=(n.m_int96.Lo64 shl 32 ) shr 32   if k<=96 then      if k>=32 then         a=b         b=c         c=0         n.m_int96.Hi32=a         n.m_int96.Lo64=c         n.m_int96.Mid32=b         return shift_left96(n,k-32)      else         if k=0 then            return n         else            a=(a shl k) or (b shr (32 - k))            b = (b shl k) or (c shr (32 - k))            c = c shl k                        n.m_int96.Hi32=a            n.m_int96.Lo64=c            n.m_int96.Mid32=b         end if      end if   end if   return nend function`

test

Code: Select all

`#include "CInt96.inc"DIM AS CInt96 big=8for k as long=1 to 92   print  k,shift_left96( big,k)next`

shift right

Code: Select all

`function shift_right96(byval n as CInt96, byval k as long) as CInt96   dim as ulong a, b, c   a=n.m_int96.Hi32   b=n.m_int96.Mid32   c=(n.m_int96.Lo64 shl 32 ) shr 32   if k<=96 then      if k>=32 then         c = b         b = a         a = 0         n.m_int96.Hi32=a         n.m_int96.Lo64=c         n.m_int96.Mid32=b         return shift_right96(n,k-32)      else         if k=0 then            return n         else            c = (b shl (32-k)) or (c shr k)            b = (a shl (32-k)) or (b shr k)            a = a shr k                        n.m_int96.Hi32=a            n.m_int96.Lo64=c            n.m_int96.Mid32=b         end if      end if   end if   return nend function`
fxm
Posts: 8892
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: CInt96 - 96 bit integer dta type

About your previous remark but now suppressed (code works with "Return' but not with 'Function ='):
- 'Return' calls the copy-constructor while 'Function =' calls the let-operator but as the two procedures have the same code, so the problem is not coming for here!
- The other difference between 'Return' and 'Function' is that 'Return' exits the procedure but not 'Function ='.
Therefore you must add 'exit function' after the first two 'Function =' (the last being the final instruction):

Code: Select all

`function shift_left96(byval n as CInt96, byval k as long) as CInt96   dim as ulong a, b, c   a=n.m_int96.Hi32   b=n.m_int96.Mid32   c=(n.m_int96.Lo64 shl 32 ) shr 32   if k<=96 then      if k>=32 then         a=b         b=c         c=0         n.m_int96.Hi32=a         n.m_int96.Lo64=c         n.m_int96.Mid32=b         function = shift_left96(n,k-32)         exit function      else         if k=0 then            function = n            exit function         else            a=(a shl k) or (b shr (32 - k))            b = (b shl k) or (c shr (32 - k))            c = c shl k                        n.m_int96.Hi32=a            n.m_int96.Lo64=c            n.m_int96.Mid32=b         end if      end if   end if   function = nend function`
srvaldez
Posts: 1879
Joined: Sep 25, 2005 21:54

### Re: CInt96 - 96 bit integer dta type

thank you fxm for the info, much appreciated :-)
like I mentioned, am not feeling well and my poor brain is barely functioning hence my coding blunders.