nx_perineum_distance.nx source
↩ module page · 81 lines · 3196 B
1// nx_perineum_distance.nx -- fourchette → anal verge distance + canon check.
2//
3// Given the vulva fourchette point (bottom of labia majora cleft) and
4// the anal verge point, measure the perineum length in pixels and
5// score against the canon range (≈ 0.3-0.5 × face_width for adult
6// female). Too short or too long flags an anatomical anomaly.
7//
8// Math:
9// perineum_px = |fourchette_y - anal_y| (vertical distance — works for
10// presenting or laying-back poses where the line is vertical)
11// perineum_ratio_q10 = perineum_px * 1024 / face_width_px
12// target = NX_R_PERINEUM_FACE_W (0.4 Q10 = 410)
13//
14// Output flat-array:
15// result[0] = perineum_px
16// result[1] = perineum_ratio_q10
17// result[2] = ratio_score_q10 (1024 in canon range, 0 far out)
18// result[3] = verdict (0=TOO_SHORT, 1=AMBIGUOUS, 2=IN_CANON, 3=TOO_LONG)
19
20// nx_safety_envelope:
21// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
22// sil_target: SIL1
23// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
24// verdict: NOT_YET_EVALUATED
25
26import "nx_syscalls.nx"
27import "nx_phi.nx"
28import "nx_canon_proportions.nx"
29const NX_MAGIC_1024: i64 = 1024
30
31const NX_PERIN_RES_PX: i64 = 0
32const NX_PERIN_RES_RATIO_Q10: i64 = 1
33const NX_PERIN_RES_SCORE_Q10: i64 = 2
34const NX_PERIN_RES_VERDICT: i64 = 3
35const NX_PERIN_RES_FIELDS: i64 = 4
36
37const NX_PERIN_V_TOO_SHORT: i64 = 0
38const NX_PERIN_V_AMBIGUOUS: i64 = 1
39const NX_PERIN_V_IN_CANON: i64 = 2
40const NX_PERIN_V_TOO_LONG: i64 = 3
41
42// Per the canon, perineum_ratio_q10 should fall within target ± tolerance.
43const NX_PERIN_TARGET_MIN: i64 = 256 // 0.25 Q10
44const NX_PERIN_TARGET_MAX: i64 = 614 // 0.60 Q10
45const NX_PERIN_AMBIG_SPREAD: i64 = 100 // 0.10 Q10 outside band = ambiguous
46
47func nx_perineum_distance(fourchette_y: i64, anal_y: i64,
48 face_width_px: i64, result: *i64) -> i64 {
49 var i: i64 = 0
50 while i < NX_PERIN_RES_FIELDS { result[i] = 0; i = i + 1 }
51 if face_width_px <= 0 { return 1 }
52
53 var perineum_px: i64 = anal_y - fourchette_y
54 if perineum_px < 0 { perineum_px = -perineum_px }
55 result[NX_PERIN_RES_PX] = perineum_px
56
57 let ratio: i64 = (perineum_px * NX_MAGIC_1024) / face_width_px
58 result[NX_PERIN_RES_RATIO_Q10] = ratio
59
60 // Score with proportion scorer (using target = NX_R_PERINEUM_FACE_W as center).
61 let center: i64 = NX_R_PERINEUM_FACE_W
62 let half_band: i64 = (NX_PERIN_TARGET_MAX - NX_PERIN_TARGET_MIN) / 2
63 let score: i64 = nx_proportion_score_q10(ratio, center, half_band + NX_PERIN_AMBIG_SPREAD)
64 result[NX_PERIN_RES_SCORE_Q10] = score
65
66 var verdict: i64 = NX_PERIN_V_AMBIGUOUS
67 if ratio >= NX_PERIN_TARGET_MIN {
68 if ratio <= NX_PERIN_TARGET_MAX { verdict = NX_PERIN_V_IN_CANON }
69 else {
70 if ratio > NX_PERIN_TARGET_MAX + NX_PERIN_AMBIG_SPREAD {
71 verdict = NX_PERIN_V_TOO_LONG
72 }
73 }
74 } else {
75 if ratio < NX_PERIN_TARGET_MIN - NX_PERIN_AMBIG_SPREAD {
76 verdict = NX_PERIN_V_TOO_SHORT
77 }
78 }
79 result[NX_PERIN_RES_VERDICT] = verdict
80 return 0
81}