fpIsItSquare (Fp plugin) does not work

Hi all,

Does anyone use Fp plugin (originally Bob Delaney, now Einhugur) and mainly its BigInteger function fpIsItSquare?
In a simple project, I’m trying this function and my App (IDE or Compiled) crashes when the value is not a perfect square, whereas all is Ok when it is and the square root is correctly returned.

Here is the very simple code, in a PushButton:

Blockquote
Dim Bsq, NSquare , Temp As BigInteger
Bsq=New BigInteger(“65536”)
Do
NSquare=0
TextArea1.Text=Str(NSquare)+" - “+Str(Bsq)
Try
If fpIsItSquare(NSquare, Bsq)=True Then Exit Do
Catch err
TextArea1.Text=err.Message
End Try
Bsq=Bsq+1
Loop
TextArea1.Text=Str(NSquare)+” - "+Str(Bsq)
Blockquote

With “65536” value, I’m getting “256” as expected result.
With “65535” or any other value not a perfect square, the App crashes on fpIsItSquare function and no error is catched.

Any suggestion or idea welcome.
I will sent this post to Einhugur’s support, in addition.

TIA

Sorry, I forgot that:
iMac Intel, Mac OS Sonoma 14.4.1 French language
Xojo 2024r1.1
Fp plugin 12.5.1 (last Einhugur release)

Its a bug in the original’s authors BigInteger And operator that causes it.

Dim Bsq, NSquare , Temp As BigInteger

Bsq=New BigInteger("65535")

Bsq = Bsq and 5

This reproduces the crash in easier way.

I do not know though how to fix his code since I do not understand his deeper math code well.

I think it happens in here but I dont see anything obvious that could cause crash there, unless the issue goes deeper into the twosComplement or the mbNormalize there I do not really know:

// does bit by bit AND of x with y and returns resultant mb; we ignore signs so resultant>=0
// the number of bits starting with the leading 1 is always the same or less than the equivalent in the smaller of (x, y)
mb mbAnd(const mb& x, const mb& y)
{
	INT32		i, m, numBlocks;
	mb			xx, yy, z;
	
	if(x.n==0 || y.n==0)
	{	
		z = 0;
		return z;
	}
	
	numBlocks = Max(abs(x.n), abs(y.n));
	
	if(x.n<0)
		xx = twosComplement(x, numBlocks);
	else
	{
		xx = x;
	}
	
	if(y.n<0)
		yy = twosComplement(y, numBlocks);
	else
	{
		yy = y;
	}
	
	// find minimum number of blocks
	m = Min(abs(xx.n), abs(yy.n));
	z.n = z.nn = m;
	z.b = (UINT32*)malloc(m*sizeof(UINT32));
	for(i=0;i<m;i++)
	{
		z.b[i] = (xx.b[i] & yy.b[i]);
	}
	
	mbNormalize(z);
	
	return z;
	
}/* mbAnd */

So all in all its unlikely that this problem can or will be fixed unless some math person analyses it and finds a solution.

I actually have a fix on the way it seems.

It was because of lack of Copy constructor in his base math engine.

Lack of it caused invalid memory to be passed around.

2 Likes

We have posted version 13.1 now which fixes this.

1 Like

mb mbAnd(const mb& x, const mb& y)
{
INT32 i, m, numBlocks;
mb xx, yy, z = {0}; // Ensure z is initialized properly

if (x.n == 0 || y.n == 0)
{
    z.n = 0;
    z.nn = 0;
    z.b = nullptr; // Explicitly setting to nullptr for clarity
    return z;
}

numBlocks = Max(abs(x.n), abs(y.n));

if (x.n < 0)
    xx = twosComplement(x, numBlocks);
else
    xx = x;

if (y.n < 0)
    yy = twosComplement(y, numBlocks);
else
    yy = y;

// Find minimum number of blocks
m = Min(abs(xx.n), abs(yy.n));
z.n = z.nn = m;
z.b = (UINT32*)malloc(m * sizeof(UINT32));
if (z.b == nullptr)
{
    // Handle memory allocation failure
    z.n = z.nn = 0;
    return z;
}

for (i = 0; i < m; i++)
{
    z.b[i] = (xx.b[i] & yy.b[i]);
}

mbNormalize(z);

return z;

} /* mbAnd */

Key issues I see in the provided code - see changes above:

Initialization of z: Added initialization for z to ensure all fields are properly set. Prevent hard crash.

Memory Allocation Check: Added a check after malloc to ensure the memory allocation was successful. Prevent a hard crash.

Setting z.b to nullptr: Explicitly setting z.b to nullptr when input x or y is zero for clarity. <-asthetic

**Freeing Allocated Memory: Ensure that mbNormalize correctly handles memory to prevent leaks. (Without looking at rest of code this is just a suggestion).

Will take a peek in github.

The problem in the code turned out to be lack of copy constructor. on the mb class that he is working with there.

So returning the class as a instance at bottom with return z then did not copy the needed memory because it had no copy constructor.

2 Likes