Skip to content

Commit 870badf

Browse files
committed
add asVector() function to Eidos
1 parent 1674323 commit 870badf

7 files changed

Lines changed: 59 additions & 7 deletions

File tree

EidosScribe/EidosHelpFunctions.rtf

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{\rtf1\ansi\ansicpg1252\cocoartf2709
1+
{\rtf1\ansi\ansicpg1252\cocoartf2761
22
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Optima-Bold;\f1\fnil\fcharset0 Menlo-Regular;\f2\froman\fcharset0 TimesNewRomanPSMT;
33
\f3\fswiss\fcharset0 Optima-Regular;\f4\fswiss\fcharset0 Optima-BoldItalic;\f5\fnil\fcharset0 Menlo-Italic;
44
\f6\fnil\fcharset0 AppleSymbols;\f7\fswiss\fcharset0 Optima-Italic;\f8\froman\fcharset0 TimesNewRomanPS-ItalicMT;
@@ -8,9 +8,9 @@
88
\red150\green150\blue150;}
99
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c0\c0\c100000;\cssrgb\c87536\c0\c0;
1010
\cssrgb\c65500\c65500\c65500;}
11-
{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
11+
{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
1212
{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}
13-
{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3}}
13+
{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3}}
1414
{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}}
1515
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
1616
\deftab397
@@ -4574,7 +4574,24 @@ The elements of
45744574
\f3\fs20 . The new array will be filled in dimension order: one element in each row until a column is filled, then on to the next column in the same manner until all columns are filled, and then onward into the higher-order dimensions in the same manner.\
45754575
\pard\pardeftab720\li720\fi-446\ri720\sb180\sa60\partightenfactor0
45764576

