{ Analytica Model SipMath_3_1, encoding="UTF-8" } SoftwareVersion 7.2.2 LinkLibrary SipMath_3_1 Title: SipMath 3.1 Description: SIPmath 3.1 reader and array-native numerical toolkit for Analytica 7.2. Uses the existing Hubbard HDR library, native Metalog 2.0 quantiles, normal inverse/CDF, Cholesky decomposition and DIST codec. Explicit trial API and Run sampling preserve coherence. Main model contains offline canonical regression tests and examples. Supported: Metalog 1.0/2.0, bounded/rounded quantiles, Gaussian and stored copulas, discrete lookup, arrays and XML DIST; external data must be explicitly preloaded. GeneralizedMetalog application-specific lookup and full external JSON Schema validation are not implemented. NodeSize: 88,32 DiagState: 2,0,1,796,451,17,10 WindState: 2,98,82,720,350 FontStyle: Arial,15 FileInfo: 0,LinkLibrary SipMath_3_1,2,2,0,0,SipMath 3.1 library.ana {!40600|Att_WikiHelpURL: [wiki]SipMath_3.1_library} Include 0,LinkLibrary Hubbard_HDR_Library,2,2,0,0,Hubbard_HDR_Library.ana NodeLocation Hubbard_HDR_Library: 128,272,2 NodeSize Hubbard_HDR_Library: 88,32 Library SIP_Numeric Title: SIP Numeric Description: Array-native SIPmath primitives: explicit trials, HDR seeds, Metalog quantiles, lookup tables, rounding and Gaussian copulas. No file access. NodeLocation: 128,368,2 NodeSize: 88,32 NodeInfo: 1,,,,,,,0,,,,,,0 DiagState: 2,276,186,1264,476,17,10 WindState: 2,98,82,720,350 Function SIP_Uniform(trial : positive; entity : nonNegative = 1; varId : positive = 1; seed3, seed4 : nonNegative = 0) Title: SIP Uniform Description: HDR_2_0 uniform for explicit positive integer trial numbers. SIPmath entity maps to Hubbard_HDR seed2; varId maps to seed1. Extra indexes on trials or seeds are preserved. This is deterministic in both Mid and Sample modes. Definition: If trial <> Floor(trial) or entity <> Floor(entity) or varId <> Floor(varId)~ or seed3 <> Floor(seed3) or seed4 <> Floor(seed4)~ or entity > 100M or varId > 100M or seed3 > 10M or seed4 > 10M~ Then Error('SIP Uniform: trials and seeds must be integers within HDR seed limits.')~ Else Hubbard_HDR(trial, varId, entity, seed3, seed4) NodeLocation: 128,96,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 WindState: 2,659,71,720,350 Function SIP_Metalog(p : numeric; a : numeric [K]; K : Index; lowerBound, upperBound : optional numeric atom orNull = Null; version : numeric atom = 2) Title: SIP Metalog Description: Quantile from 2..16 coefficients on K using native CumKeelinFromAInv (Metalog 2.0). version=1 explicitly converts the legacy basis, zero-padding odd legacy terms when needed; does NOT rely on native flag 64, which is ineffective in FromA inverse on 7.2.2. Bounds use SIPmath exponential/logistic transforms. p must lie in (0,1). K is consumed and extra indexes propagate. Definition: If IndexLength(K) < 2 or IndexLength(K) > 16 Then~ Error('SIP Metalog: supply 2 through 16 coefficients.')~ Else If p <= 0 or p >= 1 Then~ Error('SIP Metalog: probability must be strictly between zero and one.')~ Else If version <> 1 and version <> 2 Then~ Error('SIP Metalog: version must be 1 or 2.')~ Else If not IsNull(lowerBound) and not IsNull(upperBound) and lowerBound >= upperBound Then~ Error('SIP Metalog: lowerBound must be below upperBound.')~ Else (~ Local q := If version = 2 Then CumKeelinFromAInv(p, a, K)~ Else (~ { Convert legacy coefficients; FromA inverse ignores flag 64 in 7.2.2. }~ Local n := IndexLength(K);~ LocalIndex B := 1..(If n >= 7 and Mod(n, 4) = 3 Then n + 1 Else n);~ Local oldPosition :=~ If B >= 7 and Mod(B, 4) = 3 Then B + 1~ Else If B >= 8 and Mod(B, 4) = 0 Then B - 1~ Else B;~ Local coefficients := a[@K = oldPosition, defVal:0];~ CumKeelinFromAInv(p, coefficients, B)~ );~ { Use SIPmath bound conventions, especially upper-only UB-Exp(-q). }~ If IsNull(lowerBound) and IsNull(upperBound) Then q~ Else If IsNull(upperBound) Then lowerBound + Exp(q)~ Else If IsNull(lowerBound) Then upperBound - Exp(-q)~ Else lowerBound + (upperBound - lowerBound) * CumLogistic(q, 0, 1)~ ) NodeLocation: 384,96,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 WindState: 2,98,82,1166,657 Function SIP_Round(x; rounding : text atom = 'none') Title: SIP Round Description: Apply canonical SIPmath integer rounding: down=toward zero, up=away from zero, nearest=half away from zero, matching Excel ROUND/ROUNDUP/ROUNDDOWN and canonical library 08. This differs from floor/ceiling for negative values. Precision metadata is not silently interpreted as a rounding increment. Definition: Local r := TextLowerCase(rounding);~ If r = 'none' or r = '' Then x~ Else If r = 'down' Then Sign(x) * Floor(Abs(x))~ Else If r = 'up' Then Sign(x) * Ceil(Abs(x))~ Else If r = 'nearest' Then Sign(x) * Floor(Abs(x) + 0.5)~ Else Error('SIP Round: unknown rounding mode ' & rounding) NodeLocation: 384,256,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Lookup(p : numeric; cumulative : numeric [I]; values : [I]; I : Index) Title: SIP Lookup Description: Discrete inverse CDF: first value with cumulative probability >= p. CDF must be nondecreasing in [0,1], finish at 1, and have no missing values. p in [0,1]. Values can be numeric or textual; category index I is consumed, extra indexes propagate. Definition: If IndexLength(I) = 0 Then Error('SIP Lookup: empty table.')~ Else If p < 0 or p > 1 Then Error('SIP Lookup: probability outside [0,1].')~ Else If Min(cumulative, I) < 0 or Max(cumulative, I) > 1~ or cumulative[@I = IndexLength(I)] <> 1~ or Sum(IsNull(cumulative), I) > 0~ or Min(cumulative - cumulative[@I = @I - 1, defVal:0], I) < 0~ Then Error('SIP Lookup: invalid cumulative probability table.')~ Else~ Local pos := Min(If cumulative >= p Then @I Else IndexLength(I) + 1, I);~ values[@I = pos] NodeLocation: 128,176,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Gaussian_Copula(u : numeric [I]; matrix : numeric [I,J]; I, J : Index; isCholesky : boolean atom = False) Title: SIP Gaussian Copula Description: Transform independent uniforms on I using a latent-normal correlation matrix on [I,J]. Uses native Decompose, CumNormalInv and CumNormal. Output is on I; J is consumed. Trial/scenario indexes are preserved. With isCholesky=True matrix must be lower triangular L, C=L L-transpose. Does not draw or rank-reorder samples. Rejects invalid matrices. Definition: If IndexLength(I) <> IndexLength(J) Then~ Error('SIP Gaussian Copula: matrix must be square.')~ Else If u <= 0 or u >= 1 Then~ Error('SIP Gaussian Copula: uniforms must be strictly inside (0,1).')~ Else (~ Local L := If isCholesky Then matrix Else (~ If Max(Max(Abs(matrix - Transpose(matrix, I, J)), I), J) > 1e-10~ or Max(Max(Abs(matrix), I), J) > 1 + 1e-10~ or Max(Abs(Sum(If @I = @J Then matrix Else 0, J) - 1), I) > 1e-10~ Then Error('SIP Gaussian Copula: invalid correlation matrix.')~ Else Decompose(matrix, I, J)~ );~ If Max(Max(If @J > @I Then Abs(L) Else 0, I), J) > 1e-10~ or Max(Abs(Sum(L^2, J) - 1), I) > 1e-8~ Then Error('SIP Gaussian Copula: expected a lower Cholesky factor with unit row variance.')~ Else CumNormal(Sum(L * CumNormalInv(u[@I = @J]), J))~ ) NodeLocation: 384,176,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Array_At(data : [T]; T : Index; trial : positive) Title: SIP Array At Description: Select stored SIP trials by 1-based position, regardless of T labels. Preserves other indexes. Errors beyond stored trials; never wraps, resamples or independently permutes coherent SIPs. Definition: If trial <> Floor(trial) or trial > IndexLength(T) Then~ Error('SIP Array At: requested trial exceeds stored trials or is not an integer.')~ Else data[@T = trial] NodeLocation: 128,256,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 Close SIP_Numeric Library SIP_JSON Title: SIP JSON Description: Safe interpretation of SIPmath JSON libraries. No evaluation of text as Analytica code and no automatic external downloads. NodeLocation: 344,368,2 NodeSize: 88,32 NodeInfo: 1,,,,,,,0,,,,,,0 DiagState: 2,0,1,1264,476,17,10 WindState: 2,98,82,720,350 Function SIP_Parse(json : text atom) Title: SIP Parse Description: Parse SIPmath JSON into native _JSON structs and preserve metadata. Validate sipModel header and unique nonempty name/environment pairs. Environment alternatives may share a name. This is runtime validation, not full external JSON Schema certification. Keep the parsed library in a variable and reuse it. No external URLs or files are read. Definition: Local lib := ParseJSON(json);~ If SIP_Field(lib, 'objectType', '') <> 'sipModel' Then~ Error('SIP Parse: objectType must be sipModel.')~ Else (~ LocalIndex S := SIP_Field(lib, 'sips', []);~ Local keys := SIP_Field(S, 'name', '') & ':' & SIP_Field(S, 'environment', '');~ If IndexLength(S) = 0 or Sum(SIP_Field(S, 'name', '') = '', S) > 0~ or Size(Unique(keys)) <> IndexLength(S)~ Then Error('SIP Parse: sips must have unique nonempty name/environment pairs.')~ Else lib~ ) NodeLocation: 128,96,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Module SIP_JSON_Data Title: SIP JSON Data Description: Helpers for safe JSON list, parameter, matrix, and stored-data access. NodeLocation: 384,352,2 NodeSize: 88,32 NodeInfo: 1,,,,,,,0,,,,,,0 DiagState: 2,0,1,1264,476,17,10 Function SIP_Field(obj : atom; field : text atom; default : optional = Null) Title: SIP Field Description: Internal helper: case-sensitive JSON member access, with default for missing member or Null container. Uses native struct member access; does not execute text. Definition: If IsNull(obj) Then default~ Else `->`(obj, field, defVal:default) NodeLocation: 128,96,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Find(items : List; name : text atom) Title: SIP Find Description: Internal helper: unique named object lookup in a JSON list. Missing or duplicate names produce an error. Definition: LocalIndex N := items;~ Local matches := SIP_Field(N, 'name', '') = name;~ If Sum(matches, N) <> 1 Then~ Error('SIP Find: missing or duplicate name ' & name)~ Else N[@N = Sum(If matches Then @N Else 0, N)] NodeLocation: 384,96,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Resolve(value : atom; library : atom; parameters : atom = Null) Title: SIP Resolve Description: Resolve a canonical parameter or globalVariables reference. Parameter names are JSON member names in parameters. Unknown reference types fail; plain objects/numbers are returned unchanged. Does not evaluate code or fetch resources. Definition: Local kind := Try(SIP_Field(value, 'type', ''), catch:'');~ If kind = 'parameter' Then (~ Local name := SIP_Field(value, 'name');~ Local result := SIP_Field(parameters, name);~ If IsNull(result) Then Error('SIP Resolve: missing parameter ' & name)~ Else result~ )~ Else If kind = 'globalVariables' Then~ SIP_Field(SIP_Find(SIP_Field(library, 'globalVariables', []), SIP_Field(value, 'value')), 'value')~ Else value NodeLocation: 640,96,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Matrix(value : atom; I, J : Index; symmetric : boolean atom = True) Title: SIP Matrix Description: Map canonical sparse {rows,columns,matrix:[{row,col,value},...]} to caller indexes I,J in declared row/column order. For correlations, fill an omitted triangular entry from its transpose. Cholesky factors use symmetric=False. Duplicate cells and dimension mismatches error. Definition: LocalIndex Rows := SIP_Field(value, 'rows');~ LocalIndex Cols := SIP_Field(value, 'columns');~ LocalIndex E := SIP_Field(value, 'matrix');~ If IndexLength(Rows) <> IndexLength(I) or IndexLength(Cols) <> IndexLength(J) Then~ Error('SIP Matrix: declared matrix size does not match copula inputs.')~ Else (~ Local matches := SIP_Field(E, 'row') = Rows[@Rows = @I]~ and SIP_Field(E, 'col') = Cols[@Cols = @J];~ Local count := Sum(matches, E);~ Local m := Sum(If matches Then SIP_Field(E, 'value') Else 0, E);~ If Max(Max(count, I), J) > 1 Then Error('SIP Matrix: duplicate matrix entries.')~ Else If symmetric Then (~ If Min(Min(count + Transpose(count, I, J), I), J) = 0 Then~ Error('SIP Matrix: correlation entry missing from both triangles.')~ Else If count = 0 Then Transpose(m, I, J) Else m~ )~ Else m~ ) NodeLocation: 128,176,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Stored(arguments : atom; trial : positive; resources : atom = Null) Title: SIP Stored Description: Read array/DIST stored trials. type=array consumes value list; type=csv/xlsx resolves explicitly supplied resources by URL to a parsed JSON-style table struct {columnName:[trials]}. Resources must be preloaded by caller; never auto-fetches. value selects columns. Error on trial overflow. For DIST use type=DIST and XML value. Definition: Local kind := SIP_Field(arguments, 'type', 'array');~ Local value := SIP_Field(arguments, 'value');~ If kind = 'DIST' Then (~ Local data := SipDecode(value, localIndexName:'Stored_trial');~ SIP_Array_At(data, data.Stored_trial, trial)~ )~ Else If kind = 'array' Then (~ LocalIndex T := value;~ SIP_Array_At(T, T, trial)~ )~ Else If kind = 'csv' or kind = 'xlsx' Then (~ Local url := SIP_Field(arguments, 'url', '');~ Local table := SIP_Field(resources, url);~ If IsNull(table) Then Error('SIP Stored: preload external resource ' & url)~ Else (~ LocalIndex Column := value;~ Local values := (~ Local col[] := Column;~ Local data := SIP_Field(table, col);~ If IsNull(data) Then Error('SIP Stored: missing resource column ' & col)~ Else (~ LocalIndex T := data;~ SIP_Array_At(T, T, trial)~ )~ );~ If IndexLength(Column) = 1 Then values[@Column = 1] Else values~ )~ )~ Else Error('SIP Stored: unsupported stored-data type ' & kind) NodeLocation: 384,176,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Tensor_At(value : List; trial : positive) Title: SIP Tensor At Description: Select the last (trial) dimension of an inline nested JSON array. Earlier dimensions remain local Dim1, Dim2,... indexes. Rectangular numeric arrays only. Use caller-owned indexes and native SIP_Array_At instead when dimension identities must be shared with other model arrays. Definition: Local data := ParseJSON(MakeJSON(_Struct(value:value), flags:1), flags:1)->value;~ LocalIndex D := IndexesOf(data);~ LocalAlias T := D[@D = IndexLength(D)];~ SIP_Array_At(data, T, trial) NodeLocation: 640,176,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Close SIP_JSON_Data Function SIP_Names(library : atom) Title: SIP Names Description: Return unique SIP names as a list, collapsing environment-specific alternatives. Use as a model Index definition to choose the output dimension identity. Definition: LocalIndex S := SIP_Field(library, 'sips', []);~ Unique(SIP_Field(S, 'name')) NodeLocation: 384,96,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Select(library : atom; name : text atom; environment : text atom = 'Analytica') Title: SIP Select Description: Select named SIP: prefer an exact environment entry; otherwise use the environment-independent entry. Never silently use another environment. Missing or ambiguous names error. Definition: LocalIndex S := SIP_Field(library, 'sips', []);~ Local matches := SIP_Field(S, 'name', '') = name;~ Local env := SIP_Field(S, 'environment', '');~ Local exact := matches and env = environment;~ Local choose := If Sum(exact, S) > 0 Then exact Else matches and env = '';~ If Sum(choose, S) <> 1 Then~ Error('SIP Select: missing or ambiguous SIP/environment ' & name & '/' & environment)~ Else S[@S = Sum(If choose Then @S Else 0, S)] NodeLocation: 640,96,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Rng(library : atom; name : text atom; trial : positive; parameters : atom = Null) Title: SIP Rng Description: Evaluate a named U01.rng HDR_2_0 or Index generator. counter=PM_Index uses explicit trial; other numeric/parameter counters are supported. Unknown functions fail closed. Native HDR mapping preserves stream identity. Definition: Local rng := SIP_Find(SIP_Field(SIP_Field(library, 'U01'), 'rng', []), name);~ Local kind := SIP_Field(rng, 'function', '');~ Local a := SIP_Field(rng, 'arguments');~ Local c := SIP_Field(a, 'counter', 'PM_Index');~ Local counter := If IsText(c) and c = 'PM_Index' Then trial Else SIP_Resolve(c, library, parameters);~ If kind = 'Index' Then counter~ Else If kind = 'HDR_2_0' Then~ SIP_Uniform(~ counter,~ SIP_Resolve(SIP_Field(a, 'entity', 1), library, parameters),~ SIP_Resolve(SIP_Field(a, 'varId', 1), library, parameters),~ SIP_Resolve(SIP_Field(a, 'seed3', 0), library, parameters),~ SIP_Resolve(SIP_Field(a, 'seed4', 0), library, parameters)~ )~ Else Error('SIP Rng: unsupported generator ' & kind) NodeLocation: 128,256,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Copula(library : atom; name, layer : text atom; trial : positive; parameters : atom = Null; resources : atom = Null) Title: SIP Copula Description: Evaluate a named GaussianCopula or SIP_Array copula layer. Gaussian input order follows arguments.rng; output order follows copulaLayer. Matrix refs resolve globalVariables. Cholesky factors are interpreted lower triangular. Stored copulas use explicitly supplied external resources or inline arrays. Definition: Local cop := SIP_Find(SIP_Field(SIP_Field(library, 'U01'), 'copula', []), name);~ Local kind := SIP_Field(cop, 'function');~ Local a := SIP_Field(cop, 'arguments');~ LocalIndex Layers := SIP_Field(cop, 'copulaLayer');~ Local pos := Sum(If Layers = layer Then @Layers Else 0, Layers);~ If Sum(Layers = layer, Layers) <> 1 Then Error('SIP Copula: unknown or duplicate layer ' & layer)~ Else If kind = 'GaussianCopula' Then (~ LocalIndex I := SIP_Field(a, 'rng');~ LocalIndex J := CopyIndex(I);~ Local u := SIP_Rng(library, I, trial, parameters);~ Local chol := SIP_Field(a, 'choleskyMatrix');~ Local isChol := not IsNull(chol);~ Local raw := SIP_Resolve(If isChol Then chol Else SIP_Field(a, 'correlationMatrix'), library, parameters);~ Local m := SIP_Matrix(raw, I, J, not isChol);~ Local result := SIP_Gaussian_Copula(u, m, I, J, isChol);~ If IndexLength(Layers) <> IndexLength(I) Then Error('SIP Copula: layer count differs from input count.')~ Else result[@I = pos]~ )~ Else If kind = 'SIP_Array' Then (~ Local storage := SIP_Field(a, 'type', 'array');~ If storage = 'array' Then (~ Local values := SIP_Tensor_At(SIP_Field(a, 'value'), trial);~ SIP_Array_At(values, values.Dim1, pos)~ )~ Else (~ Local url := SIP_Field(a, 'url', '');~ Local table := SIP_Field(resources, url);~ If IsNull(table) Then Error('SIP Copula: preload external resource ' & url)~ Else (~ LocalIndex Columns := SIP_Field(a, 'value');~ Local data := SIP_Field(table, Columns[@Columns = pos]);~ If IsNull(data) Then Error('SIP Copula: missing copula resource column.')~ Else (~ LocalIndex T := data;~ SIP_Array_At(T, T, trial)~ )~ )~ )~ )~ Else Error('SIP Copula: unsupported copula ' & kind) NodeLocation: 384,256,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Source(library : atom; ref : atom; trial : positive; parameters : atom = Null; resources : atom = Null) Title: SIP Source Description: Resolve a SIP ref to its specified HDR/Index stream or copula layer. Does not substitute another RNG or reorder samples. Definition: Local source := SIP_Field(ref, 'source', '');~ Local name := SIP_Field(ref, 'name', '');~ If source = 'rng' Then SIP_Rng(library, name, trial, parameters)~ Else If source = 'copula' Then~ SIP_Copula(library, name, SIP_Field(ref, 'copulaLayer'), trial, parameters, resources)~ Else Error('SIP Source: unsupported reference source ' & source) NodeLocation: 640,256,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Evaluate(library : atom; name : text atom; trial : positive; parameters : atom = Null; resources : atom = Null; environment : text atom = 'Analytica') Title: SIP Evaluate Description: Evaluate a parsed library SIP at finite positive 1-based trial numbers. Array-abstracts over caller name/trial/scenario indexes. Supports Metalog_1_0/2_0, Lookup_Table, SIP_Array, inline multiDimSIP_Array, XML DIST and whitelisted Normal/CumNormalInv/PsiNormal/RiskNormal. Parameters/resources are structs. Unknown functions (including application-specific GeneralizedMetalog) error; imported text is never executed. Metadata precision is retained, not used to silently round results. Definition: If trial <> Floor(trial) or trial >= Inf Then Error('SIP Evaluate: trial numbers must be finite positive integers.')~ Else (~ Local sip := SIP_Select(library, name, environment);~ Local kind := SIP_Field(sip, 'function', '');~ Local a := SIP_Field(sip, 'arguments');~ Local ref := SIP_Field(sip, 'ref');~ Local result := If kind = 'SIP_Array' Then (~ Local counter := If IsNull(ref) Then trial Else SIP_Source(library, ref, trial, parameters, resources);~ SIP_Stored(a, counter, resources)~ )~ Else If kind = 'multiDimSIP_Array' Then~ SIP_Tensor_At(SIP_Field(a, 'value'), trial)~ Else If kind = 'DIST' Then (~ Local data := SipDecode(SIP_Field(a, 'value'), localIndexName:'Stored_trial');~ SIP_Array_At(data, data.Stored_trial, trial)~ )~ Else (~ Local p := SIP_Source(library, ref, trial, parameters, resources);~ If kind = 'Metalog_1_0' or kind = 'Metalog_2_0' Then (~ Local coeff := SIP_Resolve(SIP_Field(a, 'aCoefficients'), library, parameters);~ LocalIndex K := coeff;~ SIP_Metalog(~ p, K, K,~ SIP_Resolve(SIP_Field(a, 'lowerBound'), library, parameters),~ SIP_Resolve(SIP_Field(a, 'upperBound'), library, parameters),~ If kind = 'Metalog_1_0' Then 1 Else 2~ )~ )~ Else If kind = 'Lookup_Table' Then (~ LocalIndex Row := SIP_Resolve(SIP_Field(a, 'value'), library, parameters);~ LocalIndex Pair := [1, 2];~ Local table := Local entry[] := Row Do Array(Pair, #entry);~ SIP_Lookup(p, table[Pair = 1], table[Pair = 2], Row)~ )~ Else If kind = 'Normal' or kind = 'PsiNormal' or kind = 'RiskNormal' or kind = 'CumNormalInv' Then (~ Local mean := SIP_Resolve(SIP_Field(a, 'mean', 0), library, parameters);~ Local sd := SIP_Resolve(SIP_Field(a, 'stdDev', 1), library, parameters);~ If sd <= 0 Then Error('SIP Evaluate: Normal stdDev must be positive.')~ Else CumNormalInv(p, mean, sd)~ )~ Else If kind = 'GeneralizedMetalog' Then~ Error('SIP Evaluate: GeneralizedMetalog requires an application-specific coefficient lookup; use SIP_Metalog after resolving that lookup.')~ Else Error('SIP Evaluate: unsupported function ' & kind)~ );~ SIP_Round(result, SIP_Field(sip, 'rounding', 'none'))~ ) NodeLocation: 128,176,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Sample(library : atom; name : text atom; parameters : atom = Null; resources : atom = Null; environment : text atom = 'Analytica') Title: SIP Sample Description: Normal Analytica uncertainty interface. In Sample mode evaluates explicit Run trials; in Mid mode evaluates trial 1 (a reproducible representative trial, NOT a mean or median). Global sample size selects virtual trial count. Stored arrays error on overflow. Extra name/scenario indexes are retained. Definition: SIP_Evaluate(~ library, name,~ If IsSampleEvalMode Then Run Else 1,~ parameters, resources, environment~ ) NodeLocation: 384,176,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Export_Metalog(name : text atom; a : numeric [K]; K : Index; entity : nonNegative atom = 1; varId : positive atom = 1; seed3, seed4 : nonNegative atom = 0; lowerBound, upperBound : optional numeric atom orNull = Null; version : numeric atom = 2) Title: SIP Export Metalog Description: Construct one-variable virtual-SIP JSON using existing coefficient vectors, not refitting them. Explicit version controls coefficient convention. Seed mapping matches SIP_Uniform. Extra scenario indexes produce one JSON text per scenario. Metadata can be added using native structs/MakeJSON. Definition: Local check := SIP_Metalog(0.5, a, K, lowerBound, upperBound, version)~ + SIP_Uniform(1, entity, varId, seed3, seed4);~ If IsNull(check) Then Error('SIP Export Metalog: invalid parameters.')~ Else MakeJSON(~ _Struct(~ objectType:'sipModel', libraryType:'SIPmath_3_1',~ name:name,~ U01:_Struct(rng:[_Struct(~ name:'HDR1', function:'HDR_2_0',~ arguments:_Struct(counter:'PM_Index', entity:entity, varId:varId, seed3:seed3, seed4:seed4)~ )]),~ sips:[_Struct(~ name:name,~ ref:_Struct(source:'rng', name:'HDR1'),~ function:If version = 1 Then 'Metalog_1_0' Else 'Metalog_2_0',~ arguments:_Struct(aCoefficients:a, lowerBound:lowerBound, upperBound:upperBound)~ )]~ ),~ flags:33~ ) NodeLocation: 128,352,2 NodeSize: 96,24 NodeInfo: 1,,,,,,,0,,,,,,0 Function SIP_Calibration(library : atom; name : text atom; trial : positive atom; parameters : atom = Null; resources : atom = Null; atol : nonNegative atom = 1e-6; rtol : nonNegative atom = 1e-8; environment : text atom = 'Analytica') Title: SIP Calibration Description: Compare one trial against metadata.TrialN or metadata.calibrationTrials. Returns a struct with name, trial, actual, expected, absoluteError and passed. Missing expectation gives Null passed, never a false success. Array-abstracts over name and trial indexes. Definition: Local sip := SIP_Select(library, name, environment);~ Local meta := SIP_Field(sip, 'metadata');~ Local expected := SIP_Field(meta, 'Trial' & trial);~ If IsNull(expected) Then (~ Local values := SIP_Field(meta, 'calibrationTrials');~ If not IsNull(values) Then (~ LocalIndex T := values;~ expected := If trial <= IndexLength(T) Then T[@T = trial] Else Null~ )~ );~ Local actual := SIP_Evaluate(library, name, trial, parameters, resources, environment);~ Local err := Abs(actual - expected);~ _Struct(~ name:name, trial:trial, actual:actual, expected:expected,~ absoluteError:err,~ passed:If IsNull(expected) Then Null Else err <= atol + rtol * Abs(expected)~ ) NodeLocation: 640,176,2 NodeSize: 88,24 NodeInfo: 1,,,,,,,0,,,,,,0 Close SIP_JSON Text SIP_Read_me Title: SIP Read me Description: SIPmath 3.1 for Analytica 7.2~ ~ SIP Numeric: array-native primitives with caller-owned indexes.~ SIP JSON: Parse -> Names -> Evaluate or Sample.~ Explicit trials preserve coherent cross-platform streams.~ External data must be preloaded; imported code is never executed.~ ~ Tests and worked examples are in the parent model.~ GeneralizedMetalog lookup and full schema certification are not included. NodeLocation: 352,120,1 NodeSize: 320,96 NodeInfo: 1,,,,,,,0,,,,,,0 Close SipMath_3_1