• Welcome to PlanetSquires Forums.
 

CWindow Release Candidate 31

Started by José Roca, August 06, 2017, 02:51:36 PM

Previous topic - Next topic

Johan Klassen

#120
yes that works at least for the values tested, but maybe you will consider the following alternatives for inspiration: A public domain complex math library for Arduino

Paul Squires

All this math is making my head hurt :)
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca


Paul Squires

lol, I consider myself a smart and educated guy, but I had to google quaternions  :)  :)  :)
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#124
Tonight I have been working in the implementation of a currency data type.

' CCur class
' CCUR is a wrapper for the CURRENCY data type. CURRENCY is implemented as an 8-byte
' two's-complement integer value scaled by 10,000. This gives a fixed-point number with
' 15 digits to the left of the decimal point and 4 digits to the right. The CURRENCY data
' type is extremely useful for calculations involving money, or for any fixed-point
' calculations where accuracy is important.
' The CCUR wrapper implements arithmetic, assignment, and comparison operations for this
' fixed-point type, and provides access to the numbers on either side of the decimal point
' in the form of two components: an integer component which stores the value to the left
' of the decimal point, and a fractional component which stores the value to the right of
' the decimal point. The fractional component is stored internally as an integer value
' between -9999 (CY_MIN_FRACTION) and +9999 (CY_MAX_FRACTION). The function GetFraction
' returns a value scaled by a factor of 10000 (CY_SCALE).
' When specifying the integer and fractional components of a CCUR object, remember that
' the fractional component is a number in the range 0 to 9999. This is important when
' dealing with a currency such as the US dollar that expresses amounts using only two
' significant digits after the decimal point. Even though the last two digits are not
' displayed, they must be taken into account.

const CY_MIN_INTEGER   = -922337203685477LL
const CY_MAX_INTEGER   = 922337203685477LL
const CY_MIN_FRACTION  = -9999
const CY_MAX_FRACTION  = 9999
const CY_SCALE         = 10000

Test code:


'#CONSOLE ON
#INCLUDE ONCE "Afx/CCur.inc"
using Afx

DIM c AS CCUR = 12345.1234
print c
c = c + 111.11
print c
c = c - 111.11
print c
c = c * 2
print c
c = c / 2
print c
c += 123
print c
c -= 123
print c
c *= 2.3
print c
c /= 2.3
print c
c = c ^ 2
print c
c = SQR(c)
print c
DIM c2 AS CCUR = c
print c2
DIM c3 AS CCUR = c * 2
print c3
DIM c4 AS CCUR = c3 / 2
print c4
DIM c5 AS CCUR = "1234.789"
print c5
DIM c6 AS CCUR
c6 = "77777.999"
print c6
DIM c7 AS CCUR
c7 = c6
print c7
DIM cl AS CCUR = 3
cl = LOG(cl)
print cl
DIM v AS VARIANT = cl
dim cv AS CCUR = v
print cv
print "--------------"
DIM cx AS CCUR
FOR i AS LONG = 1 TO 1000000
   cx += 0.0001
NEXT
PRINT "0.0001 added 1,000,000 times = "; cx

PRINT
PRINT "Press any key..."
SLEEP


Petrus Vorster

Quotelol, I consider myself a smart and educated guy, but I had to google quaternions  :)  :)  :)

O dear heavens. This is how i feel amongst you two....
-Regards
Peter

José Roca

The currency data type was one of the few things supported by PowerBasic missing in the framework. No more. PowerBasic also supports CURX, that uses two decimals instead of four, but this is not a standard data type, which limits is usefulness because it can't be used with COM or databases, unless you first convert it to currency, losing the advantage of having two additional integer digits.

Other useful data types to consider are BigInteger and Decimal.

José Roca

#127
Modified the constructors that accept integer numeric values. They were setting the fractional part of the complex numbers instead of the integer part.

José Roca

#128
The attached zip file contains three include files:

AfxGslComplex.inc

This was my original attempt, using code from the GNU Scientific Library.

AfxComplex.inc

Because GSL has a restrictive GPL license, I reworked the functions to use Microsoft .NET code, that has a more permissive MIT license.

CComplex.inc

This one provides compound dotted syntax. However, you must be aware that the compound syntax can confuse programmers only used to standard functions.

Using the flat API of AfxComplex.inc you can nest functions this way:


