Skip to content

Suggestion to add stackunits to the calculation in maxima code. #1612

@ablluu

Description

@ablluu

Currently Moodle Stack units are Blocks that can only under specific circumstances interact with normal math operations which is quite counterintuitive. For example:

stackunits(2,m) * stackunits(3,m)

will not equate to 6 m^2. I am unaware of how well one can overload or edit the functions of maxima but i have a set of maxima functions that one can use to solve this problem. The are briefly tested but might still have some bugs in them:

stack_unit_si_declare(true)$

su(x,y)                 := stackunits(x,y)$
b(x)                    := stack_unit_si_to_si_base(x)$
bf(x)                   := ev(stack_unit_si_to_si_base(x), NULLUNITS=1)$
u(x)                    := ev(stack_units_units(x), NULLUNITS=1)$
ua(x)                   := stack_units_units(x)$
v(x)                    := stack_units_nums(x)$
numer(x)                := ev(x, numer)$
to_su(x)                := block([nun:emptyp(listofunits(x))], if nun then su(numer(x),1) else x)$

uadd(x,y)               := block([Xb:b(x),Yb:b(y)], if is(ua(Xb)=ua(Yb)) then su(numer(ratsimp(v(Xb)+v(Yb))),ua(Xb)) else su(numer(v(Xb)),ua(Xb))+su(numer(v(Yb)),ua(Yb)))$
usub(x,y)               := uadd(x, -y)$
usum(L)                 := block([acc:first(L)], for z in rest(L) do acc:uadd(acc,z), acc)$

umult(x,y)              := b(su(numer(ratsimp(v(b(x))*v(b(y)))), ratsimp(u(b(x))*u(b(y)))))$
uprod(L)                := block([acc:first(L)], for z in rest(L) do acc:umult(acc,z), acc)$

upow(x,p)               := b(su(numer(v(b(x))^p), block([assume_pos:true], ratsimp(u(b(x))^p))))$
usqrt(x)                := upow(x,1/2)$
udiv(x, y)              := umult(x, upow(y, -1))$
uabs(x)                 := b(su(numer(abs(v(x))), u(x)))$
usin(x)                 := sin(b(x))
ucos(x)                 := cos(b(x))
utan(x)                 := tan(b(x))

round_decimals_u(x,n)   := block([X:to_su(x),k:10^n], su(numer(round(float(v(X))*k)/k), u(X)))$
round_sig_u(x,s)        := block([X:to_su(x),a:abs(float(v(X)))], if a=0 then su(0.0,u(X)) else block([e:floor(log10(a)),k:10^(s-1-e)], su(numer(round(v(X)*k)/k),u(X))))$

And here are some testcases that ran through using these functions:

\( 3\text{m} + 4\text{m} = {@ uadd( su(3,m), su(4,m) ) @} \) ( \( 7 \text{m} \) )
\( 400\text{m} + 1\text{km} = {@ uadd( su(400,m), su(1,km) ) @} \) ( \( 1400 \text{m} \) )

\( 3\text{m} + 4\text{s} = {@ uadd( su(3,m), su(4,s) ) @} \) ( \( 3\text{m} + 4\text{s} \) )
\( 3\text{m} + 0\text{m} = {@ uadd( su(3,m), su(0,m) ) @} \) ( \( 3\text{m} \) )
\( 3\text{m} + 0\text{s} = {@ uadd( su(3,m), su(0,s) ) @} \) ( \( 3\text{m} + 0\text{s} \) )

\( 3\text{m} + 4 = {@ uadd( su(3,m), 4 ) @} \) ( \( 3\text{m} + 4 \) )
\( 3\text{m} + 0 = {@ uadd( su(3,m), 0 ) @} \) ( \( 3\text{m} \) )

\( 3\text{1} + 4 = {@ uadd( su(3,1), 4 ) @} \) ( \( 7 \) )

\( 3 + 4 = {@ uadd( 3, 4 ) @} \) ( \( 7 \) )
\( 3 + 0 = {@ uadd( 3, 0 ) @} \) ( \( 3 \) )

\( 3 + (-4) = {@ uadd( 3, -4 ) @} \) ( \( -1 \) )
\( 3\text{m} + (-4\text{m}) = {@ uadd( su(3,m), su(-4,m) ) @} \) ( \( - 1\text{m} \) )

