├── .document ├── .github ├── dependabot.yml └── workflows │ └── test.yml ├── .gitignore ├── .rdoc_options ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── cmath.gemspec ├── lib └── cmath.rb ├── rakelib └── epoch.rake └── test ├── lib └── helper.rb └── test_cmath.rb /.document: -------------------------------------------------------------------------------- 1 | *.txt 2 | *.md 3 | lib/ 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'github-actions' 4 | directory: '/' 5 | schedule: 6 | interval: 'weekly' 7 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | ruby-versions: 7 | uses: ruby/actions/.github/workflows/ruby_versions.yml@master 8 | with: 9 | engine: cruby 10 | min_version: 2.5 11 | 12 | test: 13 | needs: ruby-versions 14 | name: test (${{ matrix.ruby }} / ${{ matrix.os }}) 15 | strategy: 16 | matrix: 17 | ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }} 18 | os: [ ubuntu-latest, macos-latest, windows-latest ] 19 | runs-on: ${{ matrix.os }} 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Set up Ruby 23 | uses: ruby/setup-ruby@v1 24 | with: 25 | ruby-version: ${{ matrix.ruby }} 26 | bundler-cache: true 27 | - name: Run test 28 | run: bundle exec rake test 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /.rdoc_options: -------------------------------------------------------------------------------- 1 | --- 2 | main_page: README.md 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | gem "rake" 6 | gem "test-unit" 7 | gem "test-unit-ruby-core" 8 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 16 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 | SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMath 2 | 3 | Trigonometric and transcendental functions for complex numbers. 4 | 5 | CMath is a library that provides trigonometric and transcendental functions for complex numbers. The functions in this module accept integers, floating-point numbers or complex numbers as arguments. 6 | 7 | Note that the selection of functions is similar, but not identical, to that in module math. The reason for having two modules is that some users aren't interested in complex numbers, and perhaps don't even know what they are. They would rather have Math.sqrt(-1) raise an exception than return a complex number. 8 | 9 | For more information you can see Complex class. 10 | 11 | ## Installation 12 | 13 | Add this line to your application's Gemfile: 14 | 15 | ```ruby 16 | gem 'cmath' 17 | ``` 18 | 19 | And then execute: 20 | 21 | $ bundle 22 | 23 | Or install it yourself as: 24 | 25 | $ gem install cmath 26 | 27 | ## Usage 28 | 29 | To start using this library, simply require cmath library: 30 | 31 | ``` 32 | require "cmath" 33 | ``` 34 | 35 | ## Development 36 | 37 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 38 | 39 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 40 | 41 | ## Contributing 42 | 43 | Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/cmath. 44 | 45 | 46 | ## License 47 | 48 | The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause). 49 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rake/testtask" 3 | 4 | Rake::TestTask.new(:test) do |t| 5 | t.libs << "test/lib" 6 | t.ruby_opts << "-rhelper" 7 | t.test_files = FileList["test/**/test_*.rb"] 8 | end 9 | 10 | task :default => :test 11 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "cmath" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start(__FILE__) 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /cmath.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # frozen_string_literal: true 3 | 4 | version = File.read("#{__dir__}/lib/cmath.rb")[/^\s*VERSION\s*=\s*"([^"]*)"/, 1] 5 | Gem::Specification.new do |spec| 6 | spec.name = "cmath" 7 | spec.version = version 8 | spec.authors = ["Tadayoshi Funaba"] 9 | spec.email = ["tadf@dotrb.org"] 10 | 11 | spec.summary = "Provides Trigonometric and Transcendental functions for complex numbers" 12 | spec.description = "CMath is a library that provides trigonometric and transcendental functions for complex numbers. The functions in this module accept integers, floating-point numbers or complex numbers as arguments." 13 | spec.homepage = "https://github.com/ruby/cmath" 14 | spec.license = "BSD-2-Clause" 15 | 16 | spec.files = %w[.document .rdoc_options LICENSE.txt README.md lib/cmath.rb] 17 | spec.bindir = "exe" 18 | spec.executables = [] 19 | spec.require_paths = ["lib"] 20 | spec.required_ruby_version = ">= 2.5.0" 21 | end 22 | -------------------------------------------------------------------------------- /lib/cmath.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | ## 3 | # = Trigonometric and transcendental functions for complex numbers. 4 | # 5 | # CMath is a library that provides trigonometric and transcendental 6 | # functions for complex numbers. The functions in this module accept 7 | # integers, floating-point numbers or complex numbers as arguments. 8 | # 9 | # Note that the selection of functions is similar, but not identical, 10 | # to that in module math. The reason for having two modules is that 11 | # some users aren't interested in complex numbers, and perhaps don't 12 | # even know what they are. They would rather have Math.sqrt(-1) raise 13 | # an exception than return a complex number. 14 | # 15 | # For more information you can see Complex class. 16 | # 17 | # == Usage 18 | # 19 | # To start using this library, simply require cmath library: 20 | # 21 | # require "cmath" 22 | 23 | module CMath 24 | 25 | include Math 26 | 27 | # The version string. 28 | VERSION = "1.0.0" 29 | 30 | # Backup of Math is needed because mathn.rb replaces Math with CMath. 31 | RealMath = Math # :nodoc: 32 | private_constant :RealMath 33 | 34 | module_function 35 | 36 | # Returns +false+ if _z_ is real but not in domain by the block. 37 | # If no block is given, domain is not limited. 38 | # If _z_ is not real, returns _nonreal_ that is defaulted to +false+. 39 | # If _z_ does not have +real?+ method, returns +true+. 40 | private def domain?(z, nonreal = false) # :nodoc: 41 | unless z.respond_to?(:real?) 42 | return true 43 | end 44 | if z.real? 45 | return defined?(yield) ? yield(z) : true 46 | else 47 | nonreal 48 | end 49 | end 50 | 51 | ## 52 | # Math::E raised to the +z+ power 53 | # 54 | # CMath.exp(1.i * Math::PI) #=> (-1.0+1.2246467991473532e-16i) 55 | def exp(z) 56 | if domain?(z) 57 | RealMath.exp(z) 58 | else 59 | Complex.polar(RealMath.exp(z.real), z.imag) 60 | end 61 | end 62 | 63 | ## 64 | # Returns the natural logarithm of Complex. If a second argument is given, 65 | # it will be the base of logarithm. 66 | # 67 | # CMath.log(1 + 4i) #=> (1.416606672028108+1.3258176636680326i) 68 | # CMath.log(1 + 4i, 10) #=> (0.6152244606891369+0.5757952953408879i) 69 | def log(z, b=::Math::E) 70 | zpos = domain?(z) {!z.negative?} 71 | if domain?(b) {!b.negative?} 72 | if zpos 73 | RealMath.log(z, b) 74 | else 75 | Complex(RealMath.log(z.abs, b), (z.real? ? Math::PI : z.arg) / RealMath.log(b)) 76 | end 77 | else 78 | b = Complex(RealMath.log(b.abs), b.real? ? Math::PI : b.arg) 79 | if zpos 80 | RealMath.log(z) / b 81 | else 82 | Complex(RealMath.log(z.abs), z.real? ? Math::PI : z.arg) / b 83 | end 84 | end 85 | end 86 | 87 | ## 88 | # Returns the base 2 logarithm of +z+ 89 | # 90 | # CMath.log2(-1) => (0.0+4.532360141827194i) 91 | def log2(z) 92 | if domain?(z) {!z.negative?} 93 | RealMath.log2(z) 94 | else 95 | Complex(RealMath.log2(z.abs), z.arg / RealMath.log(2)) 96 | end 97 | end 98 | 99 | ## 100 | # Returns the base 10 logarithm of +z+ 101 | # 102 | # CMath.log10(-1) #=> (0.0+1.3643763538418412i) 103 | def log10(z) 104 | if domain?(z) {!z.negative?} 105 | RealMath.log10(z) 106 | else 107 | Complex(RealMath.log10(z.abs), z.arg / RealMath.log(10)) 108 | end 109 | end 110 | 111 | ## 112 | # Returns the non-negative square root of Complex. 113 | # 114 | # CMath.sqrt(-1 + 0i) #=> 0.0+1.0i 115 | def sqrt(z) 116 | if domain?(z, true) {!z.negative?} 117 | RealMath.sqrt(z) 118 | else 119 | Complex(0, RealMath.sqrt(-z)) 120 | end 121 | end 122 | 123 | ## 124 | # Returns the principal value of the cube root of +z+ 125 | # 126 | # CMath.cbrt(1 + 4i) #=> (1.449461632813119+0.6858152562177092i) 127 | def cbrt(z) 128 | z ** (1.0/3) 129 | end 130 | 131 | ## 132 | # Returns the sine of +z+, where +z+ is given in radians 133 | # 134 | # CMath.sin(1 + 1i) #=> (1.2984575814159773+0.6349639147847361i) 135 | def sin(z) 136 | if domain?(z) 137 | RealMath.sin(z) 138 | else 139 | Complex(RealMath.sin(z.real) * RealMath.cosh(z.imag), 140 | RealMath.cos(z.real) * RealMath.sinh(z.imag)) 141 | end 142 | end 143 | 144 | ## 145 | # Returns the cosine of +z+, where +z+ is given in radians 146 | # 147 | # CMath.cos(1 + 1i) #=> (0.8337300251311491-0.9888977057628651i) 148 | def cos(z) 149 | if domain?(z) 150 | RealMath.cos(z) 151 | else 152 | Complex(RealMath.cos(z.real) * RealMath.cosh(z.imag), 153 | -RealMath.sin(z.real) * RealMath.sinh(z.imag)) 154 | end 155 | end 156 | 157 | ## 158 | # Returns the tangent of +z+, where +z+ is given in radians 159 | # 160 | # CMath.tan(1 + 1i) #=> (0.27175258531951174+1.0839233273386943i) 161 | def tan(z) 162 | if domain?(z) 163 | RealMath.tan(z) 164 | else 165 | sin(z) / cos(z) 166 | end 167 | end 168 | 169 | ## 170 | # Returns the hyperbolic sine of +z+, where +z+ is given in radians 171 | # 172 | # CMath.sinh(1 + 1i) #=> (0.6349639147847361+1.2984575814159773i) 173 | def sinh(z) 174 | if domain?(z) 175 | RealMath.sinh(z) 176 | else 177 | Complex(RealMath.sinh(z.real) * RealMath.cos(z.imag), 178 | RealMath.cosh(z.real) * RealMath.sin(z.imag)) 179 | end 180 | end 181 | 182 | ## 183 | # Returns the hyperbolic cosine of +z+, where +z+ is given in radians 184 | # 185 | # CMath.cosh(1 + 1i) #=> (0.8337300251311491+0.9888977057628651i) 186 | def cosh(z) 187 | if domain?(z) 188 | RealMath.cosh(z) 189 | else 190 | Complex(RealMath.cosh(z.real) * RealMath.cos(z.imag), 191 | RealMath.sinh(z.real) * RealMath.sin(z.imag)) 192 | end 193 | end 194 | 195 | ## 196 | # Returns the hyperbolic tangent of +z+, where +z+ is given in radians 197 | # 198 | # CMath.tanh(1 + 1i) #=> (1.0839233273386943+0.27175258531951174i) 199 | def tanh(z) 200 | if domain?(z) 201 | RealMath.tanh(z) 202 | else 203 | sinh(z) / cosh(z) 204 | end 205 | end 206 | 207 | ## 208 | # Returns the arc sine of +z+ 209 | # 210 | # CMath.asin(1 + 1i) #=> (0.6662394324925153+1.0612750619050355i) 211 | def asin(z) 212 | if domain?(z) {(-1..1).cover?(z)} 213 | RealMath.asin(z) 214 | else 215 | -1i * log(1i * z + sqrt(1.0 - z * z)) 216 | end 217 | end 218 | 219 | ## 220 | # Returns the arc cosine of +z+ 221 | # 222 | # CMath.acos(1 + 1i) #=> (0.9045568943023813-1.0612750619050357i) 223 | def acos(z) 224 | if domain?(z) {(-1..1).cover?(z)} 225 | RealMath.acos(z) 226 | else 227 | -1i * log(z + 1i * sqrt(1.0 - z * z)) 228 | end 229 | end 230 | 231 | ## 232 | # Returns the arc tangent of +z+ 233 | # 234 | # CMath.atan(1 + 1i) #=> (1.0172219678978514+0.4023594781085251i) 235 | def atan(z) 236 | if domain?(z) 237 | RealMath.atan(z) 238 | else 239 | 1i * log((1i + z) / (1i - z)) / 2 240 | end 241 | end 242 | 243 | ## 244 | # returns the arc tangent of +y+ divided by +x+ using the signs of +y+ and 245 | # +x+ to determine the quadrant 246 | # 247 | # CMath.atan2(1 + 1i, 0) #=> (1.5707963267948966+0.0i) 248 | def atan2(y,x) 249 | if domain?(y) and domain?(x) 250 | RealMath.atan2(y,x) 251 | else 252 | -1i * log((x + 1i * y) / sqrt(x * x + y * y)) 253 | end 254 | end 255 | 256 | ## 257 | # returns the inverse hyperbolic sine of +z+ 258 | # 259 | # CMath.asinh(1 + 1i) #=> (1.0612750619050357+0.6662394324925153i) 260 | def asinh(z) 261 | if domain?(z) 262 | RealMath.asinh(z) 263 | else 264 | log(z + sqrt(1.0 + z * z)) 265 | end 266 | end 267 | 268 | ## 269 | # returns the inverse hyperbolic cosine of +z+ 270 | # 271 | # CMath.acosh(1 + 1i) #=> (1.0612750619050357+0.9045568943023813i) 272 | def acosh(z) 273 | if domain?(z) {z >= 1} 274 | RealMath.acosh(z) 275 | else 276 | log(z + sqrt(z * z - 1.0)) 277 | end 278 | end 279 | 280 | ## 281 | # returns the inverse hyperbolic tangent of +z+ 282 | # 283 | # CMath.atanh(1 + 1i) #=> (0.4023594781085251+1.0172219678978514i) 284 | def atanh(z) 285 | if domain?(z) {(-1..1).cover?(z)} 286 | RealMath.atanh(z) 287 | else 288 | log((1.0 + z) / (1.0 - z)) / 2.0 289 | end 290 | end 291 | 292 | end 293 | -------------------------------------------------------------------------------- /rakelib/epoch.rake: -------------------------------------------------------------------------------- 1 | task "build" => "date_epoch" 2 | 3 | task "date_epoch" do 4 | ENV["SOURCE_DATE_EPOCH"] = IO.popen(%W[git -C #{__dir__} log -1 --format=%ct], &:read).chomp 5 | end 6 | -------------------------------------------------------------------------------- /test/lib/helper.rb: -------------------------------------------------------------------------------- 1 | require "test/unit" 2 | require "core_assertions" 3 | 4 | Test::Unit::TestCase.include Test::Unit::CoreAssertions 5 | 6 | module Test 7 | module Unit 8 | class TestCase 9 | def assert_in_delta exp, act, delta = 0.001, msg = nil 10 | n = (exp - act).abs 11 | msg = message(msg) { 12 | "Expected |#{exp} - #{act}| (#{n}) to be <= #{delta}" 13 | } 14 | assert delta >= n, msg 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/test_cmath.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'test/unit' 3 | require 'cmath' 4 | 5 | class TestCMath < Test::Unit::TestCase 6 | def test_sqrt 7 | assert_equal 1, CMath.sqrt(1) 8 | assert_equal CMath.sqrt(1i), CMath.sqrt(1.0i), '[ruby-core:31672]' 9 | assert_equal Complex(0,2), CMath.sqrt(-4.0) 10 | assert_equal Complex(0,2), CMath.sqrt(-4) 11 | assert_equal Complex(0,2), CMath.sqrt(Rational(-4)) 12 | assert_equal Complex(0,3), CMath.sqrt(-9.0) 13 | assert_equal Complex(0,3), CMath.sqrt(-9) 14 | assert_equal Complex(0,3), CMath.sqrt(Rational(-9)) 15 | assert_in_delta (1.272019649514069+0.7861513777574233i), CMath.sqrt(1+2i) 16 | assert_in_delta 3.0i, CMath.sqrt(-9) 17 | assert_raise(TypeError) { CMath.sqrt("1") } 18 | end 19 | 20 | def test_log 21 | assert_in_delta (0.8047189562170503+1.1071487177940904i), CMath.log(1+2i) 22 | assert_in_delta (0.7324867603589635+1.0077701926457874i), CMath.log(1+2i,3) 23 | assert_in_delta Math::PI*1i , CMath.log(-1) 24 | assert_in_delta 3.0 , CMath.log(8, 2) 25 | assert_in_delta (1.092840647090816-0.42078724841586035i), CMath.log(-8, -2) 26 | end 27 | 28 | def test_trigonometric_functions 29 | assert_equal 0, CMath.asin(0) 30 | assert_equal 0, CMath.acos(1) 31 | assert_equal 0, CMath.atan(0) 32 | assert_equal 0, CMath.asinh(0) 33 | assert_equal 0, CMath.acosh(1) 34 | assert_equal 0, CMath.atanh(0) 35 | 36 | assert_in_delta CMath.sinh(2).i, CMath.sin(2i) 37 | assert_in_delta CMath.cosh(2), CMath.cos(2i) 38 | assert_in_delta CMath.tanh(2).i, CMath.tan(2i) 39 | 40 | assert_in_delta CMath.sin(2).i, CMath.sinh(2i) 41 | assert_in_delta CMath.cos(2), CMath.cosh(2i) 42 | assert_in_delta CMath.tan(2).i, CMath.tanh(2i) 43 | 44 | assert_in_delta 1+1i, CMath.sin(CMath.asin(1+1i)) 45 | assert_in_delta 1+1i, CMath.cos(CMath.acos(1+1i)) 46 | assert_in_delta 1+1i, CMath.tan(CMath.atan(1+1i)) 47 | 48 | assert_in_delta 1+1i, CMath.sinh(CMath.asinh(1+1i)) 49 | assert_in_delta 1+1i, CMath.cosh(CMath.acosh(1+1i)) 50 | assert_in_delta 1+1i, CMath.tanh(CMath.atanh(1+1i)) 51 | 52 | assert_in_delta (3.165778513216168+1.959601041421606i), CMath.sin(1+2i) 53 | assert_in_delta (2.0327230070196656-3.0518977991517997i), CMath.cos(1+2i) 54 | assert_in_delta (0.033812826079896774+1.0147936161466338i), CMath.tan(1+2i) 55 | assert_in_delta (-0.4890562590412937+1.4031192506220405i), CMath.sinh(1+2i) 56 | assert_in_delta (-0.64214812471552+1.0686074213827783i), CMath.cosh(1+2i) 57 | assert_in_delta (1.16673625724092-0.2434582011857252i), CMath.tanh(1+2i) 58 | assert_in_delta (0.4270785863924755+1.5285709194809978i), CMath.asin(1+2i) 59 | assert_in_delta (1.1437177404024204-1.528570919480998i), CMath.acos(1+2i) 60 | assert_in_delta (1.3389725222944935+0.4023594781085251i), CMath.atan(1+2i) 61 | assert_in_delta (1.4693517443681852+1.0634400235777521i), CMath.asinh(1+2i) 62 | assert_in_delta (1.528570919480998+1.1437177404024204i), CMath.acosh(1+2i) 63 | assert_in_delta (0.17328679513998635+1.1780972450961724i), CMath.atanh(1+2i) 64 | 65 | assert_raise(TypeError) { CMath.sin("0") } 66 | assert_raise(TypeError) { CMath.cos("0") } 67 | assert_raise(TypeError) { CMath.tan("0") } 68 | assert_raise(TypeError) { CMath.sinh("0") } 69 | assert_raise(TypeError) { CMath.cosh("0") } 70 | assert_raise(TypeError) { CMath.tanh("0") } 71 | assert_raise(TypeError) { CMath.asin("0") } 72 | assert_raise(TypeError) { CMath.atan("0") } 73 | assert_raise(TypeError) { CMath.asinh("0") } 74 | assert_raise(TypeError) { CMath.acosh("0") } 75 | assert_raise(TypeError) { CMath.atanh("0") } 76 | end 77 | 78 | def test_functions 79 | assert_equal (1), CMath.exp(0) 80 | assert_in_delta (-1.1312043837568135+2.4717266720048188i), CMath.exp(1+2i) 81 | assert_in_delta (-1), CMath.exp(Math::PI.i) 82 | assert_raise(TypeError) { CMath.exp("0") } 83 | 84 | assert_equal (0), CMath.log2(1) 85 | assert_in_delta (1.1609640474436813+1.5972779646881088i), CMath.log2(1+2i) 86 | assert_raise(TypeError) { CMath.log2("1") } 87 | 88 | assert_equal (0), CMath.log10(1) 89 | assert_in_delta (0.3494850021680094+0.480828578784234i), CMath.log10(1+2i) 90 | assert_raise(TypeError) { CMath.log10("1") } 91 | 92 | assert_equal (0), CMath.atan2(0,1) 93 | assert_in_delta (1.3389725222944935+0.4023594781085251i), CMath.atan2(1+2i,1) 94 | assert_raise(TypeError) { CMath.atan2("0", 1) } 95 | end 96 | 97 | def test_error_handling 98 | assert_raise(TypeError) { CMath.acos("2") } 99 | assert_raise(TypeError) { CMath.log("2") } 100 | assert_raise(TypeError) { CMath.log(2, "2") } 101 | end 102 | 103 | def test_cbrt_returns_principal_value_of_cube_root 104 | assert_equal (-8)**(1.0/3), CMath.cbrt(-8), '#3676' 105 | end 106 | end 107 | --------------------------------------------------------------------------------