# ============================================================================ # SelectiveRenderingReports.cmake - Reporting and Diagnostic Functions # Split from SelectiveRenderingCore.cmake for modularity # ============================================================================ function(report_selective_rendering_statistics) message(STATUS "") message(STATUS "╔════════════════════════════════════════════════════════════╗") message(STATUS "║ SELECTIVE RENDERING STATISTICS ║") message(STATUS "╠════════════════════════════════════════════════════════════╣") # Get type count if(DEFINED UNIFIED_TYPE_COUNT) set(type_count ${UNIFIED_TYPE_COUNT}) elseif(DEFINED UNIFIED_ACTIVE_TYPES) list(LENGTH UNIFIED_ACTIVE_TYPES type_count) else() set(type_count 0) endif() # Calculate theoretical maximums if(type_count GREATER 0) math(EXPR theoretical_1 "${type_count}") math(EXPR theoretical_2 "${type_count} * ${type_count}") math(EXPR theoretical_3 "${type_count} * ${type_count} * ${type_count}") else() set(theoretical_1 0) set(theoretical_2 0) set(theoretical_3 0) endif() # Get actual filtered counts if(DEFINED UNIFIED_COMBINATIONS_1) list(LENGTH UNIFIED_COMBINATIONS_1 actual_1) else() set(actual_1 ${type_count}) endif() if(DEFINED UNIFIED_COMBINATIONS_2) list(LENGTH UNIFIED_COMBINATIONS_2 actual_2) else() set(actual_2 0) endif() if(DEFINED UNIFIED_COMBINATIONS_3) list(LENGTH UNIFIED_COMBINATIONS_3 actual_3) else() set(actual_3 0) endif() # Format type count display if(type_count LESS 10) set(type_display " ${type_count}") else() set(type_display " ${type_count}") endif() message(STATUS "║ Active Types: ${type_display} types ║") # Show profile if set if(DEFINED SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "") set(profile_display "${SD_TYPE_PROFILE}") string(LENGTH "${profile_display}" profile_len) if(profile_len LESS 20) string(REPEAT " " ${profile_len} spaces) string(SUBSTRING " " ${profile_len} -1 padding) set(profile_display "${profile_display}${padding}") endif() message(STATUS "║ Active Profile: ${profile_display} ║") endif() message(STATUS "╠════════════════════════════════════════════════════════════╣") message(STATUS "║ Template Combinations: ║") # Calculate reductions if(theoretical_2 GREATER 0 AND actual_2 GREATER 0) math(EXPR saved_2 "${theoretical_2} - ${actual_2}") if(saved_2 GREATER 0) math(EXPR reduction_2 "100 * ${saved_2} / ${theoretical_2}") else() set(reduction_2 0) endif() else() set(reduction_2 0) endif() if(theoretical_3 GREATER 0 AND actual_3 GREATER 0) math(EXPR saved_3 "${theoretical_3} - ${actual_3}") if(saved_3 GREATER 0) math(EXPR reduction_3 "100 * ${saved_3} / ${theoretical_3}") else() set(reduction_3 0) endif() else() set(reduction_3 0) endif() # Display statistics message(STATUS "║ 1-type: ${actual_1}/${theoretical_1} (no filtering needed) ║") message(STATUS "║ 2-type: ${actual_2}/${theoretical_2} (${reduction_2}% reduction) ║") message(STATUS "║ 3-type: ${actual_3}/${theoretical_3} (${reduction_3}% reduction) ║") message(STATUS "╠════════════════════════════════════════════════════════════╣") # Build impact math(EXPR total_instantiations "${actual_2} + ${actual_3}") math(EXPR memory_per_instance 50) math(EXPR total_memory_kb "${total_instantiations} * ${memory_per_instance}") math(EXPR total_memory_mb "${total_memory_kb} / 1024") message(STATUS "║ Build Impact: ║") message(STATUS "║ Total instantiations: ${total_instantiations} ║") message(STATUS "║ Estimated memory: ~${total_memory_mb} MB ║") # Optimization level if(reduction_3 GREATER 85) set(optimization_level "EXCELLENT 🟢") elseif(reduction_3 GREATER 70) set(optimization_level "GOOD 🟡 ") else() set(optimization_level "POOR 🔴 ") endif() message(STATUS "║ Optimization level: ${optimization_level} ║") # Create output directory set(COMBINATION_REPORT_DIR "${CMAKE_BINARY_DIR}/type_combinations") file(MAKE_DIRECTORY "${COMBINATION_REPORT_DIR}") # Dump combinations to disk dump_type_combinations_to_disk("${COMBINATION_REPORT_DIR}") message(STATUS "║ Reports written to: type_combinations/ ║") message(STATUS "╚════════════════════════════════════════════════════════════╝") message(STATUS "") endfunction() function(dump_type_combinations_to_disk output_dir) # Get timestamp for unique filenames string(TIMESTAMP timestamp "%Y%m%d_%H%M%S") # Get profile name for filename if(DEFINED SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "") set(profile_suffix "_${SD_TYPE_PROFILE}") else() set(profile_suffix "_default") endif() # Get type information _internal_get_type_statistics(type_count actual_1 actual_2 actual_3 theoretical_1 theoretical_2 theoretical_3 reduction_2 reduction_3) # Create main summary file _internal_write_summary_file("${output_dir}" "${profile_suffix}" "${timestamp}" ${type_count} ${actual_1} ${actual_2} ${actual_3} ${theoretical_1} ${theoretical_2} ${theoretical_3} ${reduction_2} ${reduction_3}) # Write 2-type combinations _internal_write_2type_combinations("${output_dir}" "${profile_suffix}") # Write 3-type combinations with analysis _internal_write_3type_combinations("${output_dir}" "${profile_suffix}") # Write CSV matrix for analysis _internal_write_csv_matrix("${output_dir}" "${profile_suffix}") # Write JSON format for programmatic analysis _internal_write_json_analysis("${output_dir}" "${profile_suffix}" "${timestamp}") # Write validation rules documentation _internal_write_validation_rules("${output_dir}" "${profile_suffix}") # NEW: Generate template usage analysis _internal_analyze_template_usage(template_data) set(template_report_file "${output_dir}/template_usage_report${profile_suffix}_${timestamp}.txt") set(template_csv_file "${output_dir}/template_usage_matrix${profile_suffix}_${timestamp}.csv") set(template_json_file "${output_dir}/template_usage${profile_suffix}_${timestamp}.json") _internal_write_template_usage_report("${template_report_file}" "${template_data}") _internal_write_template_usage_csv("${template_csv_file}" "${template_data}") _internal_write_template_usage_json("${template_json_file}" "${template_data}") # Generate visual HTML report if enabled if(SD_ENABLE_VISUAL_REPORTS) _internal_generate_html_report("${output_dir}" "${profile_suffix}" "${timestamp}") endif() # Enhanced logging with better formatting _internal_log_output_locations("${output_dir}" "${profile_suffix}" "${timestamp}") endfunction() function(_internal_get_type_statistics type_count_var actual_1_var actual_2_var actual_3_var theoretical_1_var theoretical_2_var theoretical_3_var reduction_2_var reduction_3_var) # Get type count if(DEFINED UNIFIED_TYPE_COUNT) set(type_count ${UNIFIED_TYPE_COUNT}) elseif(DEFINED UNIFIED_ACTIVE_TYPES) list(LENGTH UNIFIED_ACTIVE_TYPES type_count) else() set(type_count 0) endif() # Calculate theoretical maximums if(type_count GREATER 0) math(EXPR theoretical_1 "${type_count}") math(EXPR theoretical_2 "${type_count} * ${type_count}") math(EXPR theoretical_3 "${type_count} * ${type_count} * ${type_count}") else() set(theoretical_1 0) set(theoretical_2 0) set(theoretical_3 0) endif() # Get actual filtered counts if(DEFINED UNIFIED_COMBINATIONS_1) list(LENGTH UNIFIED_COMBINATIONS_1 actual_1) else() set(actual_1 ${type_count}) endif() if(DEFINED UNIFIED_COMBINATIONS_2) list(LENGTH UNIFIED_COMBINATIONS_2 actual_2) else() set(actual_2 0) endif() if(DEFINED UNIFIED_COMBINATIONS_3) list(LENGTH UNIFIED_COMBINATIONS_3 actual_3) else() set(actual_3 0) endif() # Calculate reductions if(theoretical_2 GREATER 0 AND actual_2 GREATER 0) math(EXPR saved_2 "${theoretical_2} - ${actual_2}") math(EXPR reduction_2 "100 * ${saved_2} / ${theoretical_2}") else() set(reduction_2 0) endif() if(theoretical_3 GREATER 0 AND actual_3 GREATER 0) math(EXPR saved_3 "${theoretical_3} - ${actual_3}") math(EXPR reduction_3 "100 * ${saved_3} / ${theoretical_3}") else() set(reduction_3 0) endif() # Set output variables set(${type_count_var} ${type_count} PARENT_SCOPE) set(${actual_1_var} ${actual_1} PARENT_SCOPE) set(${actual_2_var} ${actual_2} PARENT_SCOPE) set(${actual_3_var} ${actual_3} PARENT_SCOPE) set(${theoretical_1_var} ${theoretical_1} PARENT_SCOPE) set(${theoretical_2_var} ${theoretical_2} PARENT_SCOPE) set(${theoretical_3_var} ${theoretical_3} PARENT_SCOPE) set(${reduction_2_var} ${reduction_2} PARENT_SCOPE) set(${reduction_3_var} ${reduction_3} PARENT_SCOPE) endfunction() function(_internal_write_summary_file output_dir profile_suffix timestamp type_count actual_1 actual_2 actual_3 theoretical_1 theoretical_2 theoretical_3 reduction_2 reduction_3) set(summary_file "${output_dir}/combination_summary${profile_suffix}_${timestamp}.txt") file(WRITE "${summary_file}" "================================================================================\n") file(APPEND "${summary_file}" " TYPE COMBINATION ANALYSIS REPORT \n") file(APPEND "${summary_file}" "================================================================================\n") file(APPEND "${summary_file}" "Generated: ${timestamp}\n") file(APPEND "${summary_file}" "Build Directory: ${CMAKE_BINARY_DIR}\n") file(APPEND "${summary_file}" "Profile: ${SD_TYPE_PROFILE}\n") file(APPEND "${summary_file}" "Semantic Filtering: ${SD_ENABLE_SEMANTIC_FILTERING}\n") file(APPEND "${summary_file}" "Aggressive Filtering: ${SD_AGGRESSIVE_SEMANTIC_FILTERING}\n") file(APPEND "${summary_file}" "\n") file(APPEND "${summary_file}" "CONFIGURATION\n") file(APPEND "${summary_file}" "================================================================================\n") file(APPEND "${summary_file}" "Type Selection Mode: ") if(DEFINED SD_SELECTIVE_TYPES AND NOT SD_SELECTIVE_TYPES STREQUAL "") file(APPEND "${summary_file}" "SELECTIVE\n") file(APPEND "${summary_file}" "Selected Types: ${SD_SELECTIVE_TYPES}\n") else() file(APPEND "${summary_file}" "ALL TYPES\n") endif() file(APPEND "${summary_file}" "\n") # Active types section - display actual type names file(APPEND "${summary_file}" "ACTIVE TYPES (${type_count})\n") file(APPEND "${summary_file}" "================================================================================\n") if(DEFINED UNIFIED_ACTIVE_TYPES) set(index 0) foreach(type ${UNIFIED_ACTIVE_TYPES}) # The type variable already contains the actual type name file(APPEND "${summary_file}" " ${type}\n") # Get additional info if available if(DEFINED SRCORE_TYPE_ENUM_${index}) set(enum_val "${SRCORE_TYPE_ENUM_${index}}") else() set(enum_val "N/A") endif() if(DEFINED SRCORE_TYPE_CPP_${index}) set(cpp_type "${SRCORE_TYPE_CPP_${index}}") else() set(cpp_type "N/A") endif() file(APPEND "${summary_file}" " Enum: ${enum_val}\n") file(APPEND "${summary_file}" " C++ Type: ${cpp_type}\n") math(EXPR index "${index} + 1") endforeach() endif() file(APPEND "${summary_file}" "\n") file(APPEND "${summary_file}" "STATISTICS\n") file(APPEND "${summary_file}" "================================================================================\n") file(APPEND "${summary_file}" "Template Instantiations:\n") file(APPEND "${summary_file}" " 1-type combinations: ${actual_1}/${theoretical_1} (100% - no filtering needed)\n") file(APPEND "${summary_file}" " 2-type combinations: ${actual_2}/${theoretical_2} (${reduction_2}% reduction)\n") file(APPEND "${summary_file}" " 3-type combinations: ${actual_3}/${theoretical_3} (${reduction_3}% reduction)\n") file(APPEND "${summary_file}" "\n") math(EXPR total_instantiations "${actual_2} + ${actual_3}") math(EXPR memory_per_instance 50) math(EXPR total_memory_kb "${total_instantiations} * ${memory_per_instance}") math(EXPR total_memory_mb "${total_memory_kb} / 1024") file(APPEND "${summary_file}" "Build Impact:\n") file(APPEND "${summary_file}" " Total instantiations: ${total_instantiations}\n") file(APPEND "${summary_file}" " Estimated memory: ~${total_memory_mb} MB\n") file(APPEND "${summary_file}" " Estimated compile time impact: ") if(reduction_3 GREATER 85) file(APPEND "${summary_file}" "MINIMAL (>85% reduction)\n") elseif(reduction_3 GREATER 70) file(APPEND "${summary_file}" "LOW (>70% reduction)\n") elseif(reduction_3 GREATER 50) file(APPEND "${summary_file}" "MODERATE (>50% reduction)\n") else() file(APPEND "${summary_file}" "HIGH (<50% reduction)\n") endif() file(APPEND "${summary_file}" "\n") file(APPEND "${summary_file}" "FILTERING RULES APPLIED\n") file(APPEND "${summary_file}" "================================================================================\n") file(APPEND "${summary_file}" "2-Type Combinations:\n") file(APPEND "${summary_file}" " ✓ Same type pairs always valid\n") file(APPEND "${summary_file}" " ✓ Bool pairs with any type (masking/comparison)\n") file(APPEND "${summary_file}" " ✓ Floating point mixed precision allowed\n") file(APPEND "${summary_file}" " ✓ Integer pairs (including mixed signed/unsigned)\n") file(APPEND "${summary_file}" " ✓ Specific int-to-float promotions\n") file(APPEND "${summary_file}" "\n") file(APPEND "${summary_file}" "3-Type Combinations:\n") file(APPEND "${summary_file}" " ✓ Same type for all three always valid\n") file(APPEND "${summary_file}" " ✓ String operations (UTF types)\n") file(APPEND "${summary_file}" " ✓ Mixed precision patterns (FP16->FP32, BF16->FP32)\n") file(APPEND "${summary_file}" " ✓ Quantization/Dequantization patterns\n") file(APPEND "${summary_file}" " ✓ INT8/UINT8 accumulation patterns\n") if(SD_AGGRESSIVE_SEMANTIC_FILTERING) file(APPEND "${summary_file}" " ✗ Precision downgrades blocked\n") file(APPEND "${summary_file}" " ✗ Bool to float conversions blocked\n") file(APPEND "${summary_file}" " ✗ Invalid string conversions blocked\n") endif() file(APPEND "${summary_file}" "\n") file(APPEND "${summary_file}" "================================================================================\n") file(APPEND "${summary_file}" "For detailed combinations, see accompanying files in: ${output_dir}\n") endfunction() function(analyze_filtered_combination type1 type2 type3 reason_var) set(reason "") # ENHANCED: More specific reason detection # Check for string issues if(type1 MATCHES "UTF" OR type2 MATCHES "UTF" OR type3 MATCHES "UTF") if(NOT (type1 MATCHES "UTF" AND type2 MATCHES "UTF" AND type3 MATCHES "UTF")) if(NOT (type1 MATCHES "UTF" AND type2 MATCHES "INT" AND type3 MATCHES "INT")) set(reason "Invalid string operation pattern - strings can only combine with strings or be indexed with integers") endif() endif() # Check for bool->float elseif(type1 STREQUAL "BOOL" AND type2 STREQUAL "BOOL") if(type3 MATCHES "FLOAT|DOUBLE|HALF|BFLOAT") set(reason "Boolean operations cannot produce floating point - logical ops should produce bool or int") endif() # Check for precision downgrades elseif(type1 STREQUAL "DOUBLE" AND type2 STREQUAL "DOUBLE") if(type3 MATCHES "FLOAT32|HALF|INT") set(reason "Double precision downgrade - potential precision loss") endif() elseif(type1 STREQUAL "INT64" AND type2 STREQUAL "INT64") if(type3 MATCHES "INT32|INT16|INT8") set(reason "Integer precision loss - 64-bit to smaller int conversion") endif() # NEW: Check for invalid float-to-int patterns elseif(type1 STREQUAL "FLOAT32" AND type2 STREQUAL "FLOAT32") if(type3 MATCHES "INT16|INT32|INT64") set(reason "Invalid float-to-int pattern - not a quantization operation") endif() else() set(reason "Does not match any valid operation pattern in semantic rules") endif() set(${reason_var} "${reason}" PARENT_SCOPE) endfunction() # NEW: Helper to analyze why a pair is invalid function(_internal_analyze_invalid_pair type1 type2 reason_var) if(type1 MATCHES "UTF" AND NOT type2 MATCHES "UTF|INT") set(reason "Incompatible string operation") elseif(type2 MATCHES "UTF" AND NOT type1 MATCHES "UTF|INT") set(reason "Incompatible string operation") elseif(type1 MATCHES "FLOAT|DOUBLE" AND type2 MATCHES "QINT|UTF") set(reason "Invalid float-to-quantized conversion") else() set(reason "Type mismatch - no valid operation pattern") endif() set(${reason_var} "${reason}" PARENT_SCOPE) endfunction() # NEW: Helper to analyze why a triple is invalid function(_internal_analyze_invalid_triple type1 type2 type3 reason_var) if(type1 MATCHES "UTF" OR type2 MATCHES "UTF" OR type3 MATCHES "UTF") if(NOT (type1 MATCHES "UTF" AND type2 MATCHES "UTF" AND type3 MATCHES "UTF")) if(NOT (type1 MATCHES "UTF" AND type2 MATCHES "INT" AND type3 MATCHES "INT")) set(reason "Invalid string operation pattern") else() set(reason "Unknown string pattern") endif() else() set(reason "Unknown string pattern") endif() elseif(type1 STREQUAL "BOOL" AND type2 STREQUAL "BOOL" AND type3 MATCHES "FLOAT|DOUBLE|HALF|BFLOAT") set(reason "Boolean operations cannot produce floating point") elseif(type1 STREQUAL "DOUBLE" AND type2 STREQUAL "DOUBLE" AND type3 MATCHES "FLOAT32|HALF|INT") set(reason "Double precision downgrade not allowed") elseif(type1 STREQUAL "INT64" AND type2 STREQUAL "INT64" AND type3 MATCHES "INT32|INT16|INT8") set(reason "Integer precision loss not allowed") elseif(type1 STREQUAL "FLOAT32" AND type2 STREQUAL "FLOAT32" AND type3 MATCHES "INT16|INT32|INT64") set(reason "Invalid float-to-int pattern (not quantization)") else() set(reason "Does not match any valid operation pattern") endif() set(${reason_var} "${reason}" PARENT_SCOPE) endfunction() # Write 2-type combinations function(_internal_write_2type_combinations output_dir profile_suffix) set(valid_file "${output_dir}/valid_2type_combinations${profile_suffix}.txt") set(invalid_file "${output_dir}/invalid_2type_combinations${profile_suffix}.txt") set(analysis_file "${output_dir}/2type_combination_analysis${profile_suffix}.txt") # Headers file(WRITE "${valid_file}" "Valid 2-Type Combinations\n") file(APPEND "${valid_file}" "========================\n\n") file(WRITE "${invalid_file}" "Invalid 2-Type Combinations (Filtered Out)\n") file(APPEND "${invalid_file}" "=========================================\n\n") file(WRITE "${analysis_file}" "2-Type Combination Analysis\n") file(APPEND "${analysis_file}" "===========================\n\n") # Write valid combinations with TYPE NAMES if(DEFINED UNIFIED_COMBINATIONS_2) foreach(combo ${UNIFIED_COMBINATIONS_2}) string(REPLACE "," ";" parts "${combo}") list(GET parts 0 idx1) list(GET parts 1 idx2) # Get the actual type names from the index list(GET UNIFIED_ACTIVE_TYPES ${idx1} type1) list(GET UNIFIED_ACTIVE_TYPES ${idx2} type2) file(APPEND "${valid_file}" "(${type1}, ${type2})\n") endforeach() endif() # Analysis summary list(LENGTH UNIFIED_COMBINATIONS_2 valid_count) file(APPEND "${analysis_file}" "Total Valid: ${valid_count}\n") # Count by type category set(same_type_count 0) set(bool_pair_count 0) set(float_pair_count 0) set(int_pair_count 0) set(mixed_count 0) foreach(combo ${UNIFIED_COMBINATIONS_2}) string(REPLACE "," ";" parts "${combo}") list(GET parts 0 idx1) list(GET parts 1 idx2) list(GET UNIFIED_ACTIVE_TYPES ${idx1} type_i) list(GET UNIFIED_ACTIVE_TYPES ${idx2} type_j) if(idx1 EQUAL idx2) math(EXPR same_type_count "${same_type_count} + 1") elseif(type_i STREQUAL "BOOL" OR type_j STREQUAL "BOOL") math(EXPR bool_pair_count "${bool_pair_count} + 1") elseif(type_i MATCHES "FLOAT|DOUBLE|HALF|BFLOAT" AND type_j MATCHES "FLOAT|DOUBLE|HALF|BFLOAT") math(EXPR float_pair_count "${float_pair_count} + 1") elseif(type_i MATCHES "INT|UINT" AND type_j MATCHES "INT|UINT") math(EXPR int_pair_count "${int_pair_count} + 1") else() math(EXPR mixed_count "${mixed_count} + 1") endif() endforeach() file(APPEND "${analysis_file}" "\nBreakdown by Category:\n") file(APPEND "${analysis_file}" " Same type pairs: ${same_type_count}\n") file(APPEND "${analysis_file}" " Bool pairs: ${bool_pair_count}\n") file(APPEND "${analysis_file}" " Float pairs: ${float_pair_count}\n") file(APPEND "${analysis_file}" " Integer pairs: ${int_pair_count}\n") file(APPEND "${analysis_file}" " Mixed/Other: ${mixed_count}\n") endfunction() function(generate_template_usage_report) set(COMBINATION_REPORT_DIR "${CMAKE_BINARY_DIR}/type_combinations") file(MAKE_DIRECTORY "${COMBINATION_REPORT_DIR}") # Get timestamp and profile string(TIMESTAMP timestamp "%Y%m%d_%H%M%S") if(DEFINED SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "") set(profile_suffix "_${SD_TYPE_PROFILE}") else() set(profile_suffix "_default") endif() set(template_report_file "${COMBINATION_REPORT_DIR}/template_usage_report${profile_suffix}_${timestamp}.txt") set(template_csv_file "${COMBINATION_REPORT_DIR}/template_usage_matrix${profile_suffix}_${timestamp}.csv") set(template_json_file "${COMBINATION_REPORT_DIR}/template_usage${profile_suffix}_${timestamp}.json") # Analyze template usage _internal_analyze_template_usage(template_data) # Write reports _internal_write_template_usage_report("${template_report_file}" "${template_data}") _internal_write_template_usage_csv("${template_csv_file}" "${template_data}") _internal_write_template_usage_json("${template_json_file}" "${template_data}") message(STATUS "📊 Template usage reports written to: ${COMBINATION_REPORT_DIR}") endfunction() function(_internal_write_template_usage_json output_file template_data) file(WRITE "${output_file}" "{\n") file(APPEND "${output_file}" " \"metadata\": {\n") string(TIMESTAMP timestamp "%Y-%m-%d %H:%M:%S") file(APPEND "${output_file}" " \"generated\": \"${timestamp}\",\n") file(APPEND "${output_file}" " \"profile\": \"${SD_TYPE_PROFILE}\"\n") file(APPEND "${output_file}" " },\n") file(APPEND "${output_file}" " \"templates\": [\n") set(first TRUE) foreach(entry ${template_data}) if(NOT first) file(APPEND "${output_file}" ",\n") endif() set(first FALSE) string(REPLACE "|" ";" parts "${entry}") list(GET parts 0 template_name) list(GET parts 1 type_count) list(LENGTH parts num_parts) file(APPEND "${output_file}" " {\n") file(APPEND "${output_file}" " \"name\": \"${template_name}\",\n") file(APPEND "${output_file}" " \"type_count\": ${type_count},\n") file(APPEND "${output_file}" " \"instantiations\": [") if(num_parts GREATER 2) set(first_inst TRUE) foreach(idx RANGE 2 ${num_parts}) if(idx LESS num_parts) list(GET parts ${idx} type_info) if(NOT type_info STREQUAL "") if(NOT first_inst) file(APPEND "${output_file}" ", ") endif() set(first_inst FALSE) file(APPEND "${output_file}" "\"${type_info}\"") endif() endif() endforeach() endif() file(APPEND "${output_file}" "]\n") file(APPEND "${output_file}" " }") endforeach() file(APPEND "${output_file}" "\n ]\n") file(APPEND "${output_file}" "}\n") endfunction() function(_internal_write_template_usage_csv output_file template_data) file(WRITE "${output_file}" "Template,Type Count,Total Instantiations,Sample Types\n") foreach(entry ${template_data}) string(REPLACE "|" ";" parts "${entry}") list(GET parts 0 template_name) list(GET parts 1 type_count) list(LENGTH parts num_parts) # Count instantiations if(num_parts GREATER 2) math(EXPR instantiation_count "${num_parts} - 2") else() set(instantiation_count 0) endif() # Get sample types set(sample_types "") if(num_parts GREATER 2) set(sample_count 0) foreach(idx RANGE 2 ${num_parts}) if(idx LESS num_parts AND sample_count LESS 3) list(GET parts ${idx} type_info) if(NOT type_info STREQUAL "") if(sample_types STREQUAL "") set(sample_types "${type_info}") else() set(sample_types "${sample_types}; ${type_info}") endif() math(EXPR sample_count "${sample_count} + 1") endif() endif() endforeach() endif() file(APPEND "${output_file}" "${template_name},${type_count},${instantiation_count},\"${sample_types}\"\n") endforeach() endfunction() function(_internal_write_template_usage_report output_file template_data) file(WRITE "${output_file}" "================================================================================\n") file(APPEND "${output_file}" " TEMPLATE TYPE USAGE ANALYSIS REPORT \n") file(APPEND "${output_file}" "================================================================================\n") string(TIMESTAMP timestamp "%Y-%m-%d %H:%M:%S") file(APPEND "${output_file}" "Generated: ${timestamp}\n") file(APPEND "${output_file}" "Profile: ${SD_TYPE_PROFILE}\n") file(APPEND "${output_file}" "\n") # Count templates by type set(count_1_type 0) set(count_2_type 0) set(count_3_type 0) set(total_instantiations 0) foreach(entry ${template_data}) string(REPLACE "|" ";" parts "${entry}") list(GET parts 0 template_name) list(GET parts 1 type_count) if(type_count EQUAL 1) math(EXPR count_1_type "${count_1_type} + 1") if(DEFINED UNIFIED_COMBINATIONS_1) list(LENGTH UNIFIED_COMBINATIONS_1 combo_count) else() list(LENGTH UNIFIED_ACTIVE_TYPES combo_count) endif() math(EXPR total_instantiations "${total_instantiations} + ${combo_count}") elseif(type_count EQUAL 2) math(EXPR count_2_type "${count_2_type} + 1") list(LENGTH UNIFIED_COMBINATIONS_2 combo_count) math(EXPR total_instantiations "${total_instantiations} + ${combo_count}") elseif(type_count EQUAL 3) math(EXPR count_3_type "${count_3_type} + 1") list(LENGTH UNIFIED_COMBINATIONS_3 combo_count) math(EXPR total_instantiations "${total_instantiations} + ${combo_count}") endif() endforeach() file(APPEND "${output_file}" "SUMMARY\n") file(APPEND "${output_file}" "================================================================================\n") file(APPEND "${output_file}" "Templates using 1 type: ${count_1_type}\n") file(APPEND "${output_file}" "Templates using 2 types: ${count_2_type}\n") file(APPEND "${output_file}" "Templates using 3 types: ${count_3_type}\n") file(APPEND "${output_file}" "Total instantiations: ${total_instantiations}\n") file(APPEND "${output_file}" "\n") # Write details for each template file(APPEND "${output_file}" "TEMPLATE DETAILS\n") file(APPEND "${output_file}" "================================================================================\n") foreach(entry ${template_data}) string(REPLACE "|" ";" parts "${entry}") list(GET parts 0 template_name) list(GET parts 1 type_count) list(LENGTH parts num_parts) file(APPEND "${output_file}" "\nTemplate: ${template_name}\n") file(APPEND "${output_file}" "Type Parameters: ${type_count}\n") if(type_count EQUAL 1) file(APPEND "${output_file}" "Instantiated Types:\n") if(num_parts GREATER 2) foreach(idx RANGE 2 ${num_parts}) if(idx LESS num_parts) list(GET parts ${idx} type_name) if(NOT type_name STREQUAL "") file(APPEND "${output_file}" " - ${type_name}\n") endif() endif() endforeach() endif() # Add specific template patterns if(template_name MATCHES "random") file(APPEND "${output_file}" "CUDA Methods:\n") file(APPEND "${output_file}" " - executeCudaSingle\n") file(APPEND "${output_file}" " - executeCudaDouble\n") file(APPEND "${output_file}" " - executeCudaTriple\n") elseif(template_name MATCHES "reduce_same") file(APPEND "${output_file}" "CUDA Methods:\n") file(APPEND "${output_file}" " - execReduce\n") file(APPEND "${output_file}" " - execReduceScalar\n") elseif(template_name MATCHES "specials_single") file(APPEND "${output_file}" "CPU Methods:\n") file(APPEND "${output_file}" " - SpecialMethods\n") file(APPEND "${output_file}" " - concatCpuGeneric\n") file(APPEND "${output_file}" " - sortGeneric\n") file(APPEND "${output_file}" " - sortTadGeneric\n") endif() elseif(type_count EQUAL 2) file(APPEND "${output_file}" "Instantiated Type Pairs:\n") set(pair_count 0) if(num_parts GREATER 2) foreach(idx RANGE 2 ${num_parts}) if(idx LESS num_parts) list(GET parts ${idx} type_pair) if(NOT type_pair STREQUAL "") file(APPEND "${output_file}" " ${type_pair}\n") math(EXPR pair_count "${pair_count} + 1") if(pair_count GREATER 10) file(APPEND "${output_file}" " ... (showing first 10 of ") math(EXPR remaining "${num_parts} - 2") file(APPEND "${output_file}" "${remaining} combinations)\n") break() endif() endif() endif() endforeach() endif() elseif(type_count EQUAL 3) file(APPEND "${output_file}" "Instantiated Type Triples:\n") set(triple_count 0) if(num_parts GREATER 2) foreach(idx RANGE 2 ${num_parts}) if(idx LESS num_parts) list(GET parts ${idx} type_triple) if(NOT type_triple STREQUAL "") file(APPEND "${output_file}" " ${type_triple}\n") math(EXPR triple_count "${triple_count} + 1") if(triple_count GREATER 10) file(APPEND "${output_file}" " ... (showing first 10 of ") math(EXPR remaining "${num_parts} - 2") file(APPEND "${output_file}" "${remaining} combinations)\n") break() endif() endif() endif() endforeach() endif() endif() file(APPEND "${output_file}" "--------------------------------------------------------------------------------\n") endforeach() # Add missing symbol analysis section file(APPEND "${output_file}" "\n") file(APPEND "${output_file}" "POTENTIAL MISSING INSTANTIATIONS\n") file(APPEND "${output_file}" "================================================================================\n") file(APPEND "${output_file}" "Based on linker errors, check these specific instantiations:\n\n") file(APPEND "${output_file}" "SpecialMethods missing:\n") file(APPEND "${output_file}" " - concatCpuGeneric for: bool, bfloat16, float, double, float16, int, long long, signed char, unsigned char\n") file(APPEND "${output_file}" " - sortGeneric and sortTadGeneric for: float, unsigned char, int, long long, double\n\n") file(APPEND "${output_file}" "To fix: Ensure these types are in UNIFIED_COMBINATIONS_1 or derived from UNIFIED_COMBINATIONS_2\n") endfunction() function(_internal_analyze_template_usage result_var) set(template_usage "") # Map template names to their type requirements set(TEMPLATE_1_TYPE "random;reduce_same;specials_single") set(TEMPLATE_2_TYPE "reduce3;reduce_float;indexreduce;reduce_bool;reduce_long;specials_double;indexreduction") set(TEMPLATE_3_TYPE "pairwise;scalar;broadcast") # Analyze 1-type templates foreach(template ${TEMPLATE_1_TYPE}) set(usage_data "${template}|1") if(DEFINED UNIFIED_COMBINATIONS_1) foreach(combo ${UNIFIED_COMBINATIONS_1}) if(DEFINED SRCORE_TYPE_NAME_${combo}) string(APPEND usage_data "|${SRCORE_TYPE_NAME_${combo}}") else() string(APPEND usage_data "|type_${combo}") endif() endforeach() elseif(DEFINED UNIFIED_ACTIVE_TYPES) foreach(type ${UNIFIED_ACTIVE_TYPES}) string(APPEND usage_data "|${type}") endforeach() endif() list(APPEND template_usage "${usage_data}") endforeach() # Analyze 2-type templates foreach(template ${TEMPLATE_2_TYPE}) set(usage_data "${template}|2") set(type_pairs "") if(DEFINED UNIFIED_COMBINATIONS_2) foreach(combo ${UNIFIED_COMBINATIONS_2}) string(REPLACE "," ";" parts "${combo}") list(GET parts 0 i) list(GET parts 1 j) if(DEFINED SRCORE_TYPE_NAME_${i} AND DEFINED SRCORE_TYPE_NAME_${j}) list(APPEND type_pairs "(${SRCORE_TYPE_NAME_${i}},${SRCORE_TYPE_NAME_${j}})") else() list(APPEND type_pairs "(${i},${j})") endif() endforeach() endif() string(REPLACE ";" "|" type_pairs_str "${type_pairs}") string(APPEND usage_data "|${type_pairs_str}") list(APPEND template_usage "${usage_data}") endforeach() # Analyze 3-type templates foreach(template ${TEMPLATE_3_TYPE}) set(usage_data "${template}|3") set(type_triples "") if(DEFINED UNIFIED_COMBINATIONS_3) foreach(combo ${UNIFIED_COMBINATIONS_3}) string(REPLACE "," ";" parts "${combo}") list(GET parts 0 i) list(GET parts 1 j) list(GET parts 2 k) if(DEFINED SRCORE_TYPE_NAME_${i} AND DEFINED SRCORE_TYPE_NAME_${j} AND DEFINED SRCORE_TYPE_NAME_${k}) list(APPEND type_triples "(${SRCORE_TYPE_NAME_${i}},${SRCORE_TYPE_NAME_${j}},${SRCORE_TYPE_NAME_${k}})") else() list(APPEND type_triples "(${i},${j},${k})") endif() endforeach() endif() string(REPLACE ";" "|" type_triples_str "${type_triples}") string(APPEND usage_data "|${type_triples_str}") list(APPEND template_usage "${usage_data}") endforeach() set(${result_var} "${template_usage}" PARENT_SCOPE) endfunction() # Write 3-type combinations function(_internal_write_3type_combinations output_dir profile_suffix) set(valid_file "${output_dir}/valid_3type_combinations${profile_suffix}.txt") set(invalid_file "${output_dir}/invalid_3type_combinations${profile_suffix}.txt") set(analysis_file "${output_dir}/3type_combination_analysis${profile_suffix}.txt") set(patterns_file "${output_dir}/3type_patterns${profile_suffix}.txt") # Headers file(WRITE "${valid_file}" "Valid 3-Type Combinations\n") file(APPEND "${valid_file}" "========================\n\n") file(WRITE "${invalid_file}" "Invalid 3-Type Combinations (Filtered Out)\n") file(APPEND "${invalid_file}" "=========================================\n\n") file(WRITE "${analysis_file}" "3-Type Combination Analysis\n") file(APPEND "${analysis_file}" "===========================\n\n") file(WRITE "${patterns_file}" "3-Type Combination Patterns\n") file(APPEND "${patterns_file}" "===========================\n\n") # Write valid combinations with TYPE NAMES if(DEFINED UNIFIED_COMBINATIONS_3) foreach(combo ${UNIFIED_COMBINATIONS_3}) string(REPLACE "," ";" parts "${combo}") list(GET parts 0 idx1) list(GET parts 1 idx2) list(GET parts 2 idx3) # Get the actual type names from the indices list(GET UNIFIED_ACTIVE_TYPES ${idx1} type1) list(GET UNIFIED_ACTIVE_TYPES ${idx2} type2) list(GET UNIFIED_ACTIVE_TYPES ${idx3} type3) file(APPEND "${valid_file}" "(${type1}, ${type2}, ${type3})\n") endforeach() endif() # Pattern analysis set(identity_count 0) set(mixed_precision_count 0) set(quantization_count 0) set(accumulation_count 0) set(comparison_count 0) set(other_count 0) foreach(combo ${UNIFIED_COMBINATIONS_3}) string(REPLACE "," ";" parts "${combo}") list(GET parts 0 idx1) list(GET parts 1 idx2) list(GET parts 2 idx3) list(GET UNIFIED_ACTIVE_TYPES ${idx1} type_i) list(GET UNIFIED_ACTIVE_TYPES ${idx2} type_j) list(GET UNIFIED_ACTIVE_TYPES ${idx3} type_k) if(idx1 EQUAL idx2 AND idx2 EQUAL idx3) math(EXPR identity_count "${identity_count} + 1") elseif((type_i STREQUAL "HALF" AND type_j STREQUAL "HALF" AND type_k STREQUAL "FLOAT32") OR (type_i STREQUAL "BFLOAT16" AND type_j STREQUAL "BFLOAT16" AND type_k STREQUAL "FLOAT32")) math(EXPR mixed_precision_count "${mixed_precision_count} + 1") elseif((type_i MATCHES "INT8|UINT8" AND type_j STREQUAL "FLOAT32") OR (type_i STREQUAL "FLOAT32" AND type_j MATCHES "INT8|UINT8")) math(EXPR quantization_count "${quantization_count} + 1") elseif(type_i MATCHES "INT8|UINT8" AND type_j MATCHES "INT8|UINT8" AND type_k STREQUAL "INT32") math(EXPR accumulation_count "${accumulation_count} + 1") elseif(type_k STREQUAL "BOOL") math(EXPR comparison_count "${comparison_count} + 1") else() math(EXPR other_count "${other_count} + 1") endif() endforeach() list(LENGTH UNIFIED_COMBINATIONS_3 total_count) file(APPEND "${analysis_file}" "Total Valid: ${total_count}\n\n") file(APPEND "${analysis_file}" "Pattern Breakdown:\n") file(APPEND "${analysis_file}" " Identity (same type): ${identity_count}\n") file(APPEND "${analysis_file}" " Mixed precision: ${mixed_precision_count}\n") file(APPEND "${analysis_file}" " Quantization: ${quantization_count}\n") file(APPEND "${analysis_file}" " Accumulation: ${accumulation_count}\n") file(APPEND "${analysis_file}" " Comparison: ${comparison_count}\n") file(APPEND "${analysis_file}" " Other: ${other_count}\n") # Write pattern examples file(APPEND "${patterns_file}" "Common Patterns Found:\n\n") file(APPEND "${patterns_file}" "1. Identity Patterns (${identity_count} instances)\n") file(APPEND "${patterns_file}" " Example: (T, T, T) for same type operations\n\n") if(mixed_precision_count GREATER 0) file(APPEND "${patterns_file}" "2. Mixed Precision Patterns (${mixed_precision_count} instances)\n") file(APPEND "${patterns_file}" " Examples: (HALF, HALF, FLOAT32), (BFLOAT16, BFLOAT16, FLOAT32)\n\n") endif() if(quantization_count GREATER 0) file(APPEND "${patterns_file}" "3. Quantization Patterns (${quantization_count} instances)\n") file(APPEND "${patterns_file}" " Examples: (INT8, FLOAT32, FLOAT32), (FLOAT32, UINT8, FLOAT32)\n\n") endif() if(accumulation_count GREATER 0) file(APPEND "${patterns_file}" "4. Accumulation Patterns (${accumulation_count} instances)\n") file(APPEND "${patterns_file}" " Examples: (INT8, INT8, INT32), (UINT8, UINT8, INT32)\n\n") endif() if(comparison_count GREATER 0) file(APPEND "${patterns_file}" "5. Comparison Patterns (${comparison_count} instances)\n") file(APPEND "${patterns_file}" " Output type is BOOL for comparisons\n\n") endif() endfunction() # Write CSV matrix function(_internal_write_csv_matrix output_dir profile_suffix) set(csv_file "${output_dir}/combination_matrix${profile_suffix}.csv") file(WRITE "${csv_file}" "Type Combination Matrix\n") file(APPEND "${csv_file}" "Profile: ${SD_TYPE_PROFILE}\n") file(APPEND "${csv_file}" "\n") # Header row file(APPEND "${csv_file}" "Type1,Type2") if(DEFINED UNIFIED_ACTIVE_TYPES) foreach(type ${UNIFIED_ACTIVE_TYPES}) file(APPEND "${csv_file}" ",${type}") endforeach() endif() file(APPEND "${csv_file}" "\n") # Matrix data if(DEFINED UNIFIED_ACTIVE_TYPES) set(type_index_i 0) foreach(type_i ${UNIFIED_ACTIVE_TYPES}) foreach(type_j ${UNIFIED_ACTIVE_TYPES}) file(APPEND "${csv_file}" "${type_i},${type_j}") set(type_index_j 0) foreach(type_k ${UNIFIED_ACTIVE_TYPES}) # Check if this combination exists set(combo_key "${type_index_i},${type_index_j},${type_index_j}") list(FIND UNIFIED_COMBINATIONS_3 "${combo_key}" found_idx) if(found_idx GREATER_EQUAL 0) file(APPEND "${csv_file}" ",✓") else() file(APPEND "${csv_file}" ",") endif() math(EXPR type_index_j "${type_index_j} + 1") endforeach() file(APPEND "${csv_file}" "\n") endforeach() math(EXPR type_index_i "${type_index_i} + 1") endforeach() endif() endfunction() # NEW: Write JSON analysis for programmatic consumption function(_internal_write_json_analysis output_dir profile_suffix timestamp) set(json_file "${output_dir}/combination_analysis${profile_suffix}.json") # Get statistics _internal_get_type_statistics(type_count actual_1 actual_2 actual_3 theoretical_1 theoretical_2 theoretical_3 reduction_2 reduction_3) file(WRITE "${json_file}" "{\n") file(APPEND "${json_file}" " \"metadata\": {\n") file(APPEND "${json_file}" " \"timestamp\": \"${timestamp}\",\n") file(APPEND "${json_file}" " \"profile\": \"${SD_TYPE_PROFILE}\",\n") file(APPEND "${json_file}" " \"build_dir\": \"${CMAKE_BINARY_DIR}\",\n") file(APPEND "${json_file}" " \"semantic_filtering\": ${SD_ENABLE_SEMANTIC_FILTERING},\n") file(APPEND "${json_file}" " \"aggressive_filtering\": ${SD_AGGRESSIVE_SEMANTIC_FILTERING}\n") file(APPEND "${json_file}" " },\n") file(APPEND "${json_file}" " \"statistics\": {\n") file(APPEND "${json_file}" " \"type_count\": ${type_count},\n") file(APPEND "${json_file}" " \"combinations\": {\n") file(APPEND "${json_file}" " \"single\": { \"actual\": ${actual_1}, \"theoretical\": ${theoretical_1} },\n") file(APPEND "${json_file}" " \"pair\": { \"actual\": ${actual_2}, \"theoretical\": ${theoretical_2}, \"reduction\": ${reduction_2} },\n") file(APPEND "${json_file}" " \"triple\": { \"actual\": ${actual_3}, \"theoretical\": ${theoretical_3}, \"reduction\": ${reduction_3} }\n") file(APPEND "${json_file}" " }\n") file(APPEND "${json_file}" " },\n") # Write active types file(APPEND "${json_file}" " \"active_types\": [\n") if(DEFINED UNIFIED_ACTIVE_TYPES) set(first TRUE) foreach(type ${UNIFIED_ACTIVE_TYPES}) if(NOT first) file(APPEND "${json_file}" ",\n") endif() file(APPEND "${json_file}" " \"${type}\"") set(first FALSE) endforeach() file(APPEND "${json_file}" "\n") endif() file(APPEND "${json_file}" " ]\n") file(APPEND "${json_file}" "}\n") endfunction() # NEW: Write validation rules documentation function(_internal_write_validation_rules output_dir profile_suffix) set(rules_file "${output_dir}/validation_rules${profile_suffix}.md") file(WRITE "${rules_file}" "# Type Combination Validation Rules\n\n") file(APPEND "${rules_file}" "## Overview\n") file(APPEND "${rules_file}" "This document describes the semantic validation rules applied to type combinations.\n\n") file(APPEND "${rules_file}" "## 2-Type Combination Rules\n\n") file(APPEND "${rules_file}" "### Always Valid\n") file(APPEND "${rules_file}" "- **Same Type**: `(T, T)` for any type T\n") file(APPEND "${rules_file}" "- **Bool Operations**: `(Bool, T)` or `(T, Bool)` for any type T\n") file(APPEND "${rules_file}" "- **Float Pairs**: Any combination of float types (mixed precision)\n") file(APPEND "${rules_file}" "- **Integer Pairs**: Any combination of integer types\n\n") file(APPEND "${rules_file}" "### Conditional\n") file(APPEND "${rules_file}" "- **Int-to-Float**: Specific promotions like `(INT32, FLOAT32)`\n\n") file(APPEND "${rules_file}" "## 3-Type Combination Rules\n\n") file(APPEND "${rules_file}" "### Pattern Categories\n\n") file(APPEND "${rules_file}" "#### Identity Patterns\n") file(APPEND "${rules_file}" "- `(T, T, T)` - Same type for all three\n\n") file(APPEND "${rules_file}" "#### Mixed Precision Patterns\n") file(APPEND "${rules_file}" "- `(HALF, HALF, FLOAT32)` - FP16 to FP32 accumulation\n") file(APPEND "${rules_file}" "- `(BFLOAT16, BFLOAT16, FLOAT32)` - BF16 to FP32 accumulation\n\n") file(APPEND "${rules_file}" "#### Quantization Patterns\n") file(APPEND "${rules_file}" "- `(INT8/UINT8, FLOAT32, FLOAT32)` - Dequantization\n") file(APPEND "${rules_file}" "- `(FLOAT32, INT8/UINT8, FLOAT32)` - Quantization scale\n") file(APPEND "${rules_file}" "- `(INT8, INT8, INT32)` - INT8 accumulation\n\n") file(APPEND "${rules_file}" "#### String Patterns\n") file(APPEND "${rules_file}" "- `(UTF*, UTF*, UTF*)` - String operations\n") file(APPEND "${rules_file}" "- `(UTF*, INT32/INT64, INT32/INT64)` - String indexing\n\n") if(SD_AGGRESSIVE_SEMANTIC_FILTERING) file(APPEND "${rules_file}" "## Aggressive Filtering Rules\n\n") file(APPEND "${rules_file}" "When aggressive filtering is enabled, these patterns are blocked:\n") file(APPEND "${rules_file}" "- Precision downgrades (e.g., DOUBLE to FLOAT32)\n") file(APPEND "${rules_file}" "- Bool to floating point conversions\n") file(APPEND "${rules_file}" "- Invalid string conversions\n") file(APPEND "${rules_file}" "- Integer precision loss\n\n") endif() file(APPEND "${rules_file}" "## Profile: ${SD_TYPE_PROFILE}\n") if(SD_TYPE_PROFILE STREQUAL "quantization") file(APPEND "${rules_file}" "Optimized for INT8/UINT8 quantized operations.\n") elseif(SD_TYPE_PROFILE STREQUAL "training") file(APPEND "${rules_file}" "Optimized for mixed precision training (FP16/BF16/FP32).\n") elseif(SD_TYPE_PROFILE STREQUAL "inference") file(APPEND "${rules_file}" "Balanced for general inference workloads.\n") endif() endfunction() # NEW: Enhanced logging function function(_internal_log_output_locations output_dir profile_suffix timestamp) message(STATUS "") message(STATUS "╔════════════════════════════════════════════════════════════╗") message(STATUS "║ TYPE COMBINATION REPORTS GENERATED ║") message(STATUS "╠════════════════════════════════════════════════════════════╣") message(STATUS "║ Output Directory: ${output_dir}") message(STATUS "╠════════════════════════════════════════════════════════════╣") message(STATUS "║ Summary Files:") message(STATUS "║ • combination_summary${profile_suffix}_${timestamp}.txt") message(STATUS "║ • validation_rules${profile_suffix}.md") message(STATUS "║") message(STATUS "║ 2-Type Combinations:") message(STATUS "║ • valid_2type_combinations${profile_suffix}.txt") message(STATUS "║ • invalid_2type_combinations${profile_suffix}.txt") message(STATUS "║ • 2type_combination_analysis${profile_suffix}.txt") message(STATUS "║") message(STATUS "║ 3-Type Combinations:") message(STATUS "║ • valid_3type_combinations${profile_suffix}.txt") message(STATUS "║ • invalid_3type_combinations${profile_suffix}.txt") message(STATUS "║ • 3type_combination_analysis${profile_suffix}.txt") message(STATUS "║ • 3type_patterns${profile_suffix}.txt") message(STATUS "║") message(STATUS "║ Template Usage Reports:") message(STATUS "║ • template_usage_report${profile_suffix}_${timestamp}.txt") message(STATUS "║ • template_usage_matrix${profile_suffix}_${timestamp}.csv") message(STATUS "║ • template_usage${profile_suffix}_${timestamp}.json") message(STATUS "║") message(STATUS "║ Analysis Files:") message(STATUS "║ • combination_matrix${profile_suffix}.csv") message(STATUS "║ • combination_analysis${profile_suffix}.json") if(SD_ENABLE_VISUAL_REPORTS) message(STATUS "║ • combination_report${profile_suffix}.html") endif() message(STATUS "╚════════════════════════════════════════════════════════════╝") message(STATUS "") endfunction() # Optional HTML report generator (stub - can be implemented if needed) function(_internal_generate_html_report output_dir profile_suffix timestamp) set(html_file "${output_dir}/combination_report${profile_suffix}.html") file(WRITE "${html_file}" "\n") file(APPEND "${html_file}" "\n\n") file(APPEND "${html_file}" "Type Combination Report - ${SD_TYPE_PROFILE}\n") file(APPEND "${html_file}" "\n") file(APPEND "${html_file}" "\n\n") file(APPEND "${html_file}" "

