New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ruby-calc

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ruby-calc

  • 0.2.0
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

ruby-calc Build Status

ruby-calc provides ruby bindings for calc, a c-style arbitrary precision calculator.

For information about calc, see: http://www.isthe.com/chongo/tech/comp/calc/index.html

Installation

Calc must be installed.

OSInstructions
Fedorasudo yum install calc calc-libs calc-devel
OS XInstall Homebrew, then brew install calc
Debian/UbuntuCalc is packaged as "apcalc", but because it doesn't include a shared library it won't work, so see instructions under "Manual"
ManualDownload and install calc yourself by referring to the calc website, or using bin/install_calc from this repository

Add this line to your application's Gemfile:

gem 'ruby-calc', git: 'git://github.com/timocp/ruby-calc.git'

And then execute:

$ bundle

Or install it yourself as:

$ gem install ruby-calc

Usage

The library provides 2 types of number classes:

Rational Numbers (Calc::Q)

Rational numbers are a pair of integers (numerator and denominator). Each value can be arbitraily large; the number is always stored in lowest common terms with the sign in the numerator.

# any numeric type can be passed as a parameter
Calc::Q(42)             #=> Calc::Q(42)
Calc::Q(Rational(3,10)) #=> Calc::Q(0.3)
Calc::Q(Calc::Q(42))    #=> Calc::Q(42)
Calc::Q(0.3)            #=> Calc::Q(~0.29999999999999998890)

# strings are parsed by the calc library, which allows real, rational
# exponential, scientific, hex, octal and binary:
Calc::Q("0.3")      #=> Calc::Q("0.3")  (compare to Float example above)
Calc::Q("3/10")     #=> Calc::Q("0.3")
Calc::Q("1e10")     #=> Calc::Q(10000000000)
Calc::Q("1e-10")    #=> Calc::Q(0.0000000001)
Calc::Q("0x2a")     #=> Calc::Q(42)
Calc::Q("052")      #=> Calc::Q(42)
Calc::Q("0b101010") #=> Calc::Q(42)

# If you pass a second parameter, the first will be divided by it (if you
# are passing integers, you are effectively passing a numerator/denominator).
Calc::Q(1,4) #=> Calc::Q(0.25)

# rational arithmetic.  you can provide ruby numbers or other calc classes as
# arguments to most operators
q1 = Calc::Q(42)
q2 = Calc::Q(13,4)
q1 + q2   #=> Calc::Q(45.25)
q1 - q2   #=> Calc::Q(38.75)
q1 * q2   #=> Calc::Q(136.5)
q1 / q2   #=> Calc::Q(~12.92307692307692307692)

# raise to power
q1 ** q2  #=> Calc::Q(188608.03646237737943757212)

Complex numbers (Calc::C)

# Complex numbers can be created by passing a real and imaginary pair of
# rational numbers.  In this form, the arguments can be anything accepted by
# Calc::Q#new:
c1 = Calc::C(2, 3) #=> Calc::C(2+3i)

# You can pass a single Complex or Calc::C parameter:
c2 = Calc::C(Complex(-1,-1)) #=> Calc::C(-1-1i)
# note that ruby 2.1 and later allow complex literals which turn into Complex
# objects, so:
Calc::C(4+5i) #=> Calc::C(4+5i)

# You can also use the polar method to initialize a complex number by giving
# a modulus (radius) and argument (angle, in radians)
Calc.polar(1,2) #=> Calc::C(-0.416146836547142387+0.9092974268256816954i)
Calc.polar(c2.abs, c2.arg) #=> Calc::C(-1-1i)
# Polar will return a rational number if the result is not complex
Calc.polar(1, Calc.pi) #=> Calc::Q(-1)

# If any other single numeric type is passed, it is used as the real part and
# the imaginary part is set to zero:
c3 = Calc::C(1) #=> Calc::C(1)

# Complex arithmetic is available:
c1 + c2  #=> Calc::C(1+2i)
c1 - c2  #=> Calc::C(3+4i)
c1 * c2  #=> Calc::C(1-5i)
c1 / c2  #=> Calc::C(-2.5+0.5i)
c1 ** c2 #=> Calc::C(-0.47426003871893157744-0.56942019125139104294i)

