def return_cent_markup( note_head, ratio, quarter_tones=False, ): ratio = quicktions.Fraction(ratio) log_ratio = quicktions.Fraction(math.log10(ratio)) log_2 = quicktions.Fraction(1200 / math.log10(2)) ji_cents = quicktions.Fraction(log_ratio * log_2) semitones = ji_cents / 100 parts = math.modf(semitones) pitch = abjad.NumberedPitch(note_head.written_pitch) + parts[1] remainder = round(parts[0] * 100) if 50 < abs(remainder): if 0 < remainder: pitch += 1 remainder = -100 + remainder else: pitch -= 1 remainder = 100 + remainder if quarter_tones: if 25 < abs(remainder): if 0 < remainder: pitch += 0.5 remainder = -50 + remainder else: pitch -= 0.5 remainder = 50 + remainder if remainder < 0: cent_string = f"{remainder}" else: cent_string = f"+{remainder}" mark = abjad.Markup(rf"\markup \center-align {cent_string}", direction=abjad.Up) return mark
def detect_undefined_areas(self, ignore_rests: bool = False) -> tuple: sorted_novents = self._sorted_novents if ignore_rests: sorted_novents = tuple(novent for novent in sorted_novents if novent.pitch) undefined_areas = [] if sorted_novents[0].delay != 0: undefined_areas.append( (0, fractions.Fraction(sorted_novents[0].delay))) for novent0, novent1 in zip(sorted_novents, sorted_novents[1:]): if novent0.duration != novent1.delay: undefined_areas.append(( fractions.Fraction(novent0.duration), fractions.Fraction(novent1.delay), )) if self.size: if sorted_novents[-1].duration < self.size: undefined_areas.append(( fractions.Fraction(sorted_novents[-1].duration), fractions.Fraction(self.size), )) return tuple(undefined_areas)
def tune_to_ratio( note_head, ratio, quarter_tones=False, ): """ Tunes pitch to ratio. """ ratio = quicktions.Fraction(ratio) log_ratio = quicktions.Fraction(math.log10(ratio)) log_2 = quicktions.Fraction(1200 / math.log10(2)) ji_cents = quicktions.Fraction(log_ratio * log_2) semitones = ji_cents / 100 parts = math.modf(semitones) pitch = abjad.NumberedPitch(note_head.written_pitch) + parts[1] remainder = round(parts[0] * 100) if 50 < abs(remainder): if 0 < remainder: pitch += 1 remainder = -100 + remainder else: pitch -= 1 remainder = 100 + remainder if quarter_tones: if 25 < abs(remainder): if 0 < remainder: pitch += 0.5 remainder = -50 + remainder else: pitch -= 0.5 remainder = 50 + remainder note_head.written_pitch = pitch
def _calculate_pitch_and_deviation( self, pitch, ratio, ): ratio = quicktions.Fraction(ratio) log_ratio = quicktions.Fraction(math.log10(ratio)) log_2 = quicktions.Fraction(1200 / math.log10(2)) ji_cents = quicktions.Fraction(log_ratio * log_2) semitones = ji_cents / 100 parts = math.modf(semitones) pitch = abjad.NumberedPitch(pitch) + parts[1] remainder = round(parts[0] * 100) if 50 < abs(remainder): if 0 < remainder: pitch += 1 remainder = -100 + remainder else: pitch -= 1 remainder = 100 + remainder if self.with_quarter_tones: if 25 < abs(remainder): if 0 < remainder: pitch += 0.5 remainder = -50 + remainder else: pitch -= 0.5 remainder = 50 + remainder return pitch, remainder
def _add_keyboard_to_time_bracket( self, time_bracket: cengkoks.CengkokTimeBracket, structural_data: StructuralData, dynamic: str, ): sequential_event = events.basic.SequentialEvent([]) for _ in range(structural_data[3]): sequential_event.append( events.music.NoteLike([], fractions.Fraction(1, 4), dynamic)) sequential_event.append( events.music.NoteLike([], fractions.Fraction(structural_data[4], 4), dynamic)) if len(sequential_event) >= 4: shall_tie = next(self._tie_cycle) if shall_tie: tie_position_options = [] for n in range(len(sequential_event) - 3): tie_position_options.append(n) tie_position = self._tie_random.choice(tie_position_options) tw.eat(sequential_event, tie_position) tagged_simultaneous_event = events.basic.TaggedSimultaneousEvent( [sequential_event.copy(), sequential_event.copy()], tag=ot2_constants.instruments.ID_KEYBOARD, ) time_bracket.append(tagged_simultaneous_event)
def mixed_number(fraction_pair=(288, 5)): fraction_pair = quicktions.Fraction(fraction_pair) q = fraction_pair.numerator // fraction_pair.denominator r = quicktions.Fraction( (fraction_pair.numerator % fraction_pair.denominator) / fraction_pair.denominator).limit_denominator() return (q, (r.numerator, r.denominator))
def _make_harmonies_and_roots( k: int, r: typing.Sequence[int] ) -> typing.Tuple[typing.Dict[str, typing.Tuple[ pitches.JustIntonationPitch, ...]], typing.Dict[str, typing.Tuple[ pitches.JustIntonationPitch, ...]], ]: harmonies = {} roots = {} for exponent_k, exponent_r, name in ( (1, 1, zimmermann_constants.OTONAL_HARMONY_NAME), (-1, -1, zimmermann_constants.UTONAL_HARMONY_NAME), (-1, 1, zimmermann_constants.F_OTONAL_HARMONY_NAME), (1, -1, zimmermann_constants.F_UTONAL_HARMONY_NAME), ): harmony = [] k_pitch = pitches.JustIntonationPitch( fractions.Fraction(k**exponent_k).limit_denominator(k)) for prime_number in r: r_pitch = pitches.JustIntonationPitch( fractions.Fraction( prime_number**exponent_r).limit_denominator( prime_number)) harmony.append(r_pitch + k_pitch) harmonies.update({name: tuple(harmony)}) roots.update({name: k_pitch}) return harmonies, roots
def test_conversion_functions(self) -> None: self.assertEqual(binr.Compound.convert_int2binary_rhythm(10), (1, 0, 1, 0)) self.assertEqual(binr.Compound.convert_int2binary_rhythm(11), (1, 0, 1, 1)) self.assertEqual(binr.Compound.convert_int2binary_rhythm(12), (1, 1, 0, 0)) self.assertEqual(binr.Compound.convert_int2binary_rhythm(20), (1, 0, 1, 0, 0)) self.assertEqual( binr.Compound.convert_binary_rhythm2rhythm((1, 0, 1, 0, 0)), (2, 3)) self.assertEqual(binr.Compound.convert_binary2binary_rhythm(bin(28)), (1, 1, 1, 0, 0)) self.assertEqual(binr.Compound.convert_binary2binary_rhythm(bin(113)), (1, 1, 1, 0, 0, 0, 1)) self.assertEqual(binr.Compound.convert_binary2rhythm(bin(28)), (1, 1, 3)) self.assertEqual(binr.Compound.convert_binary2rhythm(bin(113)), (1, 1, 4, 1)) self.assertEqual( binr.Compound.convert_binary_rhythm2rhythm((1, 1, 1, 0, 0)), (1, 1, 3)) self.assertEqual( binr.Compound.convert_binary_rhythm2rhythm((1, 1, 0, 0, 1)), (1, 3, 1)) self.assertEqual(binr.Compound.convert_int2rhythm(20), (2, 3)) self.assertEqual( binr.Compound.convert_binary_rhythm2binary((1, 0, 1, 0, 0)), bin(20)) self.assertEqual( binr.Compound.convert_binary_rhythm2binary((1, 1, 0, 1, 1, 0)), bin(54)) self.assertEqual( binr.Compound.convert_int_rhythm2binary_rhythm((1, 2, 1, 2)), (1, 1, 0, 1, 1, 0), ) self.assertEqual( binr.Compound.convert_int_rhythm2binary_rhythm((4, 2, 3, 2)), (1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0), ) self.assertEqual( binr.Compound.convert_rhythm2essence_and_multiply((1, 0.5, 2, 1)), (354, fractions.Fraction(1, 2)), ) multiplied = fractions.Fraction(1, 3) self.assertEqual( binr.Compound.convert_rhythm2essence_and_multiply( tuple(r * multiplied for r in (4, 1, 1, 2))), (142, multiplied), ) self.assertEqual( binr.Compound.convert_essence_and_multiply2rhythm( 354, fractions.Fraction(1, 2)), list(fractions.Fraction(n) for n in (1, 0.5, 2, 1)), )
def __rtruediv__(self, number): """ Divides ``number`` by ratio. .. container:: example >>> 1 / abjad.Ratio((1, 1, 3)) [Fraction(1, 5), Fraction(1, 5), Fraction(3, 5)] .. container:: example >>> 1 / abjad.Ratio((1, 1, 3)) [Fraction(1, 5), Fraction(1, 5), Fraction(3, 5)] .. container:: example >>> 1.0 / abjad.Ratio((1, 1, 3)) [0.2, 0.2, 0.6] Returns list of fractions or list of floats. """ denominator = sum(self.numbers) factors = [quicktions.Fraction(_, denominator) for _ in self.numbers] result = [_ * number for _ in factors] return result
def from_int(cls, essence: int, multiply: fractions.Fraction = fractions.Fraction(1, 1)): assert Compound.is_valid_essence(essence) assert Compound.is_valid_multiply(multiply) return cls( Compound.convert_essence_and_multiply2rhythm(essence, multiply))
def seperate_by_assignablity(duration, grid) -> tuple: def find_sum_in_numbers(numbers, solution, allowed_combinations) -> tuple: return tuple( sorted(c, reverse=True) for c in itertools.combinations_with_replacement( numbers, allowed_combinations) if sum(c) == solution) if abjad.Duration(duration).is_assignable is True: return (abjad.Duration(duration), ) numerator = duration.numerator denominator = duration.denominator possible_durations = [ i for i in range(1, numerator + 1) if abjad.Duration(i, denominator).is_assignable is True ] solution = [] c = 1 while len(solution) == 0: if c == len(possible_durations): print(numerator, denominator) raise ValueError("Can't find any possible combination") s = find_sum_in_numbers(possible_durations, numerator, c) if s: solution.extend(s) else: c += 1 hof = crosstrainer.Stack(size=1, fitness="max") for s in solution: avg_diff = sum(abs(a - b) for a, b in itertools.combinations(s, 2)) hof.append(s, avg_diff) best = hof.best[0] return tuple(fractions.Fraction(s, denominator) for s in best)
def copy(self): return type(self)( self.size, fractions.Fraction(self.pulse_size), [p.copy() for p in self.primes], [att.copy() for att in self.__attractors], )
def arithmetic_mean(argument) -> typing.Union[int, float]: """ Gets arithmetic mean of ``argument``. .. container:: example >>> abjad.math.arithmetic_mean([1, 2, 2, 20, 30]) 11 >>> abjad.math.arithmetic_mean([1, 2, 20]) Fraction(23, 3) >>> abjad.math.arithmetic_mean([2, 2, 20.0]) 8.0 Raises exception when ``argument`` is not iterable. """ if not isinstance(argument, collections_abc.Sequence): raise TypeError(argument) total = sum(argument) length = len(argument) if isinstance(total, float): return total / length result = quicktions.Fraction(sum(argument), len(argument)) int_result = int(result) if int_result == result: return int_result else: return result
def _calculate_metricity_of_melody( time_signature: tuple, melody: old.Melody ) -> float: duration = melody.duration fitness_per_beat = {} rising = fractions.Fraction(1, 8) position = 0 for _ in range( int( math.ceil( duration / (time_signature[0].numerator / time_signature[0].denominator) ) ) ): for fitness in time_signature[1]: fitness_per_beat.update({position: fitness}) position += rising metricity = 0 for tone in melody.convert2absolute(): if tone.pitch: try: metricity += fitness_per_beat[tone.delay] except KeyError: metricity -= 0.01 return metricity
def test_Spacegroup(): transgen = geo.canonical c1 = geo.Coset(geo.Symmetry(nb.Matrix.onematrix(4)), transgen) c2 = geo.Coset( geo.Symmetry( nb.Matrix([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])), transgen) sg = geo.Spacegroup(transgen, [c1, c2]) assert sg.__str__() == \ "Spacegroup \n"\ "---------- \n"\ " canonical \n"\ " x,y,z\n"\ " -x,-y,-z" transgen = geo.Transgen(geo.Dif(nb.Matrix([[1], [0], [0], [0]])), geo.Dif(nb.Matrix([[0], [1], [0], [0]])), geo.Dif(nb.Matrix([[0], [0], [2], [0]]))) c1 = geo.Coset(geo.Symmetry(nb.Matrix.onematrix(4)), transgen) c2 = geo.Coset( geo.Symmetry( nb.Matrix([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])), transgen) sg = geo.Spacegroup(transgen, [c1, c2]) assert sg.__str__() == \ " Spacegroup \n"\ " ---------- \n"\ "Transgen / 1 \ / 0 \ / 0 \ \n"\ " | 0 | | 1 | | 0 | \n"\ " \ 0 / \ 0 / \ 2 / \n"\ " x,y,z\n"\ " -x,-y,-z" sg = geo.Spacegroup(geo.canonical, [ geo.Coset(geo.Symmetry(nb.Matrix.onematrix(4)), geo.canonical), geo.Coset( geo.Symmetry( nb.Matrix([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])), geo.canonical) ]) transformation = geo.Transformation( nb.Matrix([[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])) sg1 = transformation**sg sg2 = geo.Spacegroup(transformation**geo.canonical, [ geo.Coset(geo.Symmetry(nb.Matrix.onematrix(4)), geo.canonical), geo.Coset( geo.Symmetry( nb.Matrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])), geo.canonical) ]) assert sg.is_really_a_spacegroup() == True sg_error = geo.Spacegroup(geo.canonical, [ geo.Coset(geo.Symmetry(nb.Matrix.onematrix(4)), geo.canonical), geo.Coset( geo.Symmetry( nb.Matrix([[1, 0, 0, fr.Fraction(1, 4)], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])), geo.canonical) ]) assert sg_error.is_really_a_spacegroup() == False
def quarters_per_minute( self) -> typing.Union[tuple, None, quicktions.Fraction]: """ Gets metronome mark quarters per minute. .. container:: example >>> mark = abjad.MetronomeMark((1, 8), 52) >>> mark.quarters_per_minute Fraction(104, 1) Gives tuple when metronome mark ``units_per_minute`` is a range. Gives none when metronome mark is imprecise. Gives fraction otherwise. """ if self.is_imprecise: return None if isinstance(self.units_per_minute, tuple): low = Duration( 1, 4) / self.reference_duration * self.units_per_minute[0] high = Duration( 1, 4) / self.reference_duration * self.units_per_minute[1] return (low, high) result = Duration(1, 4) / self.reference_duration * self.units_per_minute return quicktions.Fraction(result)
def synthesize_applied_cantus_firmus(cantus_firmus: basic.SequentialEvent): from mutwo.converters.frontends import midi drone = basic.SequentialEvent([ music.NoteLike( note.pitch_or_pitches[0] - pitches.JustIntonationPitch("2/1"), note.duration, ) if note.pitch_or_pitches else note for note in cantus_firmus ]) melody = basic.SequentialEvent([]) for note in cantus_firmus: if note.pitch_or_pitches: pitches_cycle = itertools.cycle(sorted(note.pitch_or_pitches)) [ melody.append( music.NoteLike(next(pitches_cycle), fractions.Fraction(1, 6))) for _ in range(int(note.duration * 6)) ] else: melody.append(copy.copy(note)) for name, sequential_event in (("drone", drone), ("melody", melody)): converter = midi.MidiFileConverter( "builds/materials/applied_cantus_firmus_{}.mid".format(name)) converter.convert( sequential_event.set_parameter("duration", lambda duration: duration * 4, mutate=False))
def _make_tremolo_for_pair( self, pitches: tuple[ parameters.pitches.JustIntonationPitch, parameters.pitches.JustIntonationPitch, ], dynamic: str, ) -> tuple[events.basic.SequentialEvent, events.basic.SequentialEvent]: n_beats = next(self._n_tones_for_both_hands_cycle) rhythms = generators.toussaint.paradiddle(n_beats) if self._reverse_rhythmic_distribution_al(5): rhythms = tuple(reversed(rhythms)) bar_duration = fractions.Fraction(n_beats, 4) duration_per_beat = bar_duration / n_beats sequential_events = [] # for rhythm, pitch in zip(rhythms, reversed(pitches)): for rhythm, pitch in zip(rhythms, pitches): sequential_event = events.basic.SequentialEvent([]) is_first = True for start, stop in zip(rhythm, rhythm[1:] + (n_beats,)): if is_first and start != 0: sequential_event.append( events.music.NoteLike([], duration_per_beat * start) ) duration = (stop - start) * duration_per_beat note_like = events.music.NoteLike(pitch, duration, dynamic) sequential_event.append(note_like) is_first = False sequential_events.append(sequential_event) return tuple(sequential_events)
def _make_sequential_events( self, pitch_or_pitches: tuple[parameters.pitches.JustIntonationPitch, ...], active_hands: tuple[bool, bool], dynamic: str, ) -> typing.Optional[ tuple[events.basic.SequentialEvent, events.basic.SequentialEvent] ]: if pitch_or_pitches: n_active_pitches = sum(active_hands) if n_active_pitches == 2: sequential_events = sequential_event = self._make_tremolo_for_pair( pitch_or_pitches, dynamic ) else: bar_duration = fractions.Fraction(2, 1) sequential_events = [events.basic.SequentialEvent([]) for _ in range(2)] for nth_hand, activity in enumerate(active_hands): if activity: sequential_event = self._make_tremolo_for_one_hand( pitch_or_pitches[0], bar_duration, dynamic ) else: sequential_event = events.basic.SequentialEvent( [events.music.NoteLike([], bar_duration)] ) sequential_events[nth_hand].extend(sequential_event) return tuple(sequential_events) else: return
def to_nearest_twelfth_tone(number): """ Rounds number to nearest twelfth .. container:: example >>> l = [0, 1.111, 4.5, 2.23, 6.4, 7.3, 7.15] >>> l = [evans.to_nearest_twelfth_tone(_) for _ in l] >>> l [Fraction(0, 1), Fraction(7, 6), Fraction(9, 2), Fraction(9, 4), Fraction(19, 3), Fraction(22, 3), Fraction(43, 6)] """ semitones = quicktions.Fraction(int(round(12 * number)), 12) if semitones.denominator == 12: semitones = quicktions.Fraction(int(round(6 * number)), 6) return semitones
def post_process_common_score_parts(abjad_scores_to_post_process): add_names_to_unnamed_scores(abjad_scores_to_post_process) abjad_score_names_to_post_process = { score.items[0].name: score for score in abjad_scores_to_post_process } # print(abjad_score_names_to_post_process) last_cengkok = abjad_scores_to_post_process[-1] for nth_staff_group, staff_group in enumerate(last_cengkok.items[0]): for staff in staff_group: for voice in staff: if nth_staff_group == 0: problematic_bar = voice[19] tuplet0 = problematic_bar[0] for other_tuplet in problematic_bar[1:]: for item in other_tuplet: tuplet0.append(abjad.mutate.copy(item)) voice[19] = abjad.Container([abjad.mutate.copy(tuplet0)]) # print(problematic_bar[:]) problematic_bar = voice[28] problematic_bar[-1] = abjad.Rest(fractions.Fraction(1, 4)) elif nth_staff_group == 1: problematic_bar = voice[0] problematic_bar[1] = abjad.mutate.copy( problematic_bar[1][0]) problematic_bar[1].written_duration = abjad.Duration(1, 4) problematic_bar[1].note_head._written_pitch = voice[1][0][ 0].note_head._written_pitch problematic_bar = voice[7] tuplet = problematic_bar[0] problematic_bar[0] = abjad.mutate.copy(tuplet[0]) problematic_bar[0].written_duration = abjad.Duration(1, 2) problematic_bar[0].note_head._written_pitch = tuplet[ 0].note_head._written_pitch """
def to_nearest_eighth_tone(number, frac=False): """ Rounds number to nearest eighth .. container:: example >>> l = [0, 1.111, 4.5, 2.23, 6.4, 7.3, 7.15] >>> l = [evans.to_nearest_eighth_tone(_, frac=True) for _ in l] >>> l [Fraction(0, 1), Fraction(1, 1), Fraction(9, 2), Fraction(9, 4), Fraction(13, 2), Fraction(29, 4), Fraction(29, 4)] """ number = round(float(number) * 4) / 4 div, mod = divmod(number, 1) if mod == 0.75: div += 0.75 elif mod == 0.5: div += 0.5 elif mod == 0.25: div += 0.25 if frac is False: return abjad.math.integer_equivalent_number_to_integer(div) else: return quicktions.Fraction( abjad.math.integer_equivalent_number_to_integer(div))
def from_scl(cls, scl_line: str, concert_pitch_freq: float) -> "SimplePitch": p = tuple(l for l in scl_line.split(" ") if l)[0] if "." in p: cents = float(p) else: ratio = p.split("/") ratio_size = len(ratio) if ratio_size == 2: num, den = tuple(int(n) for n in ratio) elif ratio_size == 1: num = int(ratio[0]) den = 1 else: msg = "Can't read ratio {0}.".format(ratio) raise NotImplementedError(msg) try: assert num > den except AssertionError: msg = "ERROR: Invalide ratio {0}. ".format(ratio) msg += "Ratios have to be positiv (numerator " msg += "has to be bigger than denominator)." raise ValueError(msg) cents = abstract.AbstractPitch.ratio2ct(fractions.Fraction(num, den)) return cls(concert_pitch_freq, cents)
def _find_duration_per_pair(self, n_pairs: int) -> tuple[fractions.Fraction, ...]: walk_iterable = self._pair_duration_grammar.walk((fractions.Fraction(1, 1),)) durations = [] while len(durations) < n_pairs: durations = next(walk_iterable) difference = len(durations) - n_pairs durations = durations[difference:] return tuple(durations)
def __init__( self, stretch_factor: float = 1, n_divisions: int = 8, min_tone_size: fractions.Fraction = 0, min_rest_size: fractions.Fraction = fractions.Fraction(1, 10), ): pass
def __truediv__(self, argument): if isinstance(argument, (int, float, quicktions.Fraction)): self_ratio = self.ratio self_fraction = quicktions.Fraction(self_ratio) return type(self)( self.fundamental, quicktions.Fraction(self_fraction / argument), self.with_quarter_tones, ) elif isinstance(argument, type(self)): self_pitch = self.pitch argument_pitch = argument.pitch return type(self)( self.fundamental.number / argument.fundamental.number, quicktions.Fraction(self_pitch.number / argument_pitch.number), self.with_quarter_tones, )
def from_binary( cls, binary_number: bin, multiply: fractions.Fraction = fractions.Fraction(1, 1) ) -> "Compound": new = cls(Compound.convert_binary2rhythm(binary_number)) new.multiply = multiply return new
def from_binary_rhythm( cls, binary_rhythm: tuple, multiply: fractions.Fraction = fractions.Fraction(1, 1), ) -> "Compound": new = cls(Compound.convert_binary_rhythm2rhythm(binary_rhythm)) new.multiply = multiply return new
def _add_sustaining_instrument_to_time_bracket( self, time_bracket: cengkoks.CengkokTimeBracket, structural_data: StructuralData, active_sustaining_instrument_id: str, dynamic: str, ): sequential_event = events.basic.SequentialEvent([ events.basic.SimpleEvent(fractions.Fraction(structural_data[3], 4)), events.music.NoteLike([], fractions.Fraction(structural_data[4], 4), dynamic), ]) tagged_simultaneous_event = events.basic.TaggedSimultaneousEvent( [sequential_event], tag=active_sustaining_instrument_id) time_bracket.append(tagged_simultaneous_event)
def dsin(number): if isinstance(number, fr.Fraction): number = Mixed(number) elif isinstance(number, uc.UFloat): number = Mixed(number) elif isinstance(number, float): number = Mixed(number) elif isinstance(number, int): number = Mixed(number) assert isinstance(number, Mixed), \ "Connot calculate cos of an object of type %s." % (type(number)) if isinstance(number.value, fr.Fraction): x = number.value % 360 if x == 0: return Mixed(0) elif x == 30: return Mixed(fr.Fraction(1, 2)) elif x == 90: return Mixed(1) elif x == 150: return Mixed(fr.Fraction(1, 2)) elif x == 180: return Mixed(0) elif x == 210: return Mixed(-fr.Fraction(1, 2)) elif x == 270: return Mixed(-1) elif x == 330: return Mixed(-fr.Fraction(1, 2)) else: return Mixed(np.sin(float(deg2rad(number).value))) elif isinstance(number.value, uc.UFloat): return Mixed(unumpy.sin(deg2rad(number).value).item()) elif isinstance(number.value, float): return Mixed(np.sin(deg2rad(number).value)) elif isinstance(number.value, int): x = number.value % 360 if x == 0: return Mixed(0) elif x == 30: return Mixed(fr.Fraction(1, 2)) elif x == 90: return Mixed(1) elif x == 150: return Mixed(fr.Fraction(1, 2)) elif x == 180: return Mixed(0) elif x == 210: return Mixed(-fr.Fraction(1, 2)) elif x == 270: return Mixed(-1) elif x == 330: return Mixed(-fr.Fraction(1, 2)) else: return Mixed(np.sin(deg2rad(number).value))