Post Reply 
HP Prime complex division problem in CAS
11-22-2020, 02:59 PM (This post was last modified: 11-22-2020 04:40 PM by lyuka.)
Post: #15
RE: HP Prime complex division problem in CAS
May future firmware at least pass the next simple division test.
Code:
#CAS
// from Mc Laren's difficult complex divisions test
cdiv_test():=
BEGIN
  LOCAL c, x, y, z;
  LOCAL g, k;
  PRINT();
  g := MAXREAL / 2;
  FOR k FROM 0.0 TO 2.0 STEP 0.5 DO
    x := 1 + i;
    y := 1 + i * k;
    c := x / y;
    z := (x * g) / (y * g); PRINT(k + ":Ref.-> "+c); 
    z := cdiv(x *g, y * g); PRINT(k+":cdiv-> "+z); 
    z := (x * g) * inv(y * g); PRINT(k+":*inv-> "+z); 
    z := (x * g) / (y * g); //PRINT(k+":#/# -> "+z); // stall
  END;
END;
#END
This is the execution result. The calculation result of (x * g) / (y * g) cannot be printed because the calculator terminates abnormally when trying to print undef-undef * i.
[Image: HP-Prime-CAS-cdiv-test.png]

Anyway, I ported Robert L. Smith and Michael Baudin's "Robust Complex Division".
Code:
#CAS
// This is a workaround for the dynamic range problem of complex division in CAS.
// Conforms to HP Prime software version 2.1.14433 (2020 01 21).
// An implimentation of the following algorithm by Takayuki HOSODA (aka Lyuka).
// "Improved Complex Division in Scilab", Michael Baudin, Robert L. Smith, Jun. 2011
// http://forge.scilab.org/index.php/p/compdiv/downloads/get/improved_cdiv_v0.3.pdf
// cdiv(x, y) returns complex division x / y.
cdiv(x, y):=
BEGIN
  LOCAL z;
  LOCAL r, t, AB, CD, B, S;
  LOCAL OV2, eps, UNBeps, Be;
  AB := fmax(fabs(RE(x)), fabs(IM(x)));
  CD := fmax(fabs(RE(y)), fabs(IM(y)));
  B := 2;
  S := 1;
  // Machine dependent constants (for HP Prime)
  OV2 :=  8.988465674311581E307;  // MAXREAL / 2; 
  eps := 7.105427357601002E-15;    // 1 / 2^47; 
  UNBeps := 6.263026125028041E-294; // MINREAL * B / eps;
  Be := B / (eps * eps);
  IF (AB >= OV2)   THEN x = x / 2;  S = S * 2;  END; // Scale down x
  IF (CD >= OV2)   THEN y = y / 2;  S = S / 2;  END; // Scale down y
  IF (AB < UNBeps) THEN x = x * Be; S = S / Be; END; // Scale up   x
  IF (CD < UNBeps) THEN y = y * Be; S = S * Be; END; // Scale up   y
  IF cabs(IM(y)) <= cabs(RE(y)) THEN
    r := IM(y) / RE(y); 
    t := 1 / (RE(y) + IM(y) * r);
    IF r == 0 THEN
      z :=  (RE(x) + IM(y) * (IM(x) / RE(y))) * t + (IM(x) - IM(y) * (RE(x) / RE(y))) * t * i;
    ELSE
      z :=  (RE(x) + IM(x) * r) * t + (IM(x) - RE(x) * r) * t * i;
    END;
  ELSE
    r := RE(y) / IM(y); 
    t := 1 / (RE(y) * r + IM(y));
    IF r == 0 THEN
      z :=   (RE(y) * (RE(x) / IM(y)) + IM(x)) * t + (RE(y) * (IM(x) / IM(y)) - RE(x)) * t * i;
    ELSE
      z :=   (RE(x) * r + IM(x)) * t + (IM(x) * r - RE(x)) * t * i;
    END;
  END;
  return S * z;
END;
//fmax(a, b) -- returns the larger value from a and b.
fmax(a, b):=
BEGIN
  IF a < b THEN
    return b;
  ELSE
    return a;
  END;
END;
//fabs(a) -- returns the absolute value of 'a'.
fabs(a):=
BEGIN
  IF a < 0 THEN
    return -a;
  ELSE
    return a;
  END;
END;
// This is a workaround for the dynamic range problem of complex division and abs() in CAS.
// Conforms to HP Prime software version 2.1.14433 (2020 01 21).
// cabs(z) -- returns the magnitude of the complex number z.
cabs(z):=
BEGIN
  LOCAL x, y, t, s;
  x := RE(z);
  y := IM(z);
  IF x < 0 THEN x := -x; END;
  IF y < 0 THEN y := -y; END;
  IF x == 0 THEN return y; END;
  IF y == 0 THEN return x; END;
  IF (y > x) THEN
    t := x; x := y; y := t;
  END;
  t := x - y;
  IF t > y THEN
    t := x / y;
    t := t + sqrt(1 + t * t);
  ELSE
    t := t / y;
    s := t * (t + 2);
    t := t + s / (sqrt(2) + sqrt(2 + s));
    t := t + sqrt(2) + 1;
  END;
  return(x + y / t);
END;
#END

Have fun.
Lyuka
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: HP Prime complex division problem in CAS - lyuka - 11-22-2020 02:59 PM



User(s) browsing this thread: 1 Guest(s)