# The real and imaginary parts can be retrieved with #re/#im
# (aliases #real/#imag).  Calc::Q rational numbers are returned
(c1 / c2).re #=> Calc::Q(-2.5)
(c1 / c2).im #=> Calc::Q(-0.5)

Built in functions

Where possible, calc builtin functions are exposed by this library are implemented as methods with the same name:

MethodArgumentsDescription
absx [, b]absolute value of x (for complex x, within accuracy b)
acosx [, b]arccosine of x within accuracy b
acoshx [, b]hyperbolic arccosine of x within accuracy b
acotx [, b]inverse cotangent of x within accuracy b
acothx [, b]inverse hyperbolic cotangent of x within accuracy b
acscx [, b]inverse cosecant of x within accuracy b
acschx [, b]inverse hyperbolic cosecant of x within accuracy b
agdz [, b]inverse gudermannian function of z within accuracy b
apprx [, e, r]approximate x as a multiple of e with rounding r
argx [, b]argument (angle) of complex number x within acccuracy b
asecx [, b]inverse secant of x within accuracy b
asechx [, b]inverse hyperbolic secant of x within accuracy b
asinx [, b]arcsine of x within accuracy b
asinhx [, b]hyperbolic arcsine of x within accuracy b
atanx [, b]arctangent of x within accuracy b
atan2y, x [, b]angle determined by the point (x,y) within accuracy b
atanhx [, b]hyperbolic arctangent of x within accuracy b
avgx, y, ...arithmetic mean of values
bernoullixxth bernoulli number
bitx, ywhether bit y in value x is set (also: #bit?)
broundx [, p, r]round x to p binary places with rounding r
btruncx [, p]truncate x to p binary places
catalanxCatalan number for index x
cbrtx [, b]cube root of x within accuracy b
ceilxsmallest integer greater than or equal to x
cfapprx [, ...]approximate x within accuracy e using continued fractions
cfsimx [, r]simplify x using continued fractions
charxcharacter corresponding to integer x
cmpx, ycompare values returning -1, 0 or 1 real or complex
combx, ycombinatorial number a!/b!(a-b)!
conjxcomplex conjugate of x
cosx [, b]cosine of x within accuracy b
coshx [, b]hyperbolic cosine of x within accuracy b
cotx [, b]cotangent of x within accuracy b
cothx [, b]hyperbolic cotangent of x within accuracy b
cscx [, b]cosecant of x within accuracy b
cschx [, b]hyperbolic cosecant of x within accuracy b
denxdenominator of x
digitx, n [, b]nth digit of x in base b
digitsx [, b]number of intgral digits of x in base b
estrxtext representation of a value
eulernnth euler number
expx [, b]exponential function of x within accuracy b
factxfactorial of integer x
factorx [, limit]smallest prime factor of x not exceeding limit
fcntx, ycount number of times y divides x
fracxfractional part of x
fremx, yremove occurances of factor y from x
fibzzth Fibonacci number
freebernoullifree memory storing calculated bernoulli numbers
freeeulerfree memory storing calculated euler numbers
floorxgreatest integer less than or equal to x
gcdx [, ...]greatest common divisor
gcdremx, yx divided repeatedly by gcd with b
gdz [, b]gudermannian function of z within accuracy b
highbitxhigh bit number in base 2 representation
hmeanx, y, ...harmonic mean
hnrmodv, h, n, rcomputes v % (h * 2^n + r)
ilogx, bfloor of logarithm to base b
ilog10xfloor of logarithm to base 10
ilog2xfloor of logarithm to base 2
intxinteger part of x
inversexinverse of x
irootx, ninteger nth root of x
isevenxwhether a value is even (also: #even?)
isimagxwhether a value is imaginary (also: #imag?)
isintxwhether a value is an integer (also: #int?)
ismultx, ywhether a x exactly divides y (also: #mult?)
isoddxwhether a value is odd (also: #odd?)
isprimextests if x is a small (< 2^32) prime (also: #prime?)
isqrtxinteger part of square root of x
isrealxwhether a value is real (also: #real?)
isrelx, ytests if x and y are relatively prime
issqxtest if x is a square
jacobix, yJacobi symbol function
lcmx [, ...]least common multiple
lcmfactxlcm of positive integers up to x
lfactorn, mlowest prime factor of n in first m primes
lnx [, b]natural logarithm of x within accuracy b
logx [, b]base 10 logarithm of x within accuracy b
lowbitxlow bit number in base 2 representation
ltolx [, b]leg-to-leg of unit right triangle within accuracy b
maxx [, ...]maximum of values
meqx, y, mtest for equality of x and y modulo m (also: #meq?)
minx [, ...]minimum of values
minvx, minverse of x modulo m
mminx, yx mod y value with smallest abs value
mnex, y, mtest for inequality of x and y module m (also: #mne?)
modx, y [, r]x modulo y with rounding r
nearx, y [, b]nearness test (sign of (abs(x-y) - b)
nextcandx [, ...]next candidate prime
nextprimexnext small prime after x
normxnorm (square of absolute value)
numxnumerator of x
permx, ypermutation number x!/(x-y)!
pi[b]value of π within accuracy b
pixxnumber of primes not exceeding x
pfactxprodut of primes up to x
placesx [, b]number of places in fractional part in base b
pmodx, y, mmod of a power (x ^ y (mod m))
polarr, t [, b]complex number using polar coordinates
poly...evaluate a polynomial given coefficients or coefficient list
popcntx [, b]number of bits in x that match b (or 1)
powerx, y [, b]x raised to the power of y within accuracy b
prevcandx [, ...]previous candidate prime
prevprimexprevious small prime before x
ptestn, [, c [, s]probabilistic test of primality (also: #ptest?)
quox, y [, r]integer quotient of a by b with rounding r
quomodx, yquotient and remainder of x divided by y
rootx, n [, b]nth root of x within accuracy b
roundx [, p, r]round x to p decimal places with rounding r
scalex, yscale value up or down by a power of two
secx [, b]secant of x within accuracy b
sechx [, b]hyperbolic secant within accuracy b
sgnxsign of x (-1, 0, 1)
sinx [, b]sine of x within accuracy b
sinhx [, b]hyperbolic sine of x within accuracy b
sqrtx [, b, z]square root of x within accuracy b with rounding/sign controlled by z
ssq...sum of squares of values
sum...sum of values
tanx [, b]tangent of x within accuracy b
tanhx [, b]hyperbolic tangent of x within accuracy b
truncx [, p]truncate x to p decimal places
versionversion of calc that ruby-calc was compiled with

Builtins with at least one required parameter are implemented as class methods of Calc::Q, Calc::C (or both) to allow object orientated style. Their behaviour matches the calc builtins as closely as possible. The receiver of these methods is what would have been the first parameter in calc.

Calc::Q(1).sin      #=> Calc::Q(0.84147098480789650665)
Calc::Q(2).power(3) #=> Calc::Q(8)

If you prefer the C-like style of calc, these are also available as class methods on Calc. This allows you to include Calc and use the builtins directly. These will call the rational/complex version of the method based on the type of the first parameter.

Calc.sin(1)     #=> Calc::Q(0.84147098480789650665)
Calc.power(2,3) #=> Calc::Q(8)

Functions with no arguments (other than precision/rounding modes) are only available as class methods:

Calc.pi #=> Calc::Q(3.14159265358979323846)

Trancendental functions

Transcendental functions such as sin, cos and pi, cannot be evaluated exactly as fractions. The result will be a rational number within a specific accuracy of the correct value (usually an absolute difference).

These methods have equivalent module versions for convenience. In the module version, the first parameter is equivalent to the receiver in the instance version. Example:

# single parameter functions
Calc::Q(1).sin  #=> Calc::Q(0.84147098480789650665)
Calc.sin(1)     #=> Calc::Q(0.84147098480789650665)

# two parameter functions
Calc::Q(9).root(2)  #=> Calc::Q(3)
Calc.root(9,2)      #=> Calc::Q(3)

# functions with no parameters are only available as a module method
Calc.pi  #=> Calc::Q(3.14159265358979323846)

The accuracy of transcendental functions will be within a specified epsilon. Each method has an optional extra parameter which provides this for a single call. If omitted a global epsilon is used (defaults to 1e-20). Epsilon must be greater than 0.

# pi to default 20 decimal places:
Calc.pi  #=> Calc::Q(3.14159265358979323846)

# pi to 2 decimal places:
Calc.pi("0.01") #=> Calc::Q(3.14)

# Avoid using a ruby float as a precision, since it won't exactly represent
# what you expect (see below in "Differences from Calc").
# For this reason it is recommended to use a Calc::Q or a string as the
# epsilon.  Eg, pi to 400 decimal places:
Calc.pi("1e-400") #=> (long fraction omitted)

The default epsilon can be changed via the Calc.config method and will affect all subsequent method calls:

Calc.config(:epsilon)                 #=> Calc::Q(0.00000000000000000001)
Calc.pi                               #=> Calc::Q(3.14159265358979323846)
Calc.config(:epsilon, "0.0001")
Calc.pi                               #=> Calc::Q(3.1416)

Converting between numeric types

The following methods can be used to convert a ruby-calc class to ruby numeric types.

MethodResult
Calc::Q#to_fConverts to ruby Float (precision can be lost!)
Calc::Q#to_iConverts to ruby Fixnum/Bignum (discards remainder)
Calc::Q#to_rConverts to ruby Rational
Calc::Q#to_cConverts to ruby Complex
Calc::Q#to_complexConverts to a Calc::C with zero imaginary part
Calc::C#to_cConverts to ruby Complex
Calc::C#to_fConverts to ruby Float, error if imaginary part is non-zero
Calc::C#to_iConverts to ruby Fixnum/Bignum, error if imaginary part is non-zero
Calc::C#to_rConverts to ruby Rational, error if imaginary part is non-zero
Converting to strings

Internally, Calc::Q are always stored as a rational number (fraction). Libcalc supports various output modes. The default is "real" which will output in decimal format.

Calc.exp(1).to_s #=> "2.71828182845904523536"

Numbers are rounded after Calc::Config.display digits; if any rounding has to occur, a leading tilde is included in the output. If you don't want rounding, you can output as a fraction:

Calc::Q(1,11).to_s         #=> "~0.09090909090909090909"
Calc::Q(1,11).to_s(:frac)  #=> "1/11"

to_s takes an optional parameter which is the output mode to use. It must be a symbol or a string with one of the following values:

Calc::Q(1,20).to_s(:frac)     #=> "1/20"        base 10 fractions
Calc::Q(1,20).to_s(:int)      #=> "~0"          base 10 integers
Calc::Q(1,20).to_s(:real)     #=> "0.05"        base 10 floating point (default)
Calc::Q(1,20).to_s(:sci)      #=> "5e-2"        base 10 scientific notation
Calc::Q(1,20).to_s(:hex)      #=> "1/0x14"      base 16 fractions
Calc::Q(1,20).to_s(:oct)      #=> "1/024"       base 8 fractions
Calc::Q(1,20).to_s(:bin)      #=> "1/0b10100    base 2 fractions

The default output mode can be set with [Calc::Config]. The output of inspect will match whatever the current default is.

The argument to to_s may also be an integer. In this case, it acts like ruby Fixnum#to_s, and treats the argument as a base. This only works for integers.

Calc::Q(12345).to_s(2)  #=> "11000000111001"
Calc::Q(12345).to_s(36) #=> "9ix"

Note that you can also provide Calc::Q objects to the ruby printf method. The format string parameter will coerce the number to the right internal type first (eg %d will display as an integer, %f as a floating point number). The display may have lost precision in this conversion.

Configuration

Default output modes, precision, rounding modes, etc can be set with the Calc.config method. It acts the same as the config() function in calc:

  • The first parameter is the name of a configuration item (string or symbol)
  • If a second parameter is present, it is the new value (the old value is returned)
  • If there is no second parameter, it only returns the current value.

Not all of calc's configuration is implemented (and only onese related to maths functions will be). The defaults are the same as using calc with no command line options. The current set are:

ParameterDefaultMeaning
appr24rounding mode for appr
cfappr0rounding mode for cfappr
display20number of digits when converting to string (does NOT affect internal value)
epsilon1e-20default precision for transcendental functions
mod0rounding mode for %, default for mod
mode:realdefault output mode when converting to string
quo2rounding mode for quo
quomod0rounding mode for quomod
round24rounding mode for bround and round
sqrt24rounding mode and sign for sqrt

For more details of these, type "help config" in calc.

Differences from Calc

For people familiar with the command line interface to calc, here are some important differences to make this library more ruby-ish:

Literals

In calc, a decimal literal is interpreted as a rational number, whereas in ruby it will be a floating point number. In fact, libcalc does not use or allow C types float or double anywhere in its API.

Although you can initialize Calc::Q objects from ruby floats, their internal representation will actually be a rational number as close as possible to the ruby float, which is not necessarily the same as what you typed. This is also true for scientific notation.

Calc::Q(1.2)              #=> Calc::Q(~1.19999999999999995559)
Calc::Q(1.2).to_s(:frac)  #=> "5404319552844595/4503599627370496"
Calc::Q(1e-5)             #=> Calc::Q(~0.00001000000000000000)
Calc::Q(1e-5).to_s(:frac) #=> "5902958103587057/590295810358705651712"

In most cases where you can provide a numeric argument to a method, ruby-calc allows a string. The string will be parsed using libcalc, so the exact intended value is stored.

Calc::Q("1.2")  #=> Calc::Q(1.2)
Calc::Q("1e-5") #=> Calc::Q(0.00001)

Output Parameters

Ruby doesn't have output parameters; for functions which in calc modify their parameters, ruby-calc instead returns values, eg:

q, r = Calc::Q(a).quomod(b)   # in calc: quomod(a, b, q, r)
                              # the actual calc return value is not available

Predicate Functions and Truthiness

Predicate functions (usually starting with "is") return 0 or 1 indicating false or true, matching the original calc version. In ruby, 0 is true so you shouldn't use these in a boolean context. Each function has a more rubyish version named with a question mark which returns true or false.

If in calc you would do this:

if (iseven(q)) {
  something();
}

Three options in ruby-calc:

# preferred
if q.even?
  something
end

# or
if q.iseven == 1
  something
end

# or
if Calc.iseven(q) == 1
  something
end

These builtins work this way:

  • bit / bit?
  • iseven / even?
  • isimag / imag?
  • isint / int?
  • ismult / mult?
  • isodd / odd?
  • isprime / prime?
  • isreal / real?
  • isrel / rel?
  • meq / meq?
  • mne / mne?
  • ptest / ptest?

isimag isn't a real calc builtin but it is included anyway.

xor / power

In calc, the ^ operator raises to a power. In ruby, it is a bitwise exclusive or operator.

If you want to raise to a power, use **, which behaves the same in both calc and ruby. Alternatively, you can use the methods named power and xor.

Other Differences

  • Calc builtins mod, quo, quomod and operator % allow division by zero; ruby-calc raises a ZeroDivisonError in these cases
  • estr return format is different, intended to be eval'd by ruby rather than calc
  • nextcand and prevcand return nil instead of 0 if a candidate prime is not found
  • prevprime returns nil instead of 0 for arguments <= 2
  • the "error" argument of factor, nextprime, prevprime and pix is not implemented. errors in these methods will always raise exceptions instead of returning the supplied error value.
  • REDC related functions (freeredc, rcin, rcmul, rcout, rcpow, rcsq are not implemented for now since there are alternatives and anyone wanting the faster modular arithmetic probably shouldn't be using ruby-calc
  • Non-maths builtin functions are not implemented - use the normal ruby way of doing that
  • Not all configuration items are implemented (and only ones related to maths will be)
  • You can't define/call calc functions (ie, eval() is not implemented)
  • Libcalc provides an integer type (ZVALUE) which ruby-calc doesn't provide access to (because ruby already has arbitrary size integers and libcalc's interesting functions are all for Rational or Complex numbers)

Licence

This gem is under the MIT licence (see LICENSE.txt). However libcalc is distributed under the LGPL. Therefore a compiled version of this library (calc.so or calc.bundle) may also be under the LGPL.

Development

ruby-calc requires ruby 2.0.0 or newer.

Make sure you have calc development headers installed (yum install calc-dev / apt-get install apcalc-devel, or have manually installed calc).

After checking out the repo, run bin/setup to install dependencies. Then, run bin/console for an interactive prompt that will allow you to experiment.

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 to create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

  1. Fork it ( https://github.com/timocp/ruby-calc/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

FAQs

Package last updated on 24 Dec 2016

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc