Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
namespace Complex;
4
 
5
use InvalidArgumentException;
6
 
7
class Functions
8
{
9
    /**
10
     * Returns the absolute value (modulus) of a complex number.
11
     * Also known as the rho of the complex number, i.e. the distance/radius
12
     *   from the centrepoint to the representation of the number in polar coordinates.
13
     *
14
     * This function is a synonym for rho()
15
     *
16
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
17
     * @return    float            The absolute (or rho) value of the complex argument.
18
     * @throws    Exception        If argument isn't a valid real or complex number.
19
     *
20
     * @see    rho
21
     *
22
     */
23
    public static function abs($complex): float
24
    {
25
        return self::rho($complex);
26
    }
27
 
28
    /**
29
     * Returns the inverse cosine of a complex number.
30
     *
31
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
32
     * @return    Complex          The inverse cosine of the complex argument.
33
     * @throws    Exception        If argument isn't a valid real or complex number.
34
     */
35
    public static function acos($complex): Complex
36
    {
37
        $complex = Complex::validateComplexArgument($complex);
38
 
39
        $invsqrt = self::sqrt(Operations::subtract(1, Operations::multiply($complex, $complex)));
40
        $adjust = new Complex(
41
            $complex->getReal() - $invsqrt->getImaginary(),
42
            $complex->getImaginary() + $invsqrt->getReal()
43
        );
44
        $log = self::ln($adjust);
45
 
46
        return new Complex(
47
            $log->getImaginary(),
48
            -1 * $log->getReal()
49
        );
50
    }
51
 
52
    /**
53
     * Returns the inverse hyperbolic cosine of a complex number.
54
     *
55
     * Formula from Wolfram Alpha:
56
     *   cosh^(-1)z = ln(z + sqrt(z + 1) sqrt(z - 1)).
57
     *
58
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
59
     * @return    Complex          The inverse hyperbolic cosine of the complex argument.
60
     * @throws    Exception        If argument isn't a valid real or complex number.
61
     */
62
    public static function acosh($complex): Complex
63
    {
64
        $complex = Complex::validateComplexArgument($complex);
65
 
66
        if ($complex->isReal() && ($complex->getReal() > 1)) {
67
            return new Complex(\acosh($complex->getReal()));
68
        }
69
 
70
        $acosh = self::ln(
71
            Operations::add(
72
                $complex,
73
                Operations::multiply(
74
                    self::sqrt(Operations::add($complex, 1)),
75
                    self::sqrt(Operations::subtract($complex, 1))
76
                )
77
            )
78
        );
79
 
80
        return $acosh;
81
    }
82
 
83
    /**
84
     * Returns the inverse cotangent of a complex number.
85
     *
86
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
87
     * @return    Complex          The inverse cotangent of the complex argument.
88
     * @throws    Exception        If argument isn't a valid real or complex number.
89
     * @throws    \InvalidArgumentException    If function would result in a division by zero
90
     */
91
    public static function acot($complex): Complex
92
    {
93
        $complex = Complex::validateComplexArgument($complex);
94
 
95
        return self::atan(self::inverse($complex));
96
    }
97
 
98
    /**
99
     * Returns the inverse hyperbolic cotangent of a complex number.
100
     *
101
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
102
     * @return    Complex          The inverse hyperbolic cotangent of the complex argument.
103
     * @throws    Exception        If argument isn't a valid real or complex number.
104
     * @throws    \InvalidArgumentException    If function would result in a division by zero
105
     */
106
    public static function acoth($complex): Complex
107
    {
108
        $complex = Complex::validateComplexArgument($complex);
109
 
110
        return self::atanh(self::inverse($complex));
111
    }
112
 
113
    /**
114
     * Returns the inverse cosecant of a complex number.
115
     *
116
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
117
     * @return    Complex          The inverse cosecant of the complex argument.
118
     * @throws    Exception        If argument isn't a valid real or complex number.
119
     * @throws    \InvalidArgumentException    If function would result in a division by zero
120
     */
121
    public static function acsc($complex): Complex
122
    {
123
        $complex = Complex::validateComplexArgument($complex);
124
 
125
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
126
            return new Complex(INF);
127
        }
128
 
129
        return self::asin(self::inverse($complex));
130
    }
