Check for a branch cut in a function. Assert that `x0` lies on a branch cut of function `f` and `f` is continuous from the direction `dx`. Parameters ---------- f : func Function to check x0 : array-like Point on branch cut dx : array-like D
(f, x0, dx, re_sign=1, im_sign=-1, sig_zero_ok=False,
dtype=complex)
| 4363 | |
| 4364 | |
| 4365 | def _check_branch_cut(f, x0, dx, re_sign=1, im_sign=-1, sig_zero_ok=False, |
| 4366 | dtype=complex): |
| 4367 | """ |
| 4368 | Check for a branch cut in a function. |
| 4369 | |
| 4370 | Assert that `x0` lies on a branch cut of function `f` and `f` is |
| 4371 | continuous from the direction `dx`. |
| 4372 | |
| 4373 | Parameters |
| 4374 | ---------- |
| 4375 | f : func |
| 4376 | Function to check |
| 4377 | x0 : array-like |
| 4378 | Point on branch cut |
| 4379 | dx : array-like |
| 4380 | Direction to check continuity in |
| 4381 | re_sign, im_sign : {1, -1} |
| 4382 | Change of sign of the real or imaginary part expected |
| 4383 | sig_zero_ok : bool |
| 4384 | Whether to check if the branch cut respects signed zero (if applicable) |
| 4385 | dtype : dtype |
| 4386 | Dtype to check (should be complex) |
| 4387 | |
| 4388 | """ |
| 4389 | x0 = np.atleast_1d(x0).astype(dtype) |
| 4390 | dx = np.atleast_1d(dx).astype(dtype) |
| 4391 | |
| 4392 | if np.dtype(dtype).char == 'F': |
| 4393 | scale = np.finfo(dtype).eps * 1e2 |
| 4394 | atol = np.float32(1e-2) |
| 4395 | else: |
| 4396 | scale = np.finfo(dtype).eps * 1e3 |
| 4397 | atol = 1e-4 |
| 4398 | |
| 4399 | y0 = f(x0) |
| 4400 | yp = f(x0 + dx*scale*np.absolute(x0)/np.absolute(dx)) |
| 4401 | ym = f(x0 - dx*scale*np.absolute(x0)/np.absolute(dx)) |
| 4402 | |
| 4403 | assert_(np.all(np.absolute(y0.real - yp.real) < atol), (y0, yp)) |
| 4404 | assert_(np.all(np.absolute(y0.imag - yp.imag) < atol), (y0, yp)) |
| 4405 | assert_(np.all(np.absolute(y0.real - ym.real*re_sign) < atol), (y0, ym)) |
| 4406 | assert_(np.all(np.absolute(y0.imag - ym.imag*im_sign) < atol), (y0, ym)) |
| 4407 | |
| 4408 | if sig_zero_ok: |
| 4409 | # check that signed zeros also work as a displacement |
| 4410 | jr = (x0.real == 0) & (dx.real != 0) |
| 4411 | ji = (x0.imag == 0) & (dx.imag != 0) |
| 4412 | if np.any(jr): |
| 4413 | x = x0[jr] |
| 4414 | x.real = np.NZERO |
| 4415 | ym = f(x) |
| 4416 | assert_(np.all(np.absolute(y0[jr].real - ym.real*re_sign) < atol), (y0[jr], ym)) |
| 4417 | assert_(np.all(np.absolute(y0[jr].imag - ym.imag*im_sign) < atol), (y0[jr], ym)) |
| 4418 | |
| 4419 | if np.any(ji): |
| 4420 | x = x0[ji] |
| 4421 | x.imag = np.NZERO |
| 4422 | ym = f(x) |