Class: AppMath::C
- Inherits:
-
Numeric
- Object
- Numeric
- AppMath::C
- Defined in:
- lib/cnum.rb
Overview
Class of arbitrary precision complex numbers. The underlying real numbers may be Float or R.
Instance Attribute Summary collapse
-
#im ⇒ Object
readonly
Returns the value of attribute im.
-
#re ⇒ Object
readonly
Returns the value of attribute re.
Class Method Summary collapse
-
.i ⇒ Object
The constant i.
-
.one ⇒ Object
The constant 1.
-
.ran(anInteger) ⇒ Object
Random value (sine-floor random generator).
-
.test(n0, verbose = false) ⇒ Object
Consistency test for class C This is intended to keep the class consistent despite of modifications.
-
.tob(anInteger, small = false) ⇒ Object
Test object.
-
.zero ⇒ Object
The constant 0.
Instance Method Summary collapse
-
#*(a) ⇒ Object
Returns the C-object self * a.
-
#**(a) ⇒ Object
Returns the a-th power of self.
-
#+(a) ⇒ Object
Returns the C-object self + a.
-
#+@ ⇒ Object
Unary plus operator.
-
#-(a) ⇒ Object
Returns the C-object self - a.
-
#-@ ⇒ Object
Unary minus operator.
-
#/(a) ⇒ Object
Returns the C-object self / a.
-
#<=>(a) ⇒ Object
The order relation is here lexicographic ordering based on the agreement that re is the ‘first letter’ and im the ‘second letter’ of ‘the word’.
-
#abs ⇒ Object
Returns the absolute value of self.
-
#abs2 ⇒ Object
Returns the absolute value squared of self.
-
#acos ⇒ Object
Inverse cosine.
-
#acosh ⇒ Object
Inverse hyperbolic cosine.
-
#acot ⇒ Object
Inverse cotangent.
-
#acoth ⇒ Object
Inverse hyperbolic cotangent.
-
#arg ⇒ Object
Returns the argument (i.e. the polar angle) of self.
-
#asin ⇒ Object
Inverse sine.
-
#asinh ⇒ Object
Inverse hyperbolic sine.
-
#atan ⇒ Object
Inverse tangent.
-
#atanh ⇒ Object
Inverse hyperbolic tangent.
- #clone ⇒ Object
-
#complex? ⇒ Boolean
Supports the unified treatment of real and complex numbers.
-
#conj ⇒ Object
(Complex) conjugation, no effect on real numbers.
-
#cos ⇒ Object
Cosine.
-
#cosh ⇒ Object
Hyperbolic cosine.
-
#cot ⇒ Object
Cotangent.
-
#coth ⇒ Object
Hyperbolic cotangent.
-
#dbi ⇒ Object
Returns self divided by i.
-
#dis(aC) ⇒ Object
Returns a kind of relative distance between self and aR.
-
#exp ⇒ Object
Exponential function.
-
#expi ⇒ Object
Exponential function of the argument multiplied by C.i.
-
#infinite? ⇒ Boolean
Returns ‘true’ if the real art or the iaginary part of self is infinite.
-
#initialize(*arg) ⇒ C
constructor
A new instance of C.
-
#integer? ⇒ Boolean
Since R is not Fixnum or Bignum we return ‘false’.
-
#inv ⇒ Object
Returns the inverse 1/self.
-
#log ⇒ Object
Natural logarithm.
-
#nan? ⇒ Boolean
Returns ‘true’ if self is ‘not a number’ (NaN).
-
#prn(name) ⇒ Object
Printing the value together with a label.
-
#pseudo_inv ⇒ Object
The pseudo_inverse of zero is zero, and equal to the inverse for all other arguments.
-
#real? ⇒ Boolean
Supports the unified treatment of real and complex numbers.
-
#round(n) ⇒ Object
For the return value res we have res.int? true and (self - res).abs <= 0.5.
-
#sin ⇒ Object
Sine.
-
#sinh ⇒ Object
Hyperbolic sine.
-
#sqrt ⇒ Object
Returns the square root of self.
-
#tan ⇒ Object
Tangent.
-
#tanh ⇒ Object
Hyperbolic tangent.
-
#ti ⇒ Object
Returns self times i.
-
#to_0 ⇒ Object
Returns the zero-element which belongs to the same class than self.
-
#to_1 ⇒ Object
Returns the unit-element which belongs to the same class than self.
-
#to_s ⇒ Object
Conversion to String.
-
#zero? ⇒ Boolean
Returns ‘true’ iff self == C(0,0).
Constructor Details
#initialize(*arg) ⇒ C
Returns a new instance of C.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/cnum.rb', line 41 def initialize(*arg) n = arg.size case n when 0 @re = R.c0 @im = R.c0 when 1 a0 = arg[0] if a0.integer? || a0.real? @re = R.c a0 @im = R.c0 elsif a0.complex? @re = R.c a0.re @im = R.c a0.im else fail "can't construct a C from this argument" end when 2 a0 = R.c arg[0]; a1 = R.c arg[1] @re = a0 @im = a1 else fail "can't construct a C from more than two arguments" end end |
Instance Attribute Details
#im ⇒ Object (readonly)
Returns the value of attribute im.
39 40 41 |
# File 'lib/cnum.rb', line 39 def im @im end |
#re ⇒ Object (readonly)
Returns the value of attribute re.
39 40 41 |
# File 'lib/cnum.rb', line 39 def re @re end |
Class Method Details
.ran(anInteger) ⇒ Object
Random value (sine-floor random generator).
Chaotic function from the integers into the subset [0,1] x [0,1] of C
88 89 90 91 92 93 |
# File 'lib/cnum.rb', line 88 def C.ran(anInteger) ai = anInteger.to_i * 2 x1 = R.ran(ai) x2 = R.ran(ai + 1) C.new(x1,x2) end |
.test(n0, verbose = false) ⇒ Object
Consistency test for class C This is intended to keep the class consistent despite of modifications. The first argument influences the numbers which are selected for the test. Returned is a sum of numbers each of which should be numerical noise and so the result has to be << 1 if the test is to indicate success. For instance, on my system
Doing C.test(n = 137, verbose = false) for R.dig = 100:
*************************************************
class of s is AppMath::R
class of s is AppMath::R .
The error sum s is 0.95701879151814897746312007872622225589589551941
73186692168823486932509515793972625242699350133964052E-98 .
It should be close to 0.
Computation time was 1.062 seconds.
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 |
# File 'lib/cnum.rb', line 425 def C.test(n0, verbose = false ) puts "Doing C.test(n = #{n0}, verbose = #{verbose})" + " for R.dig = #{R.dig}:" puts "*************************************************" t1 = Time.now small = true # otherwise not all inverse function tests work well s = R.c0 puts "class of s is " + s.class.to_s i = n0 a = C.tob(i,small) i += 1 b = C.tob(i,small) i += 1 c = C.tob(i,small) i += 1 if verbose a.prn("a") b.prn("b") c.prn("c") end r = 2 + a l = a + 2 ds = r.dis(l) puts "coerce 2 + a: ds = " + ds.to_s if verbose s += ds r = a + 1.234 l = a + R.c(1.234) ds = r.dis(l) puts "coerce a + float: ds = " + ds.to_s if verbose s += ds r = (a + b) * c l = a * c + b * c ds = r.dis(l) puts "Distributive law for +: ds = " + ds.to_s if verbose s += ds r = (a - b) * c l = a * c - b * c ds = r.dis(l) puts "Distributive law for -: ds = " + ds.to_s if verbose s += ds r = (a * b) * c l = b * (c * a) ds = r.dis(l) puts "Multiplication: ds = " + ds.to_s if verbose s += ds r = (a * b) / c l = (a / c) * b ds = r.dis(l) puts "Division: ds = " + ds.to_s if verbose s += ds r = C.one l = a * a.inv ds = r.dis(l) puts "inv: ds = " + ds.to_s if verbose s += ds r = 1/a l = a.inv ds = r.dis(l) puts "inv and 1/x: ds = " + ds.to_s if verbose s += ds r = b l = -(-b) ds = r.dis(l) puts "Unary minus is idempotent: ds = " + ds.to_s if verbose s += ds x = -a y = x + a r = y l = C.zero ds = r.dis(l) puts "Unary -: ds = " + ds.to_s if verbose s += ds l = a x = a.sqrt r = x * x s = r.dis(l) puts "square root: ds = " + ds.to_s if verbose s += ds n = 11 l = a ** n r = a ** C.new(n) ds = r.dis(l) puts "power with integer exponent: ds = " + ds.to_s if verbose s += ds n = -7 l = a ** n r = a ** C.new(n) ds = r.dis(l) puts "power with negative integer exponent: ds = " + ds.to_s if verbose s += ds l = -C.one r = (C.i * R.pi).exp ds = r.dis(l) puts "Euler's relation: ds = " + ds.to_s if verbose s += ds l = a.sin * b.cos + a.cos * b.sin r = (a + b).sin ds = r.dis(l) puts "Addition theorem for sin: ds = " + ds.to_s if verbose s += ds l = a.exp * b.exp r = (a + b).exp ds = r.dis(l) puts "Addition theorem for exp: ds = " + ds.to_s if verbose s += ds l = b.exp r = l.log.exp ds = r.dis(l) puts "exp and log: ds = " + ds.to_s if verbose s += ds l = c.sin r = l.asin.sin ds = r.dis(l) puts "sin and asin: ds = " + ds.to_s if verbose s += ds l = b.cos r = l.acos.cos ds = r.dis(l) puts "cos and acos: ds = " + ds.to_s if verbose s += ds l = a.tan r = l.atan.tan ds = r.dis(l) puts "tan and atan: ds = " + ds.to_s if verbose s += ds l = a.cot r = l.acot.cot ds = r.dis(l) puts "cot and acot: ds = " + ds.to_s if verbose s += ds l = c.sinh r = l.asinh.sinh ds = r.dis(l) puts "sinh and asinh: ds = " + ds.to_s if verbose s += ds l = a.cosh r = l.acosh.cosh ds = r.dis(l) puts "cosh and acosh: ds = " + ds.to_s if verbose s += ds l = b.tanh r = l.atanh.tanh ds = r.dis(l) puts "tanh and atanh: ds = " + ds.to_s if verbose s += ds l = a.coth r = l.acoth.coth ds = r.dis(l) puts "coth and acoth: ds = " + ds.to_s if verbose s += ds t2 = Time.now puts "class of s is " + s.class.to_s + " ." puts "The error sum s is " + s.to_s + " ." puts "It should be close to 0." puts "Computation time was #{t2-t1} seconds." s end |
.tob(anInteger, small = false) ⇒ Object
Test object.
Needed for automatic tests of arithmetic relations. Intended to give numbers which rapidly change sign and order of magnitude when the argument grows regularly e.g. as in 1,2,3,… . However, suitibility as a random generator is not the focus. If the second argument is ‘true’, the result is multplied by a number << 1 in order to prevent the result from overloading the exponential function.
105 106 107 108 109 110 |
# File 'lib/cnum.rb', line 105 def C.tob(anInteger, small = false) ai = anInteger.to_i * 2 x1 = R.tob(ai,small) x2 = R.tob(ai + 1,small) C.new(x1,x2) end |
Instance Method Details
#*(a) ⇒ Object
Returns the C-object self * a.
205 206 207 208 209 210 211 212 213 214 |
# File 'lib/cnum.rb', line 205 def *(a) if a.integer? || a.real? b = R.c a C.new(@re * b, @im * b) elsif a.complex? C.new(@re * a.re - @im * a.im , @re * a.im + @im * a.re ) else fail "cannot multiply a complex number with this argument" end end |
#**(a) ⇒ Object
Returns the a-th power of self. A may be integer, real, or complex. The result is always complex.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/cnum.rb', line 241 def **(a) return C.nan if nan? if a.integer? if a.zero? C.one elsif a == 1 self elsif a == -1 inv else b = a.abs res = self for i in 1...b res *= self end if a < 0 res = res.inv end res end elsif a.real? b = C.new(a) (log * b).exp elsif a.complex? (log * a).exp else fail "Argument not acceptable as an exponent" end end |
#+(a) ⇒ Object
Returns the C-object self + a.
180 181 182 183 184 185 186 187 188 189 |
# File 'lib/cnum.rb', line 180 def +(a) if a.integer? || a.real? b = R.c a C.new(@re + b, @im) elsif a.complex? C.new(@re + a.re, @im + a.im) else fail "cannot add this argument to a complex number" end end |
#+@ ⇒ Object
Unary plus operator. It returns the C-object self.
116 |
# File 'lib/cnum.rb', line 116 def +@; self; end |
#-(a) ⇒ Object
Returns the C-object self - a.
192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/cnum.rb', line 192 def -(a) if a.integer? || a.real? b = R.c a C.new(@re - b, @im) elsif a.complex? C.new(@re - a.re, @im - a.im) else fail "cannot subtract this argument from a complex number" end end |
#-@ ⇒ Object
Unary minus operator. It returns the C-object -self.
113 |
# File 'lib/cnum.rb', line 113 def -@; C.new(-@re, -@im); end |
#/(a) ⇒ Object
Returns the C-object self / a.
217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/cnum.rb', line 217 def /(a) if a.integer? || a.real? b = R.c a C.new(@re / b, @im / b) elsif a.complex? r2 = a.abs2 C.new((@re * a.re + @im * a.im)/r2 , (@im * a.re - @re * a.im)/r2 ) else fail "cannot divide a complex number by this argument" end end |
#<=>(a) ⇒ Object
The order relation is here lexicographic ordering based on the agreement that re is the ‘first letter’ and im the ‘second letter’ of ‘the word’. Needed only for book-keeping purposes.
149 150 151 152 153 154 155 |
# File 'lib/cnum.rb', line 149 def <=> (a) cr = @re <=> a.re return cr unless cr.zero? ci = @im <=> a.im return ci unless ci.zero? return 0 end |
#abs ⇒ Object
Returns the absolute value of self.
129 |
# File 'lib/cnum.rb', line 129 def abs; @re.hypot(@im); end |
#abs2 ⇒ Object
Returns the absolute value squared of self.
132 |
# File 'lib/cnum.rb', line 132 def abs2; @re * @re + @im * @im; end |
#acos ⇒ Object
Inverse cosine.
394 395 396 |
# File 'lib/cnum.rb', line 394 def acos acosh.dbi end |
#acosh ⇒ Object
Inverse hyperbolic cosine.
374 375 376 |
# File 'lib/cnum.rb', line 374 def acosh ((self * self - C.one).sqrt + self).log end |
#acot ⇒ Object
Inverse cotangent.
404 405 406 |
# File 'lib/cnum.rb', line 404 def acot ti.acoth.ti end |
#acoth ⇒ Object
Inverse hyperbolic cotangent.
384 385 386 |
# File 'lib/cnum.rb', line 384 def acoth ((self + C.one)/(self - C.one)).log * R.i2 end |
#arg ⇒ Object
Returns the argument (i.e. the polar angle) of self.
135 |
# File 'lib/cnum.rb', line 135 def arg; @re.arg(@im); end |
#asin ⇒ Object
Inverse sine.
389 390 391 |
# File 'lib/cnum.rb', line 389 def asin ti.asinh.dbi end |
#asinh ⇒ Object
Inverse hyperbolic sine.
369 370 371 |
# File 'lib/cnum.rb', line 369 def asinh ((self * self + C.one).sqrt + self).log end |
#atan ⇒ Object
Inverse tangent.
399 400 401 |
# File 'lib/cnum.rb', line 399 def atan ti.atanh.dbi end |
#atanh ⇒ Object
Inverse hyperbolic tangent.
379 380 381 |
# File 'lib/cnum.rb', line 379 def atanh ((C.one + self)/(C.one - self)).log * R.i2 end |
#complex? ⇒ Boolean
Supports the unified treatment of real and complex numbers.
177 |
# File 'lib/cnum.rb', line 177 def complex?; true; end |
#conj ⇒ Object
(Complex) conjugation, no effect on real numbers. Supports the unified treatment of real and complex numbers.
120 |
# File 'lib/cnum.rb', line 120 def conj; C.new(@re, -@im); end |
#cos ⇒ Object
Cosine.
334 335 336 |
# File 'lib/cnum.rb', line 334 def cos (expi + (-self).expi) * R.i2 end |
#cosh ⇒ Object
Hyperbolic cosine.
352 |
# File 'lib/cnum.rb', line 352 def cosh; (exp + (-self).exp) * R.i2; end |
#cot ⇒ Object
Cotangent.
344 345 346 |
# File 'lib/cnum.rb', line 344 def cot cos / sin end |
#coth ⇒ Object
Hyperbolic cotangent.
362 363 364 365 366 |
# File 'lib/cnum.rb', line 362 def coth s = exp - (-self).exp c = exp + (-self).exp c/s end |
#dbi ⇒ Object
Returns self divided by i.
126 |
# File 'lib/cnum.rb', line 126 def dbi; self * C.new(0,-1); end |
#dis(aC) ⇒ Object
Returns a kind of relative distance between self and aR. The return value varies from 0 to 1, where 1 means maximum dissimilarity of the arguments. Such a function is needed for testing the validity of arithmetic laws, which, due to numerical noise, should not be expected to be fulfilled exactly.
309 310 311 312 313 314 315 316 317 |
# File 'lib/cnum.rb', line 309 def dis(aC) a = abs b = aC.abs d = (self - aC).abs s = a + b return R.c0 if s.zero? d1 = d/s Basics.inf(d,d1) end |
#exp ⇒ Object
Exponential function.
230 |
# File 'lib/cnum.rb', line 230 def exp; C.new(@im.cos, @im.sin) * @re.exp; end |
#expi ⇒ Object
Exponential function of the argument multiplied by C.i
233 |
# File 'lib/cnum.rb', line 233 def expi; (self * C.i).exp; end |
#infinite? ⇒ Boolean
Returns ‘true’ if the real art or the iaginary part of self is infinite.
165 |
# File 'lib/cnum.rb', line 165 def infinite?; @re.infinite? || @im.infinite?; end |
#integer? ⇒ Boolean
Since R is not Fixnum or Bignum we return ‘false’. In scientific computation there may be the need to use various types of ‘real number types’ but there should always a clear-cut distinction between integer types and real types.
171 |
# File 'lib/cnum.rb', line 171 def integer?; false; end |
#inv ⇒ Object
Returns the inverse 1/self.
278 279 280 |
# File 'lib/cnum.rb', line 278 def inv C.one / self end |
#log ⇒ Object
Natural logarithm.
237 |
# File 'lib/cnum.rb', line 237 def log; C.new(abs.log,arg); end |
#nan? ⇒ Boolean
Returns ‘true’ if self is ‘not a number’ (NaN).
161 |
# File 'lib/cnum.rb', line 161 def nan?; @re.nan? || @im.nan?; end |
#prn(name) ⇒ Object
Printing the value together with a label
323 324 325 |
# File 'lib/cnum.rb', line 323 def prn(name) puts "#{name} = " + to_s end |
#pseudo_inv ⇒ Object
The pseudo_inverse of zero is zero, and equal to the inverse for all other arguments.
287 288 289 |
# File 'lib/cnum.rb', line 287 def pseudo_inv zero? ? C.zero : C.one / self end |
#real? ⇒ Boolean
Supports the unified treatment of real and complex numbers.
174 |
# File 'lib/cnum.rb', line 174 def real?; false; end |
#round(n) ⇒ Object
For the return value res we have res.int? true and (self - res).abs <= 0.5
292 293 294 295 296 |
# File 'lib/cnum.rb', line 292 def round(n) u = @re.round(n) v = @im.round(n) C.new(u,v) end |
#sin ⇒ Object
Sine.
329 330 331 |
# File 'lib/cnum.rb', line 329 def sin (expi - (-self).expi) * C.new(0,-R.i2) end |
#sinh ⇒ Object
Hyperbolic sine.
349 |
# File 'lib/cnum.rb', line 349 def sinh; (exp - (-self).exp) * R.i2; end |
#sqrt ⇒ Object
Returns the square root of self.
299 300 301 |
# File 'lib/cnum.rb', line 299 def sqrt self ** R.i2 end |
#tan ⇒ Object
Tangent.
339 340 341 |
# File 'lib/cnum.rb', line 339 def tan sin / cos end |
#tanh ⇒ Object
Hyperbolic tangent.
355 356 357 358 359 |
# File 'lib/cnum.rb', line 355 def tanh s = exp - (-self).exp c = exp + (-self).exp s/c end |
#to_0 ⇒ Object
Returns the zero-element which belongs to the same class than self
272 |
# File 'lib/cnum.rb', line 272 def to_0; C.zero; end |
#to_1 ⇒ Object
Returns the unit-element which belongs to the same class than self
275 |
# File 'lib/cnum.rb', line 275 def to_1; C.one; end |
#to_s ⇒ Object
Conversion to String.
320 |
# File 'lib/cnum.rb', line 320 def to_s; "C(#{@re}, #{@im})"; end |
#zero? ⇒ Boolean
Returns ‘true’ iff self == C(0,0)
158 |
# File 'lib/cnum.rb', line 158 def zero?; @re.zero? && @im.zero?; end |