131
 
132
    /**
133
     * Returns the inverse hyperbolic cosecant of a complex number.
134
     *
135
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
136
     * @return    Complex          The inverse hyperbolic cosecant of the complex argument.
137
     * @throws    Exception        If argument isn't a valid real or complex number.
138
     * @throws    \InvalidArgumentException    If function would result in a division by zero
139
     */
140
    public static function acsch($complex): Complex
141
    {
142
        $complex = Complex::validateComplexArgument($complex);
143
 
144
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
145
            return new Complex(INF);
146
        }
147
 
148
        return self::asinh(self::inverse($complex));
149
    }
150
 
151
    /**
152
     * Returns the argument of a complex number.
153
     * Also known as the theta of the complex number, i.e. the angle in radians
154
     *   from the real axis to the representation of the number in polar coordinates.
155
     *
156
     * This function is a synonym for theta()
157
     *
158
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
159
     * @return    float            The argument (or theta) value of the complex argument.
160
     * @throws    Exception        If argument isn't a valid real or complex number.
161
     *
162
     * @see    theta
163
     */
164
    public static function argument($complex): float
165
    {
166
        return self::theta($complex);
167
    }
168
 
169
    /**
170
     * Returns the inverse secant of a complex number.
171
     *
172
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
173
     * @return    Complex          The inverse secant of the complex argument.
174
     * @throws    Exception        If argument isn't a valid real or complex number.
175
     * @throws    \InvalidArgumentException    If function would result in a division by zero
176
     */
177
    public static function asec($complex): Complex
178
    {
179
        $complex = Complex::validateComplexArgument($complex);
180
 
181
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
182
            return new Complex(INF);
183
        }
184
 
185
        return self::acos(self::inverse($complex));
186
    }
187
 
188
    /**
189
     * Returns the inverse hyperbolic secant of a complex number.
190
     *
191
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
192
     * @return    Complex          The inverse hyperbolic secant of the complex argument.
193
     * @throws    Exception        If argument isn't a valid real or complex number.
194
     * @throws    \InvalidArgumentException    If function would result in a division by zero
195
     */
196
    public static function asech($complex): Complex
197
    {
198
        $complex = Complex::validateComplexArgument($complex);
199
 
200
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
201
            return new Complex(INF);
202
        }
203
 
204
        return self::acosh(self::inverse($complex));
205
    }
206
 
207
    /**
208
     * Returns the inverse sine of a complex number.
209
     *
210
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
211
     * @return    Complex          The inverse sine of the complex argument.
212
     * @throws    Exception        If argument isn't a valid real or complex number.
213
     */
214
    public static function asin($complex): Complex
215
    {
216
        $complex = Complex::validateComplexArgument($complex);
217
 
218
        $invsqrt = self::sqrt(Operations::subtract(1, Operations::multiply($complex, $complex)));
219
        $adjust = new Complex(
220
            $invsqrt->getReal() - $complex->getImaginary(),
221
            $invsqrt->getImaginary() + $complex->getReal()
222
        );
223
        $log = self::ln($adjust);
224
 
225
        return new Complex(
226
            $log->getImaginary(),
227
            -1 * $log->getReal()
228
        );
229
    }
230
 
231
    /**
232
     * Returns the inverse hyperbolic sine of a complex number.
233
     *
234
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
235
     * @return    Complex          The inverse hyperbolic sine of the complex argument.
236
     * @throws    Exception        If argument isn't a valid real or complex number.
237
     */
238
    public static function asinh($complex): Complex
239
    {
240
        $complex = Complex::validateComplexArgument($complex);
241
 
242
        if ($complex->isReal() && ($complex->getReal() > 1)) {
243
            return new Complex(\asinh($complex->getReal()));
244
        }
245
 
246
        $asinh = clone $complex;
247
        $asinh = $asinh->reverse()
248
            ->invertReal();
249
        $asinh = self::asin($asinh);
250
 
251
        return $asinh->reverse()
252
            ->invertImaginary();
253
    }