4577-
\f1\fs18 \cf0 \kerning1\expnd0\expndtw0 (*)cbind(...)
4577+
\f1\fs18 \cf2 \kerning1\expnd0\expndtw0 (*)asVector(*\'a0x)\
4578+
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0
4579+
4580+
\f0\b\fs20 \cf2 Creates a new vector
4581+
\f3\b0 from the elements of
4582+
\f1\fs18 x
4583+
\f3\fs20 , stripping off any dimensional information associated with
4584+
\f1\fs18 x
4585+
\f3\fs20 being a vector or array. The values of the resulting vector are read out from
4586+
\f1\fs18 x
4587+
\f3\fs20 in dimension order: one element from each row until a column is completed, then on to the next column in the same manner until all columns are completed, and then onward into the higher-order dimensions in the same manner. If
4588+
\f1\fs18 x
4589+
\f3\fs20 is already a vector, it is returned unmodified. See
4590+
\f1\fs18 drop()
4591+
\f3\fs20 for a similar method that drops only matrix/array dimensions that are redundant.\
4592+
\pard\pardeftab720\li720\fi-446\ri720\sb180\sa60\partightenfactor0
4593+
4594+
\f1\fs18 \cf0 (*)cbind(...)
45784595
\f2 \
45794596
\pard\pardeftab720\li547\ri720\sb60\sa60\partightenfactor0
45804597

@@ -4714,7 +4731,10 @@ Returns the result of dropping redundant dimensions
47144731
\f1\fs18 x
47154732
\f3\fs20 . Redundant dimensions are those with a size of exactly 1. Non-redundant dimensions are retained. If only one non-redundant dimension is present, the result is a vector; if more than one non-redundant dimension is present, the result will be a matrix or array. If
47164733
\f1\fs18 x
4717-
\f3\fs20 is not a matrix or array, it is returned unmodified.\
4734+
\f3\fs20 is not a matrix or array, it is returned unmodified.\kerning1\expnd0\expndtw0 See
4735+
\f1\fs18 asVector()
4736+
\f3\fs20 for a way to drop all dimensions of a matrix or array, whether redundant or not.\expnd0\expndtw0\kerning0
4737+
\
47184738
\pard\pardeftab720\li720\fi-446\ri720\sb180\sa60\partightenfactor0
47194739

47204740
\f1\fs18 \cf2 \kerning1\expnd0\expndtw0 (float)inverse(numeric\'a0x)\

QtSLiM/help/EidosHelpFunctions.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta http-equiv="Content-Style-Type" content="text/css">
66
<title></title>
77
<meta name="Generator" content="Cocoa HTML Writer">
8-
<meta name="CocoaVersion" content="2299.77">
8+
<meta name="CocoaVersion" content="2487.7">
99
<style type="text/css">
1010
p.p1 {margin: 18.0px 0.0px 3.0px 0.0px; font: 11.0px Optima}
1111
p.p2 {margin: 9.0px 0.0px 3.0px 36.0px; text-indent: -22.3px; font: 9.0px Menlo}
@@ -360,6 +360,8 @@
360360
<p class="p2">(*)array(* data, integer dim)</p>
361361
<p class="p5"><span class="s5"><b>Creates a new array</b> from the data specified by </span><span class="s9">data</span><span class="s5">, with the dimension sizes specified by </span><span class="s9">dim</span><span class="s5">.<span class="Apple-converted-space">  </span>The first dimension size in </span><span class="s9">dim</span><span class="s5"> is the number of rows, and the second is the number of columns; further entries specify the sizes of higher-order dimensions.<span class="Apple-converted-space">  </span>As many dimensions may be specified as desired, but with a minimum of two dimensions.<span class="Apple-converted-space">  </span>An array with two dimensions is a matrix (by definition); note that </span><span class="s9">matrix()</span><span class="s5"> may provide a more convenient way to make a new matrix.<span class="Apple-converted-space">  </span>Each dimension must be of size </span><span class="s9">1</span><span class="s5"> or greater; </span><span class="s9">0</span><span class="s5">-size dimensions are not allowed.</span></p>
362362
<p class="p5"><span class="s5">The elements of </span><span class="s9">data</span><span class="s5"> are used to populate the new array; the size of </span><span class="s9">data</span><span class="s5"> must therefore be equal to the size of the new array, which is the product of all the values in </span><span class="s9">dim</span><span class="s5">.<span class="Apple-converted-space">  </span>The new array will be filled in dimension order: one element in each row until a column is filled, then on to the next column in the same manner until all columns are filled, and then onward into the higher-order dimensions in the same manner.</span></p>
363+
<p class="p4">(*)asVector(* x)</p>
364+
<p class="p5"><b>Creates a new vector</b> from the elements of <span class="s2">x</span>, stripping off any dimensional information associated with <span class="s2">x</span> being a vector or array.<span class="Apple-converted-space">  </span>The values of the resulting vector are read out from <span class="s2">x</span> in dimension order: one element from each row until a column is completed, then on to the next column in the same manner until all columns are completed, and then onward into the higher-order dimensions in the same manner.<span class="Apple-converted-space">  </span>If <span class="s2">x</span> is already a vector, it is returned unmodified.<span class="Apple-converted-space">  </span>See <span class="s2">drop()</span> for a similar method that drops only matrix/array dimensions that are redundant.</p>
363365
<p class="p2">(*)cbind(...)</p>
364366
<p class="p5"><span class="s5"><b>Combines vectors or matrices by column</b> to produce a single matrix.<span class="Apple-converted-space">  </span>The parameters must be vectors (which are interpreted by </span><span class="s9">cbind()</span><span class="s5"> as if they were one-column matrices) or matrices.<span class="Apple-converted-space">  </span>They must be of the same type, of the same class if they are of type </span><span class="s9">object</span><span class="s5">, and have the same number of rows.<span class="Apple-converted-space">  </span>If these conditions are met, the result is a single matrix with the parameters joined together, left to right.<span class="Apple-converted-space">  </span>Parameters may instead be </span><span class="s9">NULL</span><span class="s5">, in which case they are ignored; or if all parameters are </span><span class="s9">NULL</span><span class="s5">, the result is </span><span class="s9">NULL</span><span class="s5">.<span class="Apple-converted-space">  </span>A sequence of vectors, matrices, and </span><span class="s9">NULL</span><span class="s5">s may thus be concatenated with the </span><span class="s9">NULL</span><span class="s5"> values removed, analogous to </span><span class="s9">c()</span><span class="s5">.<span class="Apple-converted-space">  </span>Calling </span><span class="s9">cbind(x)</span><span class="s5"> is an easy way to create a one-column matrix from a vector.</span></p>
365367
<p class="p5"><span class="s5">To combine vectors or matrices by row instead, see </span><span class="s9">rbind()</span><span class="s5">.</span></p>
@@ -371,7 +373,7 @@
371373
<p class="p2">(integer)dim(* x)</p>
372374
<p class="p5"><span class="s5"><b>Returns the dimensions</b> of matrix or array </span><span class="s9">x</span><span class="s5">.<span class="Apple-converted-space">  </span>The first dimension value is the number of rows, the second is the number of columns, and further values indicate the sizes of higher-order dimensions, identically to how dimensions are supplied to </span><span class="s9">array()</span><span class="s5">.<span class="Apple-converted-space">  </span></span><span class="s9">NULL</span><span class="s5"> is returned if </span><span class="s9">x</span><span class="s5"> is not a matrix or array.</span></p>
373375
<p class="p2">(*)drop(* x)</p>
374-
<p class="p5"><span class="s5"><b>Returns the result of dropping redundant dimensions</b> from matrix or array </span><span class="s9">x</span><span class="s5">.<span class="Apple-converted-space">  </span>Redundant dimensions are those with a size of exactly 1.<span class="Apple-converted-space">  </span>Non-redundant dimensions are retained.<span class="Apple-converted-space">  </span>If only one non-redundant dimension is present, the result is a vector; if more than one non-redundant dimension is present, the result will be a matrix or array.<span class="Apple-converted-space">  </span>If </span><span class="s9">x</span><span class="s5"> is not a matrix or array, it is returned unmodified.</span></p>
376+
<p class="p5"><span class="s5"><b>Returns the result of dropping redundant dimensions</b> from matrix or array </span><span class="s9">x</span><span class="s5">.<span class="Apple-converted-space">  </span>Redundant dimensions are those with a size of exactly 1.<span class="Apple-converted-space">  </span>Non-redundant dimensions are retained.<span class="Apple-converted-space">  </span>If only one non-redundant dimension is present, the result is a vector; if more than one non-redundant dimension is present, the result will be a matrix or array.<span class="Apple-converted-space">  </span>If </span><span class="s9">x</span><span class="s5"> is not a matrix or array, it is returned unmodified.</span><span class="Apple-converted-space">  </span>See <span class="s2">asVector()</span> for a way to drop all dimensions of a matrix or array, whether redundant or not.</p>
375377
<p class="p4">(float)inverse(numeric x)</p>
376378
<p class="p5"><b>Returns the (multiplicative) inverse</b> of <span class="s2">x</span>, which must be a square non-singular matrix (otherwise an error is raised).<span class="Apple-converted-space">  </span>If matrix <b>B</b> is the inverse of <i>n</i>-by-<i>n</i> matrix <b>A</b>, then <b>AB</b> = <b>BA</b> = <b>I</b><span class="s13"><i><sub>n</sub></i></span>, where <b>I</b><span class="s13"><i><sub>n</sub></i></span> denotes the <i>n</i>-by-<i>n</i> identity matrix and the multiplication used is ordinary matrix multiplication as performed by <span class="s2">matrixMult()</span>.<span class="Apple-converted-space">  </span>If <span class="s2">x</span> might be singular (and thus non-invertible), and you wish to avoid the possibility of an error, you can call <span class="s2">det()</span> first to find the determinant of the matrix; if the determinant is zero, the matrix is singular and does not have an inverse, and so <span class="s2">inverse()</span> should not be called.<span class="Apple-converted-space">  </span>In Eidos the inverse is calculated from the <i>LU</i> decomposition of the matrix.</p>
377379
<p class="p4">(logical)lowerTri(* x, [logical$ diag = F])</p>

VERSIONS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ development head (in the master branch):
4444
fix #533, memory smasher in Haplosome method nucleotides(format="char"); besides causing random crashes, this also caused this method to return incorrect results
4545
fix #527, add calcLD_D() and calcLD_Rsquared() popgen functions, contributed by Vitor Sudbrack
4646
fix apparently new STL check that double comparators for std::sort() must induce a strict weak ordering, including with NAN values; self-tests started raising
47+
add new ways of subsetting matrices/arrays with A[B], or assigning into subsets of matrices/arrays with A[B] = ... : with a conformable logical matrix/array, or with an integer matrix that selects elements of the target
48+
add asVector() method to strip off dimension attributes; this can be done with c() or x[] also, but it's nice to have the function, since R has it...
4749

4850

4951
version 5.0 (Eidos version 4.0):

eidos/eidos_functions.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ const std::vector<EidosFunctionSignature_CSP> &EidosInterpreter::BuiltInFunction
296296
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("tr", Eidos_ExecuteFunction_tr, kEidosValueMaskNumeric | kEidosValueMaskSingleton))->AddNumeric("x"));
297297
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("det", Eidos_ExecuteFunction_det, kEidosValueMaskNumeric | kEidosValueMaskSingleton))->AddNumeric("x"));
298298
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("inverse", Eidos_ExecuteFunction_inverse, kEidosValueMaskFloat))->AddNumeric("x"));
299+
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("asVector", Eidos_ExecuteFunction_asVector, kEidosValueMaskAny))->AddAny("x"));
299300

