I have a freeze of my application with the following code, with TChart TPointSeries on Windows 64 bits.
I've simplified as much as I could my project to reproduce the problem.
I only have a form with a TButton and a TeeChart with a TPointSeries. On the button OnClick event I have the following code:
{******************************************************************************}
procedure TForm2.btnTestClick(Sender: TObject);
var
X1, Y1, X2 : double ;
begin
X1 := 10.5 ;
Y1 := 289 ;
X2 := ( 10.5 * 9.81 * 821 ) / ( 821 * 9.81 ) ;
Series1.AddXY( X1, Y1 ) ;
Series1.AddXY( X2, Y1 ) ;
end;
{******************************************************************************}
The problem occurs only with project built for Windows 64 bits bits, everything works well for Windows 32 bits.
The problem doesn't occur if I change the values of X2 formula, or if I replace the formula by it's result.
I need to have this code working for any values of X2 formula, as it is part of an engineering software with formula members as variables.
Can someone help for a solution ?
Thank you
I've added it to the public tracker: #2059.
Here a possible workaround:
Chart1.Axes.Bottom.Items.Automatic:=False;
Chart1.Axes.Bottom.Items.Clear;
Chart1.Axes.Bottom.Items.Add(X1, FormatFloat(Chart1.Axes.Bottom.AxisValuesFormat, X1));
Chart1.Axes.Bottom.Items.Add(X2, FormatFloat(Chart1.Axes.Bottom.AxisValuesFormat, X2));
Chart1.Axes.Bottom.SetMinMax(X1-0.5, X2+0.5);
Thank you Yeray for your solution, it works well.
As I have and several charts, and several series on the same chart in my original project, I coded the following workaround procedure. I call it for all axes with Automatic status, used by at least one serie. This solves the problem in any case.
procedure ChartBug2059_Workaround( AAxis : TChartAxis ;
AAxisMin, AAxisMax : double ) ;
begin
if IsAEqB( AxisMin, AxisMax ) then
begin
AAxis.Automatic:=False;
AAxis.SetMinMax(AxisMin-0.5, AxisMax+0.5);
end
else
AAxis.Automatic:=true;
end;
Related
I have to convert some procedures that used inline asm code in Virtual Pascal but don't know how to compare pointers in Virtual Pascal?
Here's example that causes a Operand types do not match operator on the While statement:
procedure ReverseBytes(var V; Size : Word);
{-Reverse the ordering of bytes from V[1] to V[Size]. Size must be >= 2.}
var
P1, P2 : ^Byte;
PT : Byte;
begin
P1 := #V;
P2 := P1;
Inc(P2, Size-1);
while (P1 < P2) do
begin
PT := P1^;
P1^ = P2^;
^P2 := PT;
Inc(P1);
Dec(P2);
end;
end;
How do you compare pointers (themselves - not what they point to) in Virtual Pascal?
P.S. I understand there are some flavors of Pascal (GNU Pascal for example) that support it just like C language (like I do above). But Virtual Pascal doesn't.
TIA!!
I am using version 2.9.9 of cbc in ubuntu 17.10 docker image. My test.lp file has following content:
Maximize
obj: x1 + 2 x2 + 3 x3 + x4
Subject To
c1: - x1 + x2 + x3 + 10 x4 <= 20
c2: x1 - 3 x2 + x3 <= 30
c3: x2 - 3.5 x4 = 0
Bounds
0 <= x1 <= 40
2 <= x4 <= 3
General
x4
Semis
x1 x2 x3
When trying with semis section i get error "terminate called after throwing an instance of 'CoinError?' Aborted"
on mac i get: libc++abi.dylib: terminating with uncaught exception of type CoinError? Abort trap: 6
However if I comment out Semis it works fine. I was hoping that Semis are supported. Am I doing something wrong?
My command is : cbc -presolve on -import test.lp solve solu out.txt
On further analysis i found out when in cbc prompt i type "import test.lp" it fails and shows same error is
The CBC MPS file reader seems not to accept SC bounds either. I think CBC actually supports semi-continuous variables (I tested with a small GAMS model) but it seems difficult to pass it on in an LP or MPS file. As a work around, I would suggest to use binary variables to model semi-continuous behavior:
b * L ≤ x ≤ b * U
b in {0,1}
Part of a Pascal ISO 10206 program I am building, requires me to implement a function to exponentiate a real number (x) to Eulers number (e), without using any exponentiation functions already included in Pascal(**,pow,exp...).
I have been trying different algorithms for hours but I cant figure out how to do it without using the already included exponentiation functions.
Any help would be appreciated. Any mathematical algorithm of some sort etc... Thanks in advance.
As others have said, it doesn't make sense not to use Exp() or a function based upon it. But if you really must use something else, and don't want to get too technical/mathematical, then the following should work (the real algorithm is far more complicated and requires much more knowledge of math).
The program uses a combination of the first N terms of Taylor series for the fraction of X and binary exponentiation for the integer part of X. It is probably not very fast, but pretty accurate, even for larger exponents. For comparison, I also display Exp(X). If your Pascal has a Double or Extended type, use those instead of Real.
program SimplePower;
{ Required for Delphi, you can omit it in other Pascals: }
{$APPTYPE CONSOLE}
{ Returns approximate value of e^X using sum of first N terms of Taylor series.
Works fine with X values between 0 and 1.0 and N ~ 30. }
function Exponential(N: Integer; X: Real): Real;
var
I: Integer;
begin
Result := 1.0;
for I := N - 1 downto 1 do
Result := 1.0 + X * Result / I;
end;
{ Binary exponentiation of Base by integer Exponent. }
function IntegerExp(Base: Real; Exponent: Integer): Real;
begin
Result := 1.0;
while Exponent > 0 do
begin
if Odd(Exponent) then
Result := Result * Base;
Base := Base * Base;
Exponent := Exponent shr 1;
end;
end;
{ Combines IntegerExp function for integral part with
Exponential function for fractional part. }
function MyExp(N: Integer; X: Real): Real;
const
E = 2.7182818284590452353602874713527; { from Google: "e euler" }
var
Factor: Real;
Fraction: Real;
begin
Fraction := Exponential(N, Frac(X));
Factor := IntegerExp(E, Trunc(X));
Result := Factor * Fraction;
end;
{ Simple demo: }
const
N = 30;
X = 73.4567890242421234;
begin
Writeln('MyExp(', N, ', ', X:22:18, ') = ', MyExp(N, X):22:18);
Writeln('Exp(', X:22:18, ') = ', Exp(X):22:18);
end.
Ref:
Taylor series for exponentiation
Binary exponentiation
I did not do anything for negative exponents, but just know that Exp(-x) = 1/Exp(x). You could amend MyExpwith that knowledge.
I used the solution pointed out by #RudyVelthuis in some other post, but modified it a bit. It is based upon that x^0.5 = sqrt(x), which we can use to our advantage. Ill leave the Pascal ISO 10206 code I used attached. Thank you all for your help, specially Rudy.
function MyPow(base,power,precision:real):real;
begin
if (power<0) then MyPow:=1/MyPow(base,-power,precision)
else if (power>=10) then MyPow:=sqr(MyPow(base,power/2,precision/2))
else if (power>=1) then MyPow:=base*MyPow(base,power-1,precision)
else if (precision>=1) then MyPow:=sqrt(base)
else MyPow:=sqrt(MyPow(base,power*2,precision*2));
end;
I have to code a program in pascal that, given the three coefficients of a polynomial(ax²+bx+c), outputs its roots.
Here's what I have right now:
program poly;
type
polynomial = record
a, b, c : real;
end;
procedure readPolynomial (var p : polynomial);
begin
writeln ('Input 1st coefficient: ');
readln (p.a);
writeln ('Input 2nd coefficient: ');
readln (p.b);
writeln ('Input 3rd coefficient: ');
readln (p.c);
end;
function square (x : real) : real;
begin
square := x * x;
end;
procedure roots (p : polynomial; var rP, rN : real);
begin
rP := (-p.b + (sqrt((square(p.b)) - (4 * p.a * p.c)))) / (2 * p.a);
rN := (-p.b - (sqrt((square(p.b)) - (4 * p.a * p.c)))) / (2 * p.a);
writeln('The roots are: ', rP:0:3, ' y ' ,rN:0:3);
end;
var
myPolynomial : polynomial;
r1, r2 : real;
begin
writeln ('Enter the coefficients: ');
readPolynomial (myPolynomial);
roots (myPolynomial, r1, r2);
end.
It works fine for real roots but I don't know how to make it work with complex numbers.
I am assuming your coefficients are real numbers (they user can't enter complex numbers as coefficients). That would add a whole new level of complexity (no pun intended) to the problem.
You need to check the discriminant ((square(p.b)) - (4 * p.a * p.c)) to see if it's less than 0. Currently, your code just does, sqrt((square(p.b)) - (4 * p.a * p.c)) but you aren't checking if you are taking the square root of a negative number (which you can't do using the Pascal sqrt library function).
If the discriminant is negative, then you have a complex root and you can separate the real and imaginary parts as you wish in your program. It's basic quadratic formula.
For example:
procedure roots (p : polynomial; var rP, rN : real);
var disc: real;
begin
disc := square(p.b) - 4*p.a*p.c;
if disc >= 0 then begin
rP := (-p.b + sqrt(disc)) / (2 * p.a);
rN := (-p.b - sqrt(disc)) / (2 * p.a);
writeln('The roots are: ', rP:0:3, ' y ' ,rN:0:3);
end
else begin
// Roots are:
// -p.b/(2*p.a) + (sqrt(-disc)/(2*p.a))i
// -p.b/(2*p.a) - (sqrt(-disc)/(2*p.a))i
end
end;
Here you use the fact that sqrt(x) if x is negative would be, (sqrt(-x))i where i is sqrt(-1). Note that you could also split out the disc = 0 case to avoid repeating a double root.
Since your roots function prints out the results and your main program doesn't use the returned arguments rN and rP, it's not clear to me if you need to pass back the roots at all. But if want to pass the roots back as arguments (the way you have your function currently designed), I'll leave that as an exercise. You just have to decide on a representation for complex roots. One way is to use the Complex number type for the results (if your compiler library supports them), and when the results are real, the imaginary parts will just be zero. Alternatively, if you need to create your own, just make a type which is a record consisting of a real and imaginary part.
type complex = record
re: real;
im: real;
end;
I'm doing some rigid-body rotation dynamics simulation, which means I have to compute many rotations by small angle, which has performance bottleneck in evaluation of trigonometric function. Now I do it by Taylor(McLaurin) series:
class double2{
double x,y;
// Intristic full sin/cos
final void rotate ( double a){
double x_=x;
double ca=Math.cos(a); double sa=Math.sin(a);
x=ca*x_-sa*y; y=sa*x_+ca*y;
}
// Taylor 7th-order aproximation
final void rotate_d7( double a){
double x_=x;
double a2=a*a;
double a4=a2*a2;
double a6=a4*a2;
double ca= 1.0d - a2 /2.0d + a4 /24.0d - a6/720.0d;
double sa= a - a2*a/6.0d + a4*a/120.0d - a6*a/5040.0d;
x=ca*x_-sa*y; y=sa*x_+ca*y;
}
}
but the trade of performance-speed is not so great as I would expect:
error(100x dphi=Pi/100 ) time [ns pre rotation]
v.rotate_d1() : -0.010044860504615213 9.314306 ns/op
v.rotate_d3() : 3.2624666136960023E-6 16.268745 ns/op
v.rotate_d5() : -4.600003294941146E-10 35.433617 ns/op
v.rotate_d7() : 3.416711358283919E-14 49.831547 ns/op
v.rotate() : 3.469446951953614E-16 75.70213 ns/op
Is there any faster method how to evaluate approximation of sin() and cos() for small angle ( like < Pi/100 )
I was thinking maybe some rational series, or continuous fraction approximation? Do you know any? ( Precomputed table doesn't make sense here )
You might find that adjusting your calculations can improve performance. E.g.:
const double c7 = -1/5040d;
const double c5 = 1/120d;
const double c3 = -1/6d;
double a2 = a * a;
double sa = (((c7 * a2 + c5) * a2 + c3) * a2 + 1) * a;
// similarly for cos
Now the optimiser might be doing some of this itself anyway, so your mileage may vary. Would be interested to know the results either way.
Instead of optimizing the trig functions, see if you can do without them. Rigid-body simulations tend to be a perfectly natural fit for vector math.
Two ways : reduce the precision if possible (as often in video games, use minimal acceptable precision if you aim performance)
the you should try to use tabulated values. Once per execution (when the game loads ?) compute an array of sinus/ cosinus/ that you then access in constant time.
float cosAlpha = COSINUS[(int)(k*alpha)]; // e.g: k = 1000
tune k and the array size to choose angle resolution vs. memory footprint.
edit: Don't forget to use parity of cosinus/sinus functions to avoid duplicate values in the tab
edit2: try floats instead of double. Difference will be insignificant for the player, and the performance impact way be interesting. Test it !
can you add some inline assembler? Targetting the i386 'fsincos' instruction is probably the fastest method :
Vector2 unit_vector ( Angle angle ) {
Vector2 r;
//now the normal processor detection
//and various platform specific vesions
# if defined (__i386__) && !defined (NO_ASM)
# if defined __GNUC__
# define ASM_SINCOS
asm ("fsincos" : "=t" (r.x), "=u" (r.y) : "0" (angle.radians()));
# elif defined _MSC_VER
# define ASM_SINCOS
double a = angle.radians();
__asm fld a
__asm fsincos
__asm fstp r.x
__asm fstp r.y
# endif
# endif
}
from here.
This has the added bonus of calculating both sin and cos in a single call.
EDIT : it's Java.
Are your rotations suitably self-contained that you can offload thousands at a time over JNI? Otherwise this hardware-specific approach is no good.
For small x (x<0.2 in radians) you can safely assume sin(x) = x.
The maximum deviation is 0.0013.