Erlang Central

Smooth Number Sampling

From ErlangCentral Wiki

Problem:

How to take a Sampling of the points of some Numeric Functions, suitable to be plotted on a graphic frame into Smooth Curves. Let's consider as example the pair of hyperbolic functions: Y = sinh(F), X = cosh(F), F = log(X + Y), being: Y = sqrt(X^2 - 1), X = sqrt(Y^2 + 1) (Rect. Hyperbola), on these ranges: 0 =< Y =< 3, 1 =< X =< sqrt(10) (almost 3.16), 0 =< F =< log(3 + sqrt(10)) (almost 1.82). The Solution should produce three Series of Numbers: Yn, Fn, Xn such that {Fn, Yn} should be a suitable Sampling for Y = sinh(F), and {Fn, Xn} should be a suitable Sampling for X = cosh(F).

Solution:

A possible Solution of the Problem above would be the following: 1) To build the Yn Series, consider a fixed Step, like 0.01 or 0.005; incfementing Yn+1 = Yn + Step will give 301, resp. 601 samples of Y. 2) To build the Fn Series in a smooth way, Fn may be incremented so: Fn+1 = Fn + dFn/dY * Step where dFn/dY is the Inverse Derivative of sinh(Fn), so that Fn+1 will lay on the tangent in Fn of the inverse function asinh(Yn). The Derivative, and so the slope of the tangent, is 1 on Y0 = 0, and goes decreasing slowly on the interval. So, the sampling of {Fn, Yn} would result enaugh smooth. Such derivative is computed by the delog() function.

delog(Y) ->
        Yq = Y * Y,
        Rq = 1.0 / (1.0 + Yq),
        math:sqrt(Rq).

3) To build the Xn Series, just compute it with the equation of Rect. Hyperbola: Xn+1 = sqrt((Yn+1)^2 + 1) on the samples of Yn. The sampling of {Fn, Xn} would result smooth as well. Using the inverse derivative would be impractical in this case, because it goes to infinity when X goes to 1. The building of the three Numeric Series is done by the recursive function hlog().

hlog(0, Ysav, Fusav, Xsav, Step, FId) ->
        fsav(Ysav, Fusav, Xsav, FId, 100),
        {Ysav, Fusav, Xsav, Step};
hlog(N, Ysav, Fusav, Xsav, Step, FId) ->
        fsav(Ysav, Fusav, Xsav, FId, 100),
        Dfu = delog(Ysav),
        Yu = Ysav + Step,
        Fu = Fusav + Dfu * Step,
        Xu = math:sqrt(Ysav * Ysav + 1.0),
        hlog(N-1, Yu, Fu, Xu, Step, FId).

At end, hlog() calls itself recursively, decreasing parameter N. When N becomes 0, no computation is made; just the last values are saved. The main function body() calls hlog() with the initial values for Y, F, X, Step, Number of recursions, and a File Pointer.

-module(hysamp).
-export([delog/1, fsav/5, hlog/6, body/0]).

body() ->
        {ok, Fex} = file:open("hysamp.txt", write),
        hlog(600, 0.0, 0.0, 1.0, 0.005, Fex),
        file:close(Fex).

In this Solution, the Numeric Series Yn, Fn, Xn are supposed to be saved in a file; a rough implementation of the saving function is fsav().

fsav(Y, F, X, FId, Unit) ->
        Yucar = integer_to_list( round(Y * Unit) ),
        Fucar = integer_to_list( round(F * Unit) ),
        Xucar = integer_to_list( round(X * Unit) ),
        Point = "\t" ++ Yucar ++ "\t" ++ Fucar ++ "\t" ++ Xucar,
        io:fwrite(FId, "~s~n", [Point]).

fsav() scales the numbers by 100 and rounds them to integers, as bound to become pixel coordinates.