Skip to content

Commit c55bc6a

Browse files
committed
add a sign() function to Eidos
1 parent c025265 commit c55bc6a

File tree

7 files changed

+101
-0
lines changed

7 files changed

+101
-0
lines changed

EidosScribe/EidosHelpFunctions.rtf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,34 @@
664664
\f3\fs20 must be of the same type.\
665665
\pard\pardeftab397\li720\fi-446\ri720\sb180\sa60\partightenfactor0
666666

667+
\f1\fs18 \cf2 (numeric)sign(numeric\'a0x)\
668+
\pard\pardeftab397\li547\ri720\sb60\sa60\partightenfactor0
669+
670+
\f3\fs20 \cf2 Returns the
671+
\f0\b sign
672+
\f3\b0 of
673+
\f1\fs18 x
674+
\f3\fs20 , meaning that for each element of x, a value of either
675+
\f1\fs18 -1
676+
\f3\fs20 ,
677+
\f1\fs18 0
678+
\f3\fs20 , or
679+
\f1\fs18 1
680+
\f3\fs20 will be returned as the corresponding element in the returned vector depending upon whether the original element was (respectively) negative, zero, or positive. If
681+
\f1\fs18 x
682+
\f3\fs20 is
683+
\f1\fs18 integer
684+
\f3\fs20 , an
685+
\f1\fs18 integer
686+
\f3\fs20 vector is returned; if
687+
\f1\fs18 x
688+
\f3\fs20 is
689+
\f1\fs18 float
690+
\f3\fs20 , a
691+
\f1\fs18 float
692+
\f3\fs20 vector is returned.\
693+
\pard\pardeftab397\li720\fi-446\ri720\sb180\sa60\partightenfactor0
694+
667695
\f1\fs18 \cf0 (float)sin(numeric
668696
\f2 \'a0
669697
\f1 x)\

QtSLiM/help/EidosHelpFunctions.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
<p class="p3">Returns the <b>set-theoretic symmetric difference</b> of <span class="s2">x</span> and <span class="s2">y</span>, denoted <span class="s2">x</span> <span class="s4"></span> <span class="s2">y</span>: a vector containing all elements that are in <span class="s2">x</span> or <span class="s2">y</span>, but not in both.<span class="Apple-converted-space">  </span>Duplicate elements will be stripped out, in the same manner as the <span class="s2">unique()</span> function.<span class="Apple-converted-space">  </span>The order of elements in the returned vector is arbitrary and should not be relied upon.<span class="Apple-converted-space">  </span>The returned vector will be of the same type as <span class="s2">x</span> and <span class="s2">y</span><span class="s3">,</span> and <span class="s2">x</span> and <span class="s2">y</span> must be of the same type.</p>
100100
<p class="p2">(*)setUnion(*<span class="s1"> </span>x, *<span class="s1"> </span>y)</p>
101101
<p class="p3">Returns the <b>set-theoretic union</b> of <span class="s2">x</span> and <span class="s2">y</span>, denoted <span class="s2">x</span> <span class="s4"></span> <span class="s2">y</span>: a vector containing all elements that are in <span class="s2">x</span> and/or <span class="s2">y</span>.<span class="Apple-converted-space">  </span>Duplicate elements will be stripped out, in the same manner as the <span class="s2">unique()</span> function.<span class="Apple-converted-space">  </span>This function is therefore roughly equivalent to <span class="s2">unique(c(x, y))</span>, but this function will probably be faster.<span class="Apple-converted-space">  </span>The order of elements in the returned vector is arbitrary and should not be relied upon.<span class="Apple-converted-space">  </span>The returned vector will be of the same type as <span class="s2">x</span> and <span class="s2">y</span><span class="s3">,</span> and <span class="s2">x</span> and <span class="s2">y</span> must be of the same type.</p>
102+
<p class="p4">(numeric)sign(numeric x)</p>
103+
<p class="p5">Returns the <b>sign</b> of <span class="s2">x</span>, meaning that for each element of x, a value of either <span class="s2">-1</span>, <span class="s2">0</span>, or <span class="s2">1</span> will be returned as the corresponding element in the returned vector depending upon whether the original element was (respectively) negative, zero, or positive.<span class="Apple-converted-space">  </span>If <span class="s2">x</span> is <span class="s2">integer</span>, an <span class="s2">integer</span> vector is returned; if <span class="s2">x</span> is <span class="s2">float</span>, a <span class="s2">float</span> vector is returned.</p>
102104
<p class="p2">(float)sin(numeric<span class="s1"> </span>x)</p>
103105
<p class="p3">Returns the <b>sine</b> of <span class="s2">x</span> using the C++ function <span class="s2">sin()</span><span class="s3">.</span></p>
104106
<p class="p2">(float)sqrt(numeric<span class="s1"> </span>x)</p>

VERSIONS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ development head (in the master branch):
1414
add a define of TSK_TRACE_ERRORS in Xcode for slim and SLiMguiLegacy, in DEBUG only, for easier tskit debugging; break on _tsk_trace_error()
1515
fix a regression that caused the sourceSubpop pseudo-parameter to be NULL in modifyChild() callbacks in all cases; add tests, improve documentation (#522)
1616
add chromosomeSubposition property to Haplosome, providing whether the haplosome is index 0 or 1 within its individual, within the set of haplosomes for its associated chromosome
17+
add a (numeric)sign(numeric x) function that returns the sign (-1, 0, 1) of each element
1718

1819

1920
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
@@ -100,6 +100,7 @@ const std::vector<EidosFunctionSignature_CSP> &EidosInterpreter::BuiltInFunction
100100
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("setIntersection", Eidos_ExecuteFunction_setIntersection, kEidosValueMaskAny))->AddAny("x")->AddAny("y"));
101101
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("setDifference", Eidos_ExecuteFunction_setDifference, kEidosValueMaskAny))->AddAny("x")->AddAny("y"));
102102
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("setSymmetricDifference", Eidos_ExecuteFunction_setSymmetricDifference, kEidosValueMaskAny))->AddAny("x")->AddAny("y"));
103+
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("sign", Eidos_ExecuteFunction_sign, kEidosValueMaskNumeric))->AddNumeric("x"));
103104
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("sin", Eidos_ExecuteFunction_sin, kEidosValueMaskFloat))->AddNumeric("x"));
104105
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("sqrt", Eidos_ExecuteFunction_sqrt, kEidosValueMaskFloat))->AddNumeric("x"));
105106
signatures->emplace_back((EidosFunctionSignature *)(new EidosFunctionSignature("sum", Eidos_ExecuteFunction_sum, kEidosValueMaskNumeric | kEidosValueMaskSingleton))->AddLogicalEquiv("x"));