DIM cx AS CCOmplex = CComplex(-2, 1)
cx = Afx.CArcCosH(Afx.CCosH(Afx.CSin(cx))


It evaluates from right to left. That is, Afx.CSin(cx) is the first function executed.


temp <CComplex> = Afx.CSin(cx)
temp2 <CComplex> = Afx.CCosH(temp CComplex)
temp3 <CComplex> = Afx.CArcCosH(temp2 CComplex)
cx = temp3 CComplex


The temporary CComplex classes are created and destroyed by the compiler.

The compound dotted syntax evaluates the instructions from left to right.


DIM cx AS CComplex = CComplex(-2, 1)
cx = cx.CSinH.CCosH.CArcCosH


It is equivalent to:


temp <CComplex> = cx.CSin
temp2 <CComplex> temp.CCosH
temp3 <CComplex> temp2.CArcCosH
cx = temp3


They do the same calculation, but the syntax is different.

Also code like this, using the flat API...


DIM cx AS CComplex = CComplex(-2, 1)
DIM i AS CComplex = CComplex(0, 1)
cx = Afx.CArcSinH(cx / i))


becomes


DIM cx AS CComplex = CComplex(-2, 1)
DIM i AS CComplex = CComplex(0, 1)
cx = (cx / i).CArcSinH


José Roca

#129
CCUR class

Modified the operator that casts it to a string to always return four decimals.


' ========================================================================================
PRIVATE OPERATOR CCur.CAST () AS STRING
   DIM s AS STRING = STR(m_cur.int64 / CY_SCALE)
   DIM p AS LONG = INSTR(s, ".")
   DIM dec AS STRING
   IF p THEN
      dec = MID(s + "0000", p + 1, 4)
      s = LEFT(s, p) & dec
   END IF
   IF s = "0" THEN s = "0.0000"
   OPERATOR = s
END OPERATOR
' ========================================================================================


There is not need to implement ABS, FIX or INT because the FreeBasic ones can be used.

José Roca

CCUR

Added the ToVar method to return the currency value as a VT_CY variant.

This allows to assign a CCUR to a CVAR:


DIM c AS CCUR = 12345.1234
DIM cv AS CVAR = c.ToVar


Alternate way:


DIM v AS VARIANT = c
cv = v


AfcCOM.inc

Modified the AfxVarToStr function to support VT_CY variants.


      CASE VT_CY   ' // Currency
         DIM s AS STRING = STR(pvarIn->cyVal.int64 / 10000)
         DIM p AS LONG = INSTR(s, ".")
         DIM dec AS STRING
         IF p THEN
            dec = MID(s + "0000", p + 1, 4)
            s = LEFT(s, p) & dec
         END IF
         IF s = "0" THEN s = "0.0000"
         RETURN s


José Roca

I have opened an account in GitHub where I'm uploading the changes.

See: https://github.com/JoseRoca/WinFBX

Paul Squires

Quote from: Jose Roca on September 19, 2017, 04:45:32 AM
I have opened an account in GitHub where I'm uploading the changes.

See: https://github.com/JoseRoca/WinFBX

Excellent! Are you using the GitHub Desktop client? You said it did not scale well with the high dpi.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#133
Quote from: Paul Squires on September 19, 2017, 01:10:04 PM
Quote from: Jose Roca on September 19, 2017, 04:45:32 AM
I have opened an account in GitHub where I'm uploading the changes.

See: https://github.com/JoseRoca/WinFBX

Excellent! Are you using the GitHub Desktop client? You said it did not scale well with the high dpi.


No. It is unusable at 192 dpi. It scales without any regard about the dimenensions of the monitor. It is like some programs that display a popup dialog that exceeds the height of the monitor when scaled and the OK and Cancel buttons became unreachable. This tool both exceeds the width and the height.

Using the web GUI I can do almost anything, except deleting a folder (maybe deleting all the files one by one will make the folder disapperar?).

José Roca

I'm working in a new data type, DECIMAL.

Holds signed 128-bit (16-byte) values representing 96-bit (12-byte) integer numbers scaled by a variable power of 10. The scaling factor specifies the number of digits to the right of the decimal point; it ranges from 0 through 28. With a scale of 0 (no decimal places), the largest possible value is +/-79,228,162,514,264,337,593,543,950,335 (+/-7.9228162514264337593543950335E+28). With 28 decimal places, the largest value is +/-7.9228162514264337593543950335, and the smallest nonzero value is +/-0.0000000000000000000000000001 (+/-1E-28).

In my implementation, the scale is dynamic, dictated by the number of decimal places.


DIM dec AS CDEC = 12345.12
print dec
print "scale: ", dec.m_dec.scale  ' --> scale = 2
dec += dec + 11.1111
print dec
print "new scale: ", dec.m_dec.scale  ' --> scale = 4