Type Combination Analysis Report

\n") file(APPEND "${html_file}" "

Generated: ${timestamp}

\n") file(APPEND "${html_file}" "

Profile: ${SD_TYPE_PROFILE}

\n") # Get statistics _internal_get_type_statistics(type_count actual_1 actual_2 actual_3 theoretical_1 theoretical_2 theoretical_3 reduction_2 reduction_3) file(APPEND "${html_file}" "

Statistics

\n") file(APPEND "${html_file}" "\n") file(APPEND "${html_file}" "\n") file(APPEND "${html_file}" "\n") file(APPEND "${html_file}" "\n") file(APPEND "${html_file}" "\n") file(APPEND "${html_file}" "
MetricActualTheoreticalReduction
1-Type${actual_1}${theoretical_1}0%
2-Type${actual_2}${theoretical_2}${reduction_2}%
3-Type${actual_3}${theoretical_3}${reduction_3}%
\n") file(APPEND "${html_file}" "\n\n") endfunction() # ADD this new quiet version that doesn't print to console function(_internal_quiet_dump_combinations output_dir) # Get timestamp for unique filenames string(TIMESTAMP timestamp "%Y%m%d_%H%M%S") # Get profile name for filename if(DEFINED SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "") set(profile_suffix "_${SD_TYPE_PROFILE}") else() set(profile_suffix "_default") endif() # Get type information _internal_get_type_statistics(type_count actual_1 actual_2 actual_3 theoretical_1 theoretical_2 theoretical_3 reduction_2 reduction_3) # Write all the files silently _internal_write_summary_file("${output_dir}" "${profile_suffix}" "${timestamp}" ${type_count} ${actual_1} ${actual_2} ${actual_3} ${theoretical_1} ${theoretical_2} ${theoretical_3} ${reduction_2} ${reduction_3}) _internal_write_2type_combinations("${output_dir}" "${profile_suffix}") _internal_write_3type_combinations("${output_dir}" "${profile_suffix}") _internal_write_csv_matrix("${output_dir}" "${profile_suffix}") _internal_write_json_analysis("${output_dir}" "${profile_suffix}" "${timestamp}") _internal_write_validation_rules("${output_dir}" "${profile_suffix}") # Create a simple status file file(WRITE "${output_dir}/status.txt" "Diagnostics generated: ${timestamp}\n") file(APPEND "${output_dir}/status.txt" "Profile: ${SD_TYPE_PROFILE}\n") file(APPEND "${output_dir}/status.txt" "Types: ${type_count}\n") file(APPEND "${output_dir}/status.txt" "2-type combinations: ${actual_2}/${theoretical_2}\n") file(APPEND "${output_dir}/status.txt" "3-type combinations: ${actual_3}/${theoretical_3}\n") endfunction()