Code Monkey home page Code Monkey logo

multiplesofpi.jl's Introduction

MultiplesOfPi

CI Codecov Coverage Status docs:stable docs:dev

Introduction

This package exports the type PiExpTimes that satisfies PiExpTimes(x, n) = x*π^n. It also provides the constant Pi for convenience, defined as PiExpTimes(1, 1), that behaves like π except it produces results with higher accuracy in certain trigonometric and algebraic contexts. In most scenarios the numbers Pi and π are interchangable. Expressing mathematical relations in terms of Pi instead of the more cumbersome PiExpTimes is usually cleaner, and is recommended unless it's specifically necessary to do otherwise.

Rationale

The number π is represented as an Irrational type in julia, and may be computed to an arbitrary degree of precision. In normal course of events it is converted to a float when it encounters another number, for example is computed by converting both 2 and π to floats and subsequently carrying out a floating-point multiplication. This is lossy, as both 2 and π may be represented with arbitrary precision. This package delays the conversion of the π to a float, treating it as a common factor in algebraic simplifications. This limits floating-point inaccuracies, especially if the terms multiplying π are exactly representable in binary. As an added advantage, it uses sinpi and cospi wherever possible to avoid having to convert π to a float altogether.

Features

Arithmetic

Delaying the conversion of π to a float results in precise mathematical expressions such as

