@@ -3,6 +3,7 @@ use std::sync::Arc;
33
44use num_bigint:: BigInt ;
55use num_bigint:: Sign ;
6+ use num_traits:: ToPrimitive ;
67use rssn:: symbolic:: calculus:: differentiate;
78use rssn:: symbolic:: calculus:: substitute;
89use rssn:: symbolic:: core:: Expr ;
@@ -252,6 +253,7 @@ fn main() -> Result<
252253 deriv = simplify ( & deriv)
253254 . to_ast ( )
254255 . map_err ( |e| {
256+
255257 format ! (
256258 "to_ast failed: {}" ,
257259 e
@@ -260,36 +262,54 @@ fn main() -> Result<
260262
261263 deriv = force_bigint ( deriv) ;
262264
263- // Convert payload to BigInt
264- let payload_num =
265- BigInt :: from_bytes_be (
266- Sign :: Plus ,
267- surprise
268- . payload
269- . as_bytes ( ) ,
265+ // Convert payload to BigInt in chunks (1 byte per chunk for maximum safety)
266+ let payload_bytes = surprise
267+ . payload
268+ . as_bytes ( ) ;
269+
270+ let chunk_size = 1 ;
271+
272+ let mut results = Vec :: new ( ) ;
273+
274+ for chunk in payload_bytes
275+ . chunks ( chunk_size)
276+ {
277+
278+ // Prepend a 1 byte to distinguish from trailing zeros and keep x > 255
279+ let mut chunk_with_sentinel =
280+ vec ! [ 1u8 ] ;
281+
282+ chunk_with_sentinel
283+ . extend_from_slice (
284+ chunk,
285+ ) ;
286+
287+ let p = BigInt :: from_bytes_be ( Sign :: Plus , & chunk_with_sentinel) ;
288+
289+ // Evaluate at P
290+ let eval_expr = substitute (
291+ & deriv,
292+ "x" ,
293+ & Expr :: BigInt ( p) ,
270294 ) ;
271295
272- // Evaluate at P
273- // result = f(P)
274- let eval_expr = substitute (
275- & deriv,
276- "x" ,
277- & Expr :: BigInt ( payload_num) ,
278- ) ;
296+ let r =
297+ simplify ( & eval_expr)
298+ . to_ast ( )
299+ . map_err ( |e| {
279300
280- let result_expr = simplify (
281- & eval_expr,
282- )
283- . to_ast ( )
284- . map_err ( |e| {
285- format ! (
286- "to_ast failed: {}" ,
287- e
288- )
289- } ) ?;
301+ format ! (
302+ "to_ast failed: {}" ,
303+ e
304+ )
305+ } ) ?;
290306
291- let result_expr =
292- force_bigint ( result_expr) ;
307+ // Aggressively force evaluation of numeric parts
308+ let evaled =
309+ force_bigint_eval ( r) ;
310+
311+ results. push ( evaled) ;
312+ }
293313
294314 // Serialize
295315 let assets_dir =
@@ -307,7 +327,7 @@ fn main() -> Result<
307327 Path :: new ( assets_dir)
308328 . join ( "surprise.bin" ) ;
309329
310- let encoded: Vec < u8 > = bincode_next:: serde:: encode_to_vec ( & result_expr , bincode_next:: config:: standard ( ) )
330+ let encoded: Vec < u8 > = bincode_next:: serde:: encode_to_vec ( & results , bincode_next:: config:: standard ( ) )
311331 . map_err ( |e| format ! ( "Failed to encode: {}" , e) ) ?;
312332
313333 std:: fs:: write (
@@ -411,3 +431,58 @@ fn force_bigint(expr: Expr) -> Expr {
411431 | _ => expr,
412432 }
413433}
434+
435+ fn force_bigint_eval (
436+ expr : Expr
437+ ) -> Expr {
438+
439+ match expr {
440+ Expr :: Constant ( f) if f. fract ( ) == 0.0 => Expr :: BigInt ( num_bigint:: BigInt :: from ( f as i64 ) ) ,
441+ Expr :: Add ( a, b) => {
442+ let left = force_bigint_eval ( a. as_ref ( ) . clone ( ) ) ;
443+ let right = force_bigint_eval ( b. as_ref ( ) . clone ( ) ) ;
444+ match ( left, right) {
445+ ( Expr :: BigInt ( va) , Expr :: BigInt ( vb) ) => Expr :: BigInt ( va + vb) ,
446+ ( la, ra) => Expr :: Add ( Arc :: new ( la) , Arc :: new ( ra) ) ,
447+ }
448+ }
449+ Expr :: Sub ( a, b) => {
450+ let left = force_bigint_eval ( a. as_ref ( ) . clone ( ) ) ;
451+ let right = force_bigint_eval ( b. as_ref ( ) . clone ( ) ) ;
452+ match ( left, right) {
453+ ( Expr :: BigInt ( va) , Expr :: BigInt ( vb) ) => Expr :: BigInt ( va - vb) ,
454+ ( la, ra) => Expr :: Sub ( Arc :: new ( la) , Arc :: new ( ra) ) ,
455+ }
456+ }
457+ Expr :: Mul ( a, b) => {
458+ let left = force_bigint_eval ( a. as_ref ( ) . clone ( ) ) ;
459+ let right = force_bigint_eval ( b. as_ref ( ) . clone ( ) ) ;
460+ match ( left, right) {
461+ ( Expr :: BigInt ( va) , Expr :: BigInt ( vb) ) => Expr :: BigInt ( va * vb) ,
462+ ( la, ra) => Expr :: Mul ( Arc :: new ( la) , Arc :: new ( ra) ) ,
463+ }
464+ }
465+ Expr :: Power ( a, b) => {
466+ let left = force_bigint_eval ( a. as_ref ( ) . clone ( ) ) ;
467+ let right = force_bigint_eval ( b. as_ref ( ) . clone ( ) ) ;
468+ match ( left, right) {
469+ ( Expr :: BigInt ( base) , Expr :: BigInt ( exp) ) => {
470+ if let Some ( e) = exp. to_u32 ( ) {
471+ Expr :: BigInt ( base. pow ( e) )
472+ } else {
473+ Expr :: Power ( Arc :: new ( Expr :: BigInt ( base) ) , Arc :: new ( Expr :: BigInt ( exp) ) )
474+ }
475+ }
476+ ( la, ra) => Expr :: Power ( Arc :: new ( la) , Arc :: new ( ra) ) ,
477+ }
478+ }
479+ Expr :: Neg ( a) => {
480+ let inner = force_bigint_eval ( a. as_ref ( ) . clone ( ) ) ;
481+ match inner {
482+ Expr :: BigInt ( v) => Expr :: BigInt ( -v) ,
483+ other => Expr :: Neg ( Arc :: new ( other) ) ,
484+ }
485+ }
486+ _ => expr,
487+ }
488+ }
0 commit comments