eidos/eidos_functions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ EidosValue_SP Eidos_ExecuteFunction_setDifference(const std::vector<EidosValue_S
6868
EidosValue_SP Eidos_ExecuteFunction_setIntersection(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
6969
EidosValue_SP Eidos_ExecuteFunction_setSymmetricDifference(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
7070
EidosValue_SP Eidos_ExecuteFunction_setUnion(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
71+
EidosValue_SP Eidos_ExecuteFunction_sign(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
7172
EidosValue_SP Eidos_ExecuteFunction_sin(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
7273
EidosValue_SP Eidos_ExecuteFunction_sqrt(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);
7374
EidosValue_SP Eidos_ExecuteFunction_sum(const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter);

eidos/eidos_functions_math.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,6 +2327,63 @@ EidosValue_SP Eidos_ExecuteFunction_setUnion(const std::vector<EidosValue_SP> &p
23272327
return result_SP;
23282328
}
23292329

2330+
// (numeric)sign(numeric x)
2331+
EidosValue_SP Eidos_ExecuteFunction_sign(const std::vector<EidosValue_SP> &p_arguments, __attribute__((unused)) EidosInterpreter &p_interpreter)
2332+
{
2333+
EidosValue_SP result_SP(nullptr);
2334+
2335+
EidosValue *x_value = p_arguments[0].get();
2336+
EidosValueType x_type = x_value->Type();
2337+
int x_count = x_value->Count();
2338+
2339+
if (x_type == EidosValueType::kValueInt)
2340+
{
2341+
const int64_t *int_data = x_value->IntData();
2342+
EidosValue_Int *int_result = (new (gEidosValuePool->AllocateChunk()) EidosValue_Int())->resize_no_initialize(x_count);
2343+
int64_t *int_result_data = int_result->data_mutable();
2344+
result_SP = EidosValue_SP(int_result);
2345+
2346+
// PARALLELIZE ME
2347+
for (int value_index = 0; value_index < x_count; ++value_index)
2348+
{
2349+
int64_t element = int_data[value_index];
2350+
2351+
if (element > 0)
2352+
int_result_data[value_index] = 1;
2353+
else if (element < 0)
2354+
int_result_data[value_index] = -1;
2355+
else
2356+
int_result_data[value_index] = 0;
2357+
}
2358+
}
2359+
else if (x_type == EidosValueType::kValueFloat)
2360+
{
2361+
const double *float_data = x_value->FloatData();
2362+
EidosValue_Float *float_result = (new (gEidosValuePool->AllocateChunk()) EidosValue_Float())->resize_no_initialize(x_count);
2363+
double *float_result_data = float_result->data_mutable();
2364+
result_SP = EidosValue_SP(float_result);
2365+
2366+
// PARALLELIZE ME
2367+
for (int value_index = 0; value_index < x_count; ++value_index)
2368+
{
2369+
double element = float_data[value_index];
2370+
2371+
if (element > 0)
2372+
float_result_data[value_index] = 1.0;
2373+
else if (element < 0)
2374+
float_result_data[value_index] = -1.0;
2375+
else if (std::isnan(element))
2376+
float_result_data[value_index] = std::numeric_limits<double>::quiet_NaN();
2377+
else
2378+
float_result_data[value_index] = 0.0;
2379+
}
2380+
}
2381+
2382+
result_SP->CopyDimensionsFromValue(x_value);
2383+
2384+
return result_SP;
2385+
}
2386+
23302387
// (float)sin(numeric x)
23312388
EidosValue_SP Eidos_ExecuteFunction_sin(const std::vector<EidosValue_SP> &p_arguments, __attribute__((unused)) EidosInterpreter &p_interpreter)
23322389
{

eidos/eidos_test_functions_math.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,17 @@ void _RunFunctionMathTests_setDifferenceSymmetricDifference(void)
10551055

10561056
void _RunFunctionMathTests_s_through_z(void)
10571057
{
1058+
// sign()
1059+
EidosAssertScriptSuccess_L("identical(sign(-10), -1);", true);
1060+
EidosAssertScriptSuccess_L("identical(sign(10), 1);", true);
1061+
EidosAssertScriptSuccess_L("identical(sign(0), 0);", true);
1062+
EidosAssertScriptSuccess_L("identical(sign(-10.0), -1.0);", true);
1063+
EidosAssertScriptSuccess_L("identical(sign(10.0), 1.0);", true);
1064+
EidosAssertScriptSuccess_L("identical(sign(0.0), 0.0);", true);
1065+
EidosAssertScriptSuccess_L("identical(sign(NAN), NAN);", true);
1066+
EidosAssertScriptSuccess_L("identical(sign(INF), 1.0);", true);
1067+
EidosAssertScriptSuccess_L("identical(sign(-INF), -1.0);", true);
1068+
10581069
// sin()
10591070
EidosAssertScriptSuccess_L("abs(sin(0) - 0) < 0.000001;", true);
10601071
EidosAssertScriptSuccess_L("abs(sin(0.0) - 0) < 0.000001;", true);

0 commit comments

Comments
 (0)