254
 
255
    /**
256
     * Returns the inverse tangent of a complex number.
257
     *
258
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
259
     * @return    Complex          The inverse tangent of the complex argument.
260
     * @throws    Exception        If argument isn't a valid real or complex number.
261
     * @throws    \InvalidArgumentException    If function would result in a division by zero
262
     */
263
    public static function atan($complex): Complex
264
    {
265
        $complex = Complex::validateComplexArgument($complex);
266
 
267
        if ($complex->isReal()) {
268
            return new Complex(\atan($complex->getReal()));
269
        }
270
 
271
        $t1Value = new Complex(-1 * $complex->getImaginary(), $complex->getReal());
272
        $uValue = new Complex(1, 0);
273
 
274
        $d1Value = clone $uValue;
275
        $d1Value = Operations::subtract($d1Value, $t1Value);
276
        $d2Value = Operations::add($t1Value, $uValue);
277
        $uResult = $d1Value->divideBy($d2Value);
278
        $uResult = self::ln($uResult);
279
 
280
        $realMultiplier = -0.5;
281
        $imaginaryMultiplier = 0.5;
282
 
283
        if (abs($uResult->getImaginary()) === M_PI) {
284
            // If we have an imaginary value at the max or min (PI or -PI), then we need to ensure
285
            //    that the primary is assigned for the correct quadrant.
286
            $realMultiplier = (
287
                ($uResult->getImaginary() === M_PI && $uResult->getReal() > 0.0) ||
288
                ($uResult->getImaginary() === -M_PI && $uResult->getReal() < 0.0)
289
            ) ? 0.5 : -0.5;
290
        }
291
 
292
        return new Complex(
293
            $uResult->getImaginary() * $realMultiplier,
294
            $uResult->getReal() * $imaginaryMultiplier,
295
            $complex->getSuffix()
296
        );
297
    }
298
 
299
    /**
300
     * Returns the inverse hyperbolic tangent of a complex number.
301
     *
302
     * Formula from Wolfram Alpha:
303
     *  tanh^(-1)z = 1/2 [ln(1 + z) - ln(1 - z)].
304
     *
305
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
306
     * @return    Complex          The inverse hyperbolic tangent of the complex argument.
307
     * @throws    Exception        If argument isn't a valid real or complex number.
308
     */
309
    public static function atanh($complex): Complex
310
    {
311
        $complex = Complex::validateComplexArgument($complex);
312
 
313
        if ($complex->isReal()) {
314
            $real = $complex->getReal();
315
            if ($real >= -1.0 && $real <= 1.0) {
316
                return new Complex(\atanh($real));
317
            } else {
318
                return new Complex(\atanh(1 / $real), (($real < 0.0) ? M_PI_2 : -1 * M_PI_2));
319
            }
320
        }
321
 
322
        $atanh = Operations::multiply(
323
            Operations::subtract(
324
                self::ln(Operations::add(1.0, $complex)),
325
                self::ln(Operations::subtract(1.0, $complex))
326
            ),
327
            0.5
328
        );
329
 
330
        return $atanh;
331
    }
332
 
333
    /**
334
     * Returns the complex conjugate of a complex number
335
     *
336
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
337
     * @return    Complex          The conjugate of the complex argument.
338
     * @throws    Exception        If argument isn't a valid real or complex number.
339
     */
340
    public static function conjugate($complex): Complex
341
    {
342
        $complex = Complex::validateComplexArgument($complex);
343
 
344
        return new Complex(
345
            $complex->getReal(),
346
            -1 * $complex->getImaginary(),
347
            $complex->getSuffix()
348
        );
349
    }
350
 
351
    /**
352
     * Returns the cosine of a complex number.
353
     *
354
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
355
     * @return    Complex          The cosine of the complex argument.
356
     * @throws    Exception        If argument isn't a valid real or complex number.
357
     */
358
    public static function cos($complex): Complex
