@@ -763,13 +763,20 @@ summary_stats_constructor <- function(z = NULL, R = NULL, X = NULL,
763763 p <- length(z )
764764 }
765765
766+ # Standardize X so X'X = R (correlation matrix). The model assumes
767+ # column-standardized X; without this, X'X/B gives sample covariance
768+ # which != correlation when columns have different variances.
769+ if (! is.null(X )) {
770+ X <- standardize_X(X )
771+ }
772+
766773 # Stochastic LD sketch diagnostics (static, computed once at initialization).
767- # X is NOT standardized here (raw centered matrix), so x_is_standardized = FALSE .
774+ # X is standardized (X'X = R) at this point .
768775 stochastic_ld_diagnostics <- NULL
769776 if (! is.null(stochastic_ld_sample )) {
770777 stochastic_ld_diagnostics <- compute_stochastic_ld_diagnostics(
771778 X = X , R = R , B = stochastic_ld_sample , p = length(z ),
772- x_is_standardized = FALSE )
779+ x_is_standardized = TRUE )
773780 }
774781
775782 # Convert to sufficient statistics format
@@ -781,10 +788,8 @@ summary_stats_constructor <- function(z = NULL, R = NULL, X = NULL,
781788 " n is large (Inf) and the effect sizes are small (close to zero)." )
782789 if (! is.null(R )) {
783790 XtX <- R
784- } else {
785- # X path: scale so X'X = R (i.e., X'X/B_x = R, we want X'X = R)
786- X <- X / sqrt(nrow(X ))
787791 }
792+ # X path: X'X = R already after standardize_X, no further scaling needed.
788793 Xty <- z
789794 yty <- 1
790795 n <- 2
@@ -803,8 +808,8 @@ summary_stats_constructor <- function(z = NULL, R = NULL, X = NULL,
803808 if (! is.null(R )) {
804809 XtX <- (n - 1 ) * R
805810 } else {
806- # X path: scale so X'X = (n-1)*R
807- X <- X * sqrt(( n - 1 ) / nrow( X ) )
811+ # X path: X'X = R after standardize_X, scale to X'X = (n-1)*R
812+ X <- X * sqrt(n - 1 )
808813 }
809814 Xty <- sqrt(n - 1 ) * z
810815 yty <- (n - 1 ) * (if (! is.null(var_y )) var_y else 1 )
0 commit comments