fixed

Pure Haskell large fixed-width integers.
git clone git://git.ppad.tech/fixed.git
Log | Files | Refs | README | LICENSE

commit 5ca4c9d8fcfc4d7b7d0e7695e5250fd9ec539d62
parent 1ecbe9f1531db7373b0ddcc902f0a0b54ba656fd
Author: Jared Tobin <jared@jtobin.io>
Date:   Fri, 21 Nov 2025 12:49:21 +0400

lib: montgomery modular inverse

Diffstat:
M.gitignore | 2+-
Aetc/generate_inv.sh | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Agenerate_inv.sh | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/Numeric/Montgomery/Secp256k1/Curve.hs | 526++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mlib/Numeric/Montgomery/Secp256k1/Scalar.hs | 470++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 1097 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -3,9 +3,9 @@ dist-newstyle/ *.hp core .claude/ -etc/ *.ddump* *dump-llvm *.s *.ll *llvm +sandbox/ diff --git a/etc/generate_inv.sh b/etc/generate_inv.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# generates a constant-time haskell function for performing modular +# inversion with montgomery arithmetic on a secp256k1-derived field. +# +# fermat inversion is used. one proceeds through the (fixed, known) +# bit-string of the exponent in MSB order, montgomery-squaring an +# accumulator each time, and montgomery-multiplying on every '1' bit. +# this script generates a function consisting of this loop, unrolled. +# +# since the square-and-multiply schedule is fixed, then given +# constant-time 'sqr#' and 'mul#", 'inv#' is also constant-time by +# construction. + +# for fermat inversion, we raise an argument to e.g. the secp256k1 field +# prime - 2. i.e.: +# +# a^-1 = a ^ p - 2 mod p +# +# or to the secp256k1 scalar group order - 2: +# +# a^-1 = a ^ q - 2 mod q + +# secp256k1 field prime - 2 +# exponent="1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111011111111111111111111110000101101" + +# secp256k1 scalar group order - 2 +exponent="1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111010111010101011101101110011100110101011110100100010100000001110111011111111010010010111101000110011010000001101100100000101000001" + +echo "-- generated by etc/generate_inv.sh" +echo "inv#" +echo " :: (# Word#, Word#, Word#, Word# #)" +echo " -> (# Word#, Word#, Word#, Word# #)" +echo "inv# a =" +echo " let !t0 = (# 0x1000003D1##, 0##, 0##, 0## #) -- montgomery 'one'" + +label=1 + +for ((i = 0; i < ${#exponent}; i++)); do + echo " !t""$label"" = sqr# t""$((label-1))" + if [[ "${exponent:i:1}" == "1" ]]; then + label=$((label+1)) + echo " !t""$label"" = mul# a t""$((label-1))" + fi + label=$((label+1)) +done + +echo " !r = t""$((label-1))" +echo " in r" +echo '{-# INLINE inv# #-}' + diff --git a/generate_inv.sh b/generate_inv.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# generates a constant-time haskell function for performing modular +# inversion with montgomery arithmetic on a secp256k1-derived field. +# +# fermat inversion is used. one proceeds through the (fixed, known) +# bit-string of the exponent in MSB order, montgomery-squaring an +# accumulator each time, and montgomery-multiplying on every '1' bit. +# this script generates a function consisting of this loop, unrolled. +# +# since the square-and-multiply schedule is fixed, then given +# constant-time 'sqr#' and 'mul#", 'inv#' is also constant-time by +# construction. + +# for fermat inversion, we raise an argument to e.g. the secp256k1 field +# prime - 2. i.e.: +# +# a^-1 = a ^ p - 2 mod p +# +# or to the secp256k1 scalar group order - 2: +# +# a^-1 = a ^ q - 2 mod q + +# secp256k1 field prime - 2 +# exponent="1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111011111111111111111111110000101101" + +# secp256k1 scalar group order - 2 +exponent="1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111010111010101011101101110011100110101011110100100010100000001110111011111111010010010111101000110011010000001101100100000101000001" + +echo "-- generated by etc/generate_inv.sh" +echo "inv#" +echo " :: (# Word#, Word#, Word#, Word# #)" +echo " -> (# Word#, Word#, Word#, Word# #)" +echo "inv# a =" +echo " let !t0 = (# 0x1000003D1##, 0##, 0##, 0## #) -- montgomery 'one'" + +label=1 + +for ((i = 0; i < ${#exponent}; i++)); do + echo " !t""$label"" = sqr# t""$((label-1))" + if [[ "${exponent:i:1}" == "1" ]]; then + label=$((label+1)) + echo " !t""$label"" = mul# a t""$((label-1))" + fi + label=$((label+1)) +done + +echo " !r = t""$((label-1))" +echo " in r" +echo '{-# INLINE inv# #-}' + diff --git a/lib/Numeric/Montgomery/Secp256k1/Curve.hs b/lib/Numeric/Montgomery/Secp256k1/Curve.hs @@ -286,7 +286,7 @@ mul# a b = , 0xFFFFFFFFFFFFFFFF##, 0xFFFFFFFFFFFFFFFF## #) !(# nu, mc #) = mul_inner# a b in WW.sub_mod_c# nu mc m m -{-# INLINE mul# #-} +{-# NOINLINE mul# #-} -- cannot be inlined without exploding comp time mul :: Wider -- ^ lhs in montgomery form @@ -346,3 +346,527 @@ neg# a = sub# (# 0##, 0##, 0##, 0## #) a neg :: Wider -> Wider neg (Wider a) = Wider (neg# a) +sqr# :: (# Word#, Word#, Word#, Word# #) -> (# Word#, Word#, Word#, Word# #) +sqr# a = mul# a a +{-# INLINE sqr# #-} + +sqr :: Wider -> Wider +sqr (Wider a) = Wider (mul# a a) + +-- generated by etc/generate_inv.sh +inv# + :: (# Word#, Word#, Word#, Word# #) + -> (# Word#, Word#, Word#, Word# #) +inv# a = + let !t0 = (# 0x1000003D1##, 0##, 0##, 0## #) -- montgomery 'one' + !t1 = sqr# t0 + !t2 = mul# a t1 + !t3 = sqr# t2 + !t4 = mul# a t3 + !t5 = sqr# t4 + !t6 = mul# a t5 + !t7 = sqr# t6 + !t8 = mul# a t7 + !t9 = sqr# t8 + !t10 = mul# a t9 + !t11 = sqr# t10 + !t12 = mul# a t11 + !t13 = sqr# t12 + !t14 = mul# a t13 + !t15 = sqr# t14 + !t16 = mul# a t15 + !t17 = sqr# t16 + !t18 = mul# a t17 + !t19 = sqr# t18 + !t20 = mul# a t19 + !t21 = sqr# t20 + !t22 = mul# a t21 + !t23 = sqr# t22 + !t24 = mul# a t23 + !t25 = sqr# t24 + !t26 = mul# a t25 + !t27 = sqr# t26 + !t28 = mul# a t27 + !t29 = sqr# t28 + !t30 = mul# a t29 + !t31 = sqr# t30 + !t32 = mul# a t31 + !t33 = sqr# t32 + !t34 = mul# a t33 + !t35 = sqr# t34 + !t36 = mul# a t35 + !t37 = sqr# t36 + !t38 = mul# a t37 + !t39 = sqr# t38 + !t40 = mul# a t39 + !t41 = sqr# t40 + !t42 = mul# a t41 + !t43 = sqr# t42 + !t44 = mul# a t43 + !t45 = sqr# t44 + !t46 = mul# a t45 + !t47 = sqr# t46 + !t48 = mul# a t47 + !t49 = sqr# t48 + !t50 = mul# a t49 + !t51 = sqr# t50 + !t52 = mul# a t51 + !t53 = sqr# t52 + !t54 = mul# a t53 + !t55 = sqr# t54 + !t56 = mul# a t55 + !t57 = sqr# t56 + !t58 = mul# a t57 + !t59 = sqr# t58 + !t60 = mul# a t59 + !t61 = sqr# t60 + !t62 = mul# a t61 + !t63 = sqr# t62 + !t64 = mul# a t63 + !t65 = sqr# t64 + !t66 = mul# a t65 + !t67 = sqr# t66 + !t68 = mul# a t67 + !t69 = sqr# t68 + !t70 = mul# a t69 + !t71 = sqr# t70 + !t72 = mul# a t71 + !t73 = sqr# t72 + !t74 = mul# a t73 + !t75 = sqr# t74 + !t76 = mul# a t75 + !t77 = sqr# t76 + !t78 = mul# a t77 + !t79 = sqr# t78 + !t80 = mul# a t79 + !t81 = sqr# t80 + !t82 = mul# a t81 + !t83 = sqr# t82 + !t84 = mul# a t83 + !t85 = sqr# t84 + !t86 = mul# a t85 + !t87 = sqr# t86 + !t88 = mul# a t87 + !t89 = sqr# t88 + !t90 = mul# a t89 + !t91 = sqr# t90 + !t92 = mul# a t91 + !t93 = sqr# t92 + !t94 = mul# a t93 + !t95 = sqr# t94 + !t96 = mul# a t95 + !t97 = sqr# t96 + !t98 = mul# a t97 + !t99 = sqr# t98 + !t100 = mul# a t99 + !t101 = sqr# t100 + !t102 = mul# a t101 + !t103 = sqr# t102 + !t104 = mul# a t103 + !t105 = sqr# t104 + !t106 = mul# a t105 + !t107 = sqr# t106 + !t108 = mul# a t107 + !t109 = sqr# t108 + !t110 = mul# a t109 + !t111 = sqr# t110 + !t112 = mul# a t111 + !t113 = sqr# t112 + !t114 = mul# a t113 + !t115 = sqr# t114 + !t116 = mul# a t115 + !t117 = sqr# t116 + !t118 = mul# a t117 + !t119 = sqr# t118 + !t120 = mul# a t119 + !t121 = sqr# t120 + !t122 = mul# a t121 + !t123 = sqr# t122 + !t124 = mul# a t123 + !t125 = sqr# t124 + !t126 = mul# a t125 + !t127 = sqr# t126 + !t128 = mul# a t127 + !t129 = sqr# t128 + !t130 = mul# a t129 + !t131 = sqr# t130 + !t132 = mul# a t131 + !t133 = sqr# t132 + !t134 = mul# a t133 + !t135 = sqr# t134 + !t136 = mul# a t135 + !t137 = sqr# t136 + !t138 = mul# a t137 + !t139 = sqr# t138 + !t140 = mul# a t139 + !t141 = sqr# t140 + !t142 = mul# a t141 + !t143 = sqr# t142 + !t144 = mul# a t143 + !t145 = sqr# t144 + !t146 = mul# a t145 + !t147 = sqr# t146 + !t148 = mul# a t147 + !t149 = sqr# t148 + !t150 = mul# a t149 + !t151 = sqr# t150 + !t152 = mul# a t151 + !t153 = sqr# t152 + !t154 = mul# a t153 + !t155 = sqr# t154 + !t156 = mul# a t155 + !t157 = sqr# t156 + !t158 = mul# a t157 + !t159 = sqr# t158 + !t160 = mul# a t159 + !t161 = sqr# t160 + !t162 = mul# a t161 + !t163 = sqr# t162 + !t164 = mul# a t163 + !t165 = sqr# t164 + !t166 = mul# a t165 + !t167 = sqr# t166 + !t168 = mul# a t167 + !t169 = sqr# t168 + !t170 = mul# a t169 + !t171 = sqr# t170 + !t172 = mul# a t171 + !t173 = sqr# t172 + !t174 = mul# a t173 + !t175 = sqr# t174 + !t176 = mul# a t175 + !t177 = sqr# t176 + !t178 = mul# a t177 + !t179 = sqr# t178 + !t180 = mul# a t179 + !t181 = sqr# t180 + !t182 = mul# a t181 + !t183 = sqr# t182 + !t184 = mul# a t183 + !t185 = sqr# t184 + !t186 = mul# a t185 + !t187 = sqr# t186 + !t188 = mul# a t187 + !t189 = sqr# t188 + !t190 = mul# a t189 + !t191 = sqr# t190 + !t192 = mul# a t191 + !t193 = sqr# t192 + !t194 = mul# a t193 + !t195 = sqr# t194 + !t196 = mul# a t195 + !t197 = sqr# t196 + !t198 = mul# a t197 + !t199 = sqr# t198 + !t200 = mul# a t199 + !t201 = sqr# t200 + !t202 = mul# a t201 + !t203 = sqr# t202 + !t204 = mul# a t203 + !t205 = sqr# t204 + !t206 = mul# a t205 + !t207 = sqr# t206 + !t208 = mul# a t207 + !t209 = sqr# t208 + !t210 = mul# a t209 + !t211 = sqr# t210 + !t212 = mul# a t211 + !t213 = sqr# t212 + !t214 = mul# a t213 + !t215 = sqr# t214 + !t216 = mul# a t215 + !t217 = sqr# t216 + !t218 = mul# a t217 + !t219 = sqr# t218 + !t220 = mul# a t219 + !t221 = sqr# t220 + !t222 = mul# a t221 + !t223 = sqr# t222 + !t224 = mul# a t223 + !t225 = sqr# t224 + !t226 = mul# a t225 + !t227 = sqr# t226 + !t228 = mul# a t227 + !t229 = sqr# t228 + !t230 = mul# a t229 + !t231 = sqr# t230 + !t232 = mul# a t231 + !t233 = sqr# t232 + !t234 = mul# a t233 + !t235 = sqr# t234 + !t236 = mul# a t235 + !t237 = sqr# t236 + !t238 = mul# a t237 + !t239 = sqr# t238 + !t240 = mul# a t239 + !t241 = sqr# t240 + !t242 = mul# a t241 + !t243 = sqr# t242 + !t244 = mul# a t243 + !t245 = sqr# t244 + !t246 = mul# a t245 + !t247 = sqr# t246 + !t248 = mul# a t247 + !t249 = sqr# t248 + !t250 = mul# a t249 + !t251 = sqr# t250 + !t252 = mul# a t251 + !t253 = sqr# t252 + !t254 = mul# a t253 + !t255 = sqr# t254 + !t256 = mul# a t255 + !t257 = sqr# t256 + !t258 = mul# a t257 + !t259 = sqr# t258 + !t260 = mul# a t259 + !t261 = sqr# t260 + !t262 = mul# a t261 + !t263 = sqr# t262 + !t264 = mul# a t263 + !t265 = sqr# t264 + !t266 = mul# a t265 + !t267 = sqr# t266 + !t268 = mul# a t267 + !t269 = sqr# t268 + !t270 = mul# a t269 + !t271 = sqr# t270 + !t272 = mul# a t271 + !t273 = sqr# t272 + !t274 = mul# a t273 + !t275 = sqr# t274 + !t276 = mul# a t275 + !t277 = sqr# t276 + !t278 = mul# a t277 + !t279 = sqr# t278 + !t280 = mul# a t279 + !t281 = sqr# t280 + !t282 = mul# a t281 + !t283 = sqr# t282 + !t284 = mul# a t283 + !t285 = sqr# t284 + !t286 = mul# a t285 + !t287 = sqr# t286 + !t288 = mul# a t287 + !t289 = sqr# t288 + !t290 = mul# a t289 + !t291 = sqr# t290 + !t292 = mul# a t291 + !t293 = sqr# t292 + !t294 = mul# a t293 + !t295 = sqr# t294 + !t296 = mul# a t295 + !t297 = sqr# t296 + !t298 = mul# a t297 + !t299 = sqr# t298 + !t300 = mul# a t299 + !t301 = sqr# t300 + !t302 = mul# a t301 + !t303 = sqr# t302 + !t304 = mul# a t303 + !t305 = sqr# t304 + !t306 = mul# a t305 + !t307 = sqr# t306 + !t308 = mul# a t307 + !t309 = sqr# t308 + !t310 = mul# a t309 + !t311 = sqr# t310 + !t312 = mul# a t311 + !t313 = sqr# t312 + !t314 = mul# a t313 + !t315 = sqr# t314 + !t316 = mul# a t315 + !t317 = sqr# t316 + !t318 = mul# a t317 + !t319 = sqr# t318 + !t320 = mul# a t319 + !t321 = sqr# t320 + !t322 = mul# a t321 + !t323 = sqr# t322 + !t324 = mul# a t323 + !t325 = sqr# t324 + !t326 = mul# a t325 + !t327 = sqr# t326 + !t328 = mul# a t327 + !t329 = sqr# t328 + !t330 = mul# a t329 + !t331 = sqr# t330 + !t332 = mul# a t331 + !t333 = sqr# t332 + !t334 = mul# a t333 + !t335 = sqr# t334 + !t336 = mul# a t335 + !t337 = sqr# t336 + !t338 = mul# a t337 + !t339 = sqr# t338 + !t340 = mul# a t339 + !t341 = sqr# t340 + !t342 = mul# a t341 + !t343 = sqr# t342 + !t344 = mul# a t343 + !t345 = sqr# t344 + !t346 = mul# a t345 + !t347 = sqr# t346 + !t348 = mul# a t347 + !t349 = sqr# t348 + !t350 = mul# a t349 + !t351 = sqr# t350 + !t352 = mul# a t351 + !t353 = sqr# t352 + !t354 = mul# a t353 + !t355 = sqr# t354 + !t356 = mul# a t355 + !t357 = sqr# t356 + !t358 = mul# a t357 + !t359 = sqr# t358 + !t360 = mul# a t359 + !t361 = sqr# t360 + !t362 = mul# a t361 + !t363 = sqr# t362 + !t364 = mul# a t363 + !t365 = sqr# t364 + !t366 = mul# a t365 + !t367 = sqr# t366 + !t368 = mul# a t367 + !t369 = sqr# t368 + !t370 = mul# a t369 + !t371 = sqr# t370 + !t372 = mul# a t371 + !t373 = sqr# t372 + !t374 = mul# a t373 + !t375 = sqr# t374 + !t376 = mul# a t375 + !t377 = sqr# t376 + !t378 = mul# a t377 + !t379 = sqr# t378 + !t380 = mul# a t379 + !t381 = sqr# t380 + !t382 = mul# a t381 + !t383 = sqr# t382 + !t384 = mul# a t383 + !t385 = sqr# t384 + !t386 = mul# a t385 + !t387 = sqr# t386 + !t388 = mul# a t387 + !t389 = sqr# t388 + !t390 = mul# a t389 + !t391 = sqr# t390 + !t392 = mul# a t391 + !t393 = sqr# t392 + !t394 = mul# a t393 + !t395 = sqr# t394 + !t396 = mul# a t395 + !t397 = sqr# t396 + !t398 = mul# a t397 + !t399 = sqr# t398 + !t400 = mul# a t399 + !t401 = sqr# t400 + !t402 = mul# a t401 + !t403 = sqr# t402 + !t404 = mul# a t403 + !t405 = sqr# t404 + !t406 = mul# a t405 + !t407 = sqr# t406 + !t408 = mul# a t407 + !t409 = sqr# t408 + !t410 = mul# a t409 + !t411 = sqr# t410 + !t412 = mul# a t411 + !t413 = sqr# t412 + !t414 = mul# a t413 + !t415 = sqr# t414 + !t416 = mul# a t415 + !t417 = sqr# t416 + !t418 = mul# a t417 + !t419 = sqr# t418 + !t420 = mul# a t419 + !t421 = sqr# t420 + !t422 = mul# a t421 + !t423 = sqr# t422 + !t424 = mul# a t423 + !t425 = sqr# t424 + !t426 = mul# a t425 + !t427 = sqr# t426 + !t428 = mul# a t427 + !t429 = sqr# t428 + !t430 = mul# a t429 + !t431 = sqr# t430 + !t432 = mul# a t431 + !t433 = sqr# t432 + !t434 = mul# a t433 + !t435 = sqr# t434 + !t436 = mul# a t435 + !t437 = sqr# t436 + !t438 = mul# a t437 + !t439 = sqr# t438 + !t440 = mul# a t439 + !t441 = sqr# t440 + !t442 = mul# a t441 + !t443 = sqr# t442 + !t444 = mul# a t443 + !t445 = sqr# t444 + !t446 = mul# a t445 + !t447 = sqr# t446 + !t448 = sqr# t447 + !t449 = mul# a t448 + !t450 = sqr# t449 + !t451 = mul# a t450 + !t452 = sqr# t451 + !t453 = mul# a t452 + !t454 = sqr# t453 + !t455 = mul# a t454 + !t456 = sqr# t455 + !t457 = mul# a t456 + !t458 = sqr# t457 + !t459 = mul# a t458 + !t460 = sqr# t459 + !t461 = mul# a t460 + !t462 = sqr# t461 + !t463 = mul# a t462 + !t464 = sqr# t463 + !t465 = mul# a t464 + !t466 = sqr# t465 + !t467 = mul# a t466 + !t468 = sqr# t467 + !t469 = mul# a t468 + !t470 = sqr# t469 + !t471 = mul# a t470 + !t472 = sqr# t471 + !t473 = mul# a t472 + !t474 = sqr# t473 + !t475 = mul# a t474 + !t476 = sqr# t475 + !t477 = mul# a t476 + !t478 = sqr# t477 + !t479 = mul# a t478 + !t480 = sqr# t479 + !t481 = mul# a t480 + !t482 = sqr# t481 + !t483 = mul# a t482 + !t484 = sqr# t483 + !t485 = mul# a t484 + !t486 = sqr# t485 + !t487 = mul# a t486 + !t488 = sqr# t487 + !t489 = mul# a t488 + !t490 = sqr# t489 + !t491 = mul# a t490 + !t492 = sqr# t491 + !t493 = sqr# t492 + !t494 = sqr# t493 + !t495 = sqr# t494 + !t496 = sqr# t495 + !t497 = mul# a t496 + !t498 = sqr# t497 + !t499 = sqr# t498 + !t500 = mul# a t499 + !t501 = sqr# t500 + !t502 = mul# a t501 + !t503 = sqr# t502 + !t504 = sqr# t503 + !t505 = mul# a t504 + !r = t505 + in r +{-# INLINE inv# #-} + +inv :: Wider -> Wider +inv (Wider w) = Wider (inv# w) diff --git a/lib/Numeric/Montgomery/Secp256k1/Scalar.hs b/lib/Numeric/Montgomery/Secp256k1/Scalar.hs @@ -286,7 +286,7 @@ mul# a b = , 0xFFFFFFFFFFFFFFFE##, 0xFFFFFFFFFFFFFFFF## #) !(# nu, mc #) = mul_inner# a b in WW.sub_mod_c# nu mc m m -{-# INLINE mul# #-} +{-# NOINLINE mul# #-} -- cannot be inlined without exploding comp time mul :: Wider -- ^ lhs in montgomery form @@ -347,3 +347,471 @@ neg# a = sub# (# 0##, 0##, 0##, 0## #) a neg :: Wider -> Wider neg (Wider a) = Wider (neg# a) +sqr# :: (# Word#, Word#, Word#, Word# #) -> (# Word#, Word#, Word#, Word# #) +sqr# a = mul# a a +{-# INLINE sqr# #-} + +sqr :: Wider -> Wider +sqr (Wider a) = Wider (mul# a a) + +-- generated by etc/generate_inv.sh +inv# + :: (# Word#, Word#, Word#, Word# #) + -> (# Word#, Word#, Word#, Word# #) +inv# a = + let !t0 = (# 0x1000003D1##, 0##, 0##, 0## #) -- montgomery 'one' + !t1 = sqr# t0 + !t2 = mul# a t1 + !t3 = sqr# t2 + !t4 = mul# a t3 + !t5 = sqr# t4 + !t6 = mul# a t5 + !t7 = sqr# t6 + !t8 = mul# a t7 + !t9 = sqr# t8 + !t10 = mul# a t9 + !t11 = sqr# t10 + !t12 = mul# a t11 + !t13 = sqr# t12 + !t14 = mul# a t13 + !t15 = sqr# t14 + !t16 = mul# a t15 + !t17 = sqr# t16 + !t18 = mul# a t17 + !t19 = sqr# t18 + !t20 = mul# a t19 + !t21 = sqr# t20 + !t22 = mul# a t21 + !t23 = sqr# t22 + !t24 = mul# a t23 + !t25 = sqr# t24 + !t26 = mul# a t25 + !t27 = sqr# t26 + !t28 = mul# a t27 + !t29 = sqr# t28 + !t30 = mul# a t29 + !t31 = sqr# t30 + !t32 = mul# a t31 + !t33 = sqr# t32 + !t34 = mul# a t33 + !t35 = sqr# t34 + !t36 = mul# a t35 + !t37 = sqr# t36 + !t38 = mul# a t37 + !t39 = sqr# t38 + !t40 = mul# a t39 + !t41 = sqr# t40 + !t42 = mul# a t41 + !t43 = sqr# t42 + !t44 = mul# a t43 + !t45 = sqr# t44 + !t46 = mul# a t45 + !t47 = sqr# t46 + !t48 = mul# a t47 + !t49 = sqr# t48 + !t50 = mul# a t49 + !t51 = sqr# t50 + !t52 = mul# a t51 + !t53 = sqr# t52 + !t54 = mul# a t53 + !t55 = sqr# t54 + !t56 = mul# a t55 + !t57 = sqr# t56 + !t58 = mul# a t57 + !t59 = sqr# t58 + !t60 = mul# a t59 + !t61 = sqr# t60 + !t62 = mul# a t61 + !t63 = sqr# t62 + !t64 = mul# a t63 + !t65 = sqr# t64 + !t66 = mul# a t65 + !t67 = sqr# t66 + !t68 = mul# a t67 + !t69 = sqr# t68 + !t70 = mul# a t69 + !t71 = sqr# t70 + !t72 = mul# a t71 + !t73 = sqr# t72 + !t74 = mul# a t73 + !t75 = sqr# t74 + !t76 = mul# a t75 + !t77 = sqr# t76 + !t78 = mul# a t77 + !t79 = sqr# t78 + !t80 = mul# a t79 + !t81 = sqr# t80 + !t82 = mul# a t81 + !t83 = sqr# t82 + !t84 = mul# a t83 + !t85 = sqr# t84 + !t86 = mul# a t85 + !t87 = sqr# t86 + !t88 = mul# a t87 + !t89 = sqr# t88 + !t90 = mul# a t89 + !t91 = sqr# t90 + !t92 = mul# a t91 + !t93 = sqr# t92 + !t94 = mul# a t93 + !t95 = sqr# t94 + !t96 = mul# a t95 + !t97 = sqr# t96 + !t98 = mul# a t97 + !t99 = sqr# t98 + !t100 = mul# a t99 + !t101 = sqr# t100 + !t102 = mul# a t101 + !t103 = sqr# t102 + !t104 = mul# a t103 + !t105 = sqr# t104 + !t106 = mul# a t105 + !t107 = sqr# t106 + !t108 = mul# a t107 + !t109 = sqr# t108 + !t110 = mul# a t109 + !t111 = sqr# t110 + !t112 = mul# a t111 + !t113 = sqr# t112 + !t114 = mul# a t113 + !t115 = sqr# t114 + !t116 = mul# a t115 + !t117 = sqr# t116 + !t118 = mul# a t117 + !t119 = sqr# t118 + !t120 = mul# a t119 + !t121 = sqr# t120 + !t122 = mul# a t121 + !t123 = sqr# t122 + !t124 = mul# a t123 + !t125 = sqr# t124 + !t126 = mul# a t125 + !t127 = sqr# t126 + !t128 = mul# a t127 + !t129 = sqr# t128 + !t130 = mul# a t129 + !t131 = sqr# t130 + !t132 = mul# a t131 + !t133 = sqr# t132 + !t134 = mul# a t133 + !t135 = sqr# t134 + !t136 = mul# a t135 + !t137 = sqr# t136 + !t138 = mul# a t137 + !t139 = sqr# t138 + !t140 = mul# a t139 + !t141 = sqr# t140 + !t142 = mul# a t141 + !t143 = sqr# t142 + !t144 = mul# a t143 + !t145 = sqr# t144 + !t146 = mul# a t145 + !t147 = sqr# t146 + !t148 = mul# a t147 + !t149 = sqr# t148 + !t150 = mul# a t149 + !t151 = sqr# t150 + !t152 = mul# a t151 + !t153 = sqr# t152 + !t154 = mul# a t153 + !t155 = sqr# t154 + !t156 = mul# a t155 + !t157 = sqr# t156 + !t158 = mul# a t157 + !t159 = sqr# t158 + !t160 = mul# a t159 + !t161 = sqr# t160 + !t162 = mul# a t161 + !t163 = sqr# t162 + !t164 = mul# a t163 + !t165 = sqr# t164 + !t166 = mul# a t165 + !t167 = sqr# t166 + !t168 = mul# a t167 + !t169 = sqr# t168 + !t170 = mul# a t169 + !t171 = sqr# t170 + !t172 = mul# a t171 + !t173 = sqr# t172 + !t174 = mul# a t173 + !t175 = sqr# t174 + !t176 = mul# a t175 + !t177 = sqr# t176 + !t178 = mul# a t177 + !t179 = sqr# t178 + !t180 = mul# a t179 + !t181 = sqr# t180 + !t182 = mul# a t181 + !t183 = sqr# t182 + !t184 = mul# a t183 + !t185 = sqr# t184 + !t186 = mul# a t185 + !t187 = sqr# t186 + !t188 = mul# a t187 + !t189 = sqr# t188 + !t190 = mul# a t189 + !t191 = sqr# t190 + !t192 = mul# a t191 + !t193 = sqr# t192 + !t194 = mul# a t193 + !t195 = sqr# t194 + !t196 = mul# a t195 + !t197 = sqr# t196 + !t198 = mul# a t197 + !t199 = sqr# t198 + !t200 = mul# a t199 + !t201 = sqr# t200 + !t202 = mul# a t201 + !t203 = sqr# t202 + !t204 = mul# a t203 + !t205 = sqr# t204 + !t206 = mul# a t205 + !t207 = sqr# t206 + !t208 = mul# a t207 + !t209 = sqr# t208 + !t210 = mul# a t209 + !t211 = sqr# t210 + !t212 = mul# a t211 + !t213 = sqr# t212 + !t214 = mul# a t213 + !t215 = sqr# t214 + !t216 = mul# a t215 + !t217 = sqr# t216 + !t218 = mul# a t217 + !t219 = sqr# t218 + !t220 = mul# a t219 + !t221 = sqr# t220 + !t222 = mul# a t221 + !t223 = sqr# t222 + !t224 = mul# a t223 + !t225 = sqr# t224 + !t226 = mul# a t225 + !t227 = sqr# t226 + !t228 = mul# a t227 + !t229 = sqr# t228 + !t230 = mul# a t229 + !t231 = sqr# t230 + !t232 = mul# a t231 + !t233 = sqr# t232 + !t234 = mul# a t233 + !t235 = sqr# t234 + !t236 = mul# a t235 + !t237 = sqr# t236 + !t238 = mul# a t237 + !t239 = sqr# t238 + !t240 = mul# a t239 + !t241 = sqr# t240 + !t242 = mul# a t241 + !t243 = sqr# t242 + !t244 = mul# a t243 + !t245 = sqr# t244 + !t246 = mul# a t245 + !t247 = sqr# t246 + !t248 = mul# a t247 + !t249 = sqr# t248 + !t250 = mul# a t249 + !t251 = sqr# t250 + !t252 = mul# a t251 + !t253 = sqr# t252 + !t254 = mul# a t253 + !t255 = sqr# t254 + !t256 = sqr# t255 + !t257 = mul# a t256 + !t258 = sqr# t257 + !t259 = sqr# t258 + !t260 = mul# a t259 + !t261 = sqr# t260 + !t262 = mul# a t261 + !t263 = sqr# t262 + !t264 = mul# a t263 + !t265 = sqr# t264 + !t266 = sqr# t265 + !t267 = mul# a t266 + !t268 = sqr# t267 + !t269 = sqr# t268 + !t270 = mul# a t269 + !t271 = sqr# t270 + !t272 = sqr# t271 + !t273 = mul# a t272 + !t274 = sqr# t273 + !t275 = sqr# t274 + !t276 = mul# a t275 + !t277 = sqr# t276 + !t278 = mul# a t277 + !t279 = sqr# t278 + !t280 = mul# a t279 + !t281 = sqr# t280 + !t282 = sqr# t281 + !t283 = mul# a t282 + !t284 = sqr# t283 + !t285 = mul# a t284 + !t286 = sqr# t285 + !t287 = sqr# t286 + !t288 = mul# a t287 + !t289 = sqr# t288 + !t290 = mul# a t289 + !t291 = sqr# t290 + !t292 = mul# a t291 + !t293 = sqr# t292 + !t294 = sqr# t293 + !t295 = sqr# t294 + !t296 = mul# a t295 + !t297 = sqr# t296 + !t298 = mul# a t297 + !t299 = sqr# t298 + !t300 = mul# a t299 + !t301 = sqr# t300 + !t302 = sqr# t301 + !t303 = sqr# t302 + !t304 = mul# a t303 + !t305 = sqr# t304 + !t306 = mul# a t305 + !t307 = sqr# t306 + !t308 = sqr# t307 + !t309 = mul# a t308 + !t310 = sqr# t309 + !t311 = sqr# t310 + !t312 = mul# a t311 + !t313 = sqr# t312 + !t314 = sqr# t313 + !t315 = mul# a t314 + !t316 = sqr# t315 + !t317 = mul# a t316 + !t318 = sqr# t317 + !t319 = mul# a t318 + !t320 = sqr# t319 + !t321 = mul# a t320 + !t322 = sqr# t321 + !t323 = sqr# t322 + !t324 = mul# a t323 + !t325 = sqr# t324 + !t326 = sqr# t325 + !t327 = sqr# t326 + !t328 = mul# a t327 + !t329 = sqr# t328 + !t330 = sqr# t329 + !t331 = sqr# t330 + !t332 = sqr# t331 + !t333 = mul# a t332 + !t334 = sqr# t333 + !t335 = sqr# t334 + !t336 = mul# a t335 + !t337 = sqr# t336 + !t338 = sqr# t337 + !t339 = sqr# t338 + !t340 = sqr# t339 + !t341 = sqr# t340 + !t342 = sqr# t341 + !t343 = sqr# t342 + !t344 = sqr# t343 + !t345 = mul# a t344 + !t346 = sqr# t345 + !t347 = mul# a t346 + !t348 = sqr# t347 + !t349 = mul# a t348 + !t350 = sqr# t349 + !t351 = sqr# t350 + !t352 = mul# a t351 + !t353 = sqr# t352 + !t354 = mul# a t353 + !t355 = sqr# t354 + !t356 = mul# a t355 + !t357 = sqr# t356 + !t358 = sqr# t357 + !t359 = mul# a t358 + !t360 = sqr# t359 + !t361 = mul# a t360 + !t362 = sqr# t361 + !t363 = mul# a t362 + !t364 = sqr# t363 + !t365 = mul# a t364 + !t366 = sqr# t365 + !t367 = mul# a t366 + !t368 = sqr# t367 + !t369 = mul# a t368 + !t370 = sqr# t369 + !t371 = mul# a t370 + !t372 = sqr# t371 + !t373 = mul# a t372 + !t374 = sqr# t373 + !t375 = sqr# t374 + !t376 = mul# a t375 + !t377 = sqr# t376 + !t378 = sqr# t377 + !t379 = sqr# t378 + !t380 = mul# a t379 + !t381 = sqr# t380 + !t382 = sqr# t381 + !t383 = sqr# t382 + !t384 = mul# a t383 + !t385 = sqr# t384 + !t386 = sqr# t385 + !t387 = mul# a t386 + !t388 = sqr# t387 + !t389 = mul# a t388 + !t390 = sqr# t389 + !t391 = mul# a t390 + !t392 = sqr# t391 + !t393 = mul# a t392 + !t394 = sqr# t393 + !t395 = sqr# t394 + !t396 = mul# a t395 + !t397 = sqr# t396 + !t398 = sqr# t397 + !t399 = sqr# t398 + !t400 = sqr# t399 + !t401 = mul# a t400 + !t402 = sqr# t401 + !t403 = mul# a t402 + !t404 = sqr# t403 + !t405 = sqr# t404 + !t406 = sqr# t405 + !t407 = mul# a t406 + !t408 = sqr# t407 + !t409 = mul# a t408 + !t410 = sqr# t409 + !t411 = sqr# t410 + !t412 = mul# a t411 + !t413 = sqr# t412 + !t414 = sqr# t413 + !t415 = sqr# t414 + !t416 = sqr# t415 + !t417 = sqr# t416 + !t418 = sqr# t417 + !t419 = sqr# t418 + !t420 = mul# a t419 + !t421 = sqr# t420 + !t422 = mul# a t421 + !t423 = sqr# t422 + !t424 = sqr# t423 + !t425 = mul# a t424 + !t426 = sqr# t425 + !t427 = mul# a t426 + !t428 = sqr# t427 + !t429 = sqr# t428 + !t430 = sqr# t429 + !t431 = mul# a t430 + !t432 = sqr# t431 + !t433 = sqr# t432 + !t434 = sqr# t433 + !t435 = sqr# t434 + !t436 = sqr# t435 + !t437 = sqr# t436 + !t438 = mul# a t437 + !t439 = sqr# t438 + !t440 = sqr# t439 + !t441 = mul# a t440 + !t442 = sqr# t441 + !t443 = sqr# t442 + !t444 = sqr# t443 + !t445 = sqr# t444 + !t446 = sqr# t445 + !t447 = sqr# t446 + !t448 = mul# a t447 + !r = t448 + in r +{-# INLINE inv# #-} + +inv :: Wider -> Wider +inv (Wider w) = Wider (inv# w) +