Changed ofPolar to not throw IllegalArgumentException.

Method will return NaN for input arguments that are not allowed.

rho must be non-negative and non-nan.

theta must be finite.

This is in compliance with C++ behaviour.
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
index a126040..a6f8da4 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
@@ -196,46 +196,73 @@
      *
      * @param real Real part.
      * @param imaginary Imaginary part.
-     * @return {@code Complex} object
+     * @return {@code Complex} number
      */
     public static Complex ofCartesian(double real, double imaginary) {
         return new Complex(real, imaginary);
     }
 
     /**
-     * Creates a Complex from its polar representation.
+     * Creates a complex number from its polar representation using modulus {@code rho}
+     * and phase angle {@code theta}.
+     * <pre>
+     *  x = rho * cos(theta)
+     *  y = rho * sin(theta)
+     * </pre>
      *
-     * <p>If {@code r} is infinite and {@code theta} is finite, infinite or NaN
-     * values may be returned in parts of the result, following the rules for
-     * double arithmetic.</p>
+     * <p>Requires that {@code rho} is non-negative and non-NaN and {@code theta} is finite;
+     * otherwise returns a complex with NaN real and imaginary parts. A value of {@code -0.0} is
+     * considered negative and an invalid modulus.
+     *
+     * <p>A non-NaN complex number constructed using this method will satisfy the following
+     * to within floating-point error:</p>
+     * <pre>
+     *  Complex.ofPolar(rho, theta).abs() == rho
+     *  Complex.ofPolar(rho, theta).arg() == theta; theta in (\(-\pi\), \(\pi\)]
+     * </pre>
+     *
+     * <p>If {@code rho} is infinite then the resulting parts may be infinite or NaN
+     * following the rules for double arithmetic.</p>
      *
      * <pre>
      * Examples:
      * {@code
-     * ofPolar(INFINITY, \(\pi\)) = INFINITY + INFINITY i
+     * ofPolar(-0.0, 0.0) = NaN + NaN i
+     * ofPolar(0.0, 0.0) = 0.0 + 0.0 i
+     * ofPolar(1.0, 0.0) = 1.0 + 0.0 i
+     * ofPolar(1.0, \(\pi\)) = -1.0 + sin(\(\pi\)) i
+     * ofPolar(INFINITY, \(\pi\)) = -INFINITY + INFINITY i
      * ofPolar(INFINITY, 0) = INFINITY + NaN i
      * ofPolar(INFINITY, \(-\frac{\pi}{4}\)) = INFINITY - INFINITY i
      * ofPolar(INFINITY, \(5\frac{\pi}{4}\)) = -INFINITY - INFINITY i }
      * </pre>
      *
-     * @param r the modulus of the complex number to create
+     * @param rho the modulus of the complex number to create
      * @param theta the argument of the complex number to create
-     * @return {@code Complex}
-     * @throws IllegalArgumentException if {@code r} is non-positive
+     * @return {@code Complex} number
+     * @see <a href="http://mathworld.wolfram.com/PolarCoordinates.html">Polar Coordinates</a>
      */
-    public static Complex ofPolar(double r, double theta) {
-        if (r <= 0) {
-            throw new IllegalArgumentException("Non-positive polar modulus argument: " + r);
+    public static Complex ofPolar(double rho, double theta) {
+        // Require finite theta and non-negative, non-nan rho
+        if (!Double.isFinite(theta) || negative(rho) || Double.isNaN(rho)) {
+            return NAN;
         }
-        return new Complex(r * Math.cos(theta), r * Math.sin(theta));
+        final double x = rho * Math.cos(theta);
+        final double y = rho * Math.sin(theta);
+        return new Complex(x, y);
     }
 
     /**
-     * For a real constructor argument x, returns a new Complex object c
-     * where {@code c = cos(x) + i sin (x)}.
+     * Create a complex cis number. This is also known as the complex exponential:
+     * <pre>
+     * <code>
+     *   cis(x) = e<sup>ix</sup> = cos(x) + i sin(x)
+     * </code>
+     * </pre>
      *
      * @param x {@code double} to build the cis number
-     * @return {@code Complex}
+     * @return {@code Complex} cis number
+     * @see <a href="http://mathworld.wolfram.com/Cis.html">Cis</a>
      */
     public static Complex ofCis(double x) {
         return new Complex(Math.cos(x), Math.sin(x));
@@ -264,7 +291,7 @@
      * </pre>
      *
      * @param s String representation.
-     * @return an instance.
+     * @return {@code Complex} number
      * @throws NullPointerException if the string is null.
      * @throws NumberFormatException if the string does not contain a parsable complex number.
      * @see Double#parseDouble(String)
@@ -392,7 +419,7 @@
     }
 
     /**
-     * Return the absolute value of this complex number. This is also called norm, modulus,
+     * Return the absolute value of this complex number. This is also called complex norm, modulus,
      * or magnitude.
      * <pre>abs(a + b i) = sqrt(a^2 + b^2)</pre>
      *
diff --git a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
index 9d89490..13eb77c 100644
--- a/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
+++ b/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexTest.java
@@ -97,8 +97,29 @@
         Assertions.assertEquals(r * y.getReal(), z.getReal());
         Assertions.assertEquals(r * y.getImaginary(), z.getImaginary());
 
-        Assertions.assertThrows(IllegalArgumentException.class, () -> Complex.ofPolar(-1, 0),
-            "negative modulus should not be allowed");
+        // Edge cases
+        // Non-finite theta
+        Assertions.assertEquals(NAN, Complex.ofPolar(1, -inf));
+        Assertions.assertEquals(NAN, Complex.ofPolar(1, inf));
+        Assertions.assertEquals(NAN, Complex.ofPolar(1, nan));
+        // Infinite rho is invalid when theta is NaN
+        // i.e. do not create an infinite complex such as (inf, nan)
+        Assertions.assertEquals(NAN, Complex.ofPolar(inf, nan));
+        // negative or NaN rho
+        Assertions.assertEquals(NAN, Complex.ofPolar(-inf, 1));
+        Assertions.assertEquals(NAN, Complex.ofPolar(-0.0, 1));
+        Assertions.assertEquals(NAN, Complex.ofPolar(nan, 1));
+
+        // Construction from infinity has values left to double arithmetic.
+        // Test the examples from the javadoc
+        Assertions.assertEquals(NAN, Complex.ofPolar(-0.0, 0.0));
+        Assertions.assertEquals(Complex.ofCartesian(0.0, 0.0), Complex.ofPolar(0.0, 0.0));
+        Assertions.assertEquals(Complex.ofCartesian(1.0, 0.0), Complex.ofPolar(1.0, 0.0));
+        Assertions.assertEquals(Complex.ofCartesian(-1.0, Math.sin(pi)), Complex.ofPolar(1.0, pi));
+        Assertions.assertEquals(Complex.ofCartesian(-inf, inf), Complex.ofPolar(inf, pi));
+        Assertions.assertEquals(Complex.ofCartesian(inf, nan), Complex.ofPolar(inf, 0.0));
+        Assertions.assertEquals(Complex.ofCartesian(inf, -inf), Complex.ofPolar(inf, -pi / 4));
+        Assertions.assertEquals(Complex.ofCartesian(-inf, -inf), Complex.ofPolar(inf, 5 * pi / 4));
     }
 
     @Test