Decode: Difference between revisions

From APL Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(4 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Built-in|Decode|⊥}}, also called '''Base''', is a [[dyadic]] [[primitive function]] which evaluates the right [[argument]] in terms of the radix system defined by the left argument. Some implementations add [[monadic]] usage to this function, where the left argument defaults to the [[scalar]] 2. Decode is the [[inverse]] of [[Encode]] <source lang=apl inline>⊤</source> with the same left argument X, when X is a [[vector]] and the right argument is a valid representation of a number in the radix system defined by X.
{{Built-in|Decode|⊥}}, also called '''Base''', is a [[dyadic]] [[primitive function]] which evaluates the right [[argument]] in terms of the radix system defined by the left argument. Some implementations add [[monadic]] usage to this function, where the left argument defaults to the [[scalar]] 2. Decode is the [[inverse]] of [[Encode]] <syntaxhighlight lang=apl inline>⊤</syntaxhighlight> with the same left argument X, when X is a [[vector]] and the right argument is a valid representation of a number in the radix system defined by X.


== APL model ==
== APL model ==
Line 5: Line 5:
Decode can be viewed as calculating the "digit values" defined by the radix system, followed by [[Inner Product|inner product]]. The digit values are found by [[times|product]] [[scan]]. Note that the first number of the radix is ignored; it is there simply to be consistent with [[Encode]].
Decode can be viewed as calculating the "digit values" defined by the radix system, followed by [[Inner Product|inner product]]. The digit values are found by [[times|product]] [[scan]]. Note that the first number of the radix is ignored; it is there simply to be consistent with [[Encode]].


<source lang=apl>
<syntaxhighlight lang=apl>
       0 24 60⊥∘.=⍨⍳3  ⍝ 1 day is 24 hours = 1440 minutes, 1 hour is 60 minutes
       0 24 60⊥∘.=⍨⍳3  ⍝ 1 day is 24 hours = 1440 minutes, 1 hour is 60 minutes
1440 60 1
1440 60 1
       ⌽×\1,⌽1↓0 24 60  ⍝ The digit values of radix 0 24 60
       ⌽×\1,⌽1↓0 24 60  ⍝ The digit values of radix 0 24 60
1440 60 1
1440 60 1
</source>
</syntaxhighlight>


If the left argument is a [[scalar]] number, it is converted to a [[vector]] filled with that number.
If the left argument is a [[scalar]] number, it is converted to a [[vector]] filled with that number.


<source lang=apl>
<syntaxhighlight lang=apl>
       10⊥∘.=⍨⍳3  ⍝ Base 10
       10⊥∘.=⍨⍳3  ⍝ Base 10
100 10 1
100 10 1
       ⌽×\1,⌽1↓3⍴10
       ⌽×\1,⌽1↓3⍴10
100 10 1
100 10 1
</source>
</syntaxhighlight>


The resulting model looks like this:
The resulting model looks like this:


<source lang=apl>
<syntaxhighlight lang=apl>
Decode←{
Decode←{
   (⌽×\1,⌽(1↓(≢⍵)⍴⊢)⍤1⊢⍺)+.×⍵
   (⌽×\1,⌽(1↓(≢⍵)⍴⊢)⍤1⊢⍺)+.×⍵
}
}
</source>
</syntaxhighlight>


== Examples ==
== Examples ==
Line 33: Line 33:
A common use case is to convert from base-N digits to an integer, usually in base 2 or 10.
A common use case is to convert from base-N digits to an integer, usually in base 2 or 10.


<source lang=apl>
<syntaxhighlight lang=apl>
       10⊥1 2 3 4 5  ⍝ Base 10
       10⊥1 2 3 4 5  ⍝ Base 10
12345
12345
       2⊥1 0 1 0 1  ⍝ Base 2
       2⊥1 0 1 0 1  ⍝ Base 2
21
21
</source>
</syntaxhighlight>