\( 1 + 2 + 3 + 4 = {@ usum([1,2, 3, 4]) @} \) ( \( 10 \) )

\( 1\text{m} + 2\text{m} + 3\text{s} + 4\text{s} = {@ usum([su(1,m),su(2,m), su(3,s), su(4,s)]) @} \) ( \( 3\text{m} + 7\text{s}\) )

\( 3\text{m} \cdot 3\text{s} = {@ umult( su(3,m), su(3,s) ) @} \) ( \( 9\text{ms} \) )
\( 3\text{m} \cdot 1\text{km} = {@ umult( su(3,m), su(1,km) ) @} \) ( \( 3000\text{m}^2 \) )
\( 3\text{m} \cdot 0\text{m} = {@ umult( su(3,m), su(0,m) ) @} \) ( \( 0 \) )

\( 3\text{m} \cdot 3\mathbf{1} = {@ umult( su(3,m), su(3,1) ) @} \) ( \( 9\text{m} \) )

\( 3\text{m} \cdot 3 = {@ umult( su(3,m), 3 ) @} \) ( \( 9\text{m} \) )

\( 3\mathbf{1} \cdot 2 = {@ umult( su(3,1), 2 ) @} \) ( \( 6 \) )
\( 3 \cdot 0\mathbf{1} = {@ umult( 3, su(0,1) ) @} \) ( \( 0 \) )

\( 3 \cdot 2 = {@ umult( 3, 2 ) @} \) ( \( 6 \) )
\( 3 \cdot 0 = {@ umult( 3, 0 ) @} \) ( \( 0 \) )

\( 1 \cdot 2 \cdot 3 \cdot 4 \cdot 5 = {@ uprod([1, 2, 3, 4, 5]) @} \) ( \( 120 \) )

\( \frac{2\text{m}}{2\text{m}} = {@ udiv( su(2,m), su(2,m) ) @} \) ( \( 1 \) )
\( \frac{1}{5\text{s}} = {@ udiv( 1, su(5,s) ) @} \) ( \( 0.2 \frac{1}{s} \) )

\( (5\text{s})^2 = {@ upow( su(5,s), 2 ) @} \) ( \( 25\text{s}^2 \) )
\( (5\text{s})^{-1} = {@ upow( su(5,s), -1 ) @} \) ( \( 0.2 \frac{1}{s} \) )
\( \sqrt{\,25\text{s}^2\,} = {@ usqrt( su(25, s^2) ) @} \) ( \( 5\text{s} \) )

\( \left| -5\text{m} \right| = {@ uabs( su(-5,m) ) @} \) ( \( 5\text{m} \) )
\( \left| -5 \right| = {@ uabs( -5 ) @} \) ( \( 5 \) )

\( \sin(2) = {@ usin( 2 ) @} \) ( \( 0.909 \) )
\( \sin(2\cdot \mathbf{1}) = {@ usin( su(2,1) ) @} \) ( \( 0.909 \) )
\( \sin(3\text{m}) = {@ usin( su(3,m) ) @} \) ( \( \sin(3\text{m}) \) )

\( \cos(2) = {@ ucos( 2 ) @} \) ( \( -0.416 \) )
\( \cos(2\cdot \mathbf{1}) = {@ ucos( su(2,1) ) @} \) ( \( -0.416 \) )
\( \cos(3\text{m}) = {@ ucos( su(3,m) ) @} \) ( \( \cos(3\text{m}) \) )

\( \tan(2) = {@ utan( 2 ) @} \) ( \( -2.185 \) )
\( \tan(2\cdot \mathbf{1}) = {@ utan( su(2,1) ) @} \) ( \( -2.185 \) )
\( \tan(3\text{m}) = {@ utan( su(3,m) ) @} \) ( \( \tan(3\text{m}) \) )

and the results:

Image

Maybe there is a way to implement this directly into the maxima operators so the behavior of stack units is more intuitive. Hope this can be of any help.

P.S. I just realized, not all tests are successful e.g. the usum does not follow commutative law which will need to be thought thrrough a lot more then i did while throwing together these simple functions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions