On Sun, Dec 22, 2024 at 01:58:29AM +0100, Grégory Vanuxem wrote:
> Hello folks,
> 
> I am coding a sample package that performs operations on 32bit or
> 64bit floats using my Julia interface (using libjulia).
> 
> I wonder what is the best way to do it, I can use parameterized
> signatures or more generically via a parameterized package. The latter
> is not really necessary.
> Here is a sample with a parameterized package:
> 
> JuliaMachineFloatFunctions(R : JuliaMachineFloat) :
>     Exports == Implementation where
>   JF32      ==> JuliaFloat32
>   JF64      ==> JuliaFloat64
>   STR       ==> String
>   Exports ==> with
>     jlApplyFunction : (STR, R) -> R
>     ++ jlApplyFunction(func,x)
>     jlApplyFunction : (STR, R, R) -> R
>     ++ jlApplyFunction(func,x,y)
>     jlApplyFunction : (STR, R, R, R) -> R
>     ++ jlApplyFunction(func,x,y,z)
> 
>   Implementation ==> add
>     import from String
>     if R is JF64 then
>       jlApplyFunction(func,a) ==
>         jl_dbl_function_dbl(func,a)$Lisp
>       jlApplyFunction(func,a, b) ==
>         jl_dbl_function_dbl_dbl(func,a,b)$Lisp
>       jlApplyFunction(func,a, b, c) ==
>         jl_dbl_function_dbl_dbl_dbl(func,a,b,c)$Lisp
>     else -- R is JF32
>       jlApplyFunction(func,a) ==
>         jl_flt_function_flt(func,a)$Lisp
>       jlApplyFunction(func,a, b) ==
>         jl_flt_function_flt_flt(func,a,b)$Lisp
>       jlApplyFunction(func,a, b, c) ==
>         jl_flt_function_flt_flt_flt(func,a,b,c)$Lisp
> 
> But I  can of course do not parametrize the package and use signatures like:
> 
>   jlApplyFunc : (STR, JF64) -> JF64
> or
>   jlApplyFunc : (STR, JF32) -> JF32
> 
> and in the implementation:
>     jlApplyFunction(func, a : JF64) ==
>         jl_dbl_function_dbl(func,a)$Lisp
> etc.
> 
> They are replaced (inlined) by the Lisp calls for the two coding styles.
> 
> Example with the parameterized package above (Julia needs to perform
> some initialization tasks at first call):
> 
> (1) -> a:=jf64(2)
> 
>    (1)  2.0
>                                                            Type: JuliaFloat64
>                                                    Time: 4.03 (OT) = 4.03 sec
> (2) -> b:=jf32(2)
> 
>    (2)  2.0
>                                                            Type: JuliaFloat32
>                                                    Time: 0.02 (OT) = 0.02 sec
> (3) -> jlApplyFunction("sqrt",a)
> 
>    (3)  1.4142135623730951
>                                                            Type: JuliaFloat64
>                                                    Time: 0.02 (EV) = 0.03 sec
> (4) -> jlApplyFunction("sqrt",b)
> 
>    (4)  1.4142135
>                                                            Type: JuliaFloat32
>                                                    Time: 0.01 (EV) = 0.01 sec
> (5) -> % pretend SEX
> 
>    (5)  1.4142135f0
>                                                             Type: SExpression
>                                                                   Time: 0 sec
> 
> Any idea of the "best" way to do this? And the advantages and/or
> inconveniences of those two coding styles?

For some reason you did not mention third alternative, that is
two separate non-parametrized packages.  AFAICS main differences
are overload resolution and inlining.  Parametrized package
makes inlinig harder (in fact normally inlining from parametrized
package is disabled).  Single package puts more stress on
overload resolution, with separate packages (either non-parametrized
ones or two instances of parametrized package) it is easier to
control visiblity.  Interpreter normally do not invent package
parameters, so use from interpreter is easier in non-parametric
cases.  If you want to share code for both cases, then single
package makes it slightly easier.

Which of the above is more important depends on your goals.
You may notice that there is DoubleFloatVector and few similar
"DoubleFloat" domains, but no SingleFloatVector.  My rationalle
was that for math computations we frequently want higher
precision, so we need DoubleFloat version.  Single float could
in principle double performance in some cases, but ATM
I decided that increase in complexity is not worth it.  You
may notice that those packages are non-parametrized: some
operations are quite simple and benefit a lot from inlinig,
so that was natural choice maximizing performance.

You package at first glance will have rather high overhead,
so it is not clear to me if inlinig gives you measurable
benefits.

Note: There is a bug in overload resolution in Spad compiler
which may lead to compiler missing valid combination of
arguments depending on internal order of signatures.
Your various choices affect internal order of signatures,
so you may see differences due to this bug.

-- 
                              Waldek Hebisch

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to fricas-devel+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/fricas-devel/Z2hggOXV5QiuAWm2%40fricas.org.

Reply via email to