359
    {
360
        $complex = Complex::validateComplexArgument($complex);
361
 
362
        if ($complex->isReal()) {
363
            return new Complex(\cos($complex->getReal()));
364
        }
365
 
366
        return self::conjugate(
367
            new Complex(
368
                \cos($complex->getReal()) * \cosh($complex->getImaginary()),
369
                \sin($complex->getReal()) * \sinh($complex->getImaginary()),
370
                $complex->getSuffix()
371
            )
372
        );
373
    }
374
 
375
    /**
376
     * Returns the hyperbolic cosine of a complex number.
377
     *
378
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
379
     * @return    Complex          The hyperbolic cosine of the complex argument.
380
     * @throws    Exception        If argument isn't a valid real or complex number.
381
     */
382
    public static function cosh($complex): Complex
383
    {
384
        $complex = Complex::validateComplexArgument($complex);
385
 
386
        if ($complex->isReal()) {
387
            return new Complex(\cosh($complex->getReal()));
388
        }
389
 
390
        return new Complex(
391
            \cosh($complex->getReal()) * \cos($complex->getImaginary()),
392
            \sinh($complex->getReal()) * \sin($complex->getImaginary()),
393
            $complex->getSuffix()
394
        );
395
    }
396
 
397
    /**
398
     * Returns the cotangent of a complex number.
399
     *
400
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
401
     * @return    Complex          The cotangent of the complex argument.
402
     * @throws    Exception        If argument isn't a valid real or complex number.
403
     * @throws    \InvalidArgumentException    If function would result in a division by zero
404
     */
405
    public static function cot($complex): Complex
406
    {
407
        $complex = Complex::validateComplexArgument($complex);
408
 
409
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
410
            return new Complex(INF);
411
        }
412
 
413
        return self::inverse(self::tan($complex));
414
    }
415
 
416
    /**
417
     * Returns the hyperbolic cotangent of a complex number.
418
     *
419
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
420
     * @return    Complex          The hyperbolic cotangent of the complex argument.
421
     * @throws    Exception        If argument isn't a valid real or complex number.
422
     * @throws    \InvalidArgumentException    If function would result in a division by zero
423
     */
424
    public static function coth($complex): Complex
425
    {
426
        $complex = Complex::validateComplexArgument($complex);
427
 
428
        return self::inverse(self::tanh($complex));
429
    }
430
 
431
    /**
432
     * Returns the cosecant of a complex number.
433
     *
434
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
435
     * @return    Complex          The cosecant of the complex argument.
436
     * @throws    Exception        If argument isn't a valid real or complex number.
437
     * @throws    \InvalidArgumentException    If function would result in a division by zero
438
     */
439
    public static function csc($complex): Complex
440
    {
441
        $complex = Complex::validateComplexArgument($complex);
442
 
443
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
444
            return new Complex(INF);
445
        }
446
 
447
        return self::inverse(self::sin($complex));
448
    }
449
 
450
    /**
451
     * Returns the hyperbolic cosecant of a complex number.
452
     *
453
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
454
     * @return    Complex          The hyperbolic cosecant of the complex argument.
455
     * @throws    Exception        If argument isn't a valid real or complex number.
456
     * @throws    \InvalidArgumentException    If function would result in a division by zero
457
     */
458
    public static function csch($complex): Complex
459
    {
460
        $complex = Complex::validateComplexArgument($complex);
461
 
462
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
463
            return new Complex(INF);
464
        }
465
 
466
        return self::inverse(self::sinh($complex));
467
    }
468
 
469
    /**
470
     * Returns the exponential of a complex number.
471
     *
472
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
473
     * @return    Complex          The exponential of the complex argument.
474
     * @throws    Exception        If argument isn't a valid real or complex number.
475
     */
476
    public static function exp($complex): Complex
477
    {
478
        $complex = Complex::validateComplexArgument($complex);
479
 
480
        if (($complex->getReal() == 0.0) && (\abs($complex->getImaginary()) == M_PI)) {
481
            return new Complex(-1.0, 0.0);
482
        }
483
 
484
        $rho = \exp($complex->getReal());
485
 
486
        return new Complex(
487
            $rho * \cos($complex->getImaginary()),
488
            $rho * \sin($complex->getImaginary()),
489
            $complex->getSuffix()
490
        );
491
    }
