Skip to content

Commit 911727c

Browse files
authored
Merge pull request #83 from IsaMorphic/feature/fix-explog-nan
Fix: corrections to `NaN` handling for `Exp` and `Log` funcs
2 parents 29b0cd0 + 972e34f commit 911727c

1 file changed

Lines changed: 92 additions & 17 deletions

File tree

QuadrupleLib/Modules/MathOperations.cs

Lines changed: 92 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ public static Float128<TAccelerator> Acosh(Float128<TAccelerator> x)
303303
{
304304
return Log(x + Sqrt(FusedMultiplyAdd(x, x, NegativeOne)));
305305
}
306-
else if (x == One)
306+
else if (x == One)
307307
{
308308
return Zero;
309309
}
@@ -356,7 +356,11 @@ private static Float128<TAccelerator> _Log2(Float128<TAccelerator> y, int N)
356356

357357
public static Float128<TAccelerator> Log2(Float128<TAccelerator> x)
358358
{
359-
if (x <= Zero)
359+
if (IsNaN(x))
360+
{
361+
return _qNaN;
362+
}
363+
else if (x <= Zero)
360364
{
361365
return _sNaN;
362366
}
@@ -375,7 +379,11 @@ public static Float128<TAccelerator> Log2(Float128<TAccelerator> x)
375379

376380
public static Float128<TAccelerator> Log(Float128<TAccelerator> y)
377381
{
378-
if (y <= Zero)
382+
if (IsNaN(y))
383+
{
384+
return _qNaN;
385+
}
386+
else if (y <= Zero)
379387
{
380388
return _sNaN;
381389
}
@@ -396,7 +404,11 @@ public static Float128<TAccelerator> Log(Float128<TAccelerator> y)
396404

397405
public static Float128<TAccelerator> Log(Float128<TAccelerator> y, Float128<TAccelerator> newBase)
398406
{
399-
if (y <= Zero || newBase <= Zero)
407+
if (IsNaN(y) || IsNaN(newBase))
408+
{
409+
return _qNaN;
410+
}
411+
else if (y <= Zero || newBase <= Zero)
400412
{
401413
return _sNaN;
402414
}
@@ -429,7 +441,11 @@ public static Float128<TAccelerator> Log(Float128<TAccelerator> y, Float128<TAcc
429441

430442
public static Float128<TAccelerator> Log10(Float128<TAccelerator> y)
431443
{
432-
if (y <= Zero)
444+
if (IsNaN(y))
445+
{
446+
return _qNaN;
447+
}
448+
else if (y <= Zero)
433449
{
434450
return _sNaN;
435451
}
@@ -454,6 +470,11 @@ public static Float128<TAccelerator> Log10(Float128<TAccelerator> y)
454470

455471
public static Float128<TAccelerator> Exp(Float128<TAccelerator> y)
456472
{
473+
if (IsNaN(y))
474+
{
475+
return _qNaN;
476+
}
477+
457478
Float128<TAccelerator> x_n = One;
458479
if (y > Zero)
459480
{
@@ -474,15 +495,20 @@ public static Float128<TAccelerator> Exp(Float128<TAccelerator> y)
474495
{
475496
for (int n = 0; n < 5; n++)
476497
{
477-
x_n = FusedMultiplyAdd(x_n, y - Log(Abs(x_n)), x_n);
498+
x_n = Abs(FusedMultiplyAdd(x_n, y - Log(x_n), x_n));
478499
}
479500
}
480501

481-
return Abs(x_n);
502+
return x_n;
482503
}
483504

484505
public static Float128<TAccelerator> Exp10(Float128<TAccelerator> y)
485506
{
507+
if (IsNaN(y))
508+
{
509+
return _qNaN;
510+
}
511+
486512
Float128<TAccelerator> x_n = One;
487513
if (y > Zero)
488514
{
@@ -504,32 +530,54 @@ public static Float128<TAccelerator> Exp10(Float128<TAccelerator> y)
504530
Float128<TAccelerator> log10 = Log(10);
505531
for (int n = 0; n < 5; n++)
506532
{
507-
x_n = FusedMultiplyAdd(x_n * log10, y - Log10(Abs(x_n)), x_n);
533+
x_n = Abs(FusedMultiplyAdd(x_n * log10, y - Log10(x_n), x_n));
508534
}
509535
}
510536

511-
return Abs(x_n);
537+
return x_n;
512538
}
513539

514540
public static Float128<TAccelerator> Exp2(Float128<TAccelerator> y)
515541
{
542+
if (IsNaN(y))
543+
{
544+
return _qNaN;
545+
}
546+
516547
Float128<TAccelerator> x_n = ScaleB(One, (int)y);
517548

518549
if (y % One != Zero)
519550
{
520551
Float128<TAccelerator> log2 = One / Log2(E);
521552
for (int n = 0; n < 5; n++)
522553
{
523-
x_n = FusedMultiplyAdd(x_n * log2, y - Log2(Abs(x_n)), x_n);
554+
x_n = Abs(FusedMultiplyAdd(x_n * log2, y - Log2(x_n), x_n));
524555
}
525556
}
526557

527-
return Abs(x_n);
558+
return x_n;
528559
}
529560

530561
public static Float128<TAccelerator> Pow(Float128<TAccelerator> x, Float128<TAccelerator> y)
531562
{
532-
return Exp(y * Log(x));
563+
if (IsZero(x) && IsZero(y))
564+
{
565+
return _sNaN;
566+
}
567+
else if (IsInteger(x) && IsInteger(y))
568+
{
569+
Float128<TAccelerator> result = x;
570+
for (int i = 1; i < y; i++)
571+
{
572+
result *= x;
573+
}
574+
575+
return result;
576+
}
577+
else
578+
{
579+
return Exp(y * Log(x));
580+
}
533581
}
534582

535583
#endregion
@@ -538,16 +586,32 @@ public static Float128<TAccelerator> Pow(Float128<TAccelerator> x, Float128<TAcc
538586

539587
public static Float128<TAccelerator> Sqrt(Float128<TAccelerator> x)
540588
{
541-
Float128<TAccelerator> y_n = x * 0.5;
542-
for (int n = 0; n < 25; n++)
589+
if (IsNaN(x))
543590
{
544-
y_n = 0.5 * (y_n + x / y_n);
591+
return _qNaN;
592+
}
593+
else if (x < Zero)
594+
{
595+
return _sNaN;
596+
}
597+
else
598+
{
599+
Float128<TAccelerator> y_n = x * 0.5;
600+
for (int n = 0; n < 25; n++)
601+
{
602+
y_n = 0.5 * (y_n + x / y_n);
603+
}
604+
return y_n;
545605
}
546-
return y_n;
547606
}
548607

549608
public static Float128<TAccelerator> Cbrt(Float128<TAccelerator> x)
550609
{
610+
if (IsNaN(x))
611+
{
612+
return _qNaN;
613+
}
614+
551615
Float128<TAccelerator> y_n = x * 0.5;
552616
for (int n = 0; n < 25; n++)
553617
{
@@ -559,7 +623,18 @@ public static Float128<TAccelerator> Cbrt(Float128<TAccelerator> x)
559623

560624
public static Float128<TAccelerator> RootN(Float128<TAccelerator> x, int n)
561625
{
562-
return Pow(x, One / n);
626+
if (IsNaN(x))
627+
{
628+
return _qNaN;
629+
}
630+
else if (x < Zero)
631+
{
632+
return (n & 1) == 0 ? _sNaN : -Pow(-x, n);
633+
}
634+
else
635+
{
636+
return Pow(x, One / n);
637+
}
563638
}
564639

565640
#endregion

0 commit comments

Comments
 (0)