How to make Ada math function use double precision (Long float)variables? - math

Ada's standard math functions such as sin, cos, *, /, etc support Float type variables only as input and output. Is it possible to make these functions deal with double precision or long_float for both input and output variables?

Actually math functions are (fortunately) supported for any precision.
with Ada.Numerics.Generic_Elementary_Functions;
...
type Real is digits 15;
package REF is new Ada.Numerics.Generic_Elementary_Functions (Real);
use REF;

You should find
Ada.Numerics.Long_Elementary_Functions (for Long_Float)
Ada.Numerics.Short_Elementary_Functions (for Short_Float)
as well as
Ada.Numerics.Elementary_Functions (for Float).
See ARM A.5.1(9).

Related

Fortran epsilon function equivalent in Julia

I'm starting to learn Julia, and I was wondering if there is an equivalent function in Julia that is doing the same as the epsilon function in Fortran.
In Fortran, the epsilon function of variable x gives the smallest number of the same kind of x that satisfies 1+epsilon(x)>1
I thought the the function eps() in Julia would be something similar, so I tried
eps(typeof(x))
but I got the error:
MethodError: no method matching eps(::Type{Int64})
Is there any other function that resembles the Fortran one that can be used on the different variables of the code?
If you really need eps to work for both Float and Int types, you can overload a method of eps for Int by writing Base.eps(Int) = one(Int). Then your code will work. This is okay for personal projects, but not a good idea for code you intend to share.
As the docstring for eps says:
help?> eps
eps(::Type{T}) where T<:AbstractFloat
eps()
eps is only defined for subtypes of AbstractFloat i.e. floating point numbers. It seems that your variable x is an integer variable, as the error message says no method matching eps(::Type{Int64}). It doesn't really make sense to define an eps for integers since the "the smallest number of the same kind of x that satisfies 1 + epsilon(x) > 1" is always going to be 1 for integers.
If you did want to get a 1 of the specific type of integer you have, you can use the one function instead:
julia> x = UInt8(42)
0x2a
julia> one(typeof(x))
0x01
It seems like what you actually want is
eps(x)
not
eps(typeof(x))
The former is exactly equivalent to your Fortran function.

How does Erlang store large numbers?

I have been tinkering with a factorial module as follows:
-module(factorial).
-export([factorial/1]).
factorial(0) ->
1;
factorial(Val)->
Val * factorial(Val-1).
If I run:
1> c(factorial).
{ok,factorial}
2> factorial:factorial(100).
I get:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
How does Erlang so effortless hold such large numbers? On erlang.org when it talks about number types it simply states that that they hold either integers or floats. It must be some kind of dynamic integer that adjust its byte size as necessary?
I find this very cool I just don't know how its done.
It is a common feature of many functional programming languages, called Arbitrary precision arithmetic.
Notice that in Erlang, arbitrary precision is available only for integers, not floats.

How to convert a Julia Bool Array to Fortran Logical Array

How can I convert a Julia Int/Bool Array/Vector to a Fortran LOGICAL array for use within Julia's ccall?
I tried passing it as Array{Bool} in https://gist.github.com/axsk/28f297e2207365a7f4e8/, but the code is not working correctly and I am quite confident the problem is the Bool-Logical conversion.
I don't know too much about calling Fortran code, but according to this
The Fortran standard does not specify how variables of LOGICAL type
are represented, beyond requiring that LOGICAL variables of default
kind have the same storage size as default INTEGER and REAL variables.
The GNU Fortran internal representation is as follows.
A LOGICAL(KIND=N) variable is represented as an INTEGER(KIND=N)
variable, however, with only two permissible values: 1 for .TRUE. and
0 for .FALSE.. Any other integer value results in undefined behavior.
So I'd do something like the following
julia_array = rand(Bool, 1:10)
fort_array = Int[x?1:0 for x in julia_array]
Then use fort_array as the input. Which Fortran compiler are you using?
EDIT: It turns out the Julia developers already define a type that will work with the linked BLAS/LAPACK, Base.BLAS.BlasInt, that will use the correct Int variant for the system.
As iaindunning posted before, Fortran represents Logical variables as Integers.
Unfortunately the representation of the type Integer varies from platform to platform.
While I had success using Int on Windows and Cint on Linux/MacOS, in the end I used BlasInt, which adopts depending on the platform.

Smallest/Largest float or double precision constant in OpenCL

I need the smallest/largest floating point number in an OpenCL kernel program which involves computing log probability. I had a look on OpenCL reference manual but I cannot locate such constants.
In Java it is equivalent to something like Double.MAX_VALUE;
In C it is in float.h
They are called FLT_MAX / FLT_MIN, and DBL_MAX / DBL_MIN.
See Macros and Limits in the OpenCL 1.2 spec.
Well one obvious solution is to just use 1E+37. But it would be good to know if OpenCL has already defined such constants.

Is long double useful in ANSI C?

There is a data type in C89 (ANSI C) standard called long double, but there is no any mathematical function to support long double (<math.h>). For example, sin function accepts a long argument.
C99 supports mathematical functions for long double.
My question is, when there is no any mathematical functions to support long double in ANSI C, islong double useful?
Yes, "long double" is absolutely useful if you wish to compute an expression with more than double precision.
An interesting side question is "What exactly IS 'long double'"?
The answer is platform- and/or compiler dependent:
http://en.wikipedia.org/wiki/Long_double
Just because math.h doesn't support something doesn't mean you can't make it yourself.
The type existing is a good thing, because it means there is a cross-platform way to request something with more or equal precision to a long. This couldn't be done if it wasn't in the language somewhere (your best bet would be to hack something together with a struct or array of longs / doubles).
The functions are just for convenience; sometimes a built-in sin processor function can be used, but sometimes not, and instead the sin function simply contains an algorithm to produce the answer, or look it up, using standard operations.
You could copy the sinl functions for your target platform from C99 to C89 if you wanted. There's a big list of implementations here: http://sourceware.org/git/?p=glibc.git;a=tree;f=sysdeps/ieee754;hb=HEAD
Or just stick to C99.

Resources