492
 
493
    /**
494
     * Returns the inverse of a complex number.
495
     *
496
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
497
     * @return    Complex          The inverse of the complex argument.
498
     * @throws    Exception        If argument isn't a valid real or complex number.
499
     * @throws    InvalidArgumentException    If function would result in a division by zero
500
     */
501
    public static function inverse($complex): Complex
502
    {
503
        $complex = clone Complex::validateComplexArgument($complex);
504
 
505
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
506
            throw new InvalidArgumentException('Division by zero');
507
        }
508
 
509
        return $complex->divideInto(1.0);
510
    }
511
 
512
    /**
513
     * Returns the natural logarithm of a complex number.
514
     *
515
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
516
     * @return    Complex          The natural logarithm of the complex argument.
517
     * @throws    Exception        If argument isn't a valid real or complex number.
518
     * @throws    InvalidArgumentException  If the real and the imaginary parts are both zero
519
     */
520
    public static function ln($complex): Complex
521
    {
522
        $complex = Complex::validateComplexArgument($complex);
523
 
524
        if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
525
            throw new InvalidArgumentException();
526
        }
527
 
528
        return new Complex(
529
            \log(self::rho($complex)),
530
            self::theta($complex),
531
            $complex->getSuffix()
532
        );
533
    }
534
 
535
    /**
536
     * Returns the base-2 logarithm of a complex number.
537
     *
538
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
539
     * @return    Complex          The base-2 logarithm of the complex argument.
540
     * @throws    Exception        If argument isn't a valid real or complex number.
541
     * @throws    InvalidArgumentException  If the real and the imaginary parts are both zero
542
     */
543
    public static function log2($complex): Complex
544
    {
545
        $complex = Complex::validateComplexArgument($complex);
546
 
547
        if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
548
            throw new InvalidArgumentException();
549
        } elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
550
            return new Complex(\log($complex->getReal(), 2), 0.0, $complex->getSuffix());
551
        }
552
 
553
        return self::ln($complex)
554
            ->multiply(\log(Complex::EULER, 2));
555
    }
556
 
557
    /**
558
     * Returns the common logarithm (base 10) of a complex number.
559
     *
560
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
561
     * @return    Complex          The common logarithm (base 10) of the complex argument.
562
     * @throws    Exception        If argument isn't a valid real or complex number.
563
     * @throws    InvalidArgumentException  If the real and the imaginary parts are both zero
564
     */
565
    public static function log10($complex): Complex
566
    {
567
        $complex = Complex::validateComplexArgument($complex);
568
 
569
        if (($complex->getReal() == 0.0) && ($complex->getImaginary() == 0.0)) {
570
            throw new InvalidArgumentException();
571
        } elseif (($complex->getReal() > 0.0) && ($complex->getImaginary() == 0.0)) {
572
            return new Complex(\log10($complex->getReal()), 0.0, $complex->getSuffix());
573
        }
574
 
575
        return self::ln($complex)
576
            ->multiply(\log10(Complex::EULER));
577
    }
578
 
579
    /**
580
     * Returns the negative of a complex number.
581
     *
582
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
583
     * @return    Complex          The negative value of the complex argument.
584
     * @throws    Exception        If argument isn't a valid real or complex number.
585
     *
586
     * @see    rho
587
     *
588
     */
589
    public static function negative($complex): Complex
590
    {
591
        $complex = Complex::validateComplexArgument($complex);
592
 
593
        return new Complex(
594
            -1 * $complex->getReal(),
595
            -1 * $complex->getImaginary(),
596
            $complex->getSuffix()
597
        );
598
    }
599
 
600
    /**
601
     * Returns a complex number raised to a power.
602
     *
603
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
604
     * @param     float|integer    $power      The power to raise this value to
605
     * @return    Complex          The complex argument raised to the real power.
606
     * @throws    Exception        If the power argument isn't a valid real
607
     */
608
    public static function pow($complex, $power): Complex
609
    {
610
        $complex = Complex::validateComplexArgument($complex);
611
 
612
        if (!is_numeric($power)) {
613
            throw new Exception('Power argument must be a real number');
614
        }
615
 
616
        if ($complex->getImaginary() == 0.0 && $complex->getReal() >= 0.0) {
617
            return new Complex(\pow($complex->getReal(), $power));
618
        }
619
 
620
        $rValue = \sqrt(($complex->getReal() * $complex->getReal()) + ($complex->getImaginary() * $complex->getImaginary()));
621
        $rPower = \pow($rValue, $power);
622
        $theta = $complex->argument() * $power;
623
        if ($theta == 0) {
624
            return new Complex(1);
625
        }
626
 
627
        return new Complex($rPower * \cos($theta), $rPower * \sin($theta), $complex->getSuffix());
628
    }
629
 
630
    /**
631
     * Returns the rho of a complex number.
632
     * This is the distance/radius from the centrepoint to the representation of the number in polar coordinates.
633
     *
634
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
635
     * @return    float            The rho value of the complex argument.
636
     * @throws    Exception        If argument isn't a valid real or complex number.
637
     */
638
    public static function rho($complex): float
639
    {
640
        $complex = Complex::validateComplexArgument($complex);
641
 
642
        return \sqrt(
643
            ($complex->getReal() * $complex->getReal()) +
644
            ($complex->getImaginary() * $complex->getImaginary())
645
        );
646
    }
647
 
648
    /**
649
     * Returns the secant of a complex number.
650
     *
651
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
652
     * @return    Complex          The secant of the complex argument.
653
     * @throws    Exception        If argument isn't a valid real or complex number.
654
     * @throws    \InvalidArgumentException    If function would result in a division by zero
655
     */
656
    public static function sec($complex): Complex
657
    {
658
        $complex = Complex::validateComplexArgument($complex);
659
 
660
        return self::inverse(self::cos($complex));
661
    }
662
 
663
    /**
664
     * Returns the hyperbolic secant of a complex number.
665
     *
666
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
667
     * @return    Complex          The hyperbolic secant of the complex argument.
668
     * @throws    Exception        If argument isn't a valid real or complex number.
669
     * @throws    \InvalidArgumentException    If function would result in a division by zero
670
     */
671
    public static function sech($complex): Complex
672
    {
673
        $complex = Complex::validateComplexArgument($complex);
674
 
675
        return self::inverse(self::cosh($complex));
676
    }
677
 
678
    /**
679
     * Returns the sine of a complex number.
680
     *
681
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
682
     * @return    Complex          The sine of the complex argument.
683
     * @throws    Exception        If argument isn't a valid real or complex number.
684
     */
685
    public static function sin($complex): Complex
686
    {
687
        $complex = Complex::validateComplexArgument($complex);
688
 
689
        if ($complex->isReal()) {
690
            return new Complex(\sin($complex->getReal()));
691
        }
692
 
693
        return new Complex(
694
            \sin($complex->getReal()) * \cosh($complex->getImaginary()),
695
            \cos($complex->getReal()) * \sinh($complex->getImaginary()),
696
            $complex->getSuffix()
697
        );
698
    }
699
 
700
    /**
701
     * Returns the hyperbolic sine of a complex number.
702
     *
703
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
704
     * @return    Complex          The hyperbolic sine of the complex argument.
705
     * @throws    Exception        If argument isn't a valid real or complex number.
706
     */
707
    public static function sinh($complex): Complex
708
    {
709
        $complex = Complex::validateComplexArgument($complex);
710
 
711
        if ($complex->isReal()) {
712
            return new Complex(\sinh($complex->getReal()));
713
        }
714
 
715
        return new Complex(
716
            \sinh($complex->getReal()) * \cos($complex->getImaginary()),
717
            \cosh($complex->getReal()) * \sin($complex->getImaginary()),
718
            $complex->getSuffix()
719
        );
720
    }
