Coverage for models/rgb/transfer_functions/red.py: 60%
78 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
1"""
2RED Log Encodings
3=================
5Define the *RED* log encodings.
7- :func:`colour.models.log_encoding_REDLog`
8- :func:`colour.models.log_decoding_REDLog`
9- :func:`colour.models.log_encoding_REDLogFilm`
10- :func:`colour.models.log_decoding_REDLogFilm`
11- :func:`colour.models.log_encoding_Log3G10_v1`
12- :func:`colour.models.log_decoding_Log3G10_v1`
13- :func:`colour.models.log_encoding_Log3G10_v2`
14- :func:`colour.models.log_decoding_Log3G10_v2`
15- :func:`colour.models.log_encoding_Log3G10_v3`
16- :func:`colour.models.log_decoding_Log3G10_v3`
17- :attr:`colour.models.LOG3G10_ENCODING_METHODS`
18- :func:`colour.models.log_encoding_Log3G10`
19- :attr:`colour.models.LOG3G10_DECODING_METHODS`
20- :func:`colour.models.log_decoding_Log3G10`
21- :func:`colour.models.log_encoding_Log3G12`
22- :func:`colour.models.log_decoding_Log3G12`
24References
25----------
26- :cite:`Nattress2016a` : Nattress, G. (2016). Private Discussion with Shaw,
27 N.
28- :cite:`REDDigitalCinema2017` : RED Digital Cinema. (2017). White Paper on
29 REDWideGamutRGB and Log3G10. Retrieved January 16, 2021, from
30 https://www.red.com/download/white-paper-on-redwidegamutrgb-and-log3g10
31- :cite:`SonyImageworks2012a` : Sony Imageworks. (2012). make.py. Retrieved
32 November 27, 2014, from
33 https://github.com/imageworks/OpenColorIO-Configs/blob/master/\
34nuke-default/make.py
35"""
37from __future__ import annotations
39import typing
41import numpy as np
43if typing.TYPE_CHECKING:
44 from colour.hints import Literal
46from colour.hints import ( # noqa: TC001
47 ArrayLike,
48 Domain1,
49 Range1,
50)
51from colour.models.rgb.transfer_functions import (
52 log_decoding_Cineon,
53 log_encoding_Cineon,
54)
55from colour.utilities import (
56 CanonicalMapping,
57 as_float,
58 as_float_array,
59 from_range_1,
60 to_domain_1,
61 validate_method,
62)
64__author__ = "Colour Developers"
65__copyright__ = "Copyright 2013 Colour Developers"
66__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
67__maintainer__ = "Colour Developers"
68__email__ = "colour-developers@colour-science.org"
69__status__ = "Production"
71__all__ = [
72 "log_encoding_REDLog",
73 "log_decoding_REDLog",
74 "log_encoding_REDLogFilm",
75 "log_decoding_REDLogFilm",
76 "log_encoding_Log3G10_v1",
77 "log_decoding_Log3G10_v1",
78 "log_encoding_Log3G10_v2",
79 "log_decoding_Log3G10_v2",
80 "log_encoding_Log3G10_v3",
81 "log_decoding_Log3G10_v3",
82 "LOG3G10_ENCODING_METHODS",
83 "log_encoding_Log3G10",
84 "LOG3G10_DECODING_METHODS",
85 "log_decoding_Log3G10",
86 "log_encoding_Log3G12",
87 "log_decoding_Log3G12",
88]
91def log_encoding_REDLog(
92 x: Domain1,
93 black_offset: ArrayLike = 10 ** ((0 - 1023) / 511),
94) -> Range1:
95 """
96 Apply the *REDLog* log encoding opto-electronic transfer function (OETF).
98 Parameters
99 ----------
100 x
101 Linear data :math:`x`.
102 black_offset
103 Black offset value.
105 Returns
106 -------
107 :class:`numpy.ndarray`
108 *REDLog* non-linear encoded data :math:`y`.
110 Notes
111 -----
112 +------------+-----------------------+---------------+
113 | **Domain** | **Scale - Reference** | **Scale - 1** |
114 +============+=======================+===============+
115 | ``x`` | 1 | 1 |
116 +------------+-----------------------+---------------+
118 +------------+-----------------------+---------------+
119 | **Range** | **Scale - Reference** | **Scale - 1** |
120 +============+=======================+===============+
121 | ``y`` | 1 | 1 |
122 +------------+-----------------------+---------------+
124 References
125 ----------
126 :cite:`SonyImageworks2012a`
128 Examples
129 --------
130 >>> log_encoding_REDLog(0.18) # doctest: +ELLIPSIS
131 0.6376218...
132 """
134 x = to_domain_1(x)
135 black_offset = as_float_array(black_offset)
137 y = (1023 + 511 * np.log10(x * (1 - black_offset) + black_offset)) / 1023
139 return as_float(from_range_1(y))
142def log_decoding_REDLog(
143 y: Domain1,
144 black_offset: ArrayLike = 10 ** ((0 - 1023) / 511),
145) -> Range1:
146 """
147 Apply the *REDLog* log decoding inverse opto-electronic transfer function (OETF).
149 Parameters
150 ----------
151 y
152 *REDLog* non-linear encoded data :math:`y`.
153 black_offset
154 Black offset value.
156 Returns
157 -------
158 :class:`numpy.ndarray`
159 Linear data :math:`x`.
161 Notes
162 -----
163 +------------+-----------------------+---------------+
164 | **Domain** | **Scale - Reference** | **Scale - 1** |
165 +============+=======================+===============+
166 | ``y`` | 1 | 1 |
167 +------------+-----------------------+---------------+
169 +------------+-----------------------+---------------+
170 | **Range** | **Scale - Reference** | **Scale - 1** |
171 +============+=======================+===============+
172 | ``x`` | 1 | 1 |
173 +------------+-----------------------+---------------+
175 References
176 ----------
177 :cite:`SonyImageworks2012a`
179 Examples
180 --------
181 >>> log_decoding_REDLog(0.637621845988175) # doctest: +ELLIPSIS
182 0.1...
183 """
185 y = to_domain_1(y)
186 black_offset = as_float_array(black_offset)
188 x = ((10 ** ((1023 * y - 1023) / 511)) - black_offset) / (1 - black_offset)
190 return as_float(from_range_1(x))
193def log_encoding_REDLogFilm(
194 x: Domain1,
195 black_offset: ArrayLike = 10 ** ((95 - 685) / 300),
196) -> Range1:
197 """
198 Apply the *REDLogFilm* log encoding opto-electronic transfer function (OETF).
200 Parameters
201 ----------
202 x
203 Linear data :math:`x`.
204 black_offset
205 Black offset value.
207 Returns
208 -------
209 :class:`numpy.ndarray`
210 *REDLogFilm* non-linear encoded data :math:`y`.
212 Notes
213 -----
214 +------------+-----------------------+---------------+
215 | **Domain** | **Scale - Reference** | **Scale - 1** |
216 +============+=======================+===============+
217 | ``x`` | 1 | 1 |
218 +------------+-----------------------+---------------+
220 +------------+-----------------------+---------------+
221 | **Range** | **Scale - Reference** | **Scale - 1** |
222 +============+=======================+===============+
223 | ``y`` | 1 | 1 |
224 +------------+-----------------------+---------------+
226 References
227 ----------
228 :cite:`SonyImageworks2012a`
230 Examples
231 --------
232 >>> log_encoding_REDLogFilm(0.18) # doctest: +ELLIPSIS
233 0.4573196...
234 """
236 return log_encoding_Cineon(x, black_offset)
239def log_decoding_REDLogFilm(
240 y: Domain1,
241 black_offset: ArrayLike = 10 ** ((95 - 685) / 300),
242) -> Range1:
243 """
244 Apply the *REDLogFilm* log decoding inverse opto-electronic transfer
245 function (OETF).
247 Parameters
248 ----------
249 y
250 *REDLogFilm* non-linear encoded data :math:`y`.
251 black_offset
252 Black offset value.
254 Returns
255 -------
256 :class:`numpy.ndarray`
257 Linear data :math:`x`.
259 Notes
260 -----
261 +------------+-----------------------+---------------+
262 | **Domain** | **Scale - Reference** | **Scale - 1** |
263 +============+=======================+===============+
264 | ``y`` | 1 | 1 |
265 +------------+-----------------------+---------------+
267 +------------+-----------------------+---------------+
268 | **Range** | **Scale - Reference** | **Scale - 1** |
269 +============+=======================+===============+
270 | ``x`` | 1 | 1 |
271 +------------+-----------------------+---------------+
273 References
274 ----------
275 :cite:`SonyImageworks2012a`
277 Examples
278 --------
279 >>> log_decoding_REDLogFilm(0.457319613085418) # doctest: +ELLIPSIS
280 0.1799999...
281 """
283 return log_decoding_Cineon(y, black_offset)
286def log_encoding_Log3G10_v1(x: Domain1) -> Range1:
287 """
288 Apply the *Log3G10* *v1* log encoding opto-electronic transfer function (OETF).
290 From *REDCINE-X PRO Beta 42* and *Resolve 12.5.2*.
292 Parameters
293 ----------
294 x
295 Linear data :math:`x`.
297 Returns
298 -------
299 :class:`numpy.ndarray`
300 *Log3G10* *v1* non-linear encoded data :math:`y`.
302 Notes
303 -----
304 +------------+-----------------------+---------------+
305 | **Domain** | **Scale - Reference** | **Scale - 1** |
306 +============+=======================+===============+
307 | ``x`` | 1 | 1 |
308 +------------+-----------------------+---------------+
310 +------------+-----------------------+---------------+
311 | **Range** | **Scale - Reference** | **Scale - 1** |
312 +============+=======================+===============+
313 | ``y`` | 1 | 1 |
314 +------------+-----------------------+---------------+
316 References
317 ----------
318 :cite:`Nattress2016a`
320 Examples
321 --------
322 >>> log_encoding_Log3G10_v1(0.18) # doctest: +ELLIPSIS
323 0.3333336...
324 """
326 x = to_domain_1(x)
328 y = np.sign(x) * 0.222497 * np.log10((np.abs(x) * 169.379333) + 1)
330 return as_float(from_range_1(y))
333def log_decoding_Log3G10_v1(y: Domain1) -> Range1:
334 """
335 Apply the *Log3G10* *v1* log decoding inverse opto-electronic transfer
336 function (OETF).
338 From *REDCINE-X PRO Beta 42* and *Resolve 12.5.2*.
340 Parameters
341 ----------
342 y
343 *Log3G10* *v1* non-linear encoded data :math:`y`.
345 Returns
346 -------
347 :class:`numpy.ndarray`
348 Linear data :math:`x`.
350 Notes
351 -----
352 +------------+-----------------------+---------------+
353 | **Domain** | **Scale - Reference** | **Scale - 1** |
354 +============+=======================+===============+
355 | ``y`` | 1 | 1 |
356 +------------+-----------------------+---------------+
358 +------------+-----------------------+---------------+
359 | **Range** | **Scale - Reference** | **Scale - 1** |
360 +============+=======================+===============+
361 | ``x`` | 1 | 1 |
362 +------------+-----------------------+---------------+
364 References
365 ----------
366 :cite:`Nattress2016a`
368 Examples
369 --------
370 >>> log_decoding_Log3G10_v1(1.0 / 3) # doctest: +ELLIPSIS
371 0.1799994...
372 """
374 y = to_domain_1(y)
376 x = np.sign(y) * (10.0 ** (np.abs(y) / 0.222497) - 1) / 169.379333
378 return as_float(from_range_1(x))
381def log_encoding_Log3G10_v2(x: Domain1) -> Range1:
382 """
383 Apply the *Log3G10* *v2* log encoding opto-electronic transfer function (OETF).
385 Current curve used in *REDCINE-X PRO*.
387 Parameters
388 ----------
389 x
390 Linear data :math:`x`.
392 Returns
393 -------
394 :class:`numpy.ndarray`
395 *Log3G10* *v2* non-linear encoded data :math:`y`.
397 Notes
398 -----
399 +------------+-----------------------+---------------+
400 | **Domain** | **Scale - Reference** | **Scale - 1** |
401 +============+=======================+===============+
402 | ``x`` | 1 | 1 |
403 +------------+-----------------------+---------------+
405 +------------+-----------------------+---------------+
406 | **Range** | **Scale - Reference** | **Scale - 1** |
407 +============+=======================+===============+
408 | ``y`` | 1 | 1 |
409 +------------+-----------------------+---------------+
411 References
412 ----------
413 :cite:`Nattress2016a`
415 Examples
416 --------
417 >>> log_encoding_Log3G10_v2(0.0) # doctest: +ELLIPSIS
418 0.0915514...
419 """
421 x = to_domain_1(x)
423 y = np.sign(x + 0.01) * 0.224282 * np.log10((np.abs(x + 0.01) * 155.975327) + 1)
425 return as_float(from_range_1(y))
428def log_decoding_Log3G10_v2(y: Domain1) -> Range1:
429 """
430 Apply the *Log3G10* *v2* log decoding inverse opto-electronic transfer
431 function (OETF).
433 Current curve used in *REDCINE-X PRO*.
435 Parameters
436 ----------
437 y
438 *Log3G10* *v2* non-linear encoded data :math:`y`.
440 Returns
441 -------
442 :class:`numpy.ndarray`
443 Linear data :math:`x`.
445 Notes
446 -----
447 +------------+-----------------------+---------------+
448 | **Domain** | **Scale - Reference** | **Scale - 1** |
449 +============+=======================+===============+
450 | ``y`` | 1 | 1 |
451 +------------+-----------------------+---------------+
453 +------------+-----------------------+---------------+
454 | **Range** | **Scale - Reference** | **Scale - 1** |
455 +============+=======================+===============+
456 | ``x`` | 1 | 1 |
457 +------------+-----------------------+---------------+
459 References
460 ----------
461 :cite:`Nattress2016a`
463 Examples
464 --------
465 >>> log_decoding_Log3G10_v2(1.0) # doctest: +ELLIPSIS
466 184.3223476...
467 """
469 y = to_domain_1(y)
471 x = (np.sign(y) * (10.0 ** (np.abs(y) / 0.224282) - 1) / 155.975327) - 0.01
473 return as_float(from_range_1(x))
476def log_encoding_Log3G10_v3(x: Domain1) -> Range1:
477 """
478 Apply the *Log3G10* *v3* log encoding opto-electronic transfer function (OETF).
480 As described in the *RedLog3G10* whitepaper.
482 Parameters
483 ----------
484 x
485 Linear data :math:`x`.
487 Returns
488 -------
489 :class:`numpy.ndarray`
490 *Log3G10* *v3* non-linear encoded data :math:`y`.
492 Notes
493 -----
494 +------------+-----------------------+---------------+
495 | **Domain** | **Scale - Reference** | **Scale - 1** |
496 +============+=======================+===============+
497 | ``x`` | 1 | 1 |
498 +------------+-----------------------+---------------+
500 +------------+-----------------------+---------------+
501 | **Range** | **Scale - Reference** | **Scale - 1** |
502 +============+=======================+===============+
503 | ``y`` | 1 | 1 |
504 +------------+-----------------------+---------------+
506 References
507 ----------
508 :cite:`REDDigitalCinema2017`
510 Examples
511 --------
512 >>> log_encoding_Log3G10_v3(0.0) # doctest: +ELLIPSIS
513 0.09155148...
514 """
516 a = 0.224282
517 b = 155.975327
518 c = 0.01
519 g = 15.1927
521 x = to_domain_1(x)
523 x = x + c
525 y = np.where(x < 0.0, x * g, np.sign(x) * a * np.log10((np.abs(x) * b) + 1.0))
527 return as_float(from_range_1(y))
530def log_decoding_Log3G10_v3(y: Domain1) -> Range1:
531 """
532 Apply the *Log3G10* *v3* log decoding inverse opto-electronic transfer
533 function (OETF).
535 As described in the *RedLog3G10* whitepaper.
537 Parameters
538 ----------
539 y
540 *Log3G10* *v3* non-linear encoded data :math:`y`.
542 Returns
543 -------
544 :class:`numpy.ndarray`
545 Linear *Log3G10* *v3* data :math:`x`.
547 Notes
548 -----
549 +------------+-----------------------+---------------+
550 | **Domain** | **Scale - Reference** | **Scale - 1** |
551 +============+=======================+===============+
552 | ``y`` | 1 | 1 |
553 +------------+-----------------------+---------------+
555 +------------+-----------------------+---------------+
556 | **Range** | **Scale - Reference** | **Scale - 1** |
557 +============+=======================+===============+
558 | ``x`` | 1 | 1 |
559 +------------+-----------------------+---------------+
561 References
562 ----------
563 :cite:`REDDigitalCinema2017`
565 Examples
566 --------
567 >>> log_decoding_Log3G10_v3(1.0) # doctest: +ELLIPSIS
568 184.32234764...
569 """
571 a = 0.224282
572 b = 155.975327
573 c = 0.01
574 g = 15.1927
576 y = to_domain_1(y)
578 x = np.where(
579 y < 0.0,
580 (y / g) - c,
581 np.sign(y) * (10 ** (np.abs(y) / a) - 1.0) / b - c,
582 )
584 return as_float(from_range_1(x))
587LOG3G10_ENCODING_METHODS: CanonicalMapping = CanonicalMapping(
588 {
589 "v1": log_encoding_Log3G10_v1,
590 "v2": log_encoding_Log3G10_v2,
591 "v3": log_encoding_Log3G10_v3,
592 }
593)
594LOG3G10_ENCODING_METHODS.__doc__ = """
595Supported *Log3G10* log encoding curve / opto-electronic transfer (OETF)
596function methods.
598References
599----------
600:cite:`Nattress2016a`, :cite:`REDDigitalCinema2017`
601"""
604def log_encoding_Log3G10(
605 x: Domain1,
606 method: Literal["v1", "v2", "v3"] | str = "v3",
607) -> Range1:
608 """
609 Apply the *Log3G10* log encoding opto-electronic transfer function (OETF).
611 Parameters
612 ----------
613 x
614 Linear data :math:`x`.
615 method
616 Computation method.
618 Returns
619 -------
620 :class:`numpy.ndarray`
621 *Log3G10* non-linear encoded data :math:`y`.
623 Notes
624 -----
625 +------------+-----------------------+---------------+
626 | **Domain** | **Scale - Reference** | **Scale - 1** |
627 +============+=======================+===============+
628 | ``x`` | 1 | 1 |
629 +------------+-----------------------+---------------+
631 +------------+-----------------------+---------------+
632 | **Range** | **Scale - Reference** | **Scale - 1** |
633 +============+=======================+===============+
634 | ``y`` | 1 | 1 |
635 +------------+-----------------------+---------------+
637 - The *Log3G10* *v1* log encoding curve is the one used in
638 *REDCINE-X Beta 42*. *Resolve 12.5.2* also uses the *v1* curve.
639 *RED* is planning to use the *Log3G10* *v2* log encoding curve in
640 the release version of the *RED SDK*.
641 - The intent of the *Log3G10* *v1* log encoding curve is that zero
642 maps to zero, 0.18 maps to 1/3, and 10 stops above 0.18 maps to
643 1.0. The name indicates this in a similar way to the naming
644 conventions of *Sony HyperGamma* curves.
646 The constants used in the functions do not in fact quite hit these
647 values, but rather than use corrected constants, the functions here
648 use the official *RED* values, in order to match the output of the
649 *RED SDK*.
651 For those interested, solving for constants which exactly hit 1/3
652 and 1.0 yields the following values::
654 B = 25 * (np.sqrt(4093.0) - 3) / 9
655 A = 1 / np.log10(B * 184.32 + 1)
657 where the function takes the form::
659 Log3G10(x) = A * np.log10(B * x + 1)
661 Similarly for *Log3G12*, the values which hit exactly 1/3 and 1.0
662 are::
664 B = 25 * (np.sqrt(16381.0) - 3) / 9
665 A = 1 / np.log10(B * 737.28 + 1)
667 References
668 ----------
669 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017`
671 Examples
672 --------
673 >>> log_encoding_Log3G10(0.0) # doctest: +ELLIPSIS
674 0.09155148...
675 >>> log_encoding_Log3G10(0.18, method="v1") # doctest: +ELLIPSIS
676 0.3333336...
677 """
679 method = validate_method(method, tuple(LOG3G10_ENCODING_METHODS))
681 return LOG3G10_ENCODING_METHODS[method](x)
684LOG3G10_DECODING_METHODS = CanonicalMapping(
685 {
686 "v1": log_decoding_Log3G10_v1,
687 "v2": log_decoding_Log3G10_v2,
688 "v3": log_decoding_Log3G10_v3,
689 }
690)
691LOG3G10_DECODING_METHODS.__doc__ = """
692Supported *Log3G10* log decoding curve / electro-optical transfer (EOTF)
693function methods.
695References
696----------
697:cite:`Nattress2016a`, :cite:`REDDigitalCinema2017`
698"""
701def log_decoding_Log3G10(
702 y: Domain1, method: Literal["v1", "v2", "v3"] | str = "v3"
703) -> Range1:
704 """
705 Apply the *Log3G10* log decoding inverse opto-electronic transfer function (OETF).
707 Parameters
708 ----------
709 y
710 *Log3G10* non-linear encoded data :math:`y`.
711 method
712 Computation method.
714 Returns
715 -------
716 :class:`numpy.ndarray`
717 Linear data :math:`x`.
719 Notes
720 -----
721 +------------+-----------------------+---------------+
722 | **Domain** | **Scale - Reference** | **Scale - 1** |
723 +============+=======================+===============+
724 | ``y`` | 1 | 1 |
725 +------------+-----------------------+---------------+
727 +------------+-----------------------+---------------+
728 | **Range** | **Scale - Reference** | **Scale - 1** |
729 +============+=======================+===============+
730 | ``x`` | 1 | 1 |
731 +------------+-----------------------+---------------+
733 References
734 ----------
735 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017`
737 Examples
738 --------
739 >>> log_decoding_Log3G10(1.0) # doctest: +ELLIPSIS
740 184.3223476...
741 >>> log_decoding_Log3G10(1.0 / 3, method="v1") # doctest: +ELLIPSIS
742 0.1799994...
743 """
745 method = validate_method(method, tuple(LOG3G10_DECODING_METHODS))
747 return LOG3G10_DECODING_METHODS[method](y)
750def log_encoding_Log3G12(x: Domain1) -> Range1:
751 """
752 Apply the *Log3G12* log encoding opto-electronic transfer function (OETF).
754 Parameters
755 ----------
756 x
757 Linear data :math:`x`.
759 Returns
760 -------
761 :class:`numpy.ndarray`
762 *Log3G12* non-linear encoded data :math:`y`.
764 Notes
765 -----
766 +------------+-----------------------+---------------+
767 | **Domain** | **Scale - Reference** | **Scale - 1** |
768 +============+=======================+===============+
769 | ``x`` | 1 | 1 |
770 +------------+-----------------------+---------------+
772 +------------+-----------------------+---------------+
773 | **Range** | **Scale - Reference** | **Scale - 1** |
774 +============+=======================+===============+
775 | ``y`` | 1 | 1 |
776 +------------+-----------------------+---------------+
778 References
779 ----------
780 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017`
782 Examples
783 --------
784 >>> log_encoding_Log3G12(0.18) # doctest: +ELLIPSIS
785 0.3333326...
786 """
788 x = to_domain_1(x)
790 y = np.sign(x) * 0.184904 * np.log10((np.abs(x) * 347.189667) + 1)
792 return as_float(from_range_1(y))
795def log_decoding_Log3G12(y: Domain1) -> Range1:
796 """
797 Apply the *Log3G12* log decoding inverse opto-electronic transfer function (OETF).
799 Parameters
800 ----------
801 y
802 *Log3G12* non-linear encoded data :math:`y`.
804 Returns
805 -------
806 :class:`numpy.ndarray`
807 Linear data :math:`x`.
809 Notes
810 -----
811 +------------+-----------------------+---------------+
812 | **Domain** | **Scale - Reference** | **Scale - 1** |
813 +============+=======================+===============+
814 | ``y`` | 1 | 1 |
815 +------------+-----------------------+---------------+
817 +------------+-----------------------+---------------+
818 | **Range** | **Scale - Reference** | **Scale - 1** |
819 +============+=======================+===============+
820 | ``x`` | 1 | 1 |
821 +------------+-----------------------+---------------+
823 References
824 ----------
825 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017`
827 Examples
828 --------
829 >>> log_decoding_Log3G12(1.0 / 3) # doctest: +ELLIPSIS
830 0.1800015...
831 """
833 y = to_domain_1(y)
835 x = np.sign(y) * (10.0 ** (np.abs(y) / 0.184904) - 1) / 347.189667
837 return as_float(from_range_1(x))