But since the left and right argument's values are not restricted in any way, <source lang=apl inline>X⊥Y</source> with scalar X can also be thought as evaluating the [[wikipedia:Polynomial|polynomial]] Y at given value X. For example, evaluating <math>y = 2x^4 + 3x + 1</math> at <math>x = -3</math> can be done as follows:
But since the left and right argument's values are not restricted in any way, <syntaxhighlight lang=apl inline>X⊥Y</syntaxhighlight> with scalar X can also be thought as evaluating the [[wikipedia:Polynomial|polynomial]] Y at given value X. For example, evaluating <math>y = 2x^4 + 3x + 1</math> at <math>x = -3</math> can be done as follows:


<source lang=apl>
<syntaxhighlight lang=apl>
       ¯3⊥2 0 0 3 1  ⍝ Polynomial terms are written highest first, and absent terms are written as 0
       ¯3⊥2 0 0 3 1  ⍝ Polynomial terms are written highest first, and absent terms are written as 0
154
154
</source>
</syntaxhighlight>


Decode can be also used to convert from a measure given in a hierarchy of units to the smallest unit. For example, given that 1 day = 24 hours, 1 hour = 60 minutes, and 1 minute = 60 seconds, how many seconds is 2 days, 10 hours, 34 minutes, and 19 seconds?
Decode can be also used to convert from a measure given in a hierarchy of units to the smallest unit. For example, given that 1 day = 24 hours, 1 hour = 60 minutes, and 1 minute = 60 seconds, how many seconds is 2 days, 10 hours, 34 minutes, and 19 seconds?


<source lang=apl>
<syntaxhighlight lang=apl>
       0 24 60 60⊥2 10 34 19
       0 24 60 60⊥2 10 34 19
210859
210859
</source>
</syntaxhighlight>


Decode can be also found in many [[idiom|idioms]]. Some of the simple and useful ones are reproduced here:
Decode can be also found in many [[idiom|idioms]]. Some of the simple and useful ones are reproduced here:


<source lang=apl>
<syntaxhighlight lang=apl>
       ⎕←M←3 4⍴⍳12
       ⎕←M←3 4⍴⍳12
1  2  3  4
1  2  3  4
Line 77: Line 77:
       ⊥⍨1 1 0 1 1 1
       ⊥⍨1 1 0 1 1 1
3
3
</source>
</syntaxhighlight>


Decode has an important property with array [[index]]: Given an arbitrary array A with [[shape]] S, the index of an [[element]] in A can be decoded with S to obtain the corresponding index in the [[ravel]] of A. Decoding all indices given by [[Index Generator]] shows the ravel order of the elements of an array with the given shape. Note that [[index origin]] 0 (<source lang=apl inline>⎕IO←0</source>) is required for this to hold.
Kamila Szewczyk suggests the following explanation for the mechanism of action of <syntaxhighlight lang=apl inline>⊥⍨</syntaxhighlight>. Consider the model <syntaxhighlight lang=apl inline>⊥ ≡ {⍵+.×⌽×\1,⌽1↓(≢⍵)⍴⍺}</syntaxhighlight> for a vector (rank 1) <syntaxhighlight lang=apl inline>⍺</syntaxhighlight>. Setting <syntaxhighlight lang=apl inline>⍺≡⍵</syntaxhighlight> yields <syntaxhighlight lang=apl inline>⊥⍨ ≡ {⍵+.×⌽×\1,⌽1↓⍵}</syntaxhighlight> under the same assumptions. Let's dissect the model: <syntaxhighlight lang=apl inline>1,⌽1↓⍵</syntaxhighlight> drops the first element, reverses the vector and prepends it with an one; <syntaxhighlight lang=apl inline>×\</syntaxhighlight> turns off all ones after the first zero, because once it stumbles upon a zero, then for all x, 0*x = 0. Ultimately, <syntaxhighlight lang=apl inline>⌽×\1,⌽1↓⍵</syntaxhighlight> essentially sets all bit to 1 that appear after or on the last zero of a boolean vector. To count the trailing ones, count all the ones that appear after the last zero of a boolean vector. Hence, notice that multiplying the input by this bitmask from the <syntaxhighlight lang=apl inline>⌽×\1,⌽1↓⍵</syntaxhighlight> part will return a vector where ones correspond to the trailing ones, so the sum in the inner product counts them all.  