300301

301302
// ************************************************************************************

eidos/eidos_functions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ EidosValue_SP Eidos_ExecuteFunction_diag(const std::vector<EidosValue_SP> &p_arg
233233
EidosValue_SP Eidos_ExecuteFunction_tr(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
234234
EidosValue_SP Eidos_ExecuteFunction_det(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
235235
EidosValue_SP Eidos_ExecuteFunction_inverse(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
236+
EidosValue_SP Eidos_ExecuteFunction_asVector(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
236237

237238

238239
#pragma mark -

eidos/eidos_functions_matrices.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,25 @@ EidosValue_SP Eidos_ExecuteFunction_inverse(const std::vector<EidosValue_SP> &p_
15091509
return result_SP;
15101510
}
15111511

1512+
// (*)asVector(* x)
1513+
EidosValue_SP Eidos_ExecuteFunction_asVector(const std::vector<EidosValue_SP> &p_arguments, __attribute__((unused)) EidosInterpreter &p_interpreter)
1514+
{
1515+
EidosValue *x_value = p_arguments[0].get();
1516+
EidosValue_SP result_SP(nullptr);
1517+
1518+
if (x_value->DimensionCount() == 1)
1519+
{
1520+
result_SP.reset(x_value);
1521+
}
1522+
else
1523+
{
1524+
result_SP = x_value->CopyValues();
1525+
1526+
result_SP->SetDimensions(1, nullptr);
1527+
}
1528+
1529+
return result_SP;
1530+
}
15121531

15131532

15141533

eidos/eidos_test_functions_other.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,13 @@ void _RunFunctionMatrixArrayTests(void)
363363
EidosAssertScriptSuccess_IV("x = matrix(1:12, 3); ut = upperTri(x, T); x[c(ut)];", {1, 4, 5, 7, 8, 9, 10, 11, 12});
364364
EidosAssertScriptSuccess_IV("x = matrix(1:12, 4); ut = upperTri(x); x[c(ut)];", {5, 9, 10});
365365
EidosAssertScriptSuccess_IV("x = matrix(1:12, 4); ut = upperTri(x, T); x[c(ut)];", {1, 5, 6, 9, 10, 11});
366+
367+
// asVector()
368+
EidosAssertScriptRaise("x = NULL; y = matrix(x); identical(asVector(y), x);", 14, "zero elements");
369+
EidosAssertScriptSuccess_L("x = 1:12; y = matrix(x, nrow=3); identical(asVector(y), x);", true);
370+
EidosAssertScriptSuccess_L("x = 1.0:12; y = matrix(x, nrow=3); identical(asVector(y), x);", true);
371+
EidosAssertScriptSuccess_L("x = (rbinom(12, 1, 0.5) == 1); y = matrix(x, nrow=3); identical(asVector(y), x);", true);
372+
EidosAssertScriptSuccess_L("x = c('a','b','c','d','e','f','g','h','i','j','k','l'); y = matrix(x, nrow=3); identical(asVector(y), x);", true);
366373
}
367374

368375
#pragma mark filesystem access

0 commit comments

Comments
 (0)