721
 
722
    /**
723
     * Returns the square root of a complex number.
724
     *
725
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
726
     * @return    Complex          The Square root of the complex argument.
727
     * @throws    Exception        If argument isn't a valid real or complex number.
728
     */
729
    public static function sqrt($complex): Complex
730
    {
731
        $complex = Complex::validateComplexArgument($complex);
732
 
733
        $theta = self::theta($complex);
734
        $delta1 = \cos($theta / 2);
735
        $delta2 = \sin($theta / 2);
736
        $rho = \sqrt(self::rho($complex));
737
 
738
        return new Complex($delta1 * $rho, $delta2 * $rho, $complex->getSuffix());
739
    }
740
 
741
    /**
742
     * Returns the tangent of a complex number.
743
     *
744
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
745
     * @return    Complex          The tangent of the complex argument.
746
     * @throws    Exception        If argument isn't a valid real or complex number.
747
     * @throws    InvalidArgumentException    If function would result in a division by zero
748
     */
749
    public static function tan($complex): Complex
750
    {
751
        $complex = Complex::validateComplexArgument($complex);
752
 
753
        if ($complex->isReal()) {
754
            return new Complex(\tan($complex->getReal()));
755
        }
756
 
757
        $real = $complex->getReal();
758
        $imaginary = $complex->getImaginary();
759
        $divisor = 1 + \pow(\tan($real), 2) * \pow(\tanh($imaginary), 2);
760
        if ($divisor == 0.0) {
761
            throw new InvalidArgumentException('Division by zero');
762
        }
763
 
764
        return new Complex(
765
            \pow(self::sech($imaginary)->getReal(), 2) * \tan($real) / $divisor,
766
            \pow(self::sec($real)->getReal(), 2) * \tanh($imaginary) / $divisor,
767
            $complex->getSuffix()
768
        );
769
    }
770
 
771
    /**
772
     * Returns the hyperbolic tangent of a complex number.
773
     *
774
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
775
     * @return    Complex          The hyperbolic tangent of the complex argument.
776
     * @throws    Exception        If argument isn't a valid real or complex number.
777
     * @throws    \InvalidArgumentException    If function would result in a division by zero
778
     */
779
    public static function tanh($complex): Complex
780
    {
781
        $complex = Complex::validateComplexArgument($complex);
782
        $real = $complex->getReal();
783
        $imaginary = $complex->getImaginary();
784
        $divisor = \cos($imaginary) * \cos($imaginary) + \sinh($real) * \sinh($real);
785
        if ($divisor == 0.0) {
786
            throw new InvalidArgumentException('Division by zero');
787
        }
788
 
789
        return new Complex(
790
            \sinh($real) * \cosh($real) / $divisor,
791
            0.5 * \sin(2 * $imaginary) / $divisor,
792
            $complex->getSuffix()
793
        );
794
    }
795
 
796
    /**
797
     * Returns the theta of a complex number.
798
     *   This is the angle in radians from the real axis to the representation of the number in polar coordinates.
799
     *
800
     * @param     Complex|mixed    $complex    Complex number or a numeric value.
801
     * @return    float            The theta value of the complex argument.
802
     * @throws    Exception        If argument isn't a valid real or complex number.
803
     */
804
    public static function theta($complex): float
805
    {
806
        $complex = Complex::validateComplexArgument($complex);
807
 
808
        if ($complex->getReal() == 0.0) {
809
            if ($complex->isReal()) {
810
                return 0.0;
811
            } elseif ($complex->getImaginary() < 0.0) {
812
                return M_PI / -2;
813
            }
814
            return M_PI / 2;
815
        } elseif ($complex->getReal() > 0.0) {
816
            return \atan($complex->getImaginary() / $complex->getReal());
817
        } elseif ($complex->getImaginary() < 0.0) {
818
            return -(M_PI - \atan(\abs($complex->getImaginary()) / \abs($complex->getReal())));
819
        }
820
 
821
        return M_PI - \atan($complex->getImaginary() / \abs($complex->getReal()));
822
    }
823
}