<source lang=apl>
Decode has an important property with array [[index]]: Given an arbitrary array A with [[shape]] S, the index of an [[element]] in A can be decoded with S to obtain the corresponding index in the [[ravel]] of A. Decoding all indices given by [[Index Generator]] shows the ravel order of the elements of an array with the given shape. Note that [[index origin]] 0 (<syntaxhighlight lang=apl inline>⎕IO←0</syntaxhighlight>) is required for this to hold.
 
<syntaxhighlight lang=apl>
       ⎕IO←0
       ⎕IO←0
       M←2 3 4⍴⎕A
       M←2 3 4⍴⎕A
Line 94: Line 96:
16 17 18 19
16 17 18 19
20 21 22 23
20 21 22 23
</source>
</syntaxhighlight>


== External links ==
== External links ==
Line 106: Line 108:
* [https://help.dyalog.com/latest/#Language/Primitive%20Functions/Decode.htm Dyalog]
* [https://help.dyalog.com/latest/#Language/Primitive%20Functions/Decode.htm Dyalog]
* [http://microapl.com/apl_help/ch_020_020_660.htm APLX]
* [http://microapl.com/apl_help/ch_020_020_660.htm APLX]
* J [https://www.jsoftware.com/help/dictionary/d401.htm Dictionary], [https://code.jsoftware.com/wiki/Vocabulary/numberdot NuVoc] (as <source lang=j inline>#.</source>)
* J [https://www.jsoftware.com/help/dictionary/d401.htm Dictionary], [https://code.jsoftware.com/wiki/Vocabulary/numberdot#dyadic NuVoc] (as <syntaxhighlight lang=j inline>#.</syntaxhighlight>)


{{APL built-ins}}[[Category:Primitive functions]]
{{APL built-ins}}[[Category:Primitive functions]]

Latest revision as of 13:41, 3 October 2023

Decode (), also called Base, is a dyadic primitive function which evaluates the right argument in terms of the radix system defined by the left argument. Some implementations add monadic usage to this function, where the left argument defaults to the scalar 2. Decode is the inverse of Encode with the same left argument X, when X is a vector and the right argument is a valid representation of a number in the radix system defined by X.

APL model

Decode can be viewed as calculating the "digit values" defined by the radix system, followed by inner product. The digit values are found by product scan. Note that the first number of the radix is ignored; it is there simply to be consistent with Encode.

      0 24 60⊥∘.=⍨⍳3  ⍝ 1 day is 24 hours = 1440 minutes, 1 hour is 60 minutes
1440 60 1
      ⌽×\1,⌽1↓0 24 60  ⍝ The digit values of radix 0 24 60
1440 60 1

If the left argument is a scalar number, it is converted to a vector filled with that number.

      10⊥∘.=⍨⍳3  ⍝ Base 10
100 10 1
      ⌽×\1,⌽1↓3⍴10
100 10 1

The resulting model looks like this:

Decode←{
  (⌽×\1,⌽(1↓(≢⍵)⍴⊢)⍤1⊢⍺)+.×⍵
}

Examples

A common use case is to convert from base-N digits to an integer, usually in base 2 or 10.

      10⊥1 2 3 4 5  ⍝ Base 10
12345
      2⊥1 0 1 0 1  ⍝ Base 2
21

But since the left and right argument's values are not restricted in any way, X⊥Y with scalar X can also be thought as evaluating the polynomial Y at given value X. For example, evaluating at can be done as follows:

      ¯3⊥2 0 0 3 1  ⍝ Polynomial terms are written highest first, and absent terms are written as 0
154

Decode can be also used to convert from a measure given in a hierarchy of units to the smallest unit. For example, given that 1 day = 24 hours, 1 hour = 60 minutes, and 1 minute = 60 seconds, how many seconds is 2 days, 10 hours, 34 minutes, and 19 seconds?

      0 24 60 60⊥2 10 34 19
210859

Decode can be also found in many idioms. Some of the simple and useful ones are reproduced here:

      ⎕←M←3 4⍴⍳12
1  2  3  4
5  6  7  8
9 10 11 12

      ⍝ 1⊥ is sum over the first axis (+⌿)
      1⊥3 1 4 1 5 9
23
      1⊥M
15 18 21 24

      ⍝ 0⊥ is last item over the first axis (⊢⌿), or last major cell
      0⊥3 1 4 1 5 9
9
      0⊥M
9 10 11 12

      ⍝ ⊥⍨ on a boolean vector counts trailing ones
      ⊥⍨1 1 0 1 1 1
3

Kamila Szewczyk suggests the following explanation for the mechanism of action of ⊥⍨. Consider the model ⊥ ≡ {⍵+.×⌽×\1,⌽1↓(≢⍵)⍴⍺} for a vector (rank 1) . Setting ⍺≡⍵ yields ⊥⍨ ≡ {⍵+.×⌽×\1,⌽1↓⍵} under the same assumptions. Let's dissect the model: 1,⌽1↓⍵ drops the first element, reverses the vector and prepends it with an one; ×\ turns off all ones after the first zero, because once it stumbles upon a zero, then for all x, 0*x = 0. Ultimately, ⌽×\1,⌽1↓⍵ essentially sets all bit to 1 that appear after or on the last zero of a boolean vector. To count the trailing ones, count all the ones that appear after the last zero of a boolean vector. Hence, notice that multiplying the input by this bitmask from the ⌽×\1,⌽1↓⍵ part will return a vector where ones correspond to the trailing ones, so the sum in the inner product counts them all.

Decode has an important property with array index: Given an arbitrary array A with shape S, the index of an element in A can be decoded with S to obtain the corresponding index in the ravel of A. Decoding all indices given by Index Generator shows the ravel order of the elements of an array with the given shape. Note that index origin 0 (⎕IO←0) is required for this to hold.

      ⎕IO←0
      M←2 3 4⍴⎕A
      M[1;0;2]=(,M)[2 3 4⊥1 0 2]
1
      2 3 4∘⊥¨⍳2 3 4
 0  1  2  3
 4  5  6  7
 8  9 10 11
           
12 13 14 15
16 17 18 19
20 21 22 23

External links

Lesson

Documentation


APL built-ins [edit]
Primitives (Timeline) Functions
Scalar
Monadic ConjugateNegateSignumReciprocalMagnitudeExponentialNatural LogarithmFloorCeilingFactorialNotPi TimesRollTypeImaginarySquare RootRound
Dyadic AddSubtractTimesDivideResiduePowerLogarithmMinimumMaximumBinomialComparison functionsBoolean functions (And, Or, Nand, Nor) ∙ GCDLCMCircularComplexRoot
Non-Scalar
Structural ShapeReshapeTallyDepthRavelEnlistTableCatenateReverseRotateTransposeRazeMixSplitEncloseNestCut (K)PairLinkPartitioned EnclosePartition
Selection FirstPickTakeDropUniqueIdentityStopSelectReplicateExpandSet functions (IntersectionUnionWithout) ∙ Bracket indexingIndexCartesian ProductSort
Selector Index generatorGradeIndex OfInterval IndexIndicesDealPrefix and suffix vectors
Computational MatchNot MatchMembershipFindNub SieveEncodeDecodeMatrix InverseMatrix DivideFormatExecuteMaterialiseRange
Operators Monadic EachCommuteConstantReplicateExpandReduceWindowed ReduceScanOuter ProductKeyI-BeamSpawnFunction axisIdentity (Null, Ident)
Dyadic BindCompositions (Compose, Reverse Compose, Beside, Withe, Atop, Over) ∙ Inner ProductDeterminantPowerAtUnderRankDepthVariantStencilCutDirect definition (operator)Identity (Lev, Dex)
Quad names Index originComparison toleranceMigration levelAtomic vector