Using πUsing Pi
julia> (1//3+ (4//3== (5//3false

julia> float(sqrt(pi)^2) == float(pi)
false
julia> (1//3)Pi + (4//3)Pi == (5//3)Pi
true

julia> float(sqrt(Pi)^2) == float(Pi)
true

We may also simplify algebraic expressions involving powers of Pi as

julia> (2Pi^2//3) // (4Pi//5)
(5//6)Pi

julia> Pi^-2 / 4Pi^3
0.25*Pi^-5

Expressions involving Pi are automatically promoted to Complex as necessary, eg.

julia> (1+im)Pi^3 / 2Pi^2
0.5*Pi + 0.5*Pi*im

julia> (1+im)Pi^3 / 2Pi^2 * 2/Pi
Pi^0 + Pi^0*im

Trigonometric functions

The type PiTimes uses sinpi and cospi under the hood when it is used as an argument to sin and cos. This results in exact results in several contexts where the inaccuracies arise from floating-point conversions.

Using πUsing Pi
julia> cos(3π/2)
-1.8369701987210297e-16

julia> sin(-π)
-1.2246467991473532e-16

julia> tan/2)
1.633123935319537e16
julia> cos(3Pi/2)
0.0

julia> sin(-Pi)
-0.0

julia> tan(Pi/2)
Inf

We may compute complex exponential exactly:

Using πUsing Pi
julia> exp(im*π/2)
6.123233995736766e-17 + 1.0im

# Euler's identity : exp(iπ) + 1 == 0
julia> exp(im*π) + 1
0.0 + 1.2246467991473532e-16im
julia> exp(im*Pi/2)
0.0 + 1.0im

# Euler's identity : exp(iπ) + 1 == 0
julia> exp(im*Pi) + 1
0.0 + 0.0im

Hyperbolic functions work as expected:

Using πUsing Pi
# cosh(ix) = cos(x)
# Should be exactly zero for x = π/2
julia> cosh(im*π/2)
6.123233995736766e-17 + 0.0im
# cosh(ix) = cos(x)
# Should be exactly zero for x = π/2
julia> cosh(im*Pi/2)
0.0 + 0.0im

Interactions with π

The irrational number π is usually aggressively converted to Pi, eg:

julia> π * Pi
Pi^2

This ensures that subsequent calculation would not get promoted to a floating-point type. However if this behavior is not desired then one may specify the type explicitly while constructing the object as

julia> PiExpTimes{Irrational{:π}}(π)
π*Pi^0

Floating-point promotion

Addition and subtraction involving mixed exponents of Pi will involve floating-point conversions, and the resulting expression will have the minimum exponent out of the terms being summed.

julia> Pi + 3Pi
4Pi

julia> Pi + 3Pi^2
10.42477796076938*Pi

This fits with the intuition of the expression being factorized as Pi + 3Pi^2 == Pi*(1 + 3Pi).

Note that π is promoted to Pi in such operations, so we obtain

julia> Pi + π
2Pi

Note that addition and subtraction are not type-stable at present by design.

Performance

In general using Pi instead of pi will be less performant, as pi is aggressively promoted to a floating-point value in most calculations. The use of Pi is mainly intended for tests where exact fractions of Pi are desirable.

Installation

Install the package using

pkg> add MultiplesOfPi

Related packages

multiplesofpi.jl's People

Contributors

garrison avatar jishnub avatar waldyrious avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

multiplesofpi.jl's Issues

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Two "Inf NAN zero check" test failures under Julia 1.8

I noticed two test failures under Julia 1.8. All tests pass under Julia 1.6 and 1.7.

Inf NaN zero check: Test Failed at /home/garrison/.julia/dev/MultiplesOfPi/test/runtests.jl:707
  Expression: isfinite(PiExpTimes(1, -Inf))
Stacktrace:
 [1] macro expansion
   @ /usr/share/julia/stdlib/v1.8/Test/src/Test.jl:464 [inlined]
 [2] macro expansion
   @ ~/.julia/dev/MultiplesOfPi/test/runtests.jl:707 [inlined]
 [3] macro expansion
   @ /usr/share/julia/stdlib/v1.8/Test/src/Test.jl:1357 [inlined]
 [4] top-level scope
   @ ~/.julia/dev/MultiplesOfPi/test/runtests.jl:697
Inf NaN zero check: Test Failed at /home/garrison/.julia/dev/MultiplesOfPi/test/runtests.jl:718
  Expression: iszero(Pi ^ -Inf)
Stacktrace:
 [1] macro expansion
   @ /usr/share/julia/stdlib/v1.8/Test/src/Test.jl:464 [inlined]
 [2] macro expansion
   @ ~/.julia/dev/MultiplesOfPi/test/runtests.jl:718 [inlined]
 [3] macro expansion
   @ /usr/share/julia/stdlib/v1.8/Test/src/Test.jl:1357 [inlined]
 [4] top-level scope
   @ ~/.julia/dev/MultiplesOfPi/test/runtests.jl:697
Test Summary:      | Pass  Fail  Total  Time
Inf NaN zero check |   19     2     21  0.3s

`[Pi, pi]` fails to evaluate

These work:

julia> [pi, 3.14]
2-element Vector{Float64}:
 3.141592653589793
 3.14

julia> Any[pi, Pi]
2-element Vector{Any}:
  π = 3.1415926535897...
 Pi

However,

julia> [pi, Pi]
ERROR: MethodError: no method matching Int64(::Irrational{:π})
Closest candidates are:
  (::Type{T})(::T) where T<:Number at boot.jl:772
  (::Type{T})(::AbstractChar) where T<:Union{Int32, Int64} at char.jl:51
  (::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
  ...
Stacktrace:
 [1] PiExpTimes{Int64, Int64}(x::Irrational{:π})
   @ MultiplesOfPi ~/.julia/dev/MultiplesOfPi/src/MultiplesOfPi.jl:26
 [2] convert(#unused#::Type{PiExpTimes{Int64, Int64}}, x::Irrational{:π})
   @ Base ./number.jl:7
 [3] setindex!(A::Vector{PiExpTimes{Int64, Int64}}, x::Irrational{:π}, i1::Int64)
   @ Base ./array.jl:966
 [4] copyto!(dest::Vector{PiExpTimes{Int64, Int64}}, src::Tuple{Irrational{:π}, PiExpTimes{Int64, Int64}})
   @ Base ./abstractarray.jl:904
 [5] vect(::Irrational{:π}, ::Vararg{Any})
   @ Base ./array.jl:147
 [6] top-level scope
   @ REPL[17]:1

The reverse order also fails:

julia> [Pi, pi]
ERROR: MethodError: no method matching Int64(::Irrational{:π})
Closest candidates are:
  (::Type{T})(::T) where T<:Number at boot.jl:772
  (::Type{T})(::AbstractChar) where T<:Union{Int32, Int64} at char.jl:51
  (::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
  ...
Stacktrace:
 [1] PiExpTimes{Int64, Int64}(x::Irrational{:π})
   @ MultiplesOfPi ~/.julia/dev/MultiplesOfPi/src/MultiplesOfPi.jl:26
 [2] convert(#unused#::Type{PiExpTimes{Int64, Int64}}, x::Irrational{:π})
   @ Base ./number.jl:7
 [3] setindex!(A::Vector{PiExpTimes{Int64, Int64}}, x::Irrational{:π}, i1::Int64)
   @ Base ./array.jl:966
 [4] copyto!(dest::Vector{PiExpTimes{Int64, Int64}}, src::Tuple{PiExpTimes{Int64, Int64}, Irrational{:π}})
   @ Base ./abstractarray.jl:904
 [5] vect(::PiExpTimes{Int64, Int64}, ::Vararg{Any})
   @ Base ./array.jl:147
 [6] top-level scope
   @